diff --git a/internal/client/storage.go b/internal/client/storage.go index fbbfd1b8..e3bf58e0 100644 --- a/internal/client/storage.go +++ b/internal/client/storage.go @@ -17,6 +17,7 @@ import ( "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/hostsfile" "github.com/AdguardTeam/golibs/logutil/slogutil" + "github.com/AdguardTeam/golibs/timeutil" ) // allowedTags is the list of available client tags. @@ -89,6 +90,10 @@ type StorageConfig struct { // not be nil. Logger *slog.Logger + // Clock is used by [upstreamManager] to retrieve the current time. It must + // not be nil. + Clock timeutil.Clock + // DHCP is used to match IPs against MACs of persistent clients and update // [SourceDHCP] runtime client information. It must not be nil. DHCP DHCP @@ -167,7 +172,7 @@ func NewStorage(ctx context.Context, conf *StorageConfig) (s *Storage, err error mu: &sync.Mutex{}, index: newIndex(), runtimeIndex: newRuntimeIndex(), - upstreamManager: newUpstreamManager(conf.Logger), + upstreamManager: newUpstreamManager(conf.Logger, conf.Clock), dhcp: conf.DHCP, etcHosts: conf.EtcHosts, arpDB: conf.ARPDB, diff --git a/internal/client/storage_test.go b/internal/client/storage_test.go index 4a981148..d00f8350 100644 --- a/internal/client/storage_test.go +++ b/internal/client/storage_test.go @@ -18,17 +18,20 @@ import ( "github.com/AdguardTeam/golibs/hostsfile" "github.com/AdguardTeam/golibs/logutil/slogutil" "github.com/AdguardTeam/golibs/testutil" + "github.com/AdguardTeam/golibs/testutil/faketime" + "github.com/AdguardTeam/golibs/timeutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // newTestStorage is a helper function that returns initialized storage. -func newTestStorage(tb testing.TB) (s *client.Storage) { +func newTestStorage(tb testing.TB, clock timeutil.Clock) (s *client.Storage) { tb.Helper() ctx := testutil.ContextWithTimeout(tb, testTimeout) s, err := client.NewStorage(ctx, &client.StorageConfig{ Logger: slogutil.NewDiscardLogger(), + Clock: clock, }) require.NoError(tb, err) @@ -695,7 +698,7 @@ func TestStorage_Add(t *testing.T) { } ctx := testutil.ContextWithTimeout(t, testTimeout) - s := newTestStorage(t) + s := newTestStorage(t, timeutil.SystemClock{}) tags := s.AllowedTags() require.NotZero(t, len(tags)) require.True(t, slices.IsSorted(tags)) @@ -826,7 +829,7 @@ func TestStorage_RemoveByName(t *testing.T) { } ctx := testutil.ContextWithTimeout(t, testTimeout) - s := newTestStorage(t) + s := newTestStorage(t, timeutil.SystemClock{}) err := s.Add(ctx, existingClient) require.NoError(t, err) @@ -851,7 +854,7 @@ func TestStorage_RemoveByName(t *testing.T) { } t.Run("duplicate_remove", func(t *testing.T) { - s = newTestStorage(t) + s = newTestStorage(t, timeutil.SystemClock{}) err = s.Add(ctx, existingClient) require.NoError(t, err) @@ -1308,7 +1311,16 @@ func TestStorage_CustomUpstreamConfig(t *testing.T) { Upstreams: []string{"192.0.2.0"}, } - s := newTestStorage(t) + date := time.Now() + clock := &faketime.Clock{ + OnNow: func() (now time.Time) { + date = date.Add(time.Second) + + return date + }, + } + + s := newTestStorage(t, clock) s.UpdateCommonUpstreamConfig(&client.CommonUpstreamConfig{ UpstreamTimeout: testUpstreamTimeout, }) diff --git a/internal/client/upstreammanager.go b/internal/client/upstreammanager.go index bc2c4362..f6cad878 100644 --- a/internal/client/upstreammanager.go +++ b/internal/client/upstreammanager.go @@ -12,6 +12,7 @@ import ( "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/logutil/slogutil" "github.com/AdguardTeam/golibs/stringutil" + "github.com/AdguardTeam/golibs/timeutil" ) // CommonUpstreamConfig contains common settings for custom client upstream @@ -68,16 +69,20 @@ type upstreamManager struct { // commonConf is the common upstream configuration. commonConf *CommonUpstreamConfig + // clock is used to get the current time. It must not be nil. + clock timeutil.Clock + // confUpdate is the timestamp of the latest common upstream configuration // update. confUpdate time.Time } // newUpstreamManager returns the new properly initialized upstream manager. -func newUpstreamManager(logger *slog.Logger) (m *upstreamManager) { +func newUpstreamManager(logger *slog.Logger, clock timeutil.Clock) (m *upstreamManager) { return &upstreamManager{ logger: logger, uidToCustomConf: make(map[UID]*customUpstreamConfig), + clock: clock, } } @@ -85,7 +90,7 @@ func newUpstreamManager(logger *slog.Logger) (m *upstreamManager) { // timestamp of the latest configuration update. func (m *upstreamManager) updateCommonUpstreamConfig(conf *CommonUpstreamConfig) { m.commonConf = conf - m.confUpdate = time.Now() + m.confUpdate = m.clock.Now() } // updateCustomUpstreamConfig updates the stored custom client upstream diff --git a/internal/home/clients.go b/internal/home/clients.go index e2fd62fb..4a5a4d00 100644 --- a/internal/home/clients.go +++ b/internal/home/clients.go @@ -19,6 +19,7 @@ import ( "github.com/AdguardTeam/AdGuardHome/internal/whois" "github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/logutil/slogutil" + "github.com/AdguardTeam/golibs/timeutil" ) // clientsContainer is the storage of all runtime and persistent clients. @@ -106,6 +107,7 @@ func (clients *clientsContainer) Init( clients.storage, err = client.NewStorage(ctx, &client.StorageConfig{ Logger: baseLogger.With(slogutil.KeyPrefix, "client_storage"), + Clock: timeutil.SystemClock{}, InitialClients: confClients, DHCP: dhcpServer, EtcHosts: hosts,