structs: improve the interface of assertCacheInfoKeyIsComplete

This commit is contained in:
Daniel Nephin 2021-05-21 13:31:18 -04:00
parent 7c2957e24d
commit 46dfdb611f
2 changed files with 29 additions and 27 deletions

View File

@ -2218,23 +2218,22 @@ func intPointer(i int) *int {
} }
func TestConfigEntryQuery_CacheInfoKey(t *testing.T) { func TestConfigEntryQuery_CacheInfoKey(t *testing.T) {
assertCacheInfoKeyIsComplete(t, &ConfigEntryQuery{}, nil) assertCacheInfoKeyIsComplete(t, &ConfigEntryQuery{})
} }
func TestServiceConfigRequest_CacheInfoKey(t *testing.T) { func TestServiceConfigRequest_CacheInfoKey(t *testing.T) {
ignoredFields := map[string]bool{ ignoredFields := []string{
"QueryOptions": true, // TODO: should QueryOptions.Filter be included in the key?
"QueryOptions",
// TODO: should this be included in the key? // TODO: should this be included in the key?
"MeshGateway": true, "MeshGateway",
// TODO: should this be included in the key? // TODO: should this be included in the key?
"Mode": true, "Mode",
} }
assertCacheInfoKeyIsComplete(t, &ServiceConfigRequest{}, ignoredFields) assertCacheInfoKeyIsComplete(t, &ServiceConfigRequest{}, ignoredFields...)
} }
func TestDiscoveryChainRequest_CacheInfoKey(t *testing.T) { func TestDiscoveryChainRequest_CacheInfoKey(t *testing.T) {
ignoredFields := map[string]bool{ // TODO: should QueryOptions.Filter be included in the key?
"QueryOptions": true, assertCacheInfoKeyIsComplete(t, &DiscoveryChainRequest{}, "QueryOptions")
}
assertCacheInfoKeyIsComplete(t, &DiscoveryChainRequest{}, ignoredFields)
} }

View File

@ -1589,29 +1589,21 @@ func TestStructs_validateMetaPair(t *testing.T) {
} }
func TestDCSpecificRequest_CacheInfoKey(t *testing.T) { func TestDCSpecificRequest_CacheInfoKey(t *testing.T) {
assertCacheInfoKeyIsComplete(t, &DCSpecificRequest{}, nil) assertCacheInfoKeyIsComplete(t, &DCSpecificRequest{})
} }
func TestNodeSpecificRequest_CacheInfoKey(t *testing.T) { func TestNodeSpecificRequest_CacheInfoKey(t *testing.T) {
assertCacheInfoKeyIsComplete(t, &NodeSpecificRequest{}, nil) assertCacheInfoKeyIsComplete(t, &NodeSpecificRequest{})
} }
func TestServiceSpecificRequest_CacheInfoKey(t *testing.T) { func TestServiceSpecificRequest_CacheInfoKey(t *testing.T) {
ignoredFields := map[string]bool{ // TODO: should ServiceKind filed be included in the key?
// TODO: should this filed be included? assertCacheInfoKeyIsComplete(t, &ServiceSpecificRequest{}, "ServiceKind")
"ServiceKind": true,
}
assertCacheInfoKeyIsComplete(t, &ServiceSpecificRequest{}, ignoredFields)
} }
func TestServiceDumpRequest_CacheInfoKey(t *testing.T) { func TestServiceDumpRequest_CacheInfoKey(t *testing.T) {
ignoredFields := map[string]bool{
// ServiceKind is only included when UseServiceKind=true // ServiceKind is only included when UseServiceKind=true
"ServiceKind": true, assertCacheInfoKeyIsComplete(t, &ServiceDumpRequest{}, "ServiceKind")
}
assertCacheInfoKeyIsComplete(t, &ServiceDumpRequest{}, ignoredFields)
} }
// cacheInfoIgnoredFields are fields that can be ignored in all cache.Request types // cacheInfoIgnoredFields are fields that can be ignored in all cache.Request types
@ -1621,15 +1613,26 @@ func TestServiceDumpRequest_CacheInfoKey(t *testing.T) {
var cacheInfoIgnoredFields = map[string]bool{ var cacheInfoIgnoredFields = map[string]bool{
// Datacenter is part of the cache key added by the cache itself. // Datacenter is part of the cache key added by the cache itself.
"Datacenter": true, "Datacenter": true,
// QuerySource is always the same for every request a single agent, so it // QuerySource is always the same for every request from a single agent, so it
// is excluded from the key. // is excluded from the key.
"Source": true, "Source": true,
// EnterpriseMeta is an empty struct, so can not be included. // EnterpriseMeta is an empty struct, so can not be included.
enterpriseMetaField: true, enterpriseMetaField: true,
} }
func assertCacheInfoKeyIsComplete(t *testing.T, request cache.Request, ignoredFields map[string]bool) { // assertCacheInfoKeyIsComplete is an assertion to verify that all fields on a request
// struct are considered as part of the cache key. It is used to prevent regressions
// when new fields are added to the struct. If a field is not included in the cache
// key it can lead to API requests or DNS requests returning the wrong value
// because a request matches the wrong entry in the agent/cache.Cache.
func assertCacheInfoKeyIsComplete(t *testing.T, request cache.Request, ignoredFields ...string) {
t.Helper() t.Helper()
ignored := make(map[string]bool, len(ignoredFields))
for _, f := range ignoredFields {
ignored[f] = true
}
fuzzer := fuzz.NewWithSeed(time.Now().UnixNano()) fuzzer := fuzz.NewWithSeed(time.Now().UnixNano())
fuzzer.Funcs(randQueryOptions) fuzzer.Funcs(randQueryOptions)
fuzzer.Fuzz(request) fuzzer.Fuzz(request)
@ -1641,7 +1644,7 @@ func assertCacheInfoKeyIsComplete(t *testing.T, request cache.Request, ignoredFi
fieldName := requestValue.Type().Field(i).Name fieldName := requestValue.Type().Field(i).Name
originalValue := field.Interface() originalValue := field.Interface()
if cacheInfoIgnoredFields[fieldName] || ignoredFields[fieldName] { if cacheInfoIgnoredFields[fieldName] || ignored[fieldName] {
continue continue
} }