github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/common/kv_test.go (about) 1 // Copyright 2022 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package common 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 clientv3 "github.com/lfch/etcd-io/client/v3" 23 "github.com/lfch/etcd-io/tests/v3/framework" 24 "github.com/lfch/etcd-io/tests/v3/framework/config" 25 "github.com/lfch/etcd-io/tests/v3/framework/testutils" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 func TestKVPut(t *testing.T) { 30 testRunner.BeforeTest(t) 31 for _, tc := range clusterTestCases { 32 t.Run(tc.name, func(t *testing.T) { 33 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 34 defer cancel() 35 clus := testRunner.NewCluster(ctx, t, tc.config) 36 defer clus.Close() 37 cc := framework.MustClient(clus.Client(clientv3.AuthConfig{})) 38 39 testutils.ExecuteUntil(ctx, t, func() { 40 key, value := "foo", "bar" 41 42 if err := cc.Put(ctx, key, value, config.PutOptions{}); err != nil { 43 t.Fatalf("count not put key %q, err: %s", key, err) 44 } 45 resp, err := cc.Get(ctx, key, config.GetOptions{}) 46 if err != nil { 47 t.Fatalf("count not get key %q, err: %s", key, err) 48 } 49 if len(resp.Kvs) != 1 { 50 t.Errorf("Unexpected lenth of response, got %d", len(resp.Kvs)) 51 } 52 if string(resp.Kvs[0].Key) != key { 53 t.Errorf("Unexpected key, want %q, got %q", key, resp.Kvs[0].Key) 54 } 55 if string(resp.Kvs[0].Value) != value { 56 t.Errorf("Unexpected value, want %q, got %q", value, resp.Kvs[0].Value) 57 } 58 }) 59 }) 60 } 61 } 62 63 func TestKVGet(t *testing.T) { 64 testRunner.BeforeTest(t) 65 for _, tc := range clusterTestCases { 66 t.Run(tc.name, func(t *testing.T) { 67 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 68 defer cancel() 69 clus := testRunner.NewCluster(ctx, t, tc.config) 70 defer clus.Close() 71 cc := framework.MustClient(clus.Client(clientv3.AuthConfig{})) 72 73 testutils.ExecuteUntil(ctx, t, func() { 74 var ( 75 kvs = []string{"a", "b", "c", "c", "c", "foo", "foo/abc", "fop"} 76 wantKvs = []string{"a", "b", "c", "foo", "foo/abc", "fop"} 77 kvsByVersion = []string{"a", "b", "foo", "foo/abc", "fop", "c"} 78 reversedKvs = []string{"fop", "foo/abc", "foo", "c", "b", "a"} 79 ) 80 81 for i := range kvs { 82 if err := cc.Put(ctx, kvs[i], "bar", config.PutOptions{}); err != nil { 83 t.Fatalf("count not put key %q, err: %s", kvs[i], err) 84 } 85 } 86 tests := []struct { 87 begin string 88 end string 89 options config.GetOptions 90 91 wkv []string 92 }{ 93 {begin: "a", wkv: wantKvs[:1]}, 94 {begin: "a", options: config.GetOptions{Serializable: true}, wkv: wantKvs[:1]}, 95 {begin: "a", options: config.GetOptions{End: "c"}, wkv: wantKvs[:2]}, 96 {begin: "", options: config.GetOptions{Prefix: true}, wkv: wantKvs}, 97 {begin: "", options: config.GetOptions{FromKey: true}, wkv: wantKvs}, 98 {begin: "a", options: config.GetOptions{End: "x"}, wkv: wantKvs}, 99 {begin: "", options: config.GetOptions{Prefix: true, Revision: 4}, wkv: kvs[:3]}, 100 {begin: "a", options: config.GetOptions{CountOnly: true}, wkv: nil}, 101 {begin: "foo", options: config.GetOptions{Prefix: true}, wkv: []string{"foo", "foo/abc"}}, 102 {begin: "foo", options: config.GetOptions{FromKey: true}, wkv: []string{"foo", "foo/abc", "fop"}}, 103 {begin: "", options: config.GetOptions{Prefix: true, Limit: 2}, wkv: wantKvs[:2]}, 104 {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByModRevision}, wkv: wantKvs}, 105 {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortAscend, SortBy: clientv3.SortByVersion}, wkv: kvsByVersion}, 106 {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortNone, SortBy: clientv3.SortByCreateRevision}, wkv: wantKvs}, 107 {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByCreateRevision}, wkv: reversedKvs}, 108 {begin: "", options: config.GetOptions{Prefix: true, Order: clientv3.SortDescend, SortBy: clientv3.SortByKey}, wkv: reversedKvs}, 109 } 110 for _, tt := range tests { 111 resp, err := cc.Get(ctx, tt.begin, tt.options) 112 if err != nil { 113 t.Fatalf("count not get key %q, err: %s", tt.begin, err) 114 } 115 kvs := testutils.KeysFromGetResponse(resp) 116 assert.Equal(t, tt.wkv, kvs) 117 } 118 }) 119 }) 120 } 121 } 122 123 func TestKVDelete(t *testing.T) { 124 testRunner.BeforeTest(t) 125 for _, tc := range clusterTestCases { 126 t.Run(tc.name, func(t *testing.T) { 127 ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) 128 defer cancel() 129 clus := testRunner.NewCluster(ctx, t, tc.config) 130 defer clus.Close() 131 cc := framework.MustClient(clus.Client(clientv3.AuthConfig{})) 132 testutils.ExecuteUntil(ctx, t, func() { 133 kvs := []string{"a", "b", "c", "c/abc", "d"} 134 tests := []struct { 135 deleteKey string 136 options config.DeleteOptions 137 138 wantDeleted int 139 wantKeys []string 140 }{ 141 { // delete all keys 142 deleteKey: "", 143 options: config.DeleteOptions{Prefix: true}, 144 wantDeleted: 5, 145 }, 146 { // delete all keys 147 deleteKey: "", 148 options: config.DeleteOptions{FromKey: true}, 149 wantDeleted: 5, 150 }, 151 { 152 deleteKey: "a", 153 options: config.DeleteOptions{End: "c"}, 154 wantDeleted: 2, 155 wantKeys: []string{"c", "c/abc", "d"}, 156 }, 157 { 158 deleteKey: "c", 159 wantDeleted: 1, 160 wantKeys: []string{"a", "b", "c/abc", "d"}, 161 }, 162 { 163 deleteKey: "c", 164 options: config.DeleteOptions{Prefix: true}, 165 wantDeleted: 2, 166 wantKeys: []string{"a", "b", "d"}, 167 }, 168 { 169 deleteKey: "c", 170 options: config.DeleteOptions{FromKey: true}, 171 wantDeleted: 3, 172 wantKeys: []string{"a", "b"}, 173 }, 174 { 175 deleteKey: "e", 176 wantDeleted: 0, 177 wantKeys: kvs, 178 }, 179 } 180 for _, tt := range tests { 181 for i := range kvs { 182 if err := cc.Put(ctx, kvs[i], "bar", config.PutOptions{}); err != nil { 183 t.Fatalf("count not put key %q, err: %s", kvs[i], err) 184 } 185 } 186 del, err := cc.Delete(ctx, tt.deleteKey, tt.options) 187 if err != nil { 188 t.Fatalf("count not get key %q, err: %s", tt.deleteKey, err) 189 } 190 assert.Equal(t, tt.wantDeleted, int(del.Deleted)) 191 get, err := cc.Get(ctx, "", config.GetOptions{Prefix: true}) 192 if err != nil { 193 t.Fatalf("count not get key, err: %s", err) 194 } 195 kvs := testutils.KeysFromGetResponse(get) 196 assert.Equal(t, tt.wantKeys, kvs) 197 } 198 }) 199 }) 200 } 201 } 202 203 func TestKVGetNoQuorum(t *testing.T) { 204 testRunner.BeforeTest(t) 205 tcs := []struct { 206 name string 207 options config.GetOptions 208 209 wantError bool 210 }{ 211 { 212 name: "Serializable", 213 options: config.GetOptions{Serializable: true}, 214 }, 215 { 216 name: "Linearizable", 217 options: config.GetOptions{Serializable: false, Timeout: time.Second}, 218 wantError: true, 219 }, 220 } 221 for _, tc := range tcs { 222 t.Run(tc.name, func(t *testing.T) { 223 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 224 defer cancel() 225 clus := testRunner.NewCluster(ctx, t, config.ClusterConfig{ClusterSize: 3}) 226 defer clus.Close() 227 228 clus.Members()[0].Stop() 229 clus.Members()[1].Stop() 230 231 cc := clus.Members()[2].Client() 232 testutils.ExecuteUntil(ctx, t, func() { 233 key := "foo" 234 _, err := cc.Get(ctx, key, tc.options) 235 gotError := err != nil 236 if gotError != tc.wantError { 237 t.Fatalf("Unexpeted result, wantError: %v, gotErr: %v, err: %s", tc.wantError, gotError, err) 238 } 239 }) 240 }) 241 } 242 }