github.com/portworx/kvdb@v0.0.0-20241107215734-a185a966f535/test/kv.go (about) 1 package test 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "math/rand" 8 "sort" 9 "strconv" 10 "strings" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "github.com/portworx/kvdb" 17 _ "github.com/portworx/kvdb/wrappers" 18 "github.com/sirupsen/logrus" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/require" 21 ) 22 23 type watchData struct { 24 t *testing.T 25 key string 26 otherKey string 27 stop string 28 localIndex uint64 29 updateIndex uint64 30 kvp *kvdb.KVPair 31 watchStopped bool 32 iterations int 33 action kvdb.KVAction 34 writer int32 35 reader int32 36 whichKey int32 37 } 38 39 type lockTag struct { 40 nodeID string 41 funcName string 42 } 43 44 func fatalErrorCb() kvdb.FatalErrorCB { 45 return func(err error, format string, args ...interface{}) { 46 } 47 } 48 49 // StartKvdb is a func literal. 50 type StartKvdb func(bool) error 51 52 // StopKvdb is a func literal. 53 type StopKvdb func() error 54 55 // Run runs the test suite. 56 func Run(datastoreInit kvdb.DatastoreInit, t *testing.T, start StartKvdb, stop StopKvdb) { 57 err := start(true) 58 assert.NoError(t, err, "Unable to start kvdb") 59 // Wait for kvdb to start 60 time.Sleep(5 * time.Second) 61 kv, err := datastoreInit("pwx/test", nil, nil, fatalErrorCb()) 62 if err != nil { 63 t.Fatalf(err.Error()) 64 } 65 create(kv, t) 66 createWithTTL(kv, t) 67 cas(kv, t) 68 cad(kv, t) 69 snapshot(kv, t) 70 get(kv, t) 71 getInterface(kv, t) 72 update(kv, t) 73 deleteKey(kv, t) 74 deleteTree(kv, t) 75 enumerate(kv, t) 76 keys(kv, t) 77 concurrentEnum(kv, t) 78 watchKey(kv, t) 79 watchTree(kv, t) 80 watchWithIndex(kv, t) 81 collect(kv, t) 82 lockTimeoutError(kv, t) 83 lockBasic(kv, t) 84 lock(kv, t) 85 lockBetweenRestarts(kv, t, start, stop) 86 serialization(kv, t) 87 err = stop() 88 assert.NoError(t, err, "Unable to stop kvdb") 89 90 // ensure wrapper does not crash when kvdb members are stopped. 91 wrapper, err := kvdb.AddWrapper(kvdb.Wrapper_Log, kv, nil) 92 assert.NoError(t, err, "add log wrapper") 93 assert.Equal(t, kvdb.Wrapper_Log, wrapper.WrapperName(), "get log wrapper name") 94 wrapper, err = kvdb.AddWrapper(kvdb.Wrapper_NoQuorum, wrapper, nil) 95 assert.NoError(t, err, "add quorum wrapper") 96 assert.Equal(t, kvdb.Wrapper_Log, wrapper.WrapperName(), "log wrapper must be at top") 97 assert.Equal(t, kvdb.Wrapper_NoQuorum, 98 wrapper.WrappedKvdb().WrapperName(), 99 "quorum wrapper found") 100 noQuorum(wrapper, t) 101 102 // remove wrapper 103 wrapper, err = kvdb.RemoveWrapper(kvdb.Wrapper_NoQuorum, wrapper) 104 assert.NoError(t, err, "remove quorum filter wrapper") 105 assert.Equal(t, kvdb.Wrapper_Log, wrapper.WrapperName(), "get log wrapper name") 106 assert.Equal(t, kvdb.Wrapper_None, wrapper.WrappedKvdb().WrapperName(), 107 "quorum wrapper removed") 108 109 // add quorum wrapper again 110 wrapper, err = kvdb.AddWrapper(kvdb.Wrapper_NoQuorum, wrapper, nil) 111 assert.NoError(t, err, "add quorum wrapper") 112 assert.Equal(t, kvdb.Wrapper_Log, wrapper.WrapperName(), "log wrapper must be at top") 113 assert.Equal(t, kvdb.Wrapper_NoQuorum, 114 wrapper.WrappedKvdb().WrapperName(), 115 "quorum wrapper found") 116 noQuorum(wrapper, t) 117 118 // remove all wrappers 119 wrapper, err = kvdb.RemoveWrapper(kvdb.Wrapper_Log, wrapper) 120 assert.NoError(t, err, "remove quorum filter wrapper") 121 wrapper, err = kvdb.RemoveWrapper(kvdb.Wrapper_NoQuorum, wrapper) 122 assert.NoError(t, err, "remove quorum filter wrapper") 123 assert.Equal(t, kvdb.Wrapper_None, wrapper.WrapperName(), "quorum wrapper removed") 124 } 125 126 // RunBasic runs the basic test suite. 127 func RunBasic(datastoreInit kvdb.DatastoreInit, t *testing.T, start StartKvdb, stop StopKvdb) { 128 err := start(true) 129 assert.NoError(t, err, "Unable to start kvdb") 130 // Wait for kvdb to start 131 time.Sleep(5 * time.Second) 132 kv, err := datastoreInit("pwx/test", nil, nil, fatalErrorCb()) 133 if err != nil { 134 t.Fatalf(err.Error()) 135 } 136 create(kv, t) 137 cas(kv, t) 138 cad(kv, t) 139 get(kv, t) 140 getInterface(kv, t) 141 update(kv, t) 142 deleteKey(kv, t) 143 deleteTree(kv, t) 144 enumerate(kv, t) 145 keys(kv, t) 146 lockBasic(kv, t) 147 lock(kv, t) 148 err = stop() 149 assert.NoError(t, err, "Unable to stop kvdb") 150 } 151 152 // RunLock runs the lock test suite. 153 func RunLock(datastoreInit kvdb.DatastoreInit, t *testing.T, start StartKvdb, stop StopKvdb) { 154 err := start(true) 155 time.Sleep(3 * time.Second) 156 assert.NoError(t, err, "Unable to start kvdb") 157 kv, err := datastoreInit("pwx/test", nil, nil, fatalErrorCb()) 158 if err != nil { 159 t.Fatalf(err.Error()) 160 } 161 162 lockBasic(kv, t) 163 lock(kv, t) 164 lockBetweenRestarts(kv, t, start, stop) 165 166 err = stop() 167 assert.NoError(t, err, "Unable to stop kvdb") 168 } 169 170 // RunWatch runs the watch test suite. 171 func RunWatch(datastoreInit kvdb.DatastoreInit, t *testing.T, start StartKvdb, stop StopKvdb) { 172 err := start(true) 173 time.Sleep(3 * time.Second) 174 assert.NoError(t, err, "Unable to start kvdb") 175 kv, err := datastoreInit("pwx/test", nil, nil, fatalErrorCb()) 176 if err != nil { 177 t.Fatalf(err.Error()) 178 } 179 180 // watchKey(kv, t) 181 // watchTree(kv, t) 182 // watchWithIndex(kv, t) 183 collect(kv, t) 184 // serialization(kv, t) 185 // concurrentEnum(kv, t) 186 187 err = stop() 188 assert.NoError(t, err, "Unable to stop kvdb") 189 } 190 191 // RunAuth runs the authentication test suite for kvdb 192 func RunAuth(datastoreInit kvdb.DatastoreInit, t *testing.T) { 193 options := make(map[string]string) 194 // In order to run these tests, either configure your local etcd 195 // to use these options (username/password/ca-file) or modify them here. 196 options[kvdb.UsernameKey] = "root" 197 kv, err := datastoreInit("pwx/test", nil, options, fatalErrorCb()) 198 if err == nil { 199 t.Fatalf("Expected an error when no password provided") 200 } 201 options[kvdb.PasswordKey] = "test123" 202 kv, err = datastoreInit("pwx/test", nil, options, fatalErrorCb()) 203 if err == nil { 204 t.Fatalf("Expected an error when no certificate provided") 205 } 206 options[kvdb.CAFileKey] = "/etc/pwx/pwx-ca.crt" 207 options[kvdb.CertFileKey] = "/etc/pwx/pwx-user-cert.crt" 208 options[kvdb.CertKeyFileKey] = "/etc/pwx/pwx-user-key.key" 209 210 machines := []string{"https://192.168.56.101:2379"} 211 fmt.Println("Last one") 212 kv, err = datastoreInit("pwx/test", machines, options, fatalErrorCb()) 213 if err != nil { 214 t.Fatalf(err.Error()) 215 } 216 if kv == nil { 217 t.Fatalf("Expected kv to be not nil") 218 } 219 // Run the basic put get update tests using auth 220 get(kv, t) 221 create(kv, t) 222 update(kv, t) 223 // Run the auth tests 224 addUser(kv, t) 225 grantRevokeUser(kv, datastoreInit, t) 226 removeUser(kv, t) 227 } 228 229 func get(kv kvdb.Kvdb, t *testing.T) { 230 fmt.Println("get") 231 232 kvPair, err := kv.Get("DEADCAFE") 233 assert.Error(t, err, "Expecting error value for non-existent value") 234 235 key := "foo/docker" 236 val := "great" 237 defer func() { 238 kv.Delete(key) 239 }() 240 241 kvPair, err = kv.Put(key, []byte(val), 0) 242 assert.NoError(t, err, "Unexpected error in Put") 243 244 kvPair, err = kv.Get(key) 245 assert.NoError(t, err, "Failed in Get") 246 247 assert.Equal(t, key, kvPair.Key, "Key mismatch in Get") 248 assert.Equal(t, string(kvPair.Value), val, "value mismatch in Get") 249 } 250 251 func getInterface(kv kvdb.Kvdb, t *testing.T) { 252 253 fmt.Println("getInterface") 254 expected := struct { 255 N int 256 S string 257 }{ 258 N: 10, 259 S: "Ten", 260 } 261 262 actual := expected 263 actual.N = 0 264 actual.S = "zero" 265 266 key := "DEADBEEF" 267 _, err := kv.Delete(key) 268 _, err = kv.Put(key, &expected, 0) 269 assert.NoError(t, err, "Failed in Put") 270 271 _, err = kv.GetVal(key, &actual) 272 assert.NoError(t, err, "Failed in Get") 273 274 assert.Equal(t, expected, actual, "Expected %#v but got %#v", 275 expected, actual) 276 } 277 278 func create(kv kvdb.Kvdb, t *testing.T) { 279 fmt.Println("create") 280 281 key := "///create/foo" 282 kv.Delete(key) 283 284 kvp, err := kv.Create(key, []byte("bar"), 0) 285 require.NoError(t, err, "Error on create") 286 287 defer func() { 288 kv.Delete(key) 289 }() 290 assert.Equal(t, kvp.Action, kvdb.KVCreate, 291 "Expected action KVCreate, actual %v", kvp.Action) 292 293 _, err = kv.Create(key, []byte("bar"), 0) 294 assert.True(t, err == kvdb.ErrExist, 295 "Create on existing key should have errored.") 296 } 297 298 func createWithTTL(kv kvdb.Kvdb, t *testing.T) { 299 fmt.Println("create with ttl") 300 key := "create/foottl" 301 kv.Delete(key) 302 assert.NotNil(t, kv, "Default KVDB is not set") 303 _, err := kv.Create(key, []byte("bar"), 6) 304 if err != nil { 305 // Consul does not support ttl less than 10 306 assert.EqualError(t, err, kvdb.ErrTTLNotSupported.Error(), "ttl not supported") 307 _, err := kv.Create(key, []byte("bar"), 20) 308 assert.NoError(t, err, "Error on create") 309 // Consul doubles the ttl value 310 time.Sleep(time.Second * 21) 311 _, err = kv.Get(key) 312 assert.Error(t, err, "Expecting error value for expired value") 313 314 } else { 315 assert.NoError(t, err, "Error on create") 316 time.Sleep(time.Second * 7) 317 _, err = kv.Get(key) 318 assert.Error(t, err, "Expecting error value for expired value") 319 } 320 } 321 322 func update(kv kvdb.Kvdb, t *testing.T) { 323 fmt.Println("update") 324 325 key := "update/foo" 326 kv.Delete(key) 327 328 kvp, err := kv.Update(key, []byte("bar"), 0) 329 assert.Error(t, err, "Update should error on non-existent key") 330 331 defer func() { 332 kv.Delete(key) 333 }() 334 335 kvp, err = kv.Create(key, []byte("bar"), 0) 336 assert.NoError(t, err, "Unexpected error on create") 337 338 kvp, err = kv.Update(key, []byte("bar"), 0) 339 assert.NoError(t, err, "Unexpected error on update") 340 341 assert.Equal(t, kvp.Action, kvdb.KVSet, 342 "Expected action KVSet, actual %v", kvp.Action) 343 } 344 345 func deleteKey(kv kvdb.Kvdb, t *testing.T) { 346 fmt.Println("deleteKey") 347 348 key := "delete_key" 349 _, err := kv.Delete(key) 350 351 _, err = kv.Put(key, []byte("delete_me"), 0) 352 assert.NoError(t, err, "Unexpected error on Put") 353 354 _, err = kv.Get(key) 355 assert.NoError(t, err, "Unexpected error on Get") 356 357 _, err = kv.Delete(key) 358 assert.NoError(t, err, "Unexpected error on Delete") 359 360 _, err = kv.Get(key) 361 assert.Error(t, err, "Get should fail on deleted key") 362 363 _, err = kv.Delete(key) 364 assert.Error(t, err, "Delete should fail on non existent key") 365 assert.EqualError(t, err, kvdb.ErrNotFound.Error(), "Invalid error returned : %v", err) 366 } 367 368 func deleteTree(kv kvdb.Kvdb, t *testing.T) { 369 fmt.Println("deleteTree") 370 371 prefix := "tree" 372 keys := map[string]string{ 373 prefix + "/1cbc9a98-072a-4793-8608-01ab43db96c8": "bar", 374 prefix + "/foo": "baz", 375 } 376 377 for key, val := range keys { 378 _, err := kv.Put(key, []byte(val), 0) 379 assert.NoError(t, err, "Unexpected error on Put") 380 } 381 382 keyWithSamePrefix := prefix + "_some" 383 _, err := kv.Put(keyWithSamePrefix, []byte("val"), 0) 384 assert.NoError(t, err, "Unexpected error on Put") 385 386 _, err = kv.Get(keyWithSamePrefix) 387 assert.NoError(t, err, "Unexpected error on Get") 388 389 for key := range keys { 390 _, err := kv.Get(key) 391 assert.NoError(t, err, "Unexpected error on Get") 392 } 393 err = kv.DeleteTree(prefix) 394 assert.NoError(t, err, "Unexpected error on DeleteTree") 395 396 for key := range keys { 397 _, err := kv.Get(key) 398 assert.Error(t, err, "Get should fail on all keys after DeleteTree") 399 } 400 _, err = kv.Get(keyWithSamePrefix) 401 assert.NoError(t, err, "Unexpected error on Get") 402 } 403 404 func enumerate(kv kvdb.Kvdb, t *testing.T) { 405 406 fmt.Println("enumerate") 407 408 prefix := "enumerate" 409 keys := map[string]string{ 410 prefix + "/1cbc9a98-072a-4793-8608-01ab43db96c8": "bar", 411 prefix + "/foo": "baz", 412 } 413 414 kv.DeleteTree(prefix) 415 defer func() { 416 kv.DeleteTree(prefix) 417 }() 418 419 errPairs, err := kv.Enumerate(prefix) 420 assert.Equal(t, 0, len(errPairs), "Expected 0 pairs") 421 422 folderKey := prefix + "/folder/" 423 _, err = kv.Put(folderKey, []byte("value"), 0) 424 assert.NoError(t, err, "Unexpected error on Put") 425 kvPairs, err := kv.Enumerate(folderKey) 426 assert.NoError(t, err, "Unexpected error on Enumerate") 427 kv.DeleteTree(prefix) 428 429 for key, val := range keys { 430 _, err := kv.Put(key, []byte(val), 0) 431 assert.NoError(t, err, "Unexpected error on Put") 432 } 433 kvPairs, err = kv.Enumerate(prefix) 434 assert.NoError(t, err, "Unexpected error on Enumerate") 435 436 assert.Equal(t, len(kvPairs), len(keys), 437 "Expecting %d keys under %s got: %d", 438 len(keys), prefix, len(kvPairs)) 439 440 for i := range kvPairs { 441 v, ok := keys[kvPairs[i].Key] 442 assert.True(t, ok, "unexpected kvpair (%s)->(%s)", 443 kvPairs[i].Key, kvPairs[i].Value) 444 assert.Equal(t, v, string(kvPairs[i].Value), 445 "Invalid kvpair (%s)->(%s) expect value %s", 446 kvPairs[i].Key, kvPairs[i].Value, v) 447 } 448 } 449 450 func keys(kv kvdb.Kvdb, t *testing.T) { 451 452 fmt.Println("keys") 453 454 prefix := "keys" 455 testKeys := []string{"testkey1", "testkey2", "testkey99999999999999999"} 456 testRows := map[string]string{ 457 prefix + "/" + testKeys[0]: "bar", 458 prefix + "/" + testKeys[1] + "/testkey3": "baz", 459 prefix + "/" + testKeys[2] + "/here/or/there": "foo", 460 } 461 462 kv.DeleteTree(prefix) 463 defer func() { 464 kv.DeleteTree(prefix) 465 }() 466 467 keys, err := kv.Keys(prefix, "") 468 assert.Equal(t, 0, len(keys), "Expected 0 keys") 469 470 for key, val := range testRows { 471 _, err := kv.Put(key, []byte(val), 0) 472 assert.NoError(t, err, "Unexpected error on Put") 473 } 474 475 keys, err = kv.Keys(prefix, "") 476 assert.NoError(t, err, "Unexpected error on Keys") 477 478 assert.Equal(t, len(testRows), len(keys), 479 "Expecting %d keys under %s got: %d", 480 len(testRows), prefix, len(keys)) 481 482 sort.Strings(keys) 483 sort.Strings(testKeys) 484 assert.Equal(t, testKeys, keys, 485 "Expecting array %v to be equal to %v", 486 testKeys, keys) 487 } 488 489 func concurrentEnum(kv kvdb.Kvdb, t *testing.T) { 490 491 fmt.Println("concurrentEnum") 492 493 prefix := "concEnum" 494 var wg sync.WaitGroup 495 quit, latch := make(chan bool), make(chan bool) 496 shared, numGoroutines := int32(0), 0 497 498 kv.DeleteTree(prefix) 499 defer func() { 500 kv.DeleteTree(prefix) 501 }() 502 503 // start 3 "adders" 504 for i := 0; i < 3; i++ { 505 go func() { 506 id := atomic.AddInt32(&shared, 1) 507 fmt.Printf("+> Adder #%d started\n", id) 508 content := []byte(fmt.Sprintf("adder #%d", id)) 509 wg.Add(1) 510 defer wg.Done() 511 _ = <-latch // sync-point 512 numFails := 0 513 for j := 0; ; j++ { 514 select { 515 case <-quit: 516 fmt.Printf("+> Adder #%d quit (stored %d keys)\n", id, j) 517 return 518 default: 519 key := fmt.Sprintf("%s/%d-%d", prefix, id, j%100000) 520 _, err := kv.Put(key, content, 0) 521 if err != nil { 522 logrus.WithError(err).Warnf("Error inserting key %s", key) 523 numFails++ 524 // let's tolerate some errors, since we're in race w/ Deleter 525 assert.True(t, numFails < 10, "Too many failures on PUT") 526 } 527 // sleep a bit, not to be overly aggressive 528 time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) 529 } 530 } 531 }() 532 numGoroutines++ 533 } 534 535 // start 1 "deleter" 536 go func() { 537 wg.Add(1) 538 defer wg.Done() 539 fmt.Printf("+> Deleter started\n") 540 _ = <-latch // sync-point 541 for j := 0; ; { // cap at max 100k 542 select { 543 case <-quit: 544 fmt.Printf("+> Deleter quit (deleted %d keys)\n", j) 545 return 546 default: 547 key := fmt.Sprintf("%s/%d-%d", prefix, rand.Intn(numGoroutines), j%100000) 548 _, err := kv.Delete(key) 549 if err == nil { 550 // advance only on successful delete 551 j++ 552 } 553 // sleep a bit, not to be overly aggressive 554 time.Sleep(time.Duration(rand.Intn(10)) * time.Millisecond) 555 } 556 } 557 }() 558 numGoroutines++ 559 560 fmt.Printf("> MAIN waiting for workers\n") 561 time.Sleep(50 * time.Millisecond) 562 close(latch) // release sync-points 563 time.Sleep(5500 * time.Millisecond) 564 565 // make sure these two just work, otherwise we cannot assume how many elements found 566 567 sep := ':' 568 fmt.Printf("> MAIN run") 569 for i := 0; i < 5; i++ { 570 fmt.Printf("%c Enumerate", sep) 571 _, err := kv.Enumerate(prefix) 572 assert.NoError(t, err) 573 574 sep = ',' 575 fmt.Printf("%c Keys", sep) 576 _, err = kv.Keys(prefix, "") 577 assert.NoError(t, err) 578 } 579 580 fmt.Printf("%c stop workers\n", sep) 581 for i := 0; i < numGoroutines; i++ { 582 quit <- true 583 } 584 close(quit) 585 fmt.Printf("> MAIN waiting ...") 586 wg.Wait() 587 fmt.Printf("DONE.\n") 588 } 589 590 func snapshot(kv kvdb.Kvdb, t *testing.T) { 591 fmt.Println("snapshot") 592 593 prefix := "snapshot/" 594 kv.DeleteTree(prefix) 595 defer kv.DeleteTree(prefix) 596 597 prefix2 := "snapshot2/" 598 kv.DeleteTree(prefix2) 599 defer kv.DeleteTree(prefix2) 600 601 prefix3 := "snapshot2/subtree/" 602 603 ignorePrefix := "ignoreSnapshot/" 604 kv.DeleteTree(ignorePrefix) 605 defer kv.DeleteTree(ignorePrefix) 606 607 preSnapData := make(map[string]string) 608 preSnapDataVersion := make(map[string]uint64) 609 inputData := make(map[string]string) 610 inputDataVersion := make(map[string]uint64) 611 deleteKeys := make(map[string]string) 612 613 key := "key" 614 value := "bar" 615 keyd := "key-delete" 616 valued := "bar-delete" 617 count := 100 618 doneUpdate := make(chan bool, 2) 619 emptyKeyName := "" 620 updateFn := func(count int, v string, dataMap map[string]string, 621 versionMap map[string]uint64, isDelete bool) { 622 for i := 0; i < count; i++ { 623 suffix := strconv.Itoa(i) 624 var inputKey string 625 if i%3 == 0 { 626 inputKey = prefix + key + suffix 627 } else if i%3 == 1 { 628 inputKey = prefix3 + key + suffix 629 } else { 630 inputKey = prefix2 + key + suffix 631 } 632 inputValue := v 633 if i == 0 { 634 emptyKeyName = inputKey 635 inputValue = "" 636 } 637 kvp, err := kv.Put(inputKey, []byte(inputValue), 0) 638 assert.NoError(t, err, "Unexpected error on Put") 639 dataMap[inputKey] = inputValue 640 versionMap[inputKey] = kvp.ModifiedIndex 641 deleteKey := prefix + keyd + suffix 642 if !isDelete { 643 _, err := kv.Put(deleteKey, []byte(valued), 0) 644 assert.NoError(t, err, "Unexpected error on Put") 645 deleteKeys[deleteKey] = deleteKey 646 } else { 647 _, err := kv.Delete(deleteKey) 648 assert.NoError(t, err, "Unexpected error on Delete") 649 } 650 651 // update ops on keys which need to be ignore 652 inputKey = ignorePrefix + key + suffix 653 _, err = kv.Put(inputKey, []byte(inputValue), 0) 654 assert.NoError(t, err, "Unexpected error on Put") 655 656 deleteKey = ignorePrefix + keyd + suffix 657 if !isDelete { 658 _, err := kv.Put(deleteKey, []byte(valued), 0) 659 assert.NoError(t, err, "Unexpected error on Put") 660 } else { 661 _, err := kv.Delete(deleteKey) 662 assert.NoError(t, err, "Unexpected error on Delete") 663 } 664 } 665 doneUpdate <- true 666 } 667 668 updateFn(count, value, preSnapData, preSnapDataVersion, false) 669 <-doneUpdate 670 newValue := "bar2" 671 go updateFn(count, newValue, inputData, inputDataVersion, true) 672 time.Sleep(20 * time.Millisecond) 673 674 snap, snapVersion, err := kv.Snapshot([]string{prefix, prefix2, prefix3}, true) 675 assert.NoError(t, err, "Unexpected error on Snapshot") 676 <-doneUpdate 677 678 // Enumerate on prefix 1 679 kvps, err := snap.Enumerate(prefix) 680 assert.NoError(t, err, "Unexpected error on Enumerate") 681 682 // Enumerate on prefix 2 683 kvps2, err := snap.Enumerate(prefix2) 684 assert.NoError(t, err, "Unexpected error on Enumerate") 685 686 kvPairs := append(kvps, kvps2...) 687 688 processedKeys := 0 689 for i := range kvPairs { 690 if strings.Contains(kvPairs[i].Key, keyd) { 691 _, ok := deleteKeys[kvPairs[i].Key] 692 assert.True(t, ok, "Key not found in deleteKeys list (%v)", kvPairs[i].Key) 693 delete(deleteKeys, kvPairs[i].Key) 694 continue 695 } 696 processedKeys++ 697 currValue, ok1 := inputData[kvPairs[i].Key] 698 currVersion, ok2 := inputDataVersion[kvPairs[i].Key] 699 preSnapValue, ok3 := preSnapData[kvPairs[i].Key] 700 preSnapKeyVersion, ok4 := preSnapDataVersion[kvPairs[i].Key] 701 assert.True(t, ok1 && ok2 && ok3 && ok4, "unexpected kvpair (%s)->(%s)", 702 kvPairs[i].Key, kvPairs[i].Value) 703 704 assert.True(t, kvPairs[i].Key == emptyKeyName || 705 len(string(kvPairs[i].Value)) != 0, 706 "Empty value for key %f", kvPairs[i].Key) 707 708 assert.True(t, kvPairs[i].ModifiedIndex < snapVersion, 709 "snap db key (%v) has version greater than snap version (%v)", 710 kvPairs[i].ModifiedIndex, snapVersion) 711 712 if kvPairs[i].ModifiedIndex == currVersion { 713 assert.True(t, string(kvPairs[i].Value) == currValue, 714 "snapshot db does not have correct value, "+ 715 " expected %v got %v", currValue, string(kvPairs[i].Value)) 716 } else { 717 assert.True(t, kvPairs[i].ModifiedIndex == preSnapKeyVersion, 718 "snapshot db does not have correct version, expected %v got %v", 719 kvPairs[i].ModifiedIndex, preSnapKeyVersion) 720 assert.True(t, string(kvPairs[i].Value) == preSnapValue, 721 "snapshot db does not have correct value, "+ 722 " expected %v got %v", preSnapValue, string(kvPairs[i].Value)) 723 } 724 } 725 assert.Equal(t, count, processedKeys, 726 "Expecting %d keys under %s got: %d, kv: %v", 727 processedKeys, prefix, len(kvPairs), kvPairs) 728 729 // Check there are no keys under the ignored prefix 730 kvPairs, err = snap.Enumerate(ignorePrefix) 731 assert.Equal(t, 0, len(kvPairs), "Expected 0 pairs to be returned under the ignored prefix") 732 } 733 734 func getLockMethods(kv kvdb.Kvdb) []func(string) (*kvdb.KVPair, error) { 735 lockMethods := make([]func(string) (*kvdb.KVPair, error), 2) 736 lockMethods[0] = func(key string) (*kvdb.KVPair, error) { 737 return kv.Lock(key) 738 } 739 lockMethods[1] = func(key string) (*kvdb.KVPair, error) { 740 tag := "node:node_1,func:testfunc" 741 return kv.LockWithID(key, tag) 742 } 743 return lockMethods 744 } 745 746 func lock(kv kvdb.Kvdb, t *testing.T) { 747 lockMethods := getLockMethods(kv) 748 749 for _, lockMethod := range lockMethods { 750 kv.SetLockHoldDuration(time.Duration(0)) 751 fmt.Println("lock") 752 753 key := "locktest" 754 kvPair, err := lockMethod(key) 755 assert.NoError(t, err, "Unexpected error in lock") 756 757 if kvPair == nil { 758 return 759 } 760 761 // For consul unlock does not deal with the value part of the kvPair 762 /* 763 stash := *kvPair 764 stash.Value = []byte("hoohah") 765 fmt.Println("bad unlock") 766 err = kv.Unlock(&stash) 767 assert.Error(t, err, "Unlock should fail for bad KVPair") 768 */ 769 770 fmt.Println("unlock") 771 err = kv.Unlock(kvPair) 772 assert.NoError(t, err, "Unexpected error from Unlock") 773 774 fmt.Println("relock") 775 kvPair, err = lockMethod(key) 776 assert.NoError(t, err, "Failed to lock after unlock") 777 778 fmt.Println("reunlock") 779 err = kv.Unlock(kvPair) 780 assert.NoError(t, err, "Unexpected error from Unlock") 781 782 fmt.Println("repeat lock once") 783 kvPair, err = lockMethod(key) 784 assert.NoError(t, err, "Failed to lock unlock") 785 786 done := 0 787 go func() { 788 time.Sleep(time.Second * 10) 789 done = 1 790 err = kv.Unlock(kvPair) 791 fmt.Println("repeat lock unlock once") 792 assert.NoError(t, err, "Unexpected error from Unlock") 793 }() 794 fmt.Println("repeat lock lock twice") 795 kvPair, err = lockMethod(key) 796 assert.NoError(t, err, "Failed to lock") 797 assert.Equal(t, done, 1, "Locked before unlock") 798 if done != 1 { 799 logrus.Fatalf("Exiting because done != 1") 800 } 801 fmt.Println("repeat lock unlock twice") 802 err = kv.Unlock(kvPair) 803 assert.NoError(t, err, "Unexpected error from Unlock") 804 805 for done == 0 { 806 time.Sleep(time.Second) 807 } 808 809 key = "doubleLock" 810 kvPair, err = lockMethod(key) 811 assert.NoError(t, err, "Unexpected error in lock") 812 go func() { 813 time.Sleep(10 * time.Second) 814 err = kv.Unlock(kvPair) 815 assert.NoError(t, err, "Unexpected error from Unlock") 816 }() 817 kvPair2, err := lockMethod(key) 818 assert.NoError(t, err, "Double lock") 819 err = kv.Unlock(kvPair2) 820 assert.NoError(t, err, "Unexpected error from Unlock") 821 822 kvPair, err = lockMethod("key1") 823 assert.NoError(t, err, "Unexpected error in lock") 824 go func() { 825 time.Sleep(1 * time.Second) 826 err = kv.Unlock(kvPair) 827 assert.NoError(t, err, "Unexpected error from Unlock") 828 }() 829 kvPair2, err = lockMethod("key2") 830 assert.NoError(t, err, "diff lock") 831 err = kv.Unlock(kvPair2) 832 assert.NoError(t, err, "Unexpected error from Unlock") 833 834 lockTimedout := false 835 fatalLockCb := func(err error, format string, args ...interface{}) { 836 logrus.Infof("Lock timeout called: "+format, args...) 837 lockTimedout = true 838 } 839 kv.SetFatalCb(fatalLockCb) 840 kv.SetLockHoldDuration(5 * time.Second) 841 assert.Equal(t, kv.GetLockHoldDuration(), 5*time.Second, "get lock timeout") 842 kvPair2, err = lockMethod("key2") 843 time.Sleep(15 * time.Second) 844 assert.True(t, lockTimedout, "lock timeout not called") 845 err = kv.Unlock(kvPair2) 846 kv.SetLockHoldDuration(5 * time.Second) 847 } 848 } 849 850 func lockBetweenRestarts(kv kvdb.Kvdb, t *testing.T, start StartKvdb, stop StopKvdb) { 851 lockMethods := getLockMethods(kv) 852 for _, lockMethod := range lockMethods { 853 // Try to take the lock again 854 // We need this test for consul to check if LockDelay is not set 855 fmt.Println("lock before restarting kvdb") 856 kvPairBeforeRestart, err := lockMethod("key3") 857 assert.NoError(t, err, "Unable to take a lock") 858 fmt.Println("stopping kvdb") 859 err = stop() 860 assert.NoError(t, err, "Unable to stop kvdb") 861 // Unlock the key 862 go func() { kv.Unlock(kvPairBeforeRestart) }() 863 864 time.Sleep(30 * time.Second) 865 866 fmt.Println("starting kvdb") 867 err = start(false) 868 assert.NoError(t, err, "Unable to start kvdb") 869 time.Sleep(40 * time.Second) 870 871 lockChan := make(chan int) 872 var kvPair3 *kvdb.KVPair 873 go func() { 874 kvPair3, err = lockMethod("key3") 875 lockChan <- 1 876 }() 877 select { 878 case <-time.After(20 * time.Second): 879 assert.Fail(t, "Unable to take a lock whose session is expired") 880 case <-lockChan: 881 } 882 err = kv.Unlock(kvPair3) 883 assert.NoError(t, err, "unable to unlock") 884 } 885 } 886 887 func getTimeoutLock(kv kvdb.Kvdb, key string, lockerID string, tryDuration time.Duration, holdDuration time.Duration, kvChan chan *kvdb.KVPair, errChan chan error) { 888 kvPair, err := kv.LockWithTimeout(key, lockerID, tryDuration, holdDuration) 889 kvChan <- kvPair 890 errChan <- err 891 } 892 893 func lockTimeoutError(kv kvdb.Kvdb, t *testing.T) { 894 fmt.Println("lockTimeoutError() started") 895 896 kvChan := make(chan *kvdb.KVPair) 897 errChan := make(chan error) 898 key := "timeoutLockTest" 899 holdDuration := 30 * time.Second 900 tryDuration := 5 * time.Second 901 go getTimeoutLock(kv, key, "timeouttest1", tryDuration, holdDuration, kvChan, errChan) 902 time.Sleep(2 * time.Second) 903 go getTimeoutLock(kv, key, "timeouttest2", tryDuration, holdDuration, kvChan, errChan) 904 kvPair1, kvPair2 := <-kvChan, <-kvChan 905 err1, err2 := <-errChan, <-errChan 906 assert.NotNil(t, kvPair1, "Problem in acquiring Lock") 907 assert.Nil(t, kvPair2, "Lock acquired incorrectly") 908 assert.NoError(t, err1, "Unexpected error while trying to acquire lock") 909 assert.Error(t, err2, "Unexpected behaviour") 910 911 err := kv.Unlock(kvPair1) 912 assert.NoError(t, err, "Unexpected error while unlock") 913 go getTimeoutLock(kv, key, "timeouttest3", tryDuration, holdDuration, kvChan, errChan) 914 kvPair2 = <-kvChan 915 assert.NotNil(t, kvPair2, "Problem in acquiring Lock after Unlock") 916 917 fmt.Println("lockTimeoutError() ended successfully") 918 } 919 920 func lockBasic(kv kvdb.Kvdb, t *testing.T) { 921 lockMethods := getLockMethods(kv) 922 923 for _, lockMethod := range lockMethods { 924 fmt.Println("lock") 925 926 key := "locktest" 927 kvPair, err := lockMethod(key) 928 assert.NoError(t, err, "Unexpected error in lock") 929 930 if kvPair == nil { 931 return 932 } 933 934 err = kv.Unlock(kvPair) 935 assert.NoError(t, err, "Unexpected error from Unlock") 936 937 kvPair, err = lockMethod(key) 938 assert.NoError(t, err, "Failed to lock after unlock") 939 940 err = kv.Unlock(kvPair) 941 assert.NoError(t, err, "Unexpected error from Unlock") 942 } 943 944 // lock with timeout 945 key := "testTimeoutKey" 946 holdDuration := 30 * time.Second 947 tryDuration := 5 * time.Second 948 kvPair, err := kv.LockWithTimeout(key, "test", tryDuration, holdDuration) 949 assert.NoError(t, err, "Unexpected error in lock") 950 951 tryStart := time.Now() 952 _, err = kv.LockWithTimeout(key, "test", tryDuration, holdDuration) 953 if err == nil { 954 logrus.Fatalf("Exiting because expected error %v %v", tryDuration, holdDuration) 955 } 956 duration := time.Since(tryStart) 957 assert.True(t, duration < tryDuration+time.Second, "try duration") 958 assert.Error(t, err, "lock expired before timeout") 959 960 time.Sleep(holdDuration - time.Since(tryStart) - 5*time.Second) 961 962 _, err = kv.LockWithTimeout(key, "test", 1*time.Second, holdDuration) 963 duration = time.Since(tryStart) 964 assert.Error(t, err, "lock expired before timeout") 965 966 err = kv.Unlock(kvPair) 967 assert.NoError(t, err, "Unexpected error from Unlock") 968 fmt.Println("Ending lock basic") 969 } 970 971 func watchFn( 972 prefix string, 973 opaque interface{}, 974 kvp *kvdb.KVPair, 975 err error, 976 ) error { 977 data := opaque.(*watchData) 978 time.Sleep(100 * time.Millisecond) 979 if err != nil { 980 assert.Equal(data.t, err, kvdb.ErrWatchStopped) 981 data.watchStopped = true 982 return err 983 984 } 985 fmt.Printf("+") 986 987 // Doesn't work for ETCD because HTTP header contains Etcd-Index 988 /* 989 assert.True(data.t, kvp.KVDBIndex >= data.updateIndex, 990 "KVDBIndex %v must be >= than updateIndex %v", 991 kvp.KVDBIndex, data.updateIndex) 992 993 assert.True(data.t, kvp.KVDBIndex > data.localIndex, 994 "For Key (%v) : KVDBIndex %v must be > than localIndex %v action %v %v", 995 kvp.Key, kvp.KVDBIndex, data.localIndex, kvp.Action, kvdb.KVCreate) 996 */ 997 998 assert.True(data.t, kvp.ModifiedIndex > data.localIndex, 999 "For Key (%v) : ModifiedIndex %v must be > than localIndex %v", 1000 kvp.Key, kvp.ModifiedIndex, data.localIndex) 1001 1002 data.localIndex = kvp.ModifiedIndex 1003 1004 if data.whichKey == 0 { 1005 assert.Contains(data.t, data.otherKey, kvp.Key, 1006 "Bad kvpair key %s expecting %s with action %v", 1007 kvp.Key, data.key, kvp.Action) 1008 } else { 1009 assert.Contains(data.t, data.key, kvp.Key, 1010 "Bad kvpair key %s expecting %s with action %v", 1011 kvp.Key, data.key, kvp.Action) 1012 } 1013 1014 assert.Equal(data.t, data.action, kvp.Action, 1015 "For Key (%v) : Expected action %v actual %v", 1016 kvp.Key, data.action, kvp.Action) 1017 if data.action != kvp.Action { 1018 value := string(kvp.Value) 1019 logrus.Panicf("Aborting because (%v != %v) (%v) %v != %v (Value = %v)", 1020 data.action, kvp.Action, prefix, data, kvp, value) 1021 } 1022 1023 if string(kvp.Value) == data.stop { 1024 return errors.New(data.stop) 1025 } 1026 1027 atomic.AddInt32(&data.reader, 1) 1028 return nil 1029 } 1030 1031 func watchUpdate(kv kvdb.Kvdb, data *watchData) error { 1032 var err error 1033 var kvp *kvdb.KVPair 1034 1035 data.reader, data.writer = 0, 0 1036 atomic.AddInt32(&data.writer, 1) 1037 // whichKey = 1 : key 1038 // whichKey = 0 : otherKey 1039 atomic.SwapInt32(&data.whichKey, 1) 1040 data.action = kvdb.KVCreate 1041 fmt.Printf("-") 1042 fmt.Printf("XXX Creating watchUpdate key %v\n", data.key) 1043 kvp, err = kv.Create(data.key, []byte("bar"), 0) 1044 for i := 0; i < data.iterations && err == nil; i++ { 1045 fmt.Printf("-") 1046 1047 for data.writer != data.reader { 1048 time.Sleep(time.Millisecond * 100) 1049 } 1050 atomic.AddInt32(&data.writer, 1) 1051 data.action = kvdb.KVSet 1052 fmt.Printf("XXX Putting watchUpdate key %v\n", data.key) 1053 kvp, err = kv.Put(data.key, []byte("bar"), 0) 1054 1055 data.updateIndex = kvp.KVDBIndex 1056 assert.NoError(data.t, err, "Unexpected error in Put") 1057 } 1058 1059 fmt.Printf("-") 1060 for data.writer != data.reader { 1061 time.Sleep(time.Millisecond * 100) 1062 } 1063 atomic.AddInt32(&data.writer, 1) 1064 // Delete key 1065 data.action = kvdb.KVDelete 1066 kv.Delete(data.key) 1067 1068 fmt.Printf("-") 1069 for data.writer != data.reader { 1070 time.Sleep(time.Millisecond * 100) 1071 } 1072 atomic.AddInt32(&data.writer, 1) 1073 1074 atomic.SwapInt32(&data.whichKey, 0) 1075 data.action = kvdb.KVDelete 1076 // Delete otherKey 1077 kv.Delete(data.otherKey) 1078 1079 fmt.Printf("-") 1080 for data.writer != data.reader { 1081 time.Sleep(time.Millisecond * 100) 1082 } 1083 atomic.AddInt32(&data.writer, 1) 1084 1085 atomic.SwapInt32(&data.whichKey, 1) 1086 data.action = kvdb.KVCreate 1087 _, err = kv.Create(data.key, []byte(data.stop), 0) 1088 return err 1089 } 1090 1091 func watchKey(kv kvdb.Kvdb, t *testing.T) { 1092 fmt.Println("\nwatchKey") 1093 1094 watchData := watchData{ 1095 t: t, 1096 key: "tree/key1", 1097 otherKey: "tree/otherKey1", 1098 stop: "stop", 1099 iterations: 2, 1100 } 1101 1102 kv.Delete(watchData.key) 1103 kv.Delete(watchData.otherKey) 1104 // First create a key. We should not get update for this create. 1105 kvp, err := kv.Create(watchData.otherKey, []byte("bar"), 0) 1106 // Let the create operation finish and then start the watch 1107 time.Sleep(2 * time.Second) 1108 1109 err = kv.WatchKey(watchData.otherKey, kvp.ModifiedIndex, &watchData, watchFn) 1110 if err != nil { 1111 fmt.Printf("Cannot test watchKey: %v\n", err) 1112 return 1113 } 1114 1115 err = kv.WatchKey(watchData.key, 0, &watchData, watchFn) 1116 if err != nil { 1117 fmt.Printf("Cannot test watchKey: %v\n", err) 1118 return 1119 } 1120 1121 // Sleep for sometime before calling the watchUpdate go routine. 1122 time.Sleep(time.Second * 2) 1123 1124 go watchUpdate(kv, &watchData) 1125 1126 for watchData.watchStopped == false { 1127 time.Sleep(time.Millisecond * 100) 1128 } 1129 1130 // Stop the second watch 1131 atomic.SwapInt32(&watchData.whichKey, 0) 1132 watchData.action = kvdb.KVCreate 1133 _, err = kv.Create(watchData.otherKey, []byte(watchData.stop), 0) 1134 } 1135 1136 func randomUpdate(kv kvdb.Kvdb, w *watchData) { 1137 for w.watchStopped == false { 1138 kv.Put("randomKey", []byte("bar"), 0) 1139 time.Sleep(time.Millisecond * 80) 1140 } 1141 } 1142 1143 func watchTree(kv kvdb.Kvdb, t *testing.T) { 1144 fmt.Println("\nwatchTree") 1145 1146 tree := "tree" 1147 1148 watchData := watchData{ 1149 t: t, 1150 key: tree + "/key", 1151 otherKey: tree + "/otherKey", 1152 stop: "stop", 1153 iterations: 2, 1154 } 1155 _, err := kv.Delete(watchData.key) 1156 _, err = kv.Delete(watchData.otherKey) 1157 1158 // First create a tree to watch for. We should not get update for this create. 1159 kvp, err := kv.Create(watchData.otherKey, []byte("bar"), 0) 1160 // Let the create operation finish and then start the watch 1161 1162 time.Sleep(time.Second) 1163 err = kv.WatchTree(tree, kvp.ModifiedIndex, &watchData, watchFn) 1164 if err != nil { 1165 fmt.Printf("Cannot test watchKey: %v\n", err) 1166 return 1167 } 1168 1169 // Sleep for sometime before calling the watchUpdate go routine. 1170 time.Sleep(time.Millisecond * 100) 1171 1172 go randomUpdate(kv, &watchData) 1173 go watchUpdate(kv, &watchData) 1174 1175 for watchData.watchStopped == false { 1176 time.Sleep(time.Millisecond * 100) 1177 } 1178 } 1179 1180 func watchWithIndexCb( 1181 prefix string, 1182 opaque interface{}, 1183 kvp *kvdb.KVPair, 1184 err error, 1185 ) error { 1186 1187 data, ok := opaque.(*watchData) 1188 if !ok { 1189 data.t.Fatalf("Unable to parse waitIndex in watch callback") 1190 } 1191 if err != nil { 1192 assert.Equal(data.t, err, kvdb.ErrWatchStopped) 1193 data.watchStopped = true 1194 return err 1195 1196 } 1197 if kvp != nil && len(kvp.Value) != 0 && string(kvp.Value) == "stop" { 1198 // Stop the watch 1199 return fmt.Errorf("stop the watch") 1200 } 1201 assert.True(data.t, kvp.ModifiedIndex >= data.localIndex, 1202 "For key: %v. ModifiedIndex (%v) should be > than waitIndex (%v)", 1203 kvp.Key, kvp.ModifiedIndex, data.localIndex, 1204 ) 1205 assert.True(data.t, kvp.ModifiedIndex <= data.localIndex+3, 1206 "For key: %v. Got extra updates. Current ModifiedIndex: %v. Expected last update index: %v", 1207 kvp.Key, kvp.ModifiedIndex, data.localIndex+2, 1208 ) 1209 if kvp.ModifiedIndex == data.localIndex+3 { 1210 assert.True(data.t, kvp.Action == kvdb.KVDelete, 1211 "Expected action: %v, action action: %v", 1212 kvdb.KVDelete, kvp.Action, 1213 ) 1214 } 1215 return nil 1216 } 1217 1218 func watchWithIndex(kv kvdb.Kvdb, t *testing.T) { 1219 fmt.Println("\nwatchWithIndex") 1220 1221 tree := "indexTree" 1222 subtree := tree + "/subtree" 1223 key := subtree + "/watchWithIndex" 1224 key1 := subtree + "/watchWithIndex21" 1225 1226 kv.DeleteTree(tree) 1227 1228 kvp, err := kv.Create(key, []byte("bar"), 0) 1229 assert.NoError(t, err, "Unexpected error in create: %v", err) 1230 1231 time.Sleep(time.Millisecond * 100) 1232 1233 waitIndex := kvp.ModifiedIndex + 2 1234 watchData := watchData{ 1235 t: t, 1236 key: key, 1237 localIndex: waitIndex, 1238 } 1239 1240 err = kv.WatchTree(tree, waitIndex, &watchData, watchWithIndexCb) 1241 if err != nil { 1242 fmt.Printf("Cannot test watchTree for watchWithIndex: %v", err) 1243 return 1244 } 1245 // Should not get updates for these 1246 kv.Put(key, []byte("bar1"), 0) 1247 kv.Put(key, []byte("bar1"), 0) 1248 // Should get updates for these 1249 kv.Put(key, []byte("bar2"), 0) 1250 kv.Create(key1, []byte("bar"), 0) 1251 kv.Delete(key) 1252 kv.Put(key, []byte("stop"), 0) 1253 } 1254 1255 func cas(kv kvdb.Kvdb, t *testing.T) { 1256 fmt.Println("cas") 1257 1258 key := "foo/docker" 1259 val := "great" 1260 defer func() { 1261 kv.DeleteTree(key) 1262 }() 1263 1264 kvPair, err := kv.Put(key, []byte(val), 0) 1265 assert.NoError(t, err, "Unxpected error in Put") 1266 1267 kvPair, err = kv.Get(key) 1268 assert.NoError(t, err, "Failed in Get") 1269 1270 _, err = kv.CompareAndSet(kvPair, kvdb.KVFlags(0), []byte("badval")) 1271 assert.Error(t, err, "CompareAndSet should fail on an incorrect previous value") 1272 1273 copyKVPair := *kvPair 1274 copyKVPair.ModifiedIndex++ 1275 _, err = kv.CompareAndSet(©KVPair, kvdb.KVModifiedIndex, nil) 1276 assert.Error(t, err, "CompareAndSet should fail on an incorrect modified index") 1277 1278 //kvPair.ModifiedIndex-- 1279 copyKVPair.ModifiedIndex-- 1280 kvPair, err = kv.CompareAndSet(©KVPair, kvdb.KVModifiedIndex, nil) 1281 assert.NoError(t, err, "CompareAndSet should succeed on an correct modified index") 1282 1283 kvPairNew, err := kv.CompareAndSet(kvPair, kvdb.KVFlags(0), []byte(val)) 1284 assert.NoError(t, err, "CompareAndSet should succeed on an correct value") 1285 1286 if kvPairNew != nil { 1287 kvPair = kvPairNew 1288 } 1289 1290 kvPair, err = kv.CompareAndSet(kvPair, kvdb.KVModifiedIndex, []byte(val)) 1291 assert.NoError(t, err, "CompareAndSet should succeed on an correct value and modified index") 1292 } 1293 1294 func cad(kv kvdb.Kvdb, t *testing.T) { 1295 fmt.Println("cad") 1296 1297 key := "foo/docker" 1298 val := "great" 1299 defer func() { 1300 kv.DeleteTree(key) 1301 }() 1302 1303 kvPair, err := kv.Put(key, []byte(val), 0) 1304 assert.NoError(t, err, "Unxpected error in Put") 1305 1306 kvPair, err = kv.Get(key) 1307 assert.NoError(t, err, "Failed in Get") 1308 1309 copyKVPair1 := *kvPair 1310 copyKVPair1.Value = []byte("badval") 1311 _, err = kv.CompareAndDelete(©KVPair1, kvdb.KVFlags(0)) 1312 assert.Error(t, err, "CompareAndDelete should fail on an incorrect previous value") 1313 1314 copyKVPair2 := *kvPair 1315 copyKVPair2.ModifiedIndex++ 1316 _, err = kv.CompareAndDelete(©KVPair2, kvdb.KVModifiedIndex) 1317 assert.Error(t, err, "CompareAndDelete should fail on an incorrect modified index") 1318 1319 //kvPair.ModifiedIndex-- 1320 copyKVPair2.ModifiedIndex-- 1321 kvPair, err = kv.CompareAndDelete(©KVPair2, kvdb.KVModifiedIndex) 1322 assert.NoError(t, err, "CompareAndDelete should succeed on an correct modified index") 1323 1324 kvPair, err = kv.Put(key, []byte(val), 0) 1325 assert.NoError(t, err, "Unxpected error in Put") 1326 1327 _, err = kv.CompareAndDelete(kvPair, kvdb.KVFlags(0)) 1328 assert.NoError(t, err, "CompareAndDelete should succeed on an correct value") 1329 } 1330 1331 func addUser(kv kvdb.Kvdb, t *testing.T) { 1332 fmt.Println("addUser") 1333 1334 err := kv.AddUser("test", "test123") 1335 assert.NoError(t, err, "Error in Adding User") 1336 } 1337 1338 func removeUser(kv kvdb.Kvdb, t *testing.T) { 1339 fmt.Println("removeUser") 1340 1341 err := kv.RemoveUser("test") 1342 assert.NoError(t, err, "Error in Removing User") 1343 } 1344 1345 func grantRevokeUser(kvRootUser kvdb.Kvdb, datastoreInit kvdb.DatastoreInit, t *testing.T) { 1346 fmt.Println("grantRevokeUser") 1347 1348 kvRootUser.Create("allow1/foo", []byte("bar"), 0) 1349 kvRootUser.Create("allow2/foo", []byte("bar"), 0) 1350 kvRootUser.Create("disallow/foo", []byte("bar"), 0) 1351 err := kvRootUser.GrantUserAccess("test", kvdb.ReadWritePermission, "allow1/*") 1352 assert.NoError(t, err, "Error in Grant User") 1353 err = kvRootUser.GrantUserAccess("test", kvdb.ReadWritePermission, "allow2/*") 1354 assert.NoError(t, err, "Error in Grant User") 1355 err = kvRootUser.GrantUserAccess("test", kvdb.ReadWritePermission, "disallow/*") 1356 assert.NoError(t, err, "Error in Grant User") 1357 err = kvRootUser.RevokeUsersAccess("test", kvdb.ReadWritePermission, "disallow/*") 1358 assert.NoError(t, err, "Error in Revoke User") 1359 1360 options := make(map[string]string) 1361 options[kvdb.UsernameKey] = "test" 1362 options[kvdb.PasswordKey] = "test123" 1363 options[kvdb.CAFileKey] = "/etc/pwx/pwx-ca.crt" 1364 options[kvdb.CertFileKey] = "/etc/pwx/pwx-user-cert.crt" 1365 options[kvdb.CertKeyFileKey] = "/etc/pwx/pwx-user-key.key" 1366 machines := []string{"https://192.168.56.101:2379"} 1367 kvTestUser, _ := datastoreInit("pwx/test", machines, options, fatalErrorCb()) 1368 1369 actual := "actual" 1370 _, err = kvTestUser.Put("allow1/foo", []byte(actual), 0) 1371 assert.NoError(t, err, "Error in writing to allowed tree") 1372 kvPair, err := kvTestUser.Get("allow1/foo") 1373 assert.NoError(t, err, "Error in accessing allowed values") 1374 if err == nil { 1375 assert.Equal(t, string(kvPair.Value), "actual") 1376 } 1377 1378 _, err = kvTestUser.Put("allow2/foo", []byte(actual), 0) 1379 assert.NoError(t, err, "Error in writing to allowed tree") 1380 kvPair, err = kvTestUser.Get("allow2/foo") 1381 assert.NoError(t, err, "Error in accessing allowed values") 1382 if err == nil { 1383 assert.Equal(t, string(kvPair.Value), "actual") 1384 } 1385 1386 actual2 := "actual2" 1387 _, err = kvTestUser.Put("disallow/foo", []byte(actual2), 0) 1388 assert.Error(t, err, "Expected error in writing to disallowed tree") 1389 kvPair, err = kvTestUser.Get("disallow/foo") 1390 assert.Error(t, err, "Expected error in accessing disallowed values") 1391 1392 kvRootUser.DeleteTree("allow1") 1393 kvRootUser.DeleteTree("allow2") 1394 kvRootUser.DeleteTree("disallow") 1395 } 1396 1397 func collect(kv kvdb.Kvdb, t *testing.T) { 1398 for _, useStartVersion := range []bool{false, true} { 1399 1400 startVersion := func(modifiedVersion uint64) uint64 { 1401 if useStartVersion { 1402 return modifiedVersion 1403 } 1404 return 0 1405 } 1406 1407 fmt.Println("collect") 1408 1409 // XXX FIXME this is a bug... root should not have the prefix 1410 root := "pwx/test/collect" 1411 firstLevel := root + "/first" 1412 secondLevel := root + "/second" 1413 1414 kv.DeleteTree(root) 1415 1416 kvp, _ := kv.Create(firstLevel, []byte("bar"), 0) 1417 fmt.Printf("KVP is %v and KV is %v\n", kvp, kv) 1418 collector, _ := kvdb.NewUpdatesCollector(kv, secondLevel, 1419 startVersion(kvp.CreatedIndex)) 1420 time.Sleep(time.Second) 1421 var updates []*kvdb.KVPair 1422 updateFn := func(start, end int) uint64 { 1423 lastUpdateVersion := uint64(0) 1424 for i := start; i < end; i++ { 1425 newLeaf := strconv.Itoa(i) 1426 // First update the tree being watched. 1427 kvp1, _ := kv.Create(secondLevel+"/"+newLeaf, []byte(newLeaf), 0) 1428 // Next update another value in kvdb which is not being 1429 // watched, this update will cause kvdb index to move forward. 1430 kv.Update(firstLevel, []byte(newLeaf), 0) 1431 updates = append(updates, kvp1) 1432 lastUpdateVersion = kvp1.ModifiedIndex 1433 } 1434 return lastUpdateVersion 1435 } 1436 lastUpdateVersion := updateFn(0, 10) 1437 // Allow watch updates to come back. 1438 time.Sleep(time.Millisecond * 500) 1439 collector.Stop() 1440 1441 updateFn(10, 20) 1442 lastKVIndex := kvp.CreatedIndex 1443 lastLeafIndex := -1 1444 cb := func(prefix string, opaque interface{}, kvp *kvdb.KVPair, 1445 err error) error { 1446 fmt.Printf("\nReplaying KVP: %v", *kvp) 1447 assert.True(t, err == nil, "Error is nil %v", err) 1448 assert.True(t, kvp.ModifiedIndex > lastKVIndex, 1449 "Modified index %v lower than last index %v", 1450 kvp.ModifiedIndex, lastKVIndex) 1451 lastKVIndex = kvp.ModifiedIndex 1452 strValue := string(kvp.Value) 1453 value := secondLevel + "/" + strValue 1454 assert.True(t, strings.Compare(kvp.Key, value) == 0, 1455 "Key: %v, Value: %v", kvp.Key, value) 1456 leafIndex, _ := strconv.Atoi(strValue) 1457 assert.True(t, leafIndex == lastLeafIndex+1, 1458 "Last leaf: %v, leaf: %v", kvp.Key, 1459 value) 1460 lastLeafIndex = leafIndex 1461 return nil 1462 } 1463 1464 replayCb := make([]kvdb.ReplayCb, 1) 1465 replayCb[0].Prefix = secondLevel 1466 replayCb[0].WatchCB = cb 1467 replayCb[0].WaitIndex = kvp.CreatedIndex 1468 1469 lastVersion, err := collector.ReplayUpdates(replayCb) 1470 assert.True(t, err == nil, "Replay encountered error %v", err) 1471 assert.True(t, lastLeafIndex == 9, "Last leaf index %v, expected : 9", 1472 lastLeafIndex) 1473 assert.True(t, lastVersion == lastUpdateVersion, 1474 "Last update %d and last replay %d version mismatch", 1475 lastVersion, lastUpdateVersion) 1476 1477 // Test with no updates. 1478 thirdLevel := root + "/third" 1479 kvp, _ = kv.Create(thirdLevel, []byte("bar_update"), 0) 1480 collector, _ = kvdb.NewUpdatesCollector(kv, thirdLevel, 1481 startVersion(kvp.ModifiedIndex)) 1482 time.Sleep(2 * time.Second) 1483 replayCb[0].WaitIndex = kvp.ModifiedIndex 1484 _, err = collector.ReplayUpdates(replayCb) 1485 assert.True(t, err == nil, "Replay encountered error %v", err) 1486 assert.True(t, lastLeafIndex == 9, "Last leaf index %v, expected : 9", 1487 lastLeafIndex) 1488 if lastLeafIndex != 9 { 1489 logrus.Fatalf("lastLeafIndex is %v", lastLeafIndex) 1490 } 1491 1492 // Test with kvdb returning error because update index was too old. 1493 fourthLevel := root + "/fourth" 1494 kv.Create(fourthLevel, []byte(strconv.Itoa(0)), 0) 1495 for i := 1; i < 2000; i++ { 1496 kv.Update(fourthLevel, []byte(strconv.Itoa(i)), 0) 1497 } 1498 collector, _ = kvdb.NewUpdatesCollector(kv, fourthLevel, 1499 startVersion(kvp.ModifiedIndex)) 1500 kv.Update(fourthLevel, []byte(strconv.Itoa(2000)), 0) 1501 time.Sleep(500 * time.Millisecond) 1502 cb = func(prefix string, opaque interface{}, kvp *kvdb.KVPair, 1503 err error) error { 1504 fmt.Printf("Error is %v", err) 1505 assert.True(t, err != nil, "Error is nil %v", err) 1506 return nil 1507 } 1508 replayCb[0].WatchCB = cb 1509 replayCb[0].WaitIndex = kvp.ModifiedIndex 1510 collector.ReplayUpdates(replayCb) 1511 } 1512 } 1513 1514 func serialization(kv kvdb.Kvdb, t *testing.T) { 1515 fmt.Println("serialization") 1516 kv.DeleteTree("") 1517 prefix := "/folder" 1518 type A struct { 1519 A1 int 1520 A2 string 1521 } 1522 type B struct { 1523 B1 string 1524 } 1525 a1 := A{1, "a"} 1526 b1 := B{"2"} 1527 c1 := A{2, "b"} 1528 _, err := kv.Put(prefix+"/a/a1", a1, 0) 1529 assert.NoError(t, err, "Unexpected error on put") 1530 _, err = kv.Put(prefix+"/b/b1", b1, 0) 1531 assert.NoError(t, err, "Unexpected error on put") 1532 _, err = kv.Put(prefix+"/c/c1", c1, 0) 1533 assert.NoError(t, err, "Unexpected error on put") 1534 kv.Delete(prefix + "/c/c1") 1535 b, err := kv.Serialize() 1536 assert.NoError(t, err, "Unexpected error on serialize") 1537 kvps, err := kv.Deserialize(b) 1538 assert.NoError(t, err, "Unexpected error on de-serialize") 1539 for _, kvp := range kvps { 1540 if strings.Contains(kvp.Key, "/a/a1") { 1541 aa := A{} 1542 err = json.Unmarshal(kvp.Value, &aa) 1543 assert.NoError(t, err, "Unexpected error on unmarshal") 1544 assert.Equal(t, aa.A1, a1.A1, "Unequal A values") 1545 assert.Equal(t, aa.A2, a1.A2, "Unequal A values") 1546 } else if strings.Contains(kvp.Key, "/b/b1") { 1547 bb := B{} 1548 err = json.Unmarshal(kvp.Value, &bb) 1549 assert.NoError(t, err, "Unexpected error on unmarshal") 1550 assert.Equal(t, bb.B1, b1.B1, "Unequal B values") 1551 } else if strings.Contains(kvp.Key, "/c") { 1552 // ETCD v2 will return an empty folder, but v3 and consul will not 1553 assert.Equal(t, len(kvp.Value), 0, "Unexpected C values") 1554 } else { 1555 t.Fatalf("Unexpected values returned by deserialize: %v", kvp.Key) 1556 } 1557 } 1558 } 1559 1560 func noQuorum(kv kvdb.Kvdb, t *testing.T) { 1561 key := "key" 1562 value := "value" 1563 sep := "/" 1564 ttl := uint64(0) 1565 1566 assert.True(t, len(kv.String()) > 0, "Unexpected error in String") 1567 1568 _, err := kv.Create(key, value, ttl) 1569 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Create") 1570 _, err = kv.Get(key) 1571 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Get") 1572 _, err = kv.Put(key, value, ttl) 1573 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Put") 1574 _, _, err = kv.Snapshot(nil, true) 1575 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Snapshot") 1576 _, err = kv.GetVal(key, value) 1577 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in GetVal") 1578 _, err = kv.Update(key, value, ttl) 1579 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Update") 1580 _, err = kv.Enumerate(key) 1581 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Enumerate") 1582 _, err = kv.Keys(key, sep) 1583 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Keys") 1584 1585 kvp := &kvdb.KVPair{Key: key, Value: []byte(value)} 1586 _, err = kv.CompareAndSet(kvp, 0, []byte(value)) 1587 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in CompareAndSet") 1588 1589 _, err = kv.Lock(key) 1590 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Lock") 1591 _, err = kv.LockWithID(key, key) 1592 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in LockWithID") 1593 _, err = kv.LockWithTimeout(key, key, time.Minute, time.Minute) 1594 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in LockWithTimeout") 1595 1596 selectFn := func(val interface{}) bool { 1597 t.Fatal("select function called when no quorum exists") 1598 return false 1599 } 1600 copyFn := func(val interface{}) interface{} { 1601 t.Fatal("copy function called when no quorum exists") 1602 return val 1603 } 1604 _, err = kv.EnumerateWithSelect(key, selectFn, copyFn) 1605 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in EnumerateWithSelect") 1606 1607 _, err = kv.SnapPut(nil) 1608 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in SnapPut") 1609 err = kv.AddUser(key, value) 1610 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in AddUser") 1611 err = kv.RemoveUser(key) 1612 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in RemoveUser") 1613 _, err = kv.TxNew() 1614 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in TxNew") 1615 1616 _, err = kv.Serialize() 1617 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Serialize") 1618 _, err = kv.Deserialize([]byte{}) 1619 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Serialize") 1620 1621 _, err = kv.Delete(key) 1622 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in Delete") 1623 err = kv.DeleteTree(key) 1624 assert.Error(t, err, kvdb.ErrNoQuorum, "error expected in DeleteTree") 1625 1626 // watch must return an error 1627 watchCb := func(prefix string, opaque interface{}, kvp *kvdb.KVPair, err error) error { 1628 assert.Error(t, err, "watch error expected") 1629 return err 1630 } 1631 kv.WatchKey(key, ttl, key, watchCb) 1632 kv.WatchTree(key, ttl, key, watchCb) 1633 }