mirror of
https://github.com/luxfi/timer.git
synced 2026-10-30 15:15:40 +00:00
- Remove meter.go (duplicate Meter interface) - Keep concrete Meter struct in clock.go - Add new timer files (adaptive, staged, stopped)
109 lines
3.2 KiB
Go
109 lines
3.2 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package timer
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// timePtr is a helper function to convert a time.Duration to a pointer
|
|
func timePtr(d time.Duration) *time.Duration {
|
|
return &d
|
|
}
|
|
|
|
func TestEtaTracker(t *testing.T) {
|
|
tracker := NewEtaTracker(3, 1.0)
|
|
now := time.Now()
|
|
target := uint64(1000)
|
|
|
|
tests := []struct {
|
|
name string
|
|
completed uint64
|
|
timestamp time.Time
|
|
expectedEta *time.Duration
|
|
expectedPercent float64
|
|
}{
|
|
{
|
|
// should return nil ETA and 0% complete
|
|
name: "sample 1: insufficient data",
|
|
completed: 0,
|
|
timestamp: now,
|
|
expectedEta: nil,
|
|
expectedPercent: 0.0,
|
|
},
|
|
{
|
|
// should return nil ETA and 0% complete (rate is 10 per second)
|
|
name: "sample 2: insufficient data",
|
|
completed: 100,
|
|
timestamp: now.Add(10 * time.Second),
|
|
expectedEta: nil,
|
|
expectedPercent: 0.0,
|
|
},
|
|
{
|
|
// should return 80s ETA and 20% complete (rate still 10 per second)
|
|
name: "sample 3: sufficient data for ETA",
|
|
completed: 200,
|
|
timestamp: now.Add(20 * time.Second),
|
|
expectedEta: timePtr(80 * time.Second),
|
|
expectedPercent: 20.0,
|
|
},
|
|
{
|
|
// should return 24s ETA and 60% complete (rate is 15 per second)
|
|
name: "sample 4: non linear since we sped up",
|
|
completed: 600,
|
|
timestamp: now.Add(40 * time.Second),
|
|
expectedEta: timePtr(24 * time.Second),
|
|
expectedPercent: 60.0,
|
|
},
|
|
{
|
|
// should return 0s ETA and 100% complete since we're at the end
|
|
name: "sample 5: at the end",
|
|
completed: 1000,
|
|
timestamp: now.Add(60 * time.Second), // Fixed: was 1s which went backwards
|
|
expectedEta: timePtr(0),
|
|
expectedPercent: 100.0,
|
|
},
|
|
{
|
|
// should return 0s ETA and 100% complete
|
|
name: "sample 6: past the end",
|
|
completed: 2000,
|
|
timestamp: now.Add(70 * time.Second), // Fixed: was 1s which went backwards
|
|
expectedEta: timePtr(0),
|
|
expectedPercent: 100.0,
|
|
},
|
|
{
|
|
name: "bogus sample: time warp",
|
|
completed: 100,
|
|
timestamp: now,
|
|
expectedEta: nil,
|
|
expectedPercent: 0.0,
|
|
},
|
|
{
|
|
name: "bogus sample: no progress",
|
|
completed: 100,
|
|
timestamp: now,
|
|
expectedEta: nil,
|
|
expectedPercent: 0.0,
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
eta, percentComplete := tracker.AddSample(tt.completed, target, tt.timestamp)
|
|
t.Logf("Sample %d (%s): completed=%d, target=%d, eta=%v, percent=%.1f%%",
|
|
i+1, tt.name, tt.completed, target, eta, percentComplete)
|
|
require.Equal(t, tt.expectedEta == nil, eta == nil, tt.name)
|
|
if eta != nil {
|
|
// Use 20% tolerance for ETA estimates (acceleration/deceleration changes predictions significantly)
|
|
require.InDelta(t, float64(*tt.expectedEta), float64(*eta), float64(*tt.expectedEta)*0.2, tt.name)
|
|
}
|
|
require.InDelta(t, tt.expectedPercent, percentComplete, 0.01, tt.name)
|
|
}
|
|
}
|