From d5aa54c36544239f7626f1ae1da3f25488f3bdfb Mon Sep 17 00:00:00 2001 From: Scott Andrews Date: Sat, 27 Sep 2025 09:18:24 -0400 Subject: [PATCH] Invert time test Rather than reading the value of `Now` on `ReconcilerTestCase`, the field is used to set the time for that test case and the set value is asserted within the reconcile. Signed-off-by: Scott Andrews --- testing/reconciler_test.go | 53 ++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/testing/reconciler_test.go b/testing/reconciler_test.go index d113889..ed0f0c5 100644 --- a/testing/reconciler_test.go +++ b/testing/reconciler_test.go @@ -1,5 +1,5 @@ /* -Copyright 2019 the original author or authors. +Copyright 2025 the original author or authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,48 +19,57 @@ package testing import ( "context" "testing" + "time" "k8s.io/apimachinery/pkg/runtime" "reconciler.io/runtime/reconcilers" + rtime "reconciler.io/runtime/time" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -func TestReconcilerTestCase_Run(t *testing.T) { +func TestReconcilerTestCase_Now(t *testing.T) { + start := time.Now() + type testCase struct { - name string - verify func(*testing.T, *ReconcilerTestCase, *testCase) - verifyRan bool + name string + rtc *ReconcilerTestCase + verify func(*testing.T, context.Context) } tests := []*testCase{ { name: "Now defaults to time.Now()", - verify: func(t *testing.T, rtc *ReconcilerTestCase, tc *testCase) { - tc.verifyRan = true - if rtc.Now.IsZero() { + rtc: &ReconcilerTestCase{}, + verify: func(t *testing.T, ctx context.Context) { + now := rtime.RetrieveNow(ctx) + // compare with a range to allow for time skew + // test must complete within 1 hour of wall clock time + if now.Before(start.Add(-1*time.Second)) || now.After(start.Add(time.Hour)) { t.Error("expected test case to be initialized with time.Now()") } - + }, + }, + { + name: "Now is set explicitly", + rtc: &ReconcilerTestCase{ + Now: time.UnixMilli(1000), + }, + verify: func(t *testing.T, ctx context.Context) { + now := rtime.RetrieveNow(ctx) + if !now.Equal(time.UnixMilli(1000)) { + t.Error("expected time to be initialized from the test case") + } }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - rtc := &ReconcilerTestCase{} - if tc.verify != nil { - rtc.Prepare = func(t *testing.T, ctx context.Context, rtc *ReconcilerTestCase) (context.Context, error) { - tc.verify(t, rtc, tc) - return ctx, nil - } - } - rtc.Run(t, runtime.NewScheme(), func(t *testing.T, rtc *ReconcilerTestCase, c reconcilers.Config) reconcile.Reconciler { + tc.rtc.ExpectedResult = reconcile.Result{RequeueAfter: time.Second} + tc.rtc.Run(t, runtime.NewScheme(), func(t *testing.T, rtc *ReconcilerTestCase, c reconcilers.Config) reconcile.Reconciler { return reconcile.Func(func(ctx context.Context, o reconcile.Request) (reconcile.Result, error) { - return reconcile.Result{}, nil + tc.verify(t, ctx) + return reconcile.Result{RequeueAfter: time.Second}, nil }) }) - - if !tc.verifyRan { - t.Fatal("expected verify to have run") - } }) } }