go.etcd.io/etcd@v3.3.27+incompatible/mvcc/kv_test.go (about) 1 // Copyright 2015 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 mvcc 16 17 import ( 18 "fmt" 19 "os" 20 "reflect" 21 "testing" 22 "time" 23 24 "github.com/coreos/etcd/lease" 25 "github.com/coreos/etcd/mvcc/backend" 26 "github.com/coreos/etcd/mvcc/mvccpb" 27 "github.com/coreos/etcd/pkg/testutil" 28 29 "github.com/prometheus/client_golang/prometheus" 30 dto "github.com/prometheus/client_model/go" 31 ) 32 33 // Functional tests for features implemented in v3 store. It treats v3 store 34 // as a black box, and tests it by feeding the input and validating the output. 35 36 // TODO: add similar tests on operations in one txn/rev 37 38 type ( 39 rangeFunc func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) 40 putFunc func(kv KV, key, value []byte, lease lease.LeaseID) int64 41 deleteRangeFunc func(kv KV, key, end []byte) (n, rev int64) 42 ) 43 44 var ( 45 normalRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) { 46 return kv.Range(key, end, ro) 47 } 48 txnRangeFunc = func(kv KV, key, end []byte, ro RangeOptions) (*RangeResult, error) { 49 txn := kv.Read() 50 defer txn.End() 51 return txn.Range(key, end, ro) 52 } 53 54 normalPutFunc = func(kv KV, key, value []byte, lease lease.LeaseID) int64 { 55 return kv.Put(key, value, lease) 56 } 57 txnPutFunc = func(kv KV, key, value []byte, lease lease.LeaseID) int64 { 58 txn := kv.Write() 59 defer txn.End() 60 return txn.Put(key, value, lease) 61 } 62 63 normalDeleteRangeFunc = func(kv KV, key, end []byte) (n, rev int64) { 64 return kv.DeleteRange(key, end) 65 } 66 txnDeleteRangeFunc = func(kv KV, key, end []byte) (n, rev int64) { 67 txn := kv.Write() 68 defer txn.End() 69 return txn.DeleteRange(key, end) 70 } 71 ) 72 73 func TestKVRange(t *testing.T) { testKVRange(t, normalRangeFunc) } 74 func TestKVTxnRange(t *testing.T) { testKVRange(t, txnRangeFunc) } 75 76 func testKVRange(t *testing.T, f rangeFunc) { 77 b, tmpPath := backend.NewDefaultTmpBackend() 78 s := NewStore(b, &lease.FakeLessor{}, nil) 79 defer cleanup(s, b, tmpPath) 80 81 kvs := put3TestKVs(s) 82 83 wrev := int64(4) 84 tests := []struct { 85 key, end []byte 86 wkvs []mvccpb.KeyValue 87 }{ 88 // get no keys 89 { 90 []byte("doo"), []byte("foo"), 91 nil, 92 }, 93 // get no keys when key == end 94 { 95 []byte("foo"), []byte("foo"), 96 nil, 97 }, 98 // get no keys when ranging single key 99 { 100 []byte("doo"), nil, 101 nil, 102 }, 103 // get all keys 104 { 105 []byte("foo"), []byte("foo3"), 106 kvs, 107 }, 108 // get partial keys 109 { 110 []byte("foo"), []byte("foo1"), 111 kvs[:1], 112 }, 113 // get single key 114 { 115 []byte("foo"), nil, 116 kvs[:1], 117 }, 118 // get entire keyspace 119 { 120 []byte(""), []byte(""), 121 kvs, 122 }, 123 } 124 125 for i, tt := range tests { 126 r, err := f(s, tt.key, tt.end, RangeOptions{}) 127 if err != nil { 128 t.Fatal(err) 129 } 130 if r.Rev != wrev { 131 t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev) 132 } 133 if !reflect.DeepEqual(r.KVs, tt.wkvs) { 134 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs) 135 } 136 } 137 } 138 139 func TestKVRangeRev(t *testing.T) { testKVRangeRev(t, normalRangeFunc) } 140 func TestKVTxnRangeRev(t *testing.T) { testKVRangeRev(t, txnRangeFunc) } 141 142 func testKVRangeRev(t *testing.T, f rangeFunc) { 143 b, tmpPath := backend.NewDefaultTmpBackend() 144 s := NewStore(b, &lease.FakeLessor{}, nil) 145 defer cleanup(s, b, tmpPath) 146 147 kvs := put3TestKVs(s) 148 149 tests := []struct { 150 rev int64 151 wrev int64 152 wkvs []mvccpb.KeyValue 153 }{ 154 {-1, 4, kvs}, 155 {0, 4, kvs}, 156 {2, 4, kvs[:1]}, 157 {3, 4, kvs[:2]}, 158 {4, 4, kvs}, 159 } 160 161 for i, tt := range tests { 162 r, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Rev: tt.rev}) 163 if err != nil { 164 t.Fatal(err) 165 } 166 if r.Rev != tt.wrev { 167 t.Errorf("#%d: rev = %d, want %d", i, r.Rev, tt.wrev) 168 } 169 if !reflect.DeepEqual(r.KVs, tt.wkvs) { 170 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs) 171 } 172 } 173 } 174 175 func TestKVRangeBadRev(t *testing.T) { testKVRangeBadRev(t, normalRangeFunc) } 176 func TestKVTxnRangeBadRev(t *testing.T) { testKVRangeBadRev(t, txnRangeFunc) } 177 178 func testKVRangeBadRev(t *testing.T, f rangeFunc) { 179 b, tmpPath := backend.NewDefaultTmpBackend() 180 s := NewStore(b, &lease.FakeLessor{}, nil) 181 defer cleanup(s, b, tmpPath) 182 183 put3TestKVs(s) 184 if _, err := s.Compact(4); err != nil { 185 t.Fatalf("compact error (%v)", err) 186 } 187 188 tests := []struct { 189 rev int64 190 werr error 191 }{ 192 {-1, nil}, // <= 0 is most recent store 193 {0, nil}, 194 {1, ErrCompacted}, 195 {2, ErrCompacted}, 196 {4, nil}, 197 {5, ErrFutureRev}, 198 {100, ErrFutureRev}, 199 } 200 for i, tt := range tests { 201 _, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Rev: tt.rev}) 202 if err != tt.werr { 203 t.Errorf("#%d: error = %v, want %v", i, err, tt.werr) 204 } 205 } 206 } 207 208 func TestKVRangeLimit(t *testing.T) { testKVRangeLimit(t, normalRangeFunc) } 209 func TestKVTxnRangeLimit(t *testing.T) { testKVRangeLimit(t, txnRangeFunc) } 210 211 func testKVRangeLimit(t *testing.T, f rangeFunc) { 212 b, tmpPath := backend.NewDefaultTmpBackend() 213 s := NewStore(b, &lease.FakeLessor{}, nil) 214 defer cleanup(s, b, tmpPath) 215 216 kvs := put3TestKVs(s) 217 218 wrev := int64(4) 219 tests := []struct { 220 limit int64 221 wkvs []mvccpb.KeyValue 222 }{ 223 // no limit 224 {-1, kvs}, 225 // no limit 226 {0, kvs}, 227 {1, kvs[:1]}, 228 {2, kvs[:2]}, 229 {3, kvs}, 230 {100, kvs}, 231 } 232 for i, tt := range tests { 233 r, err := f(s, []byte("foo"), []byte("foo3"), RangeOptions{Limit: tt.limit}) 234 if err != nil { 235 t.Fatalf("#%d: range error (%v)", i, err) 236 } 237 if !reflect.DeepEqual(r.KVs, tt.wkvs) { 238 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs) 239 } 240 if r.Rev != wrev { 241 t.Errorf("#%d: rev = %d, want %d", i, r.Rev, wrev) 242 } 243 if r.Count != len(kvs) { 244 t.Errorf("#%d: count = %d, want %d", i, r.Count, len(kvs)) 245 } 246 } 247 } 248 249 func TestKVPutMultipleTimes(t *testing.T) { testKVPutMultipleTimes(t, normalPutFunc) } 250 func TestKVTxnPutMultipleTimes(t *testing.T) { testKVPutMultipleTimes(t, txnPutFunc) } 251 252 func testKVPutMultipleTimes(t *testing.T, f putFunc) { 253 b, tmpPath := backend.NewDefaultTmpBackend() 254 s := NewStore(b, &lease.FakeLessor{}, nil) 255 defer cleanup(s, b, tmpPath) 256 257 for i := 0; i < 10; i++ { 258 base := int64(i + 1) 259 260 rev := f(s, []byte("foo"), []byte("bar"), lease.LeaseID(base)) 261 if rev != base+1 { 262 t.Errorf("#%d: rev = %d, want %d", i, rev, base+1) 263 } 264 265 r, err := s.Range([]byte("foo"), nil, RangeOptions{}) 266 if err != nil { 267 t.Fatal(err) 268 } 269 wkvs := []mvccpb.KeyValue{ 270 {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: base + 1, Version: base, Lease: base}, 271 } 272 if !reflect.DeepEqual(r.KVs, wkvs) { 273 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs) 274 } 275 } 276 } 277 278 func TestKVDeleteRange(t *testing.T) { testKVDeleteRange(t, normalDeleteRangeFunc) } 279 func TestKVTxnDeleteRange(t *testing.T) { testKVDeleteRange(t, txnDeleteRangeFunc) } 280 281 func testKVDeleteRange(t *testing.T, f deleteRangeFunc) { 282 tests := []struct { 283 key, end []byte 284 285 wrev int64 286 wN int64 287 }{ 288 { 289 []byte("foo"), nil, 290 5, 1, 291 }, 292 { 293 []byte("foo"), []byte("foo1"), 294 5, 1, 295 }, 296 { 297 []byte("foo"), []byte("foo2"), 298 5, 2, 299 }, 300 { 301 []byte("foo"), []byte("foo3"), 302 5, 3, 303 }, 304 { 305 []byte("foo3"), []byte("foo8"), 306 4, 0, 307 }, 308 { 309 []byte("foo3"), nil, 310 4, 0, 311 }, 312 } 313 314 for i, tt := range tests { 315 b, tmpPath := backend.NewDefaultTmpBackend() 316 s := NewStore(b, &lease.FakeLessor{}, nil) 317 318 s.Put([]byte("foo"), []byte("bar"), lease.NoLease) 319 s.Put([]byte("foo1"), []byte("bar1"), lease.NoLease) 320 s.Put([]byte("foo2"), []byte("bar2"), lease.NoLease) 321 322 n, rev := f(s, tt.key, tt.end) 323 if n != tt.wN || rev != tt.wrev { 324 t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, tt.wN, tt.wrev) 325 } 326 327 cleanup(s, b, tmpPath) 328 } 329 } 330 331 func TestKVDeleteMultipleTimes(t *testing.T) { testKVDeleteMultipleTimes(t, normalDeleteRangeFunc) } 332 func TestKVTxnDeleteMultipleTimes(t *testing.T) { testKVDeleteMultipleTimes(t, txnDeleteRangeFunc) } 333 334 func testKVDeleteMultipleTimes(t *testing.T, f deleteRangeFunc) { 335 b, tmpPath := backend.NewDefaultTmpBackend() 336 s := NewStore(b, &lease.FakeLessor{}, nil) 337 defer cleanup(s, b, tmpPath) 338 339 s.Put([]byte("foo"), []byte("bar"), lease.NoLease) 340 341 n, rev := f(s, []byte("foo"), nil) 342 if n != 1 || rev != 3 { 343 t.Fatalf("n = %d, rev = %d, want (%d, %d)", n, rev, 1, 3) 344 } 345 346 for i := 0; i < 10; i++ { 347 n, rev := f(s, []byte("foo"), nil) 348 if n != 0 || rev != 3 { 349 t.Fatalf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 0, 3) 350 } 351 } 352 } 353 354 // test that range, put, delete on single key in sequence repeatedly works correctly. 355 func TestKVOperationInSequence(t *testing.T) { 356 b, tmpPath := backend.NewDefaultTmpBackend() 357 s := NewStore(b, &lease.FakeLessor{}, nil) 358 defer cleanup(s, b, tmpPath) 359 360 for i := 0; i < 10; i++ { 361 base := int64(i*2 + 1) 362 363 // put foo 364 rev := s.Put([]byte("foo"), []byte("bar"), lease.NoLease) 365 if rev != base+1 { 366 t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1) 367 } 368 369 r, err := s.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1}) 370 if err != nil { 371 t.Fatal(err) 372 } 373 wkvs := []mvccpb.KeyValue{ 374 {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)}, 375 } 376 if !reflect.DeepEqual(r.KVs, wkvs) { 377 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs) 378 } 379 if r.Rev != base+1 { 380 t.Errorf("#%d: range rev = %d, want %d", i, rev, base+1) 381 } 382 383 // delete foo 384 n, rev := s.DeleteRange([]byte("foo"), nil) 385 if n != 1 || rev != base+2 { 386 t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+2) 387 } 388 389 r, err = s.Range([]byte("foo"), nil, RangeOptions{Rev: base + 2}) 390 if err != nil { 391 t.Fatal(err) 392 } 393 if r.KVs != nil { 394 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil) 395 } 396 if r.Rev != base+2 { 397 t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+2) 398 } 399 } 400 } 401 402 func TestKVTxnBlockWriteOperations(t *testing.T) { 403 b, tmpPath := backend.NewDefaultTmpBackend() 404 s := NewStore(b, &lease.FakeLessor{}, nil) 405 406 tests := []func(){ 407 func() { s.Put([]byte("foo"), nil, lease.NoLease) }, 408 func() { s.DeleteRange([]byte("foo"), nil) }, 409 } 410 for i, tt := range tests { 411 txn := s.Write() 412 done := make(chan struct{}, 1) 413 go func() { 414 tt() 415 done <- struct{}{} 416 }() 417 select { 418 case <-done: 419 t.Fatalf("#%d: operation failed to be blocked", i) 420 case <-time.After(10 * time.Millisecond): 421 } 422 423 txn.End() 424 select { 425 case <-done: 426 case <-time.After(10 * time.Second): 427 testutil.FatalStack(t, fmt.Sprintf("#%d: operation failed to be unblocked", i)) 428 } 429 } 430 431 // only close backend when we know all the tx are finished 432 cleanup(s, b, tmpPath) 433 } 434 435 func TestKVTxnNonBlockRange(t *testing.T) { 436 b, tmpPath := backend.NewDefaultTmpBackend() 437 s := NewStore(b, &lease.FakeLessor{}, nil) 438 defer cleanup(s, b, tmpPath) 439 440 txn := s.Write() 441 defer txn.End() 442 443 donec := make(chan struct{}) 444 go func() { 445 defer close(donec) 446 s.Range([]byte("foo"), nil, RangeOptions{}) 447 }() 448 select { 449 case <-donec: 450 case <-time.After(100 * time.Millisecond): 451 t.Fatalf("range operation blocked on write txn") 452 } 453 } 454 455 // test that txn range, put, delete on single key in sequence repeatedly works correctly. 456 func TestKVTxnOperationInSequence(t *testing.T) { 457 b, tmpPath := backend.NewDefaultTmpBackend() 458 s := NewStore(b, &lease.FakeLessor{}, nil) 459 defer cleanup(s, b, tmpPath) 460 461 for i := 0; i < 10; i++ { 462 txn := s.Write() 463 base := int64(i + 1) 464 465 // put foo 466 rev := txn.Put([]byte("foo"), []byte("bar"), lease.NoLease) 467 if rev != base+1 { 468 t.Errorf("#%d: put rev = %d, want %d", i, rev, base+1) 469 } 470 471 r, err := txn.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1}) 472 if err != nil { 473 t.Fatal(err) 474 } 475 wkvs := []mvccpb.KeyValue{ 476 {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: base + 1, ModRevision: base + 1, Version: 1, Lease: int64(lease.NoLease)}, 477 } 478 if !reflect.DeepEqual(r.KVs, wkvs) { 479 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, wkvs) 480 } 481 if r.Rev != base+1 { 482 t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+1) 483 } 484 485 // delete foo 486 n, rev := txn.DeleteRange([]byte("foo"), nil) 487 if n != 1 || rev != base+1 { 488 t.Errorf("#%d: n = %d, rev = %d, want (%d, %d)", i, n, rev, 1, base+1) 489 } 490 491 r, err = txn.Range([]byte("foo"), nil, RangeOptions{Rev: base + 1}) 492 if err != nil { 493 t.Errorf("#%d: range error (%v)", i, err) 494 } 495 if r.KVs != nil { 496 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, nil) 497 } 498 if r.Rev != base+1 { 499 t.Errorf("#%d: range rev = %d, want %d", i, r.Rev, base+1) 500 } 501 502 txn.End() 503 } 504 } 505 506 func TestKVCompactReserveLastValue(t *testing.T) { 507 b, tmpPath := backend.NewDefaultTmpBackend() 508 s := NewStore(b, &lease.FakeLessor{}, nil) 509 defer cleanup(s, b, tmpPath) 510 511 s.Put([]byte("foo"), []byte("bar0"), 1) 512 s.Put([]byte("foo"), []byte("bar1"), 2) 513 s.DeleteRange([]byte("foo"), nil) 514 s.Put([]byte("foo"), []byte("bar2"), 3) 515 516 // rev in tests will be called in Compact() one by one on the same store 517 tests := []struct { 518 rev int64 519 // wanted kvs right after the compacted rev 520 wkvs []mvccpb.KeyValue 521 }{ 522 { 523 1, 524 []mvccpb.KeyValue{ 525 {Key: []byte("foo"), Value: []byte("bar0"), CreateRevision: 2, ModRevision: 2, Version: 1, Lease: 1}, 526 }, 527 }, 528 { 529 2, 530 []mvccpb.KeyValue{ 531 {Key: []byte("foo"), Value: []byte("bar1"), CreateRevision: 2, ModRevision: 3, Version: 2, Lease: 2}, 532 }, 533 }, 534 { 535 3, 536 nil, 537 }, 538 { 539 4, 540 []mvccpb.KeyValue{ 541 {Key: []byte("foo"), Value: []byte("bar2"), CreateRevision: 5, ModRevision: 5, Version: 1, Lease: 3}, 542 }, 543 }, 544 } 545 for i, tt := range tests { 546 _, err := s.Compact(tt.rev) 547 if err != nil { 548 t.Errorf("#%d: unexpect compact error %v", i, err) 549 } 550 r, err := s.Range([]byte("foo"), nil, RangeOptions{Rev: tt.rev + 1}) 551 if err != nil { 552 t.Errorf("#%d: unexpect range error %v", i, err) 553 } 554 if !reflect.DeepEqual(r.KVs, tt.wkvs) { 555 t.Errorf("#%d: kvs = %+v, want %+v", i, r.KVs, tt.wkvs) 556 } 557 } 558 } 559 560 func TestKVCompactBad(t *testing.T) { 561 b, tmpPath := backend.NewDefaultTmpBackend() 562 s := NewStore(b, &lease.FakeLessor{}, nil) 563 defer cleanup(s, b, tmpPath) 564 565 s.Put([]byte("foo"), []byte("bar0"), lease.NoLease) 566 s.Put([]byte("foo"), []byte("bar1"), lease.NoLease) 567 s.Put([]byte("foo"), []byte("bar2"), lease.NoLease) 568 569 // rev in tests will be called in Compact() one by one on the same store 570 tests := []struct { 571 rev int64 572 werr error 573 }{ 574 {0, nil}, 575 {1, nil}, 576 {1, ErrCompacted}, 577 {4, nil}, 578 {5, ErrFutureRev}, 579 {100, ErrFutureRev}, 580 } 581 for i, tt := range tests { 582 _, err := s.Compact(tt.rev) 583 if err != tt.werr { 584 t.Errorf("#%d: compact error = %v, want %v", i, err, tt.werr) 585 } 586 } 587 } 588 589 func TestKVHash(t *testing.T) { 590 hashes := make([]uint32, 3) 591 592 for i := 0; i < len(hashes); i++ { 593 var err error 594 b, tmpPath := backend.NewDefaultTmpBackend() 595 kv := NewStore(b, &lease.FakeLessor{}, nil) 596 kv.Put([]byte("foo0"), []byte("bar0"), lease.NoLease) 597 kv.Put([]byte("foo1"), []byte("bar0"), lease.NoLease) 598 hashes[i], _, err = kv.Hash() 599 if err != nil { 600 t.Fatalf("failed to get hash: %v", err) 601 } 602 cleanup(kv, b, tmpPath) 603 } 604 605 for i := 1; i < len(hashes); i++ { 606 if hashes[i-1] != hashes[i] { 607 t.Errorf("hash[%d](%d) != hash[%d](%d)", i-1, hashes[i-1], i, hashes[i]) 608 } 609 } 610 } 611 612 func TestKVRestore(t *testing.T) { 613 tests := []func(kv KV){ 614 func(kv KV) { 615 kv.Put([]byte("foo"), []byte("bar0"), 1) 616 kv.Put([]byte("foo"), []byte("bar1"), 2) 617 kv.Put([]byte("foo"), []byte("bar2"), 3) 618 kv.Put([]byte("foo2"), []byte("bar0"), 1) 619 }, 620 func(kv KV) { 621 kv.Put([]byte("foo"), []byte("bar0"), 1) 622 kv.DeleteRange([]byte("foo"), nil) 623 kv.Put([]byte("foo"), []byte("bar1"), 2) 624 }, 625 func(kv KV) { 626 kv.Put([]byte("foo"), []byte("bar0"), 1) 627 kv.Put([]byte("foo"), []byte("bar1"), 2) 628 kv.Compact(1) 629 }, 630 } 631 for i, tt := range tests { 632 b, tmpPath := backend.NewDefaultTmpBackend() 633 s := NewStore(b, &lease.FakeLessor{}, nil) 634 tt(s) 635 var kvss [][]mvccpb.KeyValue 636 for k := int64(0); k < 10; k++ { 637 r, _ := s.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k}) 638 kvss = append(kvss, r.KVs) 639 } 640 641 keysBefore := readGaugeInt(&keysGauge) 642 s.Close() 643 644 // ns should recover the the previous state from backend. 645 ns := NewStore(b, &lease.FakeLessor{}, nil) 646 647 if keysRestore := readGaugeInt(&keysGauge); keysBefore != keysRestore { 648 t.Errorf("#%d: got %d key count, expected %d", i, keysRestore, keysBefore) 649 } 650 651 // wait for possible compaction to finish 652 testutil.WaitSchedule() 653 var nkvss [][]mvccpb.KeyValue 654 for k := int64(0); k < 10; k++ { 655 r, _ := ns.Range([]byte("a"), []byte("z"), RangeOptions{Rev: k}) 656 nkvss = append(nkvss, r.KVs) 657 } 658 cleanup(ns, b, tmpPath) 659 660 if !reflect.DeepEqual(nkvss, kvss) { 661 t.Errorf("#%d: kvs history = %+v, want %+v", i, nkvss, kvss) 662 } 663 } 664 } 665 666 func readGaugeInt(g *prometheus.Gauge) int { 667 ch := make(chan prometheus.Metric, 1) 668 keysGauge.Collect(ch) 669 m := <-ch 670 mm := &dto.Metric{} 671 m.Write(mm) 672 return int(mm.GetGauge().GetValue()) 673 } 674 675 func TestKVSnapshot(t *testing.T) { 676 b, tmpPath := backend.NewDefaultTmpBackend() 677 s := NewStore(b, &lease.FakeLessor{}, nil) 678 defer cleanup(s, b, tmpPath) 679 680 wkvs := put3TestKVs(s) 681 682 newPath := "new_test" 683 f, err := os.Create(newPath) 684 if err != nil { 685 t.Fatal(err) 686 } 687 defer os.Remove(newPath) 688 689 snap := s.b.Snapshot() 690 defer snap.Close() 691 _, err = snap.WriteTo(f) 692 if err != nil { 693 t.Fatal(err) 694 } 695 f.Close() 696 697 ns := NewStore(b, &lease.FakeLessor{}, nil) 698 defer ns.Close() 699 r, err := ns.Range([]byte("a"), []byte("z"), RangeOptions{}) 700 if err != nil { 701 t.Errorf("unexpect range error (%v)", err) 702 } 703 if !reflect.DeepEqual(r.KVs, wkvs) { 704 t.Errorf("kvs = %+v, want %+v", r.KVs, wkvs) 705 } 706 if r.Rev != 4 { 707 t.Errorf("rev = %d, want %d", r.Rev, 4) 708 } 709 } 710 711 func TestWatchableKVWatch(t *testing.T) { 712 b, tmpPath := backend.NewDefaultTmpBackend() 713 s := WatchableKV(newWatchableStore(b, &lease.FakeLessor{}, nil, nil)) 714 defer cleanup(s, b, tmpPath) 715 716 w := s.NewWatchStream() 717 defer w.Close() 718 719 wid := w.Watch([]byte("foo"), []byte("fop"), 0) 720 721 wev := []mvccpb.Event{ 722 {Type: mvccpb.PUT, 723 Kv: &mvccpb.KeyValue{ 724 Key: []byte("foo"), 725 Value: []byte("bar"), 726 CreateRevision: 2, 727 ModRevision: 2, 728 Version: 1, 729 Lease: 1, 730 }, 731 }, 732 { 733 Type: mvccpb.PUT, 734 Kv: &mvccpb.KeyValue{ 735 Key: []byte("foo1"), 736 Value: []byte("bar1"), 737 CreateRevision: 3, 738 ModRevision: 3, 739 Version: 1, 740 Lease: 2, 741 }, 742 }, 743 { 744 Type: mvccpb.PUT, 745 Kv: &mvccpb.KeyValue{ 746 Key: []byte("foo1"), 747 Value: []byte("bar11"), 748 CreateRevision: 3, 749 ModRevision: 4, 750 Version: 2, 751 Lease: 3, 752 }, 753 }, 754 } 755 756 s.Put([]byte("foo"), []byte("bar"), 1) 757 select { 758 case resp := <-w.Chan(): 759 if resp.WatchID != wid { 760 t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) 761 } 762 ev := resp.Events[0] 763 if !reflect.DeepEqual(ev, wev[0]) { 764 t.Errorf("watched event = %+v, want %+v", ev, wev[0]) 765 } 766 case <-time.After(5 * time.Second): 767 // CPU might be too slow, and the routine is not able to switch around 768 testutil.FatalStack(t, "failed to watch the event") 769 } 770 771 s.Put([]byte("foo1"), []byte("bar1"), 2) 772 select { 773 case resp := <-w.Chan(): 774 if resp.WatchID != wid { 775 t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) 776 } 777 ev := resp.Events[0] 778 if !reflect.DeepEqual(ev, wev[1]) { 779 t.Errorf("watched event = %+v, want %+v", ev, wev[1]) 780 } 781 case <-time.After(5 * time.Second): 782 testutil.FatalStack(t, "failed to watch the event") 783 } 784 785 w = s.NewWatchStream() 786 wid = w.Watch([]byte("foo1"), []byte("foo2"), 3) 787 788 select { 789 case resp := <-w.Chan(): 790 if resp.WatchID != wid { 791 t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) 792 } 793 ev := resp.Events[0] 794 if !reflect.DeepEqual(ev, wev[1]) { 795 t.Errorf("watched event = %+v, want %+v", ev, wev[1]) 796 } 797 case <-time.After(5 * time.Second): 798 testutil.FatalStack(t, "failed to watch the event") 799 } 800 801 s.Put([]byte("foo1"), []byte("bar11"), 3) 802 select { 803 case resp := <-w.Chan(): 804 if resp.WatchID != wid { 805 t.Errorf("resp.WatchID got = %d, want = %d", resp.WatchID, wid) 806 } 807 ev := resp.Events[0] 808 if !reflect.DeepEqual(ev, wev[2]) { 809 t.Errorf("watched event = %+v, want %+v", ev, wev[2]) 810 } 811 case <-time.After(5 * time.Second): 812 testutil.FatalStack(t, "failed to watch the event") 813 } 814 } 815 816 func cleanup(s KV, b backend.Backend, path string) { 817 s.Close() 818 b.Close() 819 os.Remove(path) 820 } 821 822 func put3TestKVs(s KV) []mvccpb.KeyValue { 823 s.Put([]byte("foo"), []byte("bar"), 1) 824 s.Put([]byte("foo1"), []byte("bar1"), 2) 825 s.Put([]byte("foo2"), []byte("bar2"), 3) 826 return []mvccpb.KeyValue{ 827 {Key: []byte("foo"), Value: []byte("bar"), CreateRevision: 2, ModRevision: 2, Version: 1, Lease: 1}, 828 {Key: []byte("foo1"), Value: []byte("bar1"), CreateRevision: 3, ModRevision: 3, Version: 1, Lease: 2}, 829 {Key: []byte("foo2"), Value: []byte("bar2"), CreateRevision: 4, ModRevision: 4, Version: 1, Lease: 3}, 830 } 831 }