From 1bcbbf058741594e13ce6ec382edc908b383f112 Mon Sep 17 00:00:00 2001 From: favonia Date: Thu, 27 Jun 2024 02:09:46 -0500 Subject: [PATCH] feat(setter): print '(cached)' for cached results (#776) --- internal/api/base.go | 2 +- internal/api/cloudflare.go | 15 ++++----- internal/api/cloudflare_test.go | 49 ++++++++++++++++++----------- internal/mocks/mock_api.go | 13 ++++---- internal/setter/setter.go | 16 +++++++--- internal/setter/setter_test.go | 56 +++++++++++++++++++++++---------- 6 files changed, 98 insertions(+), 53 deletions(-) diff --git a/internal/api/base.go b/internal/api/base.go index 37489459..084889f5 100644 --- a/internal/api/base.go +++ b/internal/api/base.go @@ -16,7 +16,7 @@ import ( // A Handle represents a generic API to update DNS records. Currently, the only implementation is Cloudflare. type Handle interface { // ListRecords lists all matching DNS records. - ListRecords(ctx context.Context, ppfmt pp.PP, domain domain.Domain, ipNet ipnet.Type) (map[string]netip.Addr, bool) + ListRecords(ctx context.Context, ppfmt pp.PP, domain domain.Domain, ipNet ipnet.Type) (map[string]netip.Addr, bool, bool) //nolint:lll // DeleteRecord deletes one DNS record. DeleteRecord(ctx context.Context, ppfmt pp.PP, domain domain.Domain, ipNet ipnet.Type, id string) bool diff --git a/internal/api/cloudflare.go b/internal/api/cloudflare.go index 3b69494c..23e0e5a4 100644 --- a/internal/api/cloudflare.go +++ b/internal/api/cloudflare.go @@ -174,17 +174,18 @@ zoneSearch: return "", false } -// ListRecords lists all matching DNS records. +// ListRecords lists all matching DNS records. The second return value indicates whether +// the lists are from cached responses. func (h *CloudflareHandle) ListRecords(ctx context.Context, ppfmt pp.PP, domain domain.Domain, ipNet ipnet.Type, -) (map[string]netip.Addr, bool) { +) (map[string]netip.Addr, bool, bool) { if rmap := h.cache.listRecords[ipNet].Get(domain.DNSNameASCII()); rmap != nil { - return rmap.Value(), true + return rmap.Value(), true, true } zone, ok := h.ZoneOfDomain(ctx, ppfmt, domain) if !ok { - return nil, false + return nil, false, false } //nolint:exhaustruct // Other fields are intentionally unspecified @@ -196,7 +197,7 @@ func (h *CloudflareHandle) ListRecords(ctx context.Context, ppfmt pp.PP, }) if err != nil { ppfmt.Warningf(pp.EmojiError, "Failed to retrieve records of %q: %v", domain.Describe(), err) - return nil, false + return nil, false, false } rmap := map[string]netip.Addr{} @@ -204,13 +205,13 @@ func (h *CloudflareHandle) ListRecords(ctx context.Context, ppfmt pp.PP, rmap[rs[i].ID], err = netip.ParseAddr(rs[i].Content) if err != nil { ppfmt.Warningf(pp.EmojiImpossible, "Failed to parse the IP address in records of %q: %v", domain.Describe(), err) - return nil, false + return nil, false, false } } h.cache.listRecords[ipNet].Set(domain.DNSNameASCII(), rmap, ttlcache.DefaultTTL) - return rmap, true + return rmap, false, true } // DeleteRecord deletes one DNS record. diff --git a/internal/api/cloudflare_test.go b/internal/api/cloudflare_test.go index f9d1f5dc..6c390426 100644 --- a/internal/api/cloudflare_test.go +++ b/internal/api/cloudflare_test.go @@ -117,7 +117,7 @@ func newHandle(t *testing.T, emptyAccountID bool) (*http.ServeMux, api.Handle) { func TestNewValid(t *testing.T) { t.Parallel() - _, _ = newHandle(t, false) + newHandle(t, false) } func TestNewEmpty(t *testing.T) { @@ -636,15 +636,17 @@ func TestListRecords(t *testing.T) { expected := map[string]netip.Addr{"record1": mustIP("::1"), "record2": mustIP("::2")} ipNet, ips, accessCount = ipnet.IP6, expected, 1 mockPP := mocks.NewMockPP(mockCtrl) - ips, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + ips, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.True(t, ok) + require.False(t, cached) require.Equal(t, expected, ips) require.Equal(t, 0, accessCount) // testing the caching mockPP = mocks.NewMockPP(mockCtrl) - ips, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + ips, cached, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.True(t, ok) + require.True(t, cached) require.Equal(t, expected, ips) } @@ -698,8 +700,9 @@ func TestListRecordsInvalidIPAddress(t *testing.T) { "sub.test.org", gomock.Any(), ) - ips, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + ips, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.False(t, ok) + require.False(t, cached) require.Nil(t, ips) require.Equal(t, 0, accessCount) @@ -711,8 +714,9 @@ func TestListRecordsInvalidIPAddress(t *testing.T) { "sub.test.org", gomock.Any(), ) - ips, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + ips, cached, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.False(t, ok) + require.False(t, cached) require.Nil(t, ips) require.Equal(t, 0, accessCount) } @@ -762,15 +766,17 @@ func TestListRecordsWildcard(t *testing.T) { expected := map[string]netip.Addr{"record1": mustIP("::1"), "record2": mustIP("::2")} ipNet, ips, accessCount = ipnet.IP6, expected, 1 mockPP := mocks.NewMockPP(mockCtrl) - ips, ok := h.ListRecords(context.Background(), mockPP, domain.Wildcard("test.org"), ipnet.IP6) + ips, cached, ok := h.ListRecords(context.Background(), mockPP, domain.Wildcard("test.org"), ipnet.IP6) require.True(t, ok) + require.False(t, cached) require.Equal(t, expected, ips) require.Equal(t, 0, accessCount) // testing the caching mockPP = mocks.NewMockPP(mockCtrl) - ips, ok = h.ListRecords(context.Background(), mockPP, domain.Wildcard("test.org"), ipnet.IP6) + ips, cached, ok = h.ListRecords(context.Background(), mockPP, domain.Wildcard("test.org"), ipnet.IP6) require.True(t, ok) + require.True(t, cached) require.Equal(t, expected, ips) } @@ -785,14 +791,16 @@ func TestListRecordsInvalidDomain(t *testing.T) { mockPP := mocks.NewMockPP(mockCtrl) mockPP.EXPECT().Warningf(pp.EmojiError, "Failed to retrieve records of %q: %v", "sub.test.org", gomock.Any()) - ips, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP4) + ips, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP4) require.False(t, ok) + require.False(t, cached) require.Nil(t, ips) mockPP = mocks.NewMockPP(mockCtrl) mockPP.EXPECT().Warningf(pp.EmojiError, "Failed to retrieve records of %q: %v", "sub.test.org", gomock.Any()) - ips, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + ips, cached, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.False(t, ok) + require.False(t, cached) require.Nil(t, ips) } @@ -809,8 +817,9 @@ func TestListRecordsInvalidZone(t *testing.T) { "sub.test.org", gomock.Any(), ) - ips, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP4) + ips, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP4) require.False(t, ok) + require.False(t, cached) require.Nil(t, ips) mockPP = mocks.NewMockPP(mockCtrl) @@ -820,8 +829,9 @@ func TestListRecordsInvalidZone(t *testing.T) { "sub.test.org", gomock.Any(), ) - ips, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + ips, cached, ok = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.False(t, ok) + require.False(t, cached) require.Nil(t, ips) } @@ -907,10 +917,11 @@ func TestDeleteRecordValid(t *testing.T) { listAccessCount, deleteAccessCount = 1, 1 mockPP = mocks.NewMockPP(mockCtrl) - _, _ = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) _ = h.DeleteRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, "record1") - rs, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + rs, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.True(t, ok) + require.True(t, cached) require.Empty(t, rs) } @@ -1022,10 +1033,11 @@ func TestUpdateRecordValid(t *testing.T) { listAccessCount, updateAccessCount = 1, 1 mockPP = mocks.NewMockPP(mockCtrl) - _, _ = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) _ = h.UpdateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, "record1", mustIP("::2")) - rs, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + rs, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.True(t, ok) + require.True(t, cached) require.Equal(t, map[string]netip.Addr{"record1": mustIP("::2")}, rs) } @@ -1138,10 +1150,11 @@ func TestCreateRecordValid(t *testing.T) { listAccessCount, createAccessCount = 1, 1 mockPP = mocks.NewMockPP(mockCtrl) - _, _ = h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) - _, _ = h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false) //nolint:lll - rs, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) + h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false) //nolint:lll + rs, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6) require.True(t, ok) + require.True(t, cached) require.Equal(t, map[string]netip.Addr{"record1": mustIP("::1")}, rs) } diff --git a/internal/mocks/mock_api.go b/internal/mocks/mock_api.go index b16ee11e..5c90de5f 100644 --- a/internal/mocks/mock_api.go +++ b/internal/mocks/mock_api.go @@ -157,12 +157,13 @@ func (c *HandleFlushCacheCall) DoAndReturn(f func()) *HandleFlushCacheCall { } // ListRecords mocks base method. -func (m *MockHandle) ListRecords(arg0 context.Context, arg1 pp.PP, arg2 domain.Domain, arg3 ipnet.Type) (map[string]netip.Addr, bool) { +func (m *MockHandle) ListRecords(arg0 context.Context, arg1 pp.PP, arg2 domain.Domain, arg3 ipnet.Type) (map[string]netip.Addr, bool, bool) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListRecords", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(map[string]netip.Addr) ret1, _ := ret[1].(bool) - return ret0, ret1 + ret2, _ := ret[2].(bool) + return ret0, ret1, ret2 } // ListRecords indicates an expected call of ListRecords. @@ -178,19 +179,19 @@ type HandleListRecordsCall struct { } // Return rewrite *gomock.Call.Return -func (c *HandleListRecordsCall) Return(arg0 map[string]netip.Addr, arg1 bool) *HandleListRecordsCall { - c.Call = c.Call.Return(arg0, arg1) +func (c *HandleListRecordsCall) Return(arg0 map[string]netip.Addr, arg1, arg2 bool) *HandleListRecordsCall { + c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do -func (c *HandleListRecordsCall) Do(f func(context.Context, pp.PP, domain.Domain, ipnet.Type) (map[string]netip.Addr, bool)) *HandleListRecordsCall { +func (c *HandleListRecordsCall) Do(f func(context.Context, pp.PP, domain.Domain, ipnet.Type) (map[string]netip.Addr, bool, bool)) *HandleListRecordsCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *HandleListRecordsCall) DoAndReturn(f func(context.Context, pp.PP, domain.Domain, ipnet.Type) (map[string]netip.Addr, bool)) *HandleListRecordsCall { +func (c *HandleListRecordsCall) DoAndReturn(f func(context.Context, pp.PP, domain.Domain, ipnet.Type) (map[string]netip.Addr, bool, bool)) *HandleListRecordsCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/internal/setter/setter.go b/internal/setter/setter.go index 1453586f..d14ad221 100644 --- a/internal/setter/setter.go +++ b/internal/setter/setter.go @@ -52,7 +52,7 @@ func (s *setter) Set(ctx context.Context, ppfmt pp.PP, recordType := ipnet.RecordType() domainDescription := domain.Describe() - rs, ok := s.Handle.ListRecords(ctx, ppfmt, domain, ipnet) + rs, cached, ok := s.Handle.ListRecords(ctx, ppfmt, domain, ipnet) if !ok { ppfmt.Errorf(pp.EmojiError, "Failed to retrieve the current %s records of %q", recordType, domainDescription) return ResponseFailed @@ -76,7 +76,11 @@ func (s *setter) Set(ctx context.Context, ppfmt pp.PP, // If it's up to date and there are no other records, we are done! if foundMatched && len(unprocessedMatched) == 0 && len(unprocessedUnmatched) == 0 { - ppfmt.Infof(pp.EmojiAlreadyDone, "The %s records of %q are already up to date", recordType, domainDescription) + if cached { + ppfmt.Infof(pp.EmojiAlreadyDone, "The %s records of %q are already up to date (cached)", recordType, domainDescription) //nolint:lll + } else { + ppfmt.Infof(pp.EmojiAlreadyDone, "The %s records of %q are already up to date", recordType, domainDescription) + } return ResponseNoop } @@ -177,7 +181,7 @@ func (s *setter) Delete(ctx context.Context, ppfmt pp.PP, domain domain.Domain, recordType := ipnet.RecordType() domainDescription := domain.Describe() - rmap, ok := s.Handle.ListRecords(ctx, ppfmt, domain, ipnet) + rmap, cached, ok := s.Handle.ListRecords(ctx, ppfmt, domain, ipnet) if !ok { ppfmt.Errorf(pp.EmojiError, "Failed to retrieve the current %s records of %q", recordType, domainDescription) return ResponseFailed @@ -191,7 +195,11 @@ func (s *setter) Delete(ctx context.Context, ppfmt pp.PP, domain domain.Domain, sort.Strings(unmatchedIDs) if len(unmatchedIDs) == 0 { - ppfmt.Infof(pp.EmojiAlreadyDone, "The %s records of %q were already deleted", recordType, domainDescription) + if cached { + ppfmt.Infof(pp.EmojiAlreadyDone, "The %s records of %q were already deleted (cached)", recordType, domainDescription) + } else { + ppfmt.Infof(pp.EmojiAlreadyDone, "The %s records of %q were already deleted", recordType, domainDescription) + } return ResponseNoop } diff --git a/internal/setter/setter_test.go b/internal/setter/setter_test.go index 4b5a3513..3b17941d 100644 --- a/internal/setter/setter_test.go +++ b/internal/setter/setter_test.go @@ -50,7 +50,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{}, true), + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{}, true, true), m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(1), false).Return(record1, true), ) }, @@ -70,7 +70,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2}, true), + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2}, true, true), m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(true), ) }, @@ -88,7 +88,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2}, true), + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2}, true, true), m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(false), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true), m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(300), false).Return(record2, true), @@ -96,6 +96,19 @@ func TestSet(t *testing.T) { }, }, "1matched/300-false": { + ip1, + setter.ResponseNoop, + 300, + false, + func(m *mocks.MockPP) { + m.EXPECT().Infof(pp.EmojiAlreadyDone, + "The %s records of %q are already up to date (cached)", "AAAA", "sub.test.org") + }, + func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true, true) + }, + }, + "1matched/300-false/not-cached": { ip1, setter.ResponseNoop, 300, @@ -104,7 +117,7 @@ func TestSet(t *testing.T) { m.EXPECT().Infof(pp.EmojiAlreadyDone, "The %s records of %q are already up to date", "AAAA", "sub.test.org") }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true) + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, false, true) }, }, "2matched/300-false": { @@ -123,7 +136,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1, record2: ip1}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1, record2: ip1}, true, true), //nolint:lll m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(true), ) }, @@ -136,7 +149,7 @@ func TestSet(t *testing.T) { nil, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1, record2: ip1}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1, record2: ip1}, true, true), //nolint:lll m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(false), ) }, @@ -164,7 +177,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true, true), //nolint:lll m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(true), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(true), ) @@ -189,7 +202,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true, true), //nolint:lll m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(false), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true), m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(true), @@ -210,7 +223,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true, true), //nolint:lll m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(false), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true), m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(false), @@ -234,7 +247,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true, true), //nolint:lll m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(false), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(false), m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(false), @@ -258,7 +271,7 @@ func TestSet(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2, record2: ip2}, true, true), //nolint:lll m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(false), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true), m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(false), @@ -276,7 +289,7 @@ func TestSet(t *testing.T) { m.EXPECT().Errorf(pp.EmojiError, "Failed to retrieve the current %s records of %q", "AAAA", "sub.test.org") }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(nil, false) + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(nil, false, false) }, }, } { @@ -326,12 +339,21 @@ func TestDelete(t *testing.T) { prepareMockHandle func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) }{ "0": { + setter.ResponseNoop, + func(m *mocks.MockPP) { + m.EXPECT().Infof(pp.EmojiAlreadyDone, "The %s records of %q were already deleted (cached)", "AAAA", "sub.test.org") + }, + func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{}, true, true) + }, + }, + "0/not-cached": { setter.ResponseNoop, func(m *mocks.MockPP) { m.EXPECT().Infof(pp.EmojiAlreadyDone, "The %s records of %q were already deleted", "AAAA", "sub.test.org") }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{}, true) + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{}, false, true) }, }, "1unmatched": { @@ -341,7 +363,7 @@ func TestDelete(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true), + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true, true), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true), ) }, @@ -353,7 +375,7 @@ func TestDelete(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true), + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true, true), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(false), ) }, @@ -368,7 +390,7 @@ func TestDelete(t *testing.T) { }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { gomock.InOrder( - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1, record2: invalidIP}, true), //nolint:lll + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1, record2: invalidIP}, true, true), //nolint:lll m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true), m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(true), ) @@ -380,7 +402,7 @@ func TestDelete(t *testing.T) { m.EXPECT().Errorf(pp.EmojiError, "Failed to retrieve the current %s records of %q", "AAAA", "sub.test.org") }, func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) { - m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(nil, false) + m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(nil, false, false) }, }, } {