diff --git a/legacy/reqcounter/reqcounter.go b/legacy/reqcounter/reqcounter.go index efd6e98a0..84602d6e1 100644 --- a/legacy/reqcounter/reqcounter.go +++ b/legacy/reqcounter/reqcounter.go @@ -64,16 +64,22 @@ func (rc *RequestCounter) reset() { rc.Since = Clock.Now() } -// watch continuously logs the request counter at the specified intervals. +// watch indefinitely performs repeated sleep/log cycles. func (rc *RequestCounter) watch() { + // TODO: @tylerferrara create a way to cleanly terminate this goroutine. go func() { for { - Clock.Sleep(rc.Interval) - rc.Flush() + rc.Cycle() } }() } +// Cycle sleeps for the request counter's interval and flushes itself. +func (rc *RequestCounter) Cycle() { + Clock.Sleep(rc.Interval) + rc.Flush() +} + // RequestCounters holds multiple request counters. type RequestCounters []*RequestCounter diff --git a/legacy/reqcounter/reqcounter_test.go b/legacy/reqcounter/reqcounter_test.go index 2755710c7..b0790af4e 100644 --- a/legacy/reqcounter/reqcounter_test.go +++ b/legacy/reqcounter/reqcounter_test.go @@ -17,12 +17,14 @@ limitations under the License. package reqcounter_test import ( + "fmt" "sync" "testing" "time" "github.com/stretchr/testify/require" rc "sigs.k8s.io/k8s-container-image-promoter/legacy/reqcounter" + tw "sigs.k8s.io/k8s-container-image-promoter/legacy/timewrapper" ) // defaultTime should be used as a timestamp for all request counters. @@ -124,3 +126,35 @@ func TestRequestCounterIncrement(t *testing.T) { // Ensure the request counter was incremented. require.EqualValues(t, &expected, &requestCounter, "The request counter failed to increment its request field.") } + +func TestCycle(t *testing.T) { + // Create a simple request counter expected to log every 3 seconds. + requestCounter := NewRequestCounter(82) + requestCounter.Interval = time.Second * 3 + // Collect logging statements. + logs := []string{} + // Mock logrus.Debug calls. + rc.Debug = func(args ...interface{}) { + logs = append(logs, fmt.Sprint(args[0])) + } + // Mock time. + fakeTime := tw.FakeTime{ + Time: defaultTime, + } + rc.Clock = &fakeTime + // Determine the expected logs. + expected := []string{ + "From 2006-01-02 15:04:05 to 2006-01-02 15:04:08 [0 min] there have been 82 requests to GCR.", + "From 2006-01-02 15:04:08 to 2006-01-02 15:04:11 [0 min] there have been 0 requests to GCR.", + "From 2006-01-02 15:04:11 to 2006-01-02 15:04:14 [0 min] there have been 0 requests to GCR.", + "From 2006-01-02 15:04:14 to 2006-01-02 15:04:17 [0 min] there have been 0 requests to GCR.", + "From 2006-01-02 15:04:17 to 2006-01-02 15:04:20 [0 min] there have been 0 requests to GCR.", + } + // Repeatedly run sleep/log cycles. + numCycles := 5 + for i := 0; i < numCycles; i++ { + requestCounter.Cycle() + } + // Ensure the correct logs were produced. + require.EqualValues(t, expected, logs, "The request counter produced malformed logs.") +} diff --git a/legacy/timewrapper/timewrapper.go b/legacy/timewrapper/timewrapper.go index 0e6bf652d..1d48847e1 100644 --- a/legacy/timewrapper/timewrapper.go +++ b/legacy/timewrapper/timewrapper.go @@ -41,7 +41,9 @@ type FakeTime struct { } // Now returns the global fake time. -func (ft FakeTime) Now() time.Time { return ft.Time } +func (ft *FakeTime) Now() time.Time { return ft.Time } -// Sleep does not block the current goroutine. -func (ft FakeTime) Sleep(d time.Duration) {} +// Sleep adds the given duration to the global fake time. +func (ft *FakeTime) Sleep(d time.Duration) { + ft.Time = ft.Time.Add(d) +}