diff --git a/fs/accounting/stats.go b/fs/accounting/stats.go index 56eef4709..d31b23158 100644 --- a/fs/accounting/stats.go +++ b/fs/accounting/stats.go @@ -138,7 +138,7 @@ func (s *StatsInfo) totalDuration() time.Duration { var total time.Duration var i, j = 0, 1 for i < len(timeRanges) { - if j < len(timeRanges)-1 { + if j < len(timeRanges) { if timeRanges[j].start.Before(timeRanges[i].end) { if timeRanges[i].end.Before(timeRanges[j].end) { timeRanges[i].end = timeRanges[j].end diff --git a/fs/accounting/stats_test.go b/fs/accounting/stats_test.go index cb0b25243..9f354e807 100644 --- a/fs/accounting/stats_test.go +++ b/fs/accounting/stats_test.go @@ -130,52 +130,90 @@ func TestStatsError(t *testing.T) { } func TestStatsTotalDuration(t *testing.T) { - time1 := time.Now().Add(-40 * time.Second) + startTime := time.Now() + time1 := startTime.Add(-40 * time.Second) time2 := time1.Add(10 * time.Second) time3 := time2.Add(10 * time.Second) time4 := time3.Add(10 * time.Second) - s := NewStats() - s.AddTransfer(&Transfer{ - startedAt: time2, - completedAt: time3, - }) - s.AddTransfer(&Transfer{ - startedAt: time2, - completedAt: time2.Add(time.Second), - }) - s.AddTransfer(&Transfer{ - startedAt: time1, - completedAt: time3, - }) - s.AddTransfer(&Transfer{ - startedAt: time3, - completedAt: time4, - }) - s.AddTransfer(&Transfer{ - startedAt: time.Now(), + + t.Run("Single completed transfer", func(t *testing.T) { + s := NewStats() + s.AddTransfer(&Transfer{ + startedAt: time1, + completedAt: time2, + }) + + s.mu.Lock() + total := s.totalDuration() + s.mu.Unlock() + + assert.Equal(t, 10*time.Second, total) }) - time.Sleep(time.Millisecond) + t.Run("Single uncompleted transfer", func(t *testing.T) { + s := NewStats() + s.AddTransfer(&Transfer{ + startedAt: time1, + }) - s.mu.Lock() - total := s.totalDuration() - s.mu.Unlock() + s.mu.Lock() + total := s.totalDuration() + s.mu.Unlock() - assert.True(t, 30*time.Second < total && total < 31*time.Second, total) -} - -func TestStatsTotalDuration2(t *testing.T) { - time1 := time.Now().Add(-40 * time.Second) - time2 := time1.Add(10 * time.Second) - s := NewStats() - s.AddTransfer(&Transfer{ - startedAt: time1, - completedAt: time2, - }) - - s.mu.Lock() - total := s.totalDuration() - s.mu.Unlock() - - assert.Equal(t, 10*time.Second, total) + assert.Equal(t, time.Since(time1)/time.Second, total/time.Second) + }) + + t.Run("Overlapping without ending", func(t *testing.T) { + s := NewStats() + s.AddTransfer(&Transfer{ + startedAt: time2, + completedAt: time3, + }) + s.AddTransfer(&Transfer{ + startedAt: time2, + completedAt: time2.Add(time.Second), + }) + s.AddTransfer(&Transfer{ + startedAt: time1, + completedAt: time3, + }) + s.AddTransfer(&Transfer{ + startedAt: time3, + completedAt: time4, + }) + s.AddTransfer(&Transfer{ + startedAt: time.Now(), + }) + + time.Sleep(time.Millisecond) + + s.mu.Lock() + total := s.totalDuration() + s.mu.Unlock() + + assert.Equal(t, time.Duration(30), total/time.Second) + }) + + t.Run("Mixed completed and uncompleted transfers", func(t *testing.T) { + s := NewStats() + s.AddTransfer(&Transfer{ + startedAt: time1, + completedAt: time2, + }) + s.AddTransfer(&Transfer{ + startedAt: time2, + }) + s.AddTransfer(&Transfer{ + startedAt: time3, + }) + s.AddTransfer(&Transfer{ + startedAt: time3, + }) + + s.mu.Lock() + total := s.totalDuration() + s.mu.Unlock() + + assert.Equal(t, startTime.Sub(time1)/time.Second, total/time.Second) + }) }