github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/store/test/store_test.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); 2 // you may not use this file except in compliance with the License. 3 // You may obtain a copy of the License at 4 // 5 // https://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, 9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 // See the License for the specific language governing permissions and 11 // limitations under the License. 12 // 13 // Original source: github.com/micro/go-micro/v3/store/test/store_test.go 14 15 // Package test provides a way to run tests against all the various implementations of the Store interface. 16 // It can't live in the store package itself because of circular import issues 17 package test 18 19 import ( 20 "fmt" 21 "os" 22 "path/filepath" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/davecgh/go-spew/spew" 28 "github.com/kr/pretty" 29 "github.com/tickoalcantara12/micro/v3/service/store" 30 "github.com/tickoalcantara12/micro/v3/service/store/cache" 31 "github.com/tickoalcantara12/micro/v3/service/store/file" 32 "github.com/tickoalcantara12/micro/v3/service/store/memory" 33 ) 34 35 func fileStoreCleanup(db string, s store.Store) { 36 s.Close() 37 dir := filepath.Join(file.DefaultDir, db+"/") 38 os.RemoveAll(dir) 39 } 40 41 func cockroachStoreCleanup(db string, s store.Store) { 42 keys, _ := s.List() 43 for _, k := range keys { 44 s.Delete(k) 45 } 46 s.Close() 47 } 48 49 func memoryCleanup(db string, s store.Store) { 50 s.Close() 51 } 52 53 func cacheCleanup(db string, s store.Store) { 54 s.Close() 55 } 56 57 func TestStoreReInit(t *testing.T) { 58 tcs := []struct { 59 name string 60 s store.Store 61 cleanup func(db string, s store.Store) 62 }{ 63 {name: "file", s: file.NewStore(store.Table("aaa")), cleanup: fileStoreCleanup}, 64 {name: "memory", s: memory.NewStore(store.Table("aaa")), cleanup: memoryCleanup}, 65 {name: "cache", s: cache.NewStore(memory.NewStore(store.Table("aaa"))), cleanup: cacheCleanup}, 66 } 67 for _, tc := range tcs { 68 t.Run(tc.name, func(t *testing.T) { 69 defer tc.cleanup(file.DefaultDatabase, tc.s) 70 tc.s.Init(store.Table("bbb")) 71 if tc.s.Options().Table != "bbb" { 72 t.Error("Init didn't reinitialise the store") 73 } 74 }) 75 } 76 } 77 78 func TestStoreBasic(t *testing.T) { 79 tcs := []struct { 80 name string 81 s store.Store 82 cleanup func(db string, s store.Store) 83 }{ 84 {name: "file", s: file.NewStore(), cleanup: fileStoreCleanup}, 85 {name: "memory", s: memory.NewStore(), cleanup: memoryCleanup}, 86 {name: "cache", s: cache.NewStore(memory.NewStore()), cleanup: cacheCleanup}, 87 } 88 for _, tc := range tcs { 89 t.Run(tc.name, func(t *testing.T) { 90 defer tc.cleanup(file.DefaultDatabase, tc.s) 91 runStoreTest(tc.s, t) 92 }) 93 } 94 95 } 96 97 func TestStoreTable(t *testing.T) { 98 tcs := []struct { 99 name string 100 s store.Store 101 cleanup func(db string, s store.Store) 102 }{ 103 {name: "file", s: file.NewStore(store.Table("testTable")), cleanup: fileStoreCleanup}, 104 {name: "memory", s: memory.NewStore(store.Table("testTable")), cleanup: memoryCleanup}, 105 {name: "cache", s: cache.NewStore(memory.NewStore(store.Table("testTable"))), cleanup: cacheCleanup}, 106 } 107 for _, tc := range tcs { 108 t.Run(tc.name, func(t *testing.T) { 109 defer tc.cleanup(file.DefaultDatabase, tc.s) 110 runStoreTest(tc.s, t) 111 }) 112 } 113 } 114 115 func TestStoreDatabase(t *testing.T) { 116 tcs := []struct { 117 name string 118 s store.Store 119 cleanup func(db string, s store.Store) 120 }{ 121 {name: "file", s: file.NewStore(store.Database("testdb")), cleanup: fileStoreCleanup}, 122 {name: "memory", s: memory.NewStore(store.Database("testdb")), cleanup: memoryCleanup}, 123 {name: "cache", s: cache.NewStore(memory.NewStore(store.Database("testdb"))), cleanup: cacheCleanup}, 124 } 125 for _, tc := range tcs { 126 t.Run(tc.name, func(t *testing.T) { 127 defer tc.cleanup("testdb", tc.s) 128 runStoreTest(tc.s, t) 129 }) 130 } 131 } 132 133 func TestStoreDatabaseTable(t *testing.T) { 134 tcs := []struct { 135 name string 136 s store.Store 137 cleanup func(db string, s store.Store) 138 }{ 139 {name: "file", s: file.NewStore(store.Database("testdb"), store.Table("testTable")), cleanup: fileStoreCleanup}, 140 {name: "memory", s: memory.NewStore(store.Database("testdb"), store.Table("testTable")), cleanup: memoryCleanup}, 141 {name: "cache", s: cache.NewStore(memory.NewStore(store.Database("testdb"), store.Table("testTable"))), cleanup: cacheCleanup}, 142 } 143 for _, tc := range tcs { 144 t.Run(tc.name, func(t *testing.T) { 145 defer tc.cleanup("testdb", tc.s) 146 runStoreTest(tc.s, t) 147 }) 148 } 149 } 150 151 func runStoreTest(s store.Store, t *testing.T) { 152 if len(os.Getenv("IN_TRAVIS_CI")) == 0 { 153 t.Logf("Options %s %v\n", s.String(), s.Options()) 154 } 155 156 expiryTests(s, t) 157 suffixPrefixExpiryTests(s, t) 158 readTests(s, t) 159 listTests(s, t) 160 161 } 162 163 func readTests(s store.Store, t *testing.T) { 164 // Test Table, Suffix and WriteOptions 165 if err := s.Write(&store.Record{ 166 Key: "foofoobarbar", 167 Value: []byte("something"), 168 Expiry: time.Millisecond * 100, 169 }); err != nil { 170 t.Error(err) 171 } 172 if err := s.Write(&store.Record{ 173 Key: "foofoo", 174 Value: []byte("something"), 175 Expiry: time.Millisecond * 100, 176 }); err != nil { 177 t.Error(err) 178 } 179 if err := s.Write(&store.Record{ 180 Key: "barbar", 181 Value: []byte("something"), 182 Expiry: time.Millisecond * 100, 183 }); err != nil { 184 t.Error(err) 185 } 186 187 if results, err := s.Read("foo", store.ReadPrefix(), store.ReadSuffix()); err != nil { 188 t.Error(err) 189 } else { 190 if len(results) != 1 { 191 t.Errorf("Expected 1 results, got %d: %# v", len(results), spew.Sdump(results)) 192 } 193 } 194 195 time.Sleep(time.Millisecond * 100) 196 197 if results, err := s.List(); err != nil { 198 t.Fatalf("List failed: %s", err) 199 } else { 200 if len(results) != 0 { 201 t.Fatalf("Expiry options were not effective, results :%v", spew.Sdump(results)) 202 } 203 } 204 205 // write the following records 206 for i := 0; i < 10; i++ { 207 s.Write(&store.Record{ 208 Key: fmt.Sprintf("a%d", i), 209 Value: []byte{}, 210 }) 211 } 212 213 // read back a few records 214 if results, err := s.Read("a", store.ReadLimit(5), store.ReadPrefix()); err != nil { 215 t.Error(err) 216 } else { 217 if len(results) != 5 { 218 t.Fatal("Expected 5 results, got ", len(results)) 219 } 220 if !strings.HasPrefix(results[0].Key, "a") { 221 t.Fatalf("Expected a prefix, got %s", results[0].Key) 222 } 223 } 224 225 // read the rest back 226 if results, err := s.Read("a", store.ReadLimit(30), store.ReadOffset(5), store.ReadPrefix()); err != nil { 227 t.Fatal(err) 228 } else { 229 if len(results) != 5 { 230 t.Fatal("Expected 5 results, got ", len(results)) 231 } 232 } 233 } 234 235 func listTests(s store.Store, t *testing.T) { 236 for i := 0; i < 10; i++ { 237 s.Write(&store.Record{Key: fmt.Sprintf("List%d", i), Value: []byte("bar")}) 238 } 239 240 recs, err := s.List(store.ListPrefix("List")) 241 if err != nil { 242 t.Fatalf("Error listing records %s", err) 243 } 244 if len(recs) != 10 { 245 t.Fatalf("Expected 10 records, received %d", len(recs)) 246 } 247 248 recs, err = s.List(store.ListPrefix("List"), store.ListLimit(5)) 249 if err != nil { 250 t.Fatalf("Error listing records %s", err) 251 } 252 if len(recs) != 5 { 253 t.Fatalf("Expected 5 records, received %d", len(recs)) 254 } 255 256 recs, err = s.List(store.ListPrefix("List"), store.ListOffset(6)) 257 if err != nil { 258 t.Fatalf("Error listing records %s", err) 259 } 260 if len(recs) != 4 { 261 t.Fatalf("Expected 4 records, received %d %+v", len(recs), recs) 262 } 263 264 recs, err = s.List(store.ListPrefix("List"), store.ListOffset(6), store.ListLimit(2)) 265 if err != nil { 266 t.Fatalf("Error listing records %s", err) 267 } 268 if len(recs) != 2 { 269 t.Fatalf("Expected 2 records, received %d %+v", len(recs), recs) 270 } 271 272 for i := 0; i < 10; i++ { 273 s.Write(&store.Record{Key: fmt.Sprintf("ListOffset%d", i), Value: []byte("bar")}) 274 } 275 276 recs, err = s.List(store.ListPrefix("ListOffset"), store.ListOffset(6)) 277 if err != nil { 278 t.Fatalf("Error listing records %s", err) 279 } 280 if len(recs) != 4 { 281 t.Fatalf("Expected 4 records, received %d %+v", len(recs), recs) 282 } 283 284 } 285 286 func expiryTests(s store.Store, t *testing.T) { 287 // Read and Write an expiring Record 288 if err := s.Write(&store.Record{ 289 Key: "Hello", 290 Value: []byte("World"), 291 Expiry: time.Millisecond * 150, 292 }); err != nil { 293 t.Error(err) 294 } 295 296 if r, err := s.Read("Hello"); err != nil { 297 t.Fatal(err) 298 } else { 299 if len(r) != 1 { 300 t.Error("Read returned multiple records") 301 } 302 if r[0].Key != "Hello" { 303 t.Errorf("Expected %s, got %s", "Hello", r[0].Key) 304 } 305 if string(r[0].Value) != "World" { 306 t.Errorf("Expected %s, got %s", "World", r[0].Value) 307 } 308 } 309 310 // wait for expiry 311 time.Sleep(time.Millisecond * 200) 312 313 if _, err := s.Read("Hello"); err != store.ErrNotFound { 314 t.Errorf("Expected %# v, got %# v", store.ErrNotFound, err) 315 } 316 317 // exercise the records expiry 318 s.Write(&store.Record{Key: "aaa", Value: []byte("bbb"), Expiry: 1 * time.Second}) 319 s.Write(&store.Record{Key: "aaaa", Value: []byte("bbb"), Expiry: 1 * time.Second}) 320 s.Write(&store.Record{Key: "aaaaa", Value: []byte("bbb"), Expiry: 1 * time.Second}) 321 results, err := s.Read("a", store.ReadPrefix()) 322 if err != nil { 323 t.Error(err) 324 } 325 if len(results) != 3 { 326 t.Fatalf("Results should have returned 3 records, returned %d", len(results)) 327 } 328 time.Sleep(1 * time.Second) 329 results, err = s.Read("a", store.ReadPrefix()) 330 if err != nil { 331 t.Error(err) 332 } 333 if len(results) != 0 { 334 t.Fatal("Results should have returned 0 records") 335 } 336 } 337 338 func suffixPrefixExpiryTests(s store.Store, t *testing.T) { 339 // Write 3 records with various expiry and get with Prefix 340 records := []*store.Record{ 341 &store.Record{ 342 Key: "foo", 343 Value: []byte("foofoo"), 344 }, 345 &store.Record{ 346 Key: "foobar", 347 Value: []byte("foobarfoobar"), 348 Expiry: 1 * time.Second, 349 }, 350 } 351 352 for _, r := range records { 353 if err := s.Write(r); err != nil { 354 t.Errorf("Couldn't write k: %s, v: %# v (%s)", r.Key, pretty.Formatter(r.Value), err) 355 } 356 } 357 358 if results, err := s.Read("foo", store.ReadPrefix()); err != nil { 359 t.Errorf("Couldn't read all \"foo\" keys, got %#v (%s)", spew.Sdump(results), err) 360 } else { 361 if len(results) != 2 { 362 t.Errorf("Expected 2 items, got %d", len(results)) 363 } 364 } 365 366 // wait for the expiry 367 time.Sleep(1 * time.Second) 368 369 if results, err := s.Read("foo", store.ReadPrefix()); err != nil { 370 t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) 371 } else if len(results) != 1 { 372 t.Errorf("Expected 1 item, got %d", len(results)) 373 } 374 375 if err := s.Delete("foo"); err != nil { 376 t.Errorf("Delete failed (%v)", err) 377 } 378 379 if results, err := s.Read("foo"); err != store.ErrNotFound { 380 t.Errorf("Expected read failure read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) 381 } else { 382 if len(results) != 0 { 383 t.Errorf("Expected 0 items, got %d (%# v)", len(results), spew.Sdump(results)) 384 } 385 } 386 387 // Write 3 records with various expiry and get with Suffix 388 records = []*store.Record{ 389 &store.Record{ 390 Key: "foo", 391 Value: []byte("foofoo"), 392 }, 393 &store.Record{ 394 Key: "barfoo", 395 Value: []byte("barfoobarfoo"), 396 397 Expiry: time.Second * 1, 398 }, 399 &store.Record{ 400 Key: "bazbarfoo", 401 Value: []byte("bazbarfoobazbarfoo"), 402 Expiry: 2 * time.Second, 403 }, 404 } 405 for _, r := range records { 406 if err := s.Write(r); err != nil { 407 t.Errorf("Couldn't write k: %s, v: %# v (%s)", r.Key, pretty.Formatter(r.Value), err) 408 } 409 } 410 if results, err := s.Read("foo", store.ReadSuffix()); err != nil { 411 t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) 412 } else { 413 if len(results) != 3 { 414 t.Errorf("Expected 3 items, got %d", len(results)) 415 //t.Logf("Table test: %v\n", spew.Sdump(results)) 416 } 417 418 } 419 time.Sleep(time.Second * 1) 420 if results, err := s.Read("foo", store.ReadSuffix()); err != nil { 421 t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) 422 } else { 423 if len(results) != 2 { 424 t.Errorf("Expected 2 items, got %d", len(results)) 425 //t.Logf("Table test: %v\n", spew.Sdump(results)) 426 } 427 428 } 429 time.Sleep(time.Second * 1) 430 if results, err := s.Read("foo", store.ReadSuffix()); err != nil { 431 t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) 432 } else { 433 if len(results) != 1 { 434 t.Errorf("Expected 1 item, got %d", len(results)) 435 // t.Logf("Table test: %# v\n", spew.Sdump(results)) 436 } 437 } 438 if err := s.Delete("foo"); err != nil { 439 t.Errorf("Delete failed (%v)", err) 440 } 441 if results, err := s.Read("foo", store.ReadSuffix()); err != nil { 442 t.Errorf("Couldn't read all \"foo\" keys, got %# v (%s)", spew.Sdump(results), err) 443 } else { 444 if len(results) != 0 { 445 t.Errorf("Expected 0 items, got %d (%# v)", len(results), spew.Sdump(results)) 446 } 447 } 448 }