mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Reuse generic TestGet in cache tests.
This commit is contained in:
parent
e8449012e2
commit
75a1ef87b3
@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
@ -60,8 +61,9 @@ func newPod() runtime.Object {
|
|||||||
return &example.Pod{}
|
return &example.Pod{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkStorageInvariants(etcdClient *clientv3.Client, codec runtime.Codec) storagetesting.KeyValidation {
|
func checkStorageInvariants(prefix string, etcdClient *clientv3.Client, codec runtime.Codec) storagetesting.KeyValidation {
|
||||||
return func(ctx context.Context, t *testing.T, key string) {
|
return func(ctx context.Context, t *testing.T, key string) {
|
||||||
|
key = path.Join(prefix, key)
|
||||||
getResp, err := etcdClient.KV.Get(ctx, key)
|
getResp, err := etcdClient.KV.Get(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("etcdClient.KV.Get failed: %v", err)
|
t.Fatalf("etcdClient.KV.Get failed: %v", err)
|
||||||
@ -85,7 +87,7 @@ func checkStorageInvariants(etcdClient *clientv3.Client, codec runtime.Codec) st
|
|||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
func TestCreate(t *testing.T) {
|
||||||
ctx, store, etcdClient := testSetup(t)
|
ctx, store, etcdClient := testSetup(t)
|
||||||
storagetesting.RunTestCreate(ctx, t, store, checkStorageInvariants(etcdClient, store.codec))
|
storagetesting.RunTestCreate(ctx, t, store, checkStorageInvariants("/", etcdClient, store.codec))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateWithTTL(t *testing.T) {
|
func TestCreateWithTTL(t *testing.T) {
|
||||||
@ -158,7 +160,7 @@ func (s *storeWithPrefixTransformer) UpdatePrefixTransformer(modifier storagetes
|
|||||||
|
|
||||||
func TestGuaranteedUpdate(t *testing.T) {
|
func TestGuaranteedUpdate(t *testing.T) {
|
||||||
ctx, store, etcdClient := testSetup(t)
|
ctx, store, etcdClient := testSetup(t)
|
||||||
storagetesting.RunTestGuaranteedUpdate(ctx, t, &storeWithPrefixTransformer{store}, checkStorageInvariants(etcdClient, store.codec))
|
storagetesting.RunTestGuaranteedUpdate(ctx, t, &storeWithPrefixTransformer{store}, checkStorageInvariants("/", etcdClient, store.codec))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGuaranteedUpdateWithTTL(t *testing.T) {
|
func TestGuaranteedUpdateWithTTL(t *testing.T) {
|
||||||
|
@ -129,33 +129,40 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
|
|||||||
ignoreNotFound bool
|
ignoreNotFound bool
|
||||||
expectNotFoundErr bool
|
expectNotFoundErr bool
|
||||||
expectRVTooLarge bool
|
expectRVTooLarge bool
|
||||||
expectedOut *example.Pod
|
expectedOut []*example.Pod
|
||||||
rv string
|
rv string
|
||||||
}{{
|
}{{
|
||||||
name: "get existing",
|
name: "get existing",
|
||||||
key: key,
|
key: key,
|
||||||
ignoreNotFound: false,
|
ignoreNotFound: false,
|
||||||
expectNotFoundErr: false,
|
expectNotFoundErr: false,
|
||||||
expectedOut: storedObj,
|
expectedOut: []*example.Pod{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",
|
name: "resource version 0",
|
||||||
key: key,
|
key: key,
|
||||||
expectedOut: storedObj,
|
ignoreNotFound: true,
|
||||||
|
expectedOut: []*example.Pod{{}, createdObj, storedObj},
|
||||||
rv: "0",
|
rv: "0",
|
||||||
}, {
|
}, {
|
||||||
|
// Given that Get with set ResourceVersion is effectively always
|
||||||
|
// NotOlderThan semantic, both versions of object are allowed.
|
||||||
name: "object created resource version",
|
name: "object created resource version",
|
||||||
key: key,
|
key: key,
|
||||||
expectedOut: storedObj,
|
expectedOut: []*example.Pod{createdObj, storedObj},
|
||||||
rv: createdObj.ResourceVersion,
|
rv: createdObj.ResourceVersion,
|
||||||
}, {
|
}, {
|
||||||
name: "current object resource version, match=NotOlderThan",
|
name: "current object resource version, match=NotOlderThan",
|
||||||
key: key,
|
key: key,
|
||||||
expectedOut: storedObj,
|
expectedOut: []*example.Pod{storedObj},
|
||||||
rv: fmt.Sprintf("%d", currentRV),
|
rv: fmt.Sprintf("%d", currentRV),
|
||||||
}, {
|
}, {
|
||||||
name: "latest resource version",
|
name: "latest resource version",
|
||||||
key: key,
|
key: key,
|
||||||
expectedOut: storedObj,
|
expectedOut: []*example.Pod{storedObj},
|
||||||
rv: fmt.Sprintf("%d", lastUpdatedCurrentRV),
|
rv: fmt.Sprintf("%d", lastUpdatedCurrentRV),
|
||||||
}, {
|
}, {
|
||||||
name: "too high resource version",
|
name: "too high resource version",
|
||||||
@ -172,7 +179,7 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
|
|||||||
key: "/non-existing",
|
key: "/non-existing",
|
||||||
ignoreNotFound: true,
|
ignoreNotFound: true,
|
||||||
expectNotFoundErr: false,
|
expectNotFoundErr: false,
|
||||||
expectedOut: &example.Pod{},
|
expectedOut: []*example.Pod{{}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -194,7 +201,19 @@ func RunTestGet(ctx context.Context, t *testing.T, store storage.Interface) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Get failed: %v", err)
|
t.Fatalf("Get failed: %v", err)
|
||||||
}
|
}
|
||||||
ExpectNoDiff(t, fmt.Sprintf("%s: incorrect pod", tt.name), tt.expectedOut, out)
|
|
||||||
|
if len(tt.expectedOut) == 1 {
|
||||||
|
ExpectNoDiff(t, fmt.Sprintf("%s: incorrect pod", tt.name), tt.expectedOut[0], out)
|
||||||
|
} else {
|
||||||
|
toInterfaceSlice := func(pods []*example.Pod) []interface{} {
|
||||||
|
result := make([]interface{}, 0, len(pods))
|
||||||
|
for i := range pods {
|
||||||
|
result = append(result, pods[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
ExpectContains(t, fmt.Sprintf("%s: incorrect pod", tt.name), toInterfaceSlice(tt.expectedOut), out)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1675,7 +1694,7 @@ func RunTestConsistentList(ctx context.Context, t *testing.T, store InterfaceWit
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RunTestGuaranteedUpdate(ctx context.Context, t *testing.T, store InterfaceWithPrefixTransformer, validation KeyValidation) {
|
func RunTestGuaranteedUpdate(ctx context.Context, t *testing.T, store InterfaceWithPrefixTransformer, validation KeyValidation) {
|
||||||
key := "/testkey"
|
key := "/foo"
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -86,7 +86,7 @@ func DeepEqualSafePodSpec() example.PodSpec {
|
|||||||
// keys and stored objects.
|
// keys and stored objects.
|
||||||
func TestPropagateStore(ctx context.Context, t *testing.T, store storage.Interface, obj *example.Pod) (string, *example.Pod) {
|
func TestPropagateStore(ctx context.Context, t *testing.T, store storage.Interface, obj *example.Pod) (string, *example.Pod) {
|
||||||
// Setup store with a key and grab the output for returning.
|
// Setup store with a key and grab the output for returning.
|
||||||
key := "/testkey"
|
key := fmt.Sprintf("/%s/%s", obj.Namespace, obj.Name)
|
||||||
return key, TestPropagateStoreWithKey(ctx, t, store, key, obj)
|
return key, TestPropagateStoreWithKey(ctx, t, store, key, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +115,24 @@ func ExpectNoDiff(t *testing.T, msg string, expected, got interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExpectContains(t *testing.T, msg string, expectedList []interface{}, got interface{}) {
|
||||||
|
t.Helper()
|
||||||
|
for _, expected := range expectedList {
|
||||||
|
if reflect.DeepEqual(expected, got) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(expectedList) == 0 {
|
||||||
|
t.Errorf("%s: empty expectedList", msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(expectedList[0], got); diff != "" {
|
||||||
|
t.Errorf("%s: differs from all items, with first: %s", msg, diff)
|
||||||
|
} else {
|
||||||
|
t.Errorf("%s: differs from all items, first: %#v\ngot: %#v", msg, expectedList[0], got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const dummyPrefix = "adapter"
|
const dummyPrefix = "adapter"
|
||||||
|
|
||||||
func EncodeContinueOrDie(key string, resourceVersion int64) string {
|
func EncodeContinueOrDie(key string, resourceVersion int64) string {
|
||||||
|
@ -71,8 +71,8 @@ func init() {
|
|||||||
utilruntime.Must(examplev1.AddToScheme(scheme))
|
utilruntime.Must(examplev1.AddToScheme(scheme))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
// GetPodAttrs returns labels and fields of a given object for filtering purposes.
|
||||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
func GetPodAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||||
pod, ok := obj.(*example.Pod)
|
pod, ok := obj.(*example.Pod)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil, fmt.Errorf("not a pod")
|
return nil, nil, fmt.Errorf("not a pod")
|
||||||
@ -124,7 +124,7 @@ func newTestCacherWithClock(s storage.Interface, clock clock.Clock) (*cacherstor
|
|||||||
GroupResource: schema.GroupResource{Resource: "pods"},
|
GroupResource: schema.GroupResource{Resource: "pods"},
|
||||||
ResourcePrefix: prefix,
|
ResourcePrefix: prefix,
|
||||||
KeyFunc: func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) },
|
KeyFunc: func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) },
|
||||||
GetAttrsFunc: GetAttrs,
|
GetAttrsFunc: GetPodAttrs,
|
||||||
NewFunc: newPod,
|
NewFunc: newPod,
|
||||||
NewListFunc: newPodList,
|
NewListFunc: newPodList,
|
||||||
Codec: codecs.LegacyCodec(examplev1.SchemeGroupVersion),
|
Codec: codecs.LegacyCodec(examplev1.SchemeGroupVersion),
|
||||||
@ -164,37 +164,9 @@ func updatePod(t *testing.T, s storage.Interface, obj, old *example.Pod) *exampl
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
server, etcdStorage := newEtcdTestStorage(t, etcd3testing.PathPrefix())
|
ctx, cacher, terminate := testSetup(t)
|
||||||
defer server.Terminate(t)
|
defer terminate()
|
||||||
cacher, _, err := newTestCacher(etcdStorage)
|
storagetesting.RunTestGet(ctx, t, cacher)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Couldn't create cacher: %v", err)
|
|
||||||
}
|
|
||||||
defer cacher.Stop()
|
|
||||||
|
|
||||||
podFoo := makeTestPod("foo")
|
|
||||||
fooCreated := updatePod(t, etcdStorage, podFoo, nil)
|
|
||||||
|
|
||||||
// We pass the ResourceVersion from the above Create() operation.
|
|
||||||
result := &example.Pod{}
|
|
||||||
if err := cacher.Get(context.TODO(), "pods/ns/foo", storage.GetOptions{IgnoreNotFound: true, ResourceVersion: fooCreated.ResourceVersion}, result); err != nil {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if e, a := *fooCreated, *result; !reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("Expected: %#v, got: %#v", e, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cacher.Get(context.TODO(), "pods/ns/bar", storage.GetOptions{ResourceVersion: fooCreated.ResourceVersion, IgnoreNotFound: true}, result); err != nil {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
emptyPod := example.Pod{}
|
|
||||||
if e, a := emptyPod, *result; !reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("Expected: %#v, got: %#v", e, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cacher.Get(context.TODO(), "pods/ns/bar", storage.GetOptions{ResourceVersion: fooCreated.ResourceVersion}, result); !storage.IsNotFound(err) {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetListNonRecursive(t *testing.T) {
|
func TestGetListNonRecursive(t *testing.T) {
|
||||||
@ -962,3 +934,58 @@ func TestWatchBookmarksWithCorrectResourceVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===================================================
|
||||||
|
// Test-setup related function are following.
|
||||||
|
// ===================================================
|
||||||
|
|
||||||
|
type tearDownFunc func()
|
||||||
|
|
||||||
|
type setupOptions struct {
|
||||||
|
resourcePrefix string
|
||||||
|
keyFunc func(runtime.Object) (string, error)
|
||||||
|
clock clock.Clock
|
||||||
|
}
|
||||||
|
|
||||||
|
type setupOption func(*setupOptions)
|
||||||
|
|
||||||
|
func withDefaults(options *setupOptions) {
|
||||||
|
prefix := ""
|
||||||
|
|
||||||
|
options.resourcePrefix = prefix
|
||||||
|
options.keyFunc = func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) }
|
||||||
|
options.clock = clock.RealClock{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetup(t *testing.T, opts ...setupOption) (context.Context, *cacherstorage.Cacher, tearDownFunc) {
|
||||||
|
setupOpts := setupOptions{}
|
||||||
|
opts = append([]setupOption{withDefaults}, opts...)
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&setupOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
server, etcdStorage := newEtcdTestStorage(t, etcd3testing.PathPrefix())
|
||||||
|
config := cacherstorage.Config{
|
||||||
|
Storage: etcdStorage,
|
||||||
|
Versioner: storage.APIObjectVersioner{},
|
||||||
|
GroupResource: schema.GroupResource{Resource: "pods"},
|
||||||
|
ResourcePrefix: setupOpts.resourcePrefix,
|
||||||
|
KeyFunc: setupOpts.keyFunc,
|
||||||
|
GetAttrsFunc: GetPodAttrs,
|
||||||
|
NewFunc: newPod,
|
||||||
|
NewListFunc: newPodList,
|
||||||
|
Codec: codecs.LegacyCodec(examplev1.SchemeGroupVersion),
|
||||||
|
Clock: setupOpts.clock,
|
||||||
|
}
|
||||||
|
cacher, err := cacherstorage.NewCacherFromConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to initialize cacher: %v", err)
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
terminate := func() {
|
||||||
|
cacher.Stop()
|
||||||
|
server.Terminate(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx, cacher, terminate
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user