Reuse generic ListNonRecurisve test for cacher

This commit is contained in:
Wojciech Tyczyński 2022-11-03 14:58:34 +01:00
parent 37db332298
commit e301306d89
2 changed files with 88 additions and 126 deletions

View File

@ -124,45 +124,46 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
// TODO(jpbetz): Add exact test cases
tests := []struct {
name string
key string
ignoreNotFound bool
expectNotFoundErr bool
expectRVTooLarge bool
expectedOut []*example.Pod
rv string
name string
key string
ignoreNotFound bool
expectNotFoundErr bool
expectRVTooLarge bool
expectedOut *example.Pod
expectedAlternatives []*example.Pod
rv string
}{{
name: "get existing",
key: key,
ignoreNotFound: false,
expectNotFoundErr: false,
expectedOut: []*example.Pod{storedObj},
expectedOut: storedObj,
}, {
// For RV=0 arbitrarily old version is allowed, including from the moment
// when the object didn't yet exist.
// As a result, we allow it by setting ignoreNotFound and allowing an empty
// object in expectedOut.
name: "resource version 0",
key: key,
ignoreNotFound: true,
expectedOut: []*example.Pod{{}, createdObj, storedObj},
rv: "0",
name: "resource version 0",
key: key,
ignoreNotFound: true,
expectedAlternatives: []*example.Pod{{}, createdObj, storedObj},
rv: "0",
}, {
// Given that Get with set ResourceVersion is effectively always
// NotOlderThan semantic, both versions of object are allowed.
name: "object created resource version",
key: key,
expectedOut: []*example.Pod{createdObj, storedObj},
rv: createdObj.ResourceVersion,
name: "object created resource version",
key: key,
expectedAlternatives: []*example.Pod{createdObj, storedObj},
rv: createdObj.ResourceVersion,
}, {
name: "current object resource version, match=NotOlderThan",
key: key,
expectedOut: []*example.Pod{storedObj},
expectedOut: storedObj,
rv: fmt.Sprintf("%d", currentRV),
}, {
name: "latest resource version",
key: key,
expectedOut: []*example.Pod{storedObj},
expectedOut: storedObj,
rv: fmt.Sprintf("%d", lastUpdatedCurrentRV),
}, {
name: "too high resource version",
@ -179,7 +180,7 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
key: "/non-existing",
ignoreNotFound: true,
expectNotFoundErr: false,
expectedOut: []*example.Pod{{}},
expectedOut: &example.Pod{},
}}
for _, tt := range tests {
@ -202,8 +203,8 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
t.Fatalf("Get failed: %v", err)
}
if len(tt.expectedOut) == 1 {
ExpectNoDiff(t, fmt.Sprintf("%s: incorrect pod", tt.name), tt.expectedOut[0], out)
if tt.expectedAlternatives == nil {
ExpectNoDiff(t, fmt.Sprintf("%s: incorrect pod", tt.name), tt.expectedOut, out)
} else {
toInterfaceSlice := func(pods []*example.Pod) []interface{} {
result := make([]interface{}, 0, len(pods))
@ -212,7 +213,7 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
}
return result
}
ExpectContains(t, fmt.Sprintf("%s: incorrect pod", tt.name), toInterfaceSlice(tt.expectedOut), out)
ExpectContains(t, fmt.Sprintf("%s: incorrect pod", tt.name), toInterfaceSlice(tt.expectedAlternatives), out)
}
})
}
@ -1048,77 +1049,86 @@ func seedMultiLevelData(ctx context.Context, store storage.Interface) (string, [
}
func RunTestGetListNonRecursive(ctx context.Context, t *testing.T, store storage.Interface) {
prevKey, prevStoredObj := testPropagateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "prev"}})
key, prevStoredObj := testPropagateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
prevRV, _ := strconv.Atoi(prevStoredObj.ResourceVersion)
key, storedObj := testPropagateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
storedObj := &example.Pod{}
if err := store.GuaranteedUpdate(ctx, key, storedObj, false, nil,
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
newPod := prevStoredObj.DeepCopy()
newPod.Annotations = map[string]string{"version": "second"}
return newPod, nil, nil
}, nil); err != nil {
t.Fatalf("update failed: %v", err)
}
currentRV, _ := strconv.Atoi(storedObj.ResourceVersion)
tests := []struct {
name string
key string
pred storage.SelectionPredicate
expectedOut []*example.Pod
rv string
rvMatch metav1.ResourceVersionMatch
expectRVTooLarge bool
name string
key string
pred storage.SelectionPredicate
expectedOut []example.Pod
expectedAlternatives [][]example.Pod
rv string
rvMatch metav1.ResourceVersionMatch
expectRVTooLarge bool
}{{
name: "existing key",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
expectedOut: []example.Pod{*storedObj},
}, {
name: "existing key, resourceVersion=0",
name: "existing key, resourceVersion=0",
key: key,
pred: storage.Everything,
expectedAlternatives: [][]example.Pod{nil, {*storedObj}},
rv: "0",
}, {
name: "existing key, resourceVersion=0, resourceVersionMatch=notOlderThan",
key: key,
pred: storage.Everything,
expectedAlternatives: [][]example.Pod{nil, {*storedObj}},
rv: "0",
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
}, {
name: "existing key, resourceVersion=previous, resourceVersionMatch=notOlderThan",
key: key,
pred: storage.Everything,
expectedAlternatives: [][]example.Pod{{*prevStoredObj}, {*storedObj}},
rv: fmt.Sprintf("%d", prevRV),
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
}, {
name: "existing key, resourceVersion=current, resourceVersionMatch=notOlderThan",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
rv: "0",
}, {
name: "existing key, resourceVersion=0, resourceVersionMatch=notOlderThan",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
rv: "0",
expectedOut: []example.Pod{*storedObj},
rv: fmt.Sprintf("%d", currentRV),
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
}, {
name: "existing key, resourceVersion=current",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
expectedOut: []example.Pod{*storedObj},
rv: fmt.Sprintf("%d", currentRV),
}, {
name: "existing key, resourceVersion=current, resourceVersionMatch=notOlderThan",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
rv: fmt.Sprintf("%d", currentRV),
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
}, {
name: "existing key, resourceVersion=previous, resourceVersionMatch=notOlderThan",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
rv: fmt.Sprintf("%d", prevRV),
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
}, {
name: "existing key, resourceVersion=current, resourceVersionMatch=exact",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
expectedOut: []example.Pod{*storedObj},
rv: fmt.Sprintf("%d", currentRV),
rvMatch: metav1.ResourceVersionMatchExact,
}, {
name: "existing key, resourceVersion=current, resourceVersionMatch=exact",
key: prevKey,
name: "existing key, resourceVersion=previous, resourceVersionMatch=exact",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{prevStoredObj},
expectedOut: []example.Pod{*prevStoredObj},
rv: fmt.Sprintf("%d", prevRV),
rvMatch: metav1.ResourceVersionMatchExact,
}, {
name: "existing key, resourceVersion=too high",
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
expectedOut: []example.Pod{*storedObj},
rv: strconv.FormatInt(math.MaxInt64, 10),
expectRVTooLarge: true,
}, {
@ -1164,13 +1174,18 @@ func RunTestGetListNonRecursive(ctx context.Context, t *testing.T, store storage
if len(out.ResourceVersion) == 0 {
t.Errorf("%s: unset resourceVersion", tt.name)
}
if len(out.Items) != len(tt.expectedOut) {
t.Errorf("%s: length of list want=%d, get=%d", tt.name, len(tt.expectedOut), len(out.Items))
return
}
for j, wantPod := range tt.expectedOut {
getPod := &out.Items[j]
ExpectNoDiff(t, fmt.Sprintf("%s: incorrect pod", tt.name), wantPod, getPod)
if tt.expectedAlternatives == nil {
ExpectNoDiff(t, "incorrect list pods", tt.expectedOut, out.Items)
} else {
toInterfaceSlice := func(podLists [][]example.Pod) []interface{} {
result := make([]interface{}, 0, len(podLists))
for i := range podLists {
result = append(result, podLists[i])
}
return result
}
ExpectContains(t, "incorrect list pods", toInterfaceSlice(tt.expectedAlternatives), out.Items)
}
})
}

View File

@ -170,62 +170,9 @@ func TestGet(t *testing.T) {
}
func TestGetListNonRecursive(t *testing.T) {
server, etcdStorage := newEtcdTestStorage(t, etcd3testing.PathPrefix())
defer server.Terminate(t)
cacher, _, err := newTestCacher(etcdStorage)
if err != nil {
t.Fatalf("Couldn't create cacher: %v", err)
}
defer cacher.Stop()
storedObj := updatePod(t, etcdStorage, makeTestPod("foo"), nil)
key := "pods/" + storedObj.Namespace + "/" + storedObj.Name
tests := []struct {
key string
pred storage.SelectionPredicate
expectedOut []*example.Pod
}{{ // test non-recursive GetList on existing key
key: key,
pred: storage.Everything,
expectedOut: []*example.Pod{storedObj},
}, { // test non-recursive GetList on non-existing key
key: "/non-existing",
pred: storage.Everything,
expectedOut: nil,
}, { // test non-recursive GetList with matching pod name
key: "/non-existing",
pred: storage.SelectionPredicate{
Label: labels.Everything(),
Field: fields.ParseSelectorOrDie("metadata.name!=" + storedObj.Name),
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
pod := obj.(*example.Pod)
return nil, fields.Set{"metadata.name": pod.Name}, nil
},
},
expectedOut: nil,
}}
for i, tt := range tests {
out := &example.PodList{}
err := cacher.GetList(context.TODO(), tt.key, storage.ListOptions{Predicate: tt.pred, Recursive: false}, out)
if err != nil {
t.Fatalf("GetList failed: %v", err)
}
if len(out.ResourceVersion) == 0 {
t.Errorf("#%d: unset resourceVersion", i)
}
if len(out.Items) != len(tt.expectedOut) {
t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items))
continue
}
for j, wantPod := range tt.expectedOut {
getPod := &out.Items[j]
if !reflect.DeepEqual(wantPod, getPod) {
t.Errorf("#%d: pod want=%#v, get=%#v", i, wantPod, getPod)
}
}
}
ctx, cacher, terminate := testSetup(t)
defer terminate()
storagetesting.RunTestGetListNonRecursive(ctx, t, cacher)
}
func TestList(t *testing.T) {