diff --git a/libs/structs/structaccess/get.go b/libs/structs/structaccess/get.go index b42c3977d6..0c35cf520d 100644 --- a/libs/structs/structaccess/get.go +++ b/libs/structs/structaccess/get.go @@ -53,7 +53,9 @@ func getValue(v any, path *structpath.PathNode) (reflect.Value, error) { cur, ok = deref(cur) if !ok { // cannot proceed further due to nil encountered at current location - return reflect.Value{}, fmt.Errorf("%s: cannot access nil value", node.Parent().String()) + // There could be 2 cases: the type is correct but value is not found due to nil, in this case NotFoundError is 100% correct. + // It could also be that path up to nil is correct, but not after. We don't know because we stop there. In this case NotFoundError refers to path up to nil. + return reflect.Value{}, &NotFoundError{node.Parent().String() + ": cannot access nil value"} } if idx, isIndex := node.Index(); isIndex { diff --git a/libs/structs/structaccess/get_test.go b/libs/structs/structaccess/get_test.go index 593ae8a536..2544b02ae3 100644 --- a/libs/structs/structaccess/get_test.go +++ b/libs/structs/structaccess/get_test.go @@ -11,13 +11,12 @@ import ( // unexported global test case type type testCase struct { - name string - path string - want any - wantSelf bool - errFmt string - notFound string // if set, expect NotFoundError with this message - typeHasPath bool + name string + path string + want any + wantSelf bool + errFmt string + notFound string // if set, expect NotFoundError with this message } func testGet(t *testing.T, obj any, path string, want any) { @@ -197,10 +196,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "connection[0]: cannot index struct", }, { - name: "out of range index", - path: "items[5]", - notFound: "items[5]: index out of range, length is 2", - typeHasPath: true, + name: "out of range index", + path: "items[5]", + notFound: "items[5]: index out of range, length is 2", }, { name: "no json tag field should not be accessible", @@ -213,10 +211,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "items.id: cannot access key \"id\" on slice", }, { - name: "nil pointer access", - path: "connection_not_set.id", - errFmt: "connection_not_set: cannot access nil value", - typeHasPath: true, + name: "nil pointer access", + path: "connection_not_set.id", + notFound: "connection_not_set: cannot access nil value", }, { name: "map non-string key type", @@ -224,10 +221,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "map_int.any: map key must be string, got int", }, { - name: "map missing key", - path: "labels.missing", - notFound: "labels.missing: key \"missing\" not found in map", - typeHasPath: true, + name: "map missing key", + path: "labels.missing", + notFound: "labels.missing: key \"missing\" not found in map", }, { name: "json dash ignored", @@ -247,10 +243,9 @@ func runCommonTests(t *testing.T, obj any) { want: "first", }, { - name: "key-value no match", - path: "items[id='missing']", - notFound: "items[id='missing']: no element found with id=\"missing\"", - typeHasPath: true, + name: "key-value no match", + path: "items[id='missing']", + notFound: "items[id='missing']: no element found with id=\"missing\"", }, { name: "key-value on non-slice", @@ -258,22 +253,19 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "connection[id='abc']: cannot use key-value syntax on struct", }, { - name: "key-value field not found", - path: "items[missing='value']", - notFound: "items[missing='value']: no element found with missing=\"value\"", - typeHasPath: true, + name: "key-value field not found", + path: "items[missing='value']", + notFound: "items[missing='value']: no element found with missing=\"value\"", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { hasPathError := ValidateByString(reflect.TypeOf(obj), tt.path) - if tt.errFmt == "" && tt.notFound == "" || tt.typeHasPath { + if tt.errFmt == "" { require.NoError(t, hasPathError) - } else if tt.errFmt != "" { + } else { require.EqualError(t, hasPathError, tt.errFmt) - } else if tt.notFound != "" { - require.EqualError(t, hasPathError, tt.notFound) } got, err := GetByString(obj, tt.path)