github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/roachpb/data_test.go (about) 1 // Copyright 2014 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package roachpb 12 13 import ( 14 "bytes" 15 "math" 16 "math/rand" 17 "reflect" 18 "sort" 19 "strconv" 20 "testing" 21 "time" 22 23 "github.com/cockroachdb/apd" 24 "github.com/cockroachdb/cockroach/pkg/storage/enginepb" 25 "github.com/cockroachdb/cockroach/pkg/testutils/zerofields" 26 "github.com/cockroachdb/cockroach/pkg/util" 27 "github.com/cockroachdb/cockroach/pkg/util/bitarray" 28 "github.com/cockroachdb/cockroach/pkg/util/duration" 29 "github.com/cockroachdb/cockroach/pkg/util/encoding" 30 "github.com/cockroachdb/cockroach/pkg/util/hlc" 31 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 32 "github.com/cockroachdb/cockroach/pkg/util/log" 33 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 34 "github.com/cockroachdb/cockroach/pkg/util/randutil" 35 "github.com/cockroachdb/cockroach/pkg/util/uuid" 36 "github.com/kr/pretty" 37 "github.com/stretchr/testify/require" 38 "go.etcd.io/etcd/raft/raftpb" 39 ) 40 41 func makeTS(walltime int64, logical int32) hlc.Timestamp { 42 return hlc.Timestamp{ 43 WallTime: walltime, 44 Logical: logical, 45 } 46 } 47 48 // TestKeyNext tests that the method for creating lexicographic 49 // successors to byte slices works as expected. 50 func TestKeyNext(t *testing.T) { 51 a := Key("a") 52 aNext := a.Next() 53 if a.Equal(aNext) { 54 t.Errorf("expected key not equal to next") 55 } 56 if bytes.Compare(a, aNext) >= 0 { 57 t.Errorf("expected next key to be greater") 58 } 59 60 extraCap := make([]byte, 2, 4) 61 extraCap[0] = 'x' 62 extraCap[1] = 'o' 63 64 noExtraCap := make([]byte, 2) 65 noExtraCap[0] = 'x' 66 noExtraCap[1] = 'o' 67 68 testCases := []struct { 69 key Key 70 next Key 71 expReallocate int // 0 for don't test, -1 for not expected, 1 for expected. 72 }{ 73 {nil, Key("\x00"), 0}, 74 {Key(""), Key("\x00"), 0}, 75 {Key("test key"), Key("test key\x00"), 0}, 76 {Key("\xff"), Key("\xff\x00"), 0}, 77 {Key("xoxo\x00"), Key("xoxo\x00\x00"), 0}, 78 {Key(extraCap), Key("xo\x00"), -1}, 79 {Key(noExtraCap), Key("xo\x00"), 1}, 80 } 81 for i, c := range testCases { 82 next := c.key.Next() 83 if !bytes.Equal(next, c.next) { 84 t.Errorf("%d: unexpected next bytes for %q: %q", i, c.key, next) 85 } 86 if c.expReallocate != 0 { 87 if expect, reallocated := c.expReallocate > 0, (&next[0] != &c.key[0]); expect != reallocated { 88 t.Errorf("%d: unexpected next reallocation = %t, found reallocation = %t", i, expect, reallocated) 89 } 90 } 91 } 92 } 93 94 func TestKeyPrefixEnd(t *testing.T) { 95 a := Key("a1") 96 aNext := a.Next() 97 aEnd := a.PrefixEnd() 98 if bytes.Compare(a, aEnd) >= 0 { 99 t.Errorf("expected end key to be greater") 100 } 101 if bytes.Compare(aNext, aEnd) >= 0 { 102 t.Errorf("expected end key to be greater than next") 103 } 104 105 testCases := []struct { 106 key Key 107 end Key 108 }{ 109 {Key{}, KeyMax}, 110 {Key{0}, Key{0x01}}, 111 {Key{0xff}, Key{0xff}}, 112 {Key{0xff, 0xff}, Key{0xff, 0xff}}, 113 {KeyMax, KeyMax}, 114 {Key{0xff, 0xfe}, Key{0xff, 0xff}}, 115 {Key{0x00, 0x00}, Key{0x00, 0x01}}, 116 {Key{0x00, 0xff}, Key{0x01}}, 117 {Key{0x00, 0xff, 0xff}, Key{0x01}}, 118 } 119 for i, c := range testCases { 120 if !bytes.Equal(c.key.PrefixEnd(), c.end) { 121 t.Errorf("%d: unexpected prefix end bytes for %q: %q", i, c.key, c.key.PrefixEnd()) 122 } 123 } 124 } 125 126 func TestKeyEqual(t *testing.T) { 127 a1 := Key("a1") 128 a2 := Key("a2") 129 if !a1.Equal(a1) { 130 t.Errorf("expected keys equal") 131 } 132 if a1.Equal(a2) { 133 t.Errorf("expected different keys not equal") 134 } 135 } 136 137 func TestKeyLess(t *testing.T) { 138 testCases := []struct { 139 a, b Key 140 less bool 141 }{ 142 {nil, Key("\x00"), true}, 143 {Key(""), Key("\x00"), true}, 144 {Key("a"), Key("b"), true}, 145 {Key("a\x00"), Key("a"), false}, 146 {Key("a\x00"), Key("a\x01"), true}, 147 } 148 for i, c := range testCases { 149 if (bytes.Compare(c.a, c.b) < 0) != c.less { 150 t.Fatalf("%d: unexpected %q < %q: %t", i, c.a, c.b, c.less) 151 } 152 } 153 } 154 155 func TestKeyCompare(t *testing.T) { 156 testCases := []struct { 157 a, b Key 158 compare int 159 }{ 160 {nil, nil, 0}, 161 {nil, Key("\x00"), -1}, 162 {Key("\x00"), Key("\x00"), 0}, 163 {Key(""), Key("\x00"), -1}, 164 {Key("a"), Key("b"), -1}, 165 {Key("a\x00"), Key("a"), 1}, 166 {Key("a\x00"), Key("a\x01"), -1}, 167 } 168 for i, c := range testCases { 169 if c.a.Compare(c.b) != c.compare { 170 t.Fatalf("%d: unexpected %q.Compare(%q): %d", i, c.a, c.b, c.compare) 171 } 172 } 173 } 174 175 // TestNextKey tests that the method for creating successors of a Key 176 // works as expected. 177 func TestNextKey(t *testing.T) { 178 testCases := []struct { 179 key Key 180 next Key 181 }{ 182 {nil, Key("\x00")}, 183 {Key(""), Key("\x00")}, 184 {Key("test key"), Key("test key\x00")}, 185 {Key("\xff\xff"), Key("\xff\xff\x00")}, 186 {Key("xoxo\x00"), Key("xoxo\x00\x00")}, 187 } 188 for i, c := range testCases { 189 if !c.key.Next().Equal(c.next) { 190 t.Fatalf("%d: unexpected next key for %q: %s", i, c.key, c.key.Next()) 191 } 192 } 193 } 194 195 func TestIsPrev(t *testing.T) { 196 for i, tc := range []struct { 197 k, m Key 198 ok bool 199 }{ 200 {k: Key(""), m: Key{0}, ok: true}, 201 {k: nil, m: nil, ok: false}, 202 {k: Key("a"), m: Key{'a', 0, 0}, ok: false}, 203 {k: Key{'z', 'a', 0}, m: Key{'z', 'a'}, ok: false}, 204 {k: Key("bro"), m: Key{'b', 'r', 'o', 0}, ok: true}, 205 {k: Key("foo"), m: Key{'b', 'a', 'r', 0}, ok: false}, 206 } { 207 if tc.ok != tc.k.IsPrev(tc.m) { 208 t.Errorf("%d: wanted %t", i, tc.ok) 209 } 210 } 211 } 212 213 func TestValueDataEquals(t *testing.T) { 214 strVal := func(s string) *Value { 215 var v Value 216 v.SetString(s) 217 return &v 218 } 219 220 a := strVal("val1") 221 222 b := strVal("val1") 223 b.InitChecksum([]byte("key1")) 224 225 c := strVal("val1") 226 c.InitChecksum([]byte("key2")) 227 228 // Different values. 229 d := strVal("val2") 230 231 e := strVal("val2") 232 e.InitChecksum([]byte("key1")) 233 234 // Different tags. 235 f := strVal("val1") 236 f.setTag(ValueType_INT) 237 238 g := strVal("val1") 239 g.setTag(ValueType_INT) 240 g.InitChecksum([]byte("key1")) 241 242 for i, tc := range []struct { 243 v1, v2 *Value 244 eq bool 245 }{ 246 {v1: a, v2: b, eq: true}, 247 {v1: a, v2: c, eq: true}, 248 {v1: a, v2: d, eq: false}, 249 {v1: a, v2: e, eq: false}, 250 {v1: a, v2: f, eq: false}, 251 {v1: a, v2: g, eq: false}, 252 {v1: b, v2: c, eq: true}, 253 {v1: b, v2: d, eq: false}, 254 {v1: b, v2: e, eq: false}, 255 {v1: b, v2: f, eq: false}, 256 {v1: b, v2: g, eq: false}, 257 {v1: c, v2: d, eq: false}, 258 {v1: c, v2: e, eq: false}, 259 {v1: c, v2: f, eq: false}, 260 {v1: c, v2: g, eq: false}, 261 {v1: d, v2: e, eq: true}, 262 {v1: d, v2: f, eq: false}, 263 {v1: d, v2: g, eq: false}, 264 {v1: e, v2: f, eq: false}, 265 {v1: e, v2: g, eq: false}, 266 {v1: f, v2: g, eq: true}, 267 } { 268 if tc.eq != tc.v1.EqualData(*tc.v2) { 269 t.Errorf("%d: wanted eq=%t", i, tc.eq) 270 } 271 // Test symmetry. 272 if tc.eq != tc.v2.EqualData(*tc.v1) { 273 t.Errorf("%d: wanted eq=%t", i, tc.eq) 274 } 275 } 276 } 277 278 func TestValueChecksumEmpty(t *testing.T) { 279 k := []byte("key") 280 v := Value{} 281 // Before initializing checksum, always works. 282 if err := v.Verify(k); err != nil { 283 t.Error(err) 284 } 285 if err := v.Verify([]byte("key2")); err != nil { 286 t.Error(err) 287 } 288 v.InitChecksum(k) 289 if err := v.Verify(k); err != nil { 290 t.Error(err) 291 } 292 } 293 294 func TestValueChecksumWithBytes(t *testing.T) { 295 k := []byte("key") 296 v := MakeValueFromString("abc") 297 v.InitChecksum(k) 298 if err := v.Verify(k); err != nil { 299 t.Error(err) 300 } 301 // Try a different key; should fail. 302 if err := v.Verify([]byte("key2")); err == nil { 303 t.Error("expected checksum verification failure on different key") 304 } 305 // Mess with the value. In order to corrupt the data for testing purposes we 306 // have to ensure we overwrite the data without touching the checksum. 307 copy(v.RawBytes[headerSize:], "cba") 308 if err := v.Verify(k); err == nil { 309 t.Error("expected checksum verification failure on different value") 310 } 311 // Test ClearChecksum and reinitialization of checksum. 312 v.ClearChecksum() 313 v.InitChecksum(k) 314 if err := v.Verify(k); err != nil { 315 t.Error(err) 316 } 317 } 318 319 func TestSetGetChecked(t *testing.T) { 320 v := Value{} 321 322 v.SetBytes(nil) 323 if _, err := v.GetBytes(); err != nil { 324 t.Fatal(err) 325 } 326 327 f := 1.1 328 v.SetFloat(f) 329 if r, err := v.GetFloat(); err != nil { 330 t.Fatal(err) 331 } else if f != r { 332 t.Errorf("set %f on a value and extracted it, expected %f back, but got %f", f, f, r) 333 } 334 335 b := true 336 v.SetBool(b) 337 if r, err := v.GetBool(); err != nil { 338 t.Fatal(err) 339 } else if b != r { 340 t.Errorf("set %t on a value and extracted it, expected %t back, but got %t", b, b, r) 341 } 342 343 i := int64(1) 344 v.SetInt(i) 345 if r, err := v.GetInt(); err != nil { 346 t.Fatal(err) 347 } else if i != r { 348 t.Errorf("set %d on a value and extracted it, expected %d back, but got %d", i, i, r) 349 } 350 351 dec := apd.New(11, -1) 352 if err := v.SetDecimal(dec); err != nil { 353 t.Fatal(err) 354 } 355 if r, err := v.GetDecimal(); err != nil { 356 t.Fatal(err) 357 } else if dec.Cmp(&r) != 0 { 358 t.Errorf("set %s on a value and extracted it, expected %s back, but got %s", dec, dec, &r) 359 } 360 361 if err := v.SetProto(&Value{}); err != nil { 362 t.Fatal(err) 363 } 364 if err := v.GetProto(&Value{}); err != nil { 365 t.Fatal(err) 366 } 367 if _, err := v.GetBytes(); err != nil { 368 t.Fatal(err) 369 } 370 371 if err := v.SetProto(&InternalTimeSeriesData{}); err != nil { 372 t.Fatal(err) 373 } 374 if _, err := v.GetTimeseries(); err != nil { 375 t.Fatal(err) 376 } 377 378 ti := time.Time{} 379 v.SetTime(ti) 380 if r, err := v.GetTime(); err != nil { 381 t.Fatal(err) 382 } else if !ti.Equal(r) { 383 t.Errorf("set %s on a value and extracted it, expected %s back, but got %s", ti, ti, r) 384 } 385 } 386 387 func TestTransactionBumpEpoch(t *testing.T) { 388 origNow := makeTS(10, 1) 389 txn := MakeTransaction("test", Key("a"), 1, origNow, 0) 390 // Advance the txn timestamp. 391 txn.WriteTimestamp = txn.WriteTimestamp.Add(10, 2) 392 txn.BumpEpoch() 393 if a, e := txn.Epoch, enginepb.TxnEpoch(1); a != e { 394 t.Errorf("expected epoch %d; got %d", e, a) 395 } 396 } 397 398 // TestTransactionObservedTimestamp verifies that txn.{Get,Update}ObservedTimestamp work as 399 // advertised. 400 func TestTransactionObservedTimestamp(t *testing.T) { 401 var txn Transaction 402 rng, seed := randutil.NewPseudoRand() 403 t.Logf("running with seed %d", seed) 404 ids := append([]int{109, 104, 102, 108, 1000}, rand.Perm(100)...) 405 timestamps := make(map[NodeID]hlc.Timestamp, len(ids)) 406 for i := 0; i < len(ids); i++ { 407 timestamps[NodeID(i)] = hlc.Timestamp{WallTime: rng.Int63()} 408 } 409 for i, n := range ids { 410 nodeID := NodeID(n) 411 if ts, ok := txn.GetObservedTimestamp(nodeID); ok { 412 t.Fatalf("%d: false positive hit %s in %v", nodeID, ts, ids[:i+1]) 413 } 414 txn.UpdateObservedTimestamp(nodeID, timestamps[nodeID]) 415 txn.UpdateObservedTimestamp(nodeID, hlc.MaxTimestamp) // should be noop 416 if exp, act := i+1, len(txn.ObservedTimestamps); act != exp { 417 t.Fatalf("%d: expected %d entries, got %d: %v", nodeID, exp, act, txn.ObservedTimestamps) 418 } 419 } 420 for _, m := range ids { 421 checkID := NodeID(m) 422 expTS := timestamps[checkID] 423 if actTS, _ := txn.GetObservedTimestamp(checkID); actTS != expTS { 424 t.Fatalf("%d: expected %s, got %s", checkID, expTS, actTS) 425 } 426 } 427 428 var emptyTxn Transaction 429 ts := hlc.Timestamp{WallTime: 1, Logical: 2} 430 emptyTxn.UpdateObservedTimestamp(NodeID(1), ts) 431 if actTS, _ := emptyTxn.GetObservedTimestamp(NodeID(1)); actTS != ts { 432 t.Fatalf("unexpected: %s (wanted %s)", actTS, ts) 433 } 434 } 435 436 func TestFastPathObservedTimestamp(t *testing.T) { 437 var txn Transaction 438 nodeID := NodeID(1) 439 if _, ok := txn.GetObservedTimestamp(nodeID); ok { 440 t.Errorf("fetched observed timestamp where none should exist") 441 } 442 expTS := hlc.Timestamp{WallTime: 10} 443 txn.UpdateObservedTimestamp(nodeID, expTS) 444 if ts, ok := txn.GetObservedTimestamp(nodeID); !ok || !ts.Equal(expTS) { 445 t.Errorf("expected %s; got %s", expTS, ts) 446 } 447 expTS = hlc.Timestamp{WallTime: 9} 448 txn.UpdateObservedTimestamp(nodeID, expTS) 449 if ts, ok := txn.GetObservedTimestamp(nodeID); !ok || !ts.Equal(expTS) { 450 t.Errorf("expected %s; got %s", expTS, ts) 451 } 452 } 453 454 var nonZeroTxn = Transaction{ 455 TxnMeta: enginepb.TxnMeta{ 456 Key: Key("foo"), 457 ID: uuid.MakeV4(), 458 Epoch: 2, 459 WriteTimestamp: makeTS(20, 21), 460 MinTimestamp: makeTS(10, 11), 461 Priority: 957356782, 462 Sequence: 123, 463 }, 464 Name: "name", 465 Status: COMMITTED, 466 LastHeartbeat: makeTS(1, 2), 467 DeprecatedOrigTimestamp: makeTS(30, 31), 468 ReadTimestamp: makeTS(20, 22), 469 MaxTimestamp: makeTS(40, 41), 470 ObservedTimestamps: []ObservedTimestamp{{NodeID: 1, Timestamp: makeTS(1, 2)}}, 471 WriteTooOld: true, 472 LockSpans: []Span{{Key: []byte("a"), EndKey: []byte("b")}}, 473 InFlightWrites: []SequencedWrite{{Key: []byte("c"), Sequence: 1}}, 474 CommitTimestampFixed: true, 475 IgnoredSeqNums: []enginepb.IgnoredSeqNumRange{{Start: 888, End: 999}}, 476 } 477 478 func TestTransactionUpdate(t *testing.T) { 479 txn := nonZeroTxn 480 if err := zerofields.NoZeroField(txn); err != nil { 481 t.Fatal(err) 482 } 483 484 // Updating an empty Transaction copies all fields. 485 var txn2 Transaction 486 txn2.Update(&txn) 487 488 expTxn2 := txn 489 require.Equal(t, expTxn2, txn2) 490 491 // Updating a Transaction at an earlier epoch replaces all epoch-scoped fields. 492 var txn3 Transaction 493 txn3.ID = txn.ID 494 txn3.Epoch = txn.Epoch - 1 495 txn3.Status = STAGING 496 txn3.Name = "carl" 497 txn3.Priority = 123 498 txn3.Update(&txn) 499 500 expTxn3 := txn 501 expTxn3.Name = "carl" 502 require.Equal(t, expTxn3, txn3) 503 504 // Updating a Transaction at the same epoch forwards all epoch-scoped fields. 505 var txn4 Transaction 506 txn4.ID = txn.ID 507 txn4.Epoch = txn.Epoch 508 txn4.Status = STAGING 509 txn4.Sequence = txn.Sequence + 10 510 txn4.Name = "carl" 511 txn4.Priority = 123 512 txn4.Update(&txn) 513 514 expTxn4 := txn 515 expTxn4.Name = "carl" 516 expTxn4.Sequence = txn.Sequence + 10 517 require.Equal(t, expTxn4, txn4) 518 519 // Test the updates to the WriteTooOld field. The WriteTooOld field is 520 // supposed to be dictated by the transaction with the higher ReadTimestamp, 521 // or it's cumulative when the ReadTimestamps are equal. 522 { 523 txn2 := txn 524 txn2.ReadTimestamp = txn2.ReadTimestamp.Add(-1, 0) 525 txn2.WriteTooOld = false 526 txn2.Update(&txn) 527 require.True(t, txn2.WriteTooOld) 528 } 529 { 530 txn2 := txn 531 txn2.WriteTooOld = false 532 txn2.Update(&txn) 533 require.True(t, txn2.WriteTooOld) 534 } 535 { 536 txn2 := txn 537 txn2.ReadTimestamp = txn2.ReadTimestamp.Add(1, 0) 538 txn2.WriteTooOld = false 539 txn2.Update(&txn) 540 require.False(t, txn2.WriteTooOld) 541 } 542 543 // Updating a Transaction at a future epoch ignores all epoch-scoped fields. 544 var txn5 Transaction 545 txn5.ID = txn.ID 546 txn5.Epoch = txn.Epoch + 1 547 txn5.Status = PENDING 548 txn5.Sequence = txn.Sequence - 10 549 txn5.Name = "carl" 550 txn5.Priority = 123 551 txn5.Update(&txn) 552 553 expTxn5 := txn 554 expTxn5.Name = "carl" 555 expTxn5.Epoch = txn.Epoch + 1 556 expTxn5.Status = PENDING 557 expTxn5.Sequence = txn.Sequence - 10 558 expTxn5.LockSpans = nil 559 expTxn5.InFlightWrites = nil 560 expTxn5.IgnoredSeqNums = nil 561 expTxn5.WriteTooOld = false 562 expTxn5.CommitTimestampFixed = false 563 require.Equal(t, expTxn5, txn5) 564 565 // Updating a different transaction fatals. 566 var exited bool 567 log.SetExitFunc(true /* hideStack */, func(int) { exited = true }) 568 defer log.ResetExitFunc() 569 570 var txn6 Transaction 571 txn6.ID = uuid.MakeV4() 572 origTxn6 := txn6 573 txn6.Update(&txn) 574 575 require.Equal(t, origTxn6, txn6) 576 require.True(t, exited) 577 } 578 579 func TestTransactionUpdateMinTimestamp(t *testing.T) { 580 txn := nonZeroTxn 581 var txn2 Transaction 582 txn2.Update(&txn) 583 584 if a, e := txn2.MinTimestamp, txn.MinTimestamp; a != e { 585 t.Errorf("expected min timestamp %s; got %s", e, a) 586 } 587 588 txn3 := nonZeroTxn 589 txn3.MinTimestamp = nonZeroTxn.MinTimestamp.Prev() 590 txn.Update(&txn3) 591 592 if a, e := txn.MinTimestamp, txn3.MinTimestamp; a != e { 593 t.Errorf("expected min timestamp %s; got %s", e, a) 594 } 595 } 596 597 func TestTransactionUpdateStaging(t *testing.T) { 598 txn := nonZeroTxn 599 txn.Status = PENDING 600 601 txn2 := nonZeroTxn 602 txn2.Status = STAGING 603 604 // In same epoch, PENDING < STAGING. 605 txn.Update(&txn2) 606 if a, e := txn.Status, STAGING; a != e { 607 t.Errorf("expected status %s; got %s", e, a) 608 } 609 610 txn2.Status = PENDING 611 txn.Update(&txn2) 612 if a, e := txn.Status, STAGING; a != e { 613 t.Errorf("expected status %s; got %s", e, a) 614 } 615 616 // In later epoch, PENDING > STAGING. 617 txn2.Epoch++ 618 txn.Update(&txn2) 619 if a, e := txn.Status, PENDING; a != e { 620 t.Errorf("expected status %s; got %s", e, a) 621 } 622 623 txn2.Status = STAGING 624 txn.Update(&txn2) 625 if a, e := txn.Status, STAGING; a != e { 626 t.Errorf("expected status %s; got %s", e, a) 627 } 628 629 txn2.Status = COMMITTED 630 txn.Update(&txn2) 631 if a, e := txn.Status, COMMITTED; a != e { 632 t.Errorf("expected status %s; got %s", e, a) 633 } 634 } 635 636 // TestTransactionUpdateAbortedOldEpoch tests that Transaction.Update propagates 637 // an ABORTED status even when that status comes from a proto with an old epoch. 638 // Once a transaction is ABORTED, it will stay aborted, even if its coordinator 639 // doesn't know this at the time that it increments its epoch and retries. 640 func TestTransactionUpdateAbortedOldEpoch(t *testing.T) { 641 txn := nonZeroTxn 642 txn.Status = ABORTED 643 644 txnRestart := txn 645 txnRestart.Epoch++ 646 txnRestart.Status = PENDING 647 txnRestart.Update(&txn) 648 649 expTxn := txn 650 expTxn.Epoch++ 651 expTxn.Status = ABORTED 652 require.Equal(t, expTxn, txnRestart) 653 } 654 655 func TestTransactionClone(t *testing.T) { 656 txnPtr := nonZeroTxn.Clone() 657 txn := *txnPtr 658 659 fields := util.EqualPtrFields(reflect.ValueOf(nonZeroTxn), reflect.ValueOf(txn), "") 660 sort.Strings(fields) 661 662 // Verify that the only equal pointer fields after cloning are the ones 663 // listed below. If this test fails, please update the list below and/or 664 // Transaction.Clone(). 665 expFields := []string{ 666 "IgnoredSeqNums", 667 "InFlightWrites", 668 "InFlightWrites.Key", 669 "LockSpans", 670 "LockSpans.EndKey", 671 "LockSpans.Key", 672 "ObservedTimestamps", 673 "TxnMeta.Key", 674 } 675 if !reflect.DeepEqual(expFields, fields) { 676 t.Fatalf("%s != %s", expFields, fields) 677 } 678 if !reflect.DeepEqual(nonZeroTxn, txn) { 679 t.Fatalf("e = %v, v = %v", nonZeroTxn, txn) 680 } 681 } 682 683 func TestTransactionRestart(t *testing.T) { 684 txn := nonZeroTxn 685 txn.Restart(1, 1, makeTS(25, 1)) 686 687 expTxn := nonZeroTxn 688 expTxn.Epoch++ 689 expTxn.Sequence = 0 690 expTxn.WriteTimestamp = makeTS(25, 1) 691 expTxn.ReadTimestamp = makeTS(25, 1) 692 expTxn.DeprecatedOrigTimestamp = expTxn.ReadTimestamp 693 expTxn.WriteTooOld = false 694 expTxn.CommitTimestampFixed = false 695 expTxn.LockSpans = nil 696 expTxn.InFlightWrites = nil 697 expTxn.IgnoredSeqNums = nil 698 require.Equal(t, expTxn, txn) 699 } 700 701 // TestTransactionRecordRoundtrips tests a few properties about Transaction 702 // and TransactionRecord protos. Remember that the latter is wire compatible 703 // with the former and contains a subset of its protos. 704 // 705 // Assertions: 706 // 1. Transaction->TransactionRecord->Transaction is lossless for the fields 707 // in TransactionRecord. It drops all other fields. 708 // 2. TransactionRecord->Transaction->TransactionRecord is lossless. 709 // Fields not in TransactionRecord are set as zero values. 710 // 3. Transaction messages can be decoded as TransactionRecord messages. 711 // Fields not in TransactionRecord are dropped. 712 // 4. TransactionRecord messages can be decoded as Transaction messages. 713 // Fields not in TransactionRecord are decoded as zero values. 714 func TestTransactionRecordRoundtrips(t *testing.T) { 715 // Verify that converting from a Transaction to a TransactionRecord 716 // strips out fields but is lossless for the desired fields. 717 txn := nonZeroTxn 718 txnRecord := txn.AsRecord() 719 if err := zerofields.NoZeroField(txnRecord); err != nil { 720 t.Error(err) 721 } 722 if !reflect.DeepEqual(txnRecord.TxnMeta, txn.TxnMeta) { 723 t.Errorf("txnRecord.TxnMeta = %v, txn.TxnMeta = %v", txnRecord.TxnMeta, txn.TxnMeta) 724 } 725 if !reflect.DeepEqual(txnRecord.Status, txn.Status) { 726 t.Errorf("txnRecord.Status = %v, txn.Status = %v", txnRecord.Status, txn.Status) 727 } 728 if !reflect.DeepEqual(txnRecord.LastHeartbeat, txn.LastHeartbeat) { 729 t.Errorf("txnRecord.LastHeartbeat = %v, txn.LastHeartbeat = %v", txnRecord.LastHeartbeat, txn.LastHeartbeat) 730 } 731 if !reflect.DeepEqual(txnRecord.LockSpans, txn.LockSpans) { 732 t.Errorf("txnRecord.LockSpans = %v, txn.LockSpans = %v", txnRecord.LockSpans, txn.LockSpans) 733 } 734 if !reflect.DeepEqual(txnRecord.InFlightWrites, txn.InFlightWrites) { 735 t.Errorf("txnRecord.InFlightWrites = %v, txn.InFlightWrites = %v", txnRecord.InFlightWrites, txn.InFlightWrites) 736 } 737 if !reflect.DeepEqual(txnRecord.IgnoredSeqNums, txn.IgnoredSeqNums) { 738 t.Errorf("txnRecord.IgnoredSeqNums = %v, txn.IgnoredSeqNums = %v", txnRecord.IgnoredSeqNums, txn.IgnoredSeqNums) 739 } 740 741 // Verify that converting through a Transaction message and back 742 // to a TransactionRecord is a lossless round trip. 743 txn2 := txnRecord.AsTransaction() 744 txnRecord2 := txn2.AsRecord() 745 if !reflect.DeepEqual(txnRecord, txnRecord2) { 746 t.Errorf("txnRecord = %v, txnRecord2 = %v", txnRecord, txnRecord2) 747 } 748 749 // Verify that encoded Transaction messages can be decoded as 750 // TransactionRecord messages. 751 txnBytes, err := protoutil.Marshal(&txn) 752 if err != nil { 753 t.Fatal(err) 754 } 755 var txnRecord3 TransactionRecord 756 if err := protoutil.Unmarshal(txnBytes, &txnRecord3); err != nil { 757 t.Fatal(err) 758 } 759 if !reflect.DeepEqual(txnRecord, txnRecord3) { 760 t.Errorf("txnRecord = %v, txnRecord3 = %v", txnRecord, txnRecord3) 761 } 762 763 // Verify that encoded TransactionRecord messages can be decoded 764 // as Transaction messages. 765 txnRecordBytes, err := protoutil.Marshal(&txnRecord) 766 if err != nil { 767 t.Fatal(err) 768 } 769 var txn3 Transaction 770 if err := protoutil.Unmarshal(txnRecordBytes, &txn3); err != nil { 771 t.Fatal(err) 772 } 773 if !reflect.DeepEqual(txn2, txn3) { 774 t.Errorf("txn2 = %v, txn3 = %v", txn2, txn3) 775 } 776 } 777 778 // checkVal verifies if a value is close to an expected value, within a fraction (e.g. if 779 // fraction=0.1, it checks if val is within 10% of expected). 780 func checkVal(val, expected, errFraction float64) bool { 781 return val > expected*(1-errFraction) && val < expected*(1+errFraction) 782 } 783 784 // TestMakePriority verifies that setting user priority of P results 785 // in MakePriority returning priorities that are P times more likely 786 // to be higher than a priority with user priority = 1. 787 func TestMakePriority(t *testing.T) { 788 // Verify min & max. 789 if a, e := MakePriority(MinUserPriority), enginepb.MinTxnPriority; a != e { 790 t.Errorf("expected min txn priority %d; got %d", e, a) 791 } 792 if a, e := MakePriority(MaxUserPriority), enginepb.MaxTxnPriority; a != e { 793 t.Errorf("expected max txn priority %d; got %d", e, a) 794 } 795 796 userPs := []UserPriority{ 797 0.0011, 798 0.01, 799 0.1, 800 0.5, 801 0, // Same as 1.0 (special cased below) 802 1.0, 803 2.0, 804 10.0, 805 100.0, 806 999.0, 807 } 808 809 // Generate values for all priorities. 810 const trials = 100000 811 values := make([][trials]enginepb.TxnPriority, len(userPs)) 812 for i, userPri := range userPs { 813 for tr := 0; tr < trials; tr++ { 814 p := MakePriority(userPri) 815 if p == enginepb.MinTxnPriority { 816 t.Fatalf("unexpected min txn priority") 817 } 818 if p == enginepb.MaxTxnPriority { 819 t.Fatalf("unexpected max txn priority") 820 } 821 values[i][tr] = p 822 } 823 } 824 825 // Check win-vs-loss ratios for all pairs 826 for i, p1 := range userPs { 827 for j, p2 := range userPs { 828 if i >= j { 829 continue 830 } 831 832 // Special case to verify that specifying 0 has same effect as specifying 1. 833 if p1 == 0 { 834 p1 = 1 835 } 836 if p2 == 0 { 837 p2 = 1 838 } 839 priRatio := float64(p1 / p2) 840 841 // Don't verify extreme ratios (we don't have enough resolution or trials) 842 if math.Max(priRatio, 1/priRatio) >= 1000 { 843 continue 844 } 845 wins := 0 846 for t := 0; t < trials; t++ { 847 if values[i][t] > values[j][t] { 848 wins++ 849 } 850 } 851 852 winRatio := float64(wins) / float64(trials-wins) 853 854 t.Logf("%f vs %f: %d wins, %d losses (winRatio=%f, priRatio=%f)", 855 p1, p2, wins, trials-wins, winRatio, priRatio) 856 if !checkVal(winRatio, priRatio, 0.2) { 857 t.Errorf("Error (%f vs %f: %d wins, %d losses): winRatio=%f not "+ 858 "close to priRatio=%f", p1, p2, wins, trials-wins, winRatio, priRatio) 859 } 860 } 861 } 862 } 863 864 // TestMakePriorityExplicit verifies that setting priority to a negative 865 // value sets it exactly. 866 func TestMakePriorityExplicit(t *testing.T) { 867 explicitPs := []struct { 868 userPri UserPriority 869 expPri enginepb.TxnPriority 870 }{ 871 {-math.MaxInt32, math.MaxInt32}, 872 {-math.MaxInt32 + 1, math.MaxInt32 - 1}, 873 {-2, 2}, 874 {-1, 1}, 875 } 876 for i, p := range explicitPs { 877 if pri := MakePriority(p.userPri); pri != p.expPri { 878 t.Errorf("%d: explicit priority %d doesn't match expected %d", i, pri, p.expPri) 879 } 880 } 881 } 882 883 // TestMakePriorityLimits verifies that min & max priorities are 884 // enforced and yield txn priority limits. 885 func TestMakePriorityLimits(t *testing.T) { 886 userPs := []UserPriority{ 887 0.000000001, 888 0.00001, 889 0.00009, 890 10001, 891 100000, 892 math.MaxFloat64, 893 } 894 for _, userPri := range userPs { 895 expected := enginepb.MinTxnPriority 896 if userPri > 1 { 897 expected = enginepb.MaxTxnPriority 898 } 899 if actual := MakePriority(userPri); actual != expected { 900 t.Errorf("%f: expected txn priority %d; got %d", userPri, expected, actual) 901 } 902 } 903 } 904 905 func TestLeaseEquivalence(t *testing.T) { 906 r1 := ReplicaDescriptor{NodeID: 1, StoreID: 1, ReplicaID: 1} 907 r2 := ReplicaDescriptor{NodeID: 2, StoreID: 2, ReplicaID: 2} 908 ts1 := makeTS(1, 1) 909 ts2 := makeTS(2, 1) 910 ts3 := makeTS(3, 1) 911 912 epoch1 := Lease{Replica: r1, Start: ts1, Epoch: 1} 913 epoch2 := Lease{Replica: r1, Start: ts1, Epoch: 2} 914 expire1 := Lease{Replica: r1, Start: ts1, Expiration: ts2.Clone()} 915 expire2 := Lease{Replica: r1, Start: ts1, Expiration: ts3.Clone()} 916 epoch2TS2 := Lease{Replica: r2, Start: ts2, Epoch: 2} 917 expire2TS2 := Lease{Replica: r2, Start: ts2, Expiration: ts3.Clone()} 918 919 proposed1 := Lease{Replica: r1, Start: ts1, Epoch: 1, ProposedTS: ts1.Clone()} 920 proposed2 := Lease{Replica: r1, Start: ts1, Epoch: 2, ProposedTS: ts1.Clone()} 921 proposed3 := Lease{Replica: r1, Start: ts1, Epoch: 1, ProposedTS: ts2.Clone()} 922 923 stasis1 := Lease{Replica: r1, Start: ts1, Epoch: 1, DeprecatedStartStasis: ts1.Clone()} 924 stasis2 := Lease{Replica: r1, Start: ts1, Epoch: 1, DeprecatedStartStasis: ts2.Clone()} 925 926 r1Voter, r1Learner := r1, r1 927 r1Voter.Type = ReplicaTypeVoterFull() 928 r1Learner.Type = ReplicaTypeLearner() 929 epoch1Voter := Lease{Replica: r1Voter, Start: ts1, Epoch: 1} 930 epoch1Learner := Lease{Replica: r1Learner, Start: ts1, Epoch: 1} 931 932 testCases := []struct { 933 l, ol Lease 934 expSuccess bool 935 }{ 936 {epoch1, epoch1, true}, // same epoch lease 937 {expire1, expire1, true}, // same expiration lease 938 {epoch1, epoch2, false}, // different epoch leases 939 {epoch1, epoch2TS2, false}, // different epoch leases 940 {expire1, expire2TS2, false}, // different expiration leases 941 {expire1, expire2, true}, // same expiration lease, extended 942 {expire2, expire1, false}, // same expiration lease, extended but backwards 943 {epoch1, expire1, false}, // epoch and expiration leases 944 {expire1, epoch1, false}, // expiration and epoch leases 945 {proposed1, proposed1, true}, // exact leases with identical timestamps 946 {proposed1, proposed2, false}, // same proposed timestamps, but diff epochs 947 {proposed1, proposed3, true}, // different proposed timestamps, same lease 948 {stasis1, stasis2, true}, // same lease, different stasis timestamps 949 {epoch1, epoch1Voter, true}, // same epoch lease, different replica type 950 {epoch1, epoch1Learner, true}, // same epoch lease, different replica type 951 {epoch1Voter, epoch1Learner, true}, // same epoch lease, different replica type 952 } 953 954 for i, tc := range testCases { 955 if ok := tc.l.Equivalent(tc.ol); tc.expSuccess != ok { 956 t.Errorf("%d: expected success? %t; got %t", i, tc.expSuccess, ok) 957 } 958 } 959 960 // #18689 changed the nullability of the DeprecatedStartStasis, ProposedTS, and Expiration 961 // field. It introduced a bug whose regression is caught below where a zero Expiration and a nil 962 // Expiration in an epoch-based lease led to mistakenly considering leases non-equivalent. 963 prePRLease := Lease{ 964 Start: hlc.Timestamp{WallTime: 10}, 965 Epoch: 123, 966 967 // The bug-trigger. 968 Expiration: new(hlc.Timestamp), 969 970 // Similar potential bug triggers, but these were actually handled correctly. 971 DeprecatedStartStasis: new(hlc.Timestamp), 972 ProposedTS: &hlc.Timestamp{WallTime: 10}, 973 } 974 postPRLease := prePRLease 975 postPRLease.DeprecatedStartStasis = nil 976 postPRLease.Expiration = nil 977 978 if !postPRLease.Equivalent(prePRLease) || !prePRLease.Equivalent(postPRLease) { 979 t.Fatalf("leases not equivalent but should be despite diff(pre,post) = %s", pretty.Diff(prePRLease, postPRLease)) 980 } 981 } 982 983 func TestLeaseEqual(t *testing.T) { 984 type expectedLease struct { 985 Start hlc.Timestamp 986 Expiration *hlc.Timestamp 987 Replica ReplicaDescriptor 988 DeprecatedStartStasis *hlc.Timestamp 989 ProposedTS *hlc.Timestamp 990 Epoch int64 991 Sequence LeaseSequence 992 } 993 // Verify that the lease structure does not change unexpectedly. If a compile 994 // error occurs on the following line of code, update the expectedLease 995 // structure AND update Lease.Equal. 996 var _ = expectedLease(Lease{}) 997 998 // Verify that nil == &hlc.Timestamp{} for the Expiration and 999 // DeprecatedStartStasis fields. See #19843. 1000 a := Lease{} 1001 b := Lease{ 1002 Expiration: &hlc.Timestamp{}, 1003 DeprecatedStartStasis: &hlc.Timestamp{}, 1004 } 1005 if !a.Equal(b) { 1006 t.Fatalf("unexpectedly did not compare equal: %s", pretty.Diff(a, b)) 1007 } 1008 1009 if !(*Lease)(nil).Equal(nil) { 1010 t.Fatalf("unexpectedly did not compare equal") 1011 } 1012 if !(*Lease)(nil).Equal((*Lease)(nil)) { 1013 t.Fatalf("unexpectedly did not compare equal") 1014 } 1015 if (*Lease)(nil).Equal(Lease{}) { 1016 t.Fatalf("expectedly compared equal") 1017 } 1018 if (*Lease)(nil).Equal(&Lease{}) { 1019 t.Fatalf("expectedly compared equal") 1020 } 1021 if (&Lease{}).Equal(nil) { 1022 t.Fatalf("expectedly compared equal") 1023 } 1024 if (&Lease{}).Equal((*Lease)(nil)) { 1025 t.Fatalf("expectedly compared equal") 1026 } 1027 1028 ts := hlc.Timestamp{Logical: 1} 1029 testCases := []Lease{ 1030 {Start: ts}, 1031 {Expiration: &ts}, 1032 {Replica: ReplicaDescriptor{NodeID: 1}}, 1033 {DeprecatedStartStasis: &ts}, 1034 {ProposedTS: &ts}, 1035 {Epoch: 1}, 1036 {Sequence: 1}, 1037 } 1038 for _, c := range testCases { 1039 t.Run("", func(t *testing.T) { 1040 if c.Equal(Lease{}) { 1041 t.Fatalf("unexpected equality: %s", pretty.Diff(c, Lease{})) 1042 } 1043 }) 1044 } 1045 } 1046 1047 func TestSpanOverlaps(t *testing.T) { 1048 sA := Span{Key: []byte("a")} 1049 sD := Span{Key: []byte("d")} 1050 sAtoC := Span{Key: []byte("a"), EndKey: []byte("c")} 1051 sBtoD := Span{Key: []byte("b"), EndKey: []byte("d")} 1052 // Invalid spans. 1053 sCtoA := Span{Key: []byte("c"), EndKey: []byte("a")} 1054 sDtoB := Span{Key: []byte("d"), EndKey: []byte("b")} 1055 1056 testData := []struct { 1057 s1, s2 Span 1058 overlaps bool 1059 }{ 1060 {sA, sA, true}, 1061 {sA, sD, false}, 1062 {sA, sBtoD, false}, 1063 {sBtoD, sA, false}, 1064 {sD, sBtoD, false}, 1065 {sBtoD, sD, false}, 1066 {sA, sAtoC, true}, 1067 {sAtoC, sA, true}, 1068 {sAtoC, sAtoC, true}, 1069 {sAtoC, sBtoD, true}, 1070 {sBtoD, sAtoC, true}, 1071 // Invalid spans. 1072 {sAtoC, sDtoB, false}, 1073 {sDtoB, sAtoC, false}, 1074 {sBtoD, sCtoA, false}, 1075 {sCtoA, sBtoD, false}, 1076 } 1077 for i, test := range testData { 1078 if o := test.s1.Overlaps(test.s2); o != test.overlaps { 1079 t.Errorf("%d: expected overlap %t; got %t between %s vs. %s", i, test.overlaps, o, test.s1, test.s2) 1080 } 1081 } 1082 } 1083 1084 func TestSpanCombine(t *testing.T) { 1085 sA := Span{Key: []byte("a")} 1086 sD := Span{Key: []byte("d")} 1087 sAtoC := Span{Key: []byte("a"), EndKey: []byte("c")} 1088 sAtoD := Span{Key: []byte("a"), EndKey: []byte("d")} 1089 sAtoDNext := Span{Key: []byte("a"), EndKey: Key([]byte("d")).Next()} 1090 sBtoD := Span{Key: []byte("b"), EndKey: []byte("d")} 1091 sBtoDNext := Span{Key: []byte("b"), EndKey: Key([]byte("d")).Next()} 1092 // Invalid spans. 1093 sCtoA := Span{Key: []byte("c"), EndKey: []byte("a")} 1094 sDtoB := Span{Key: []byte("d"), EndKey: []byte("b")} 1095 1096 testData := []struct { 1097 s1, s2 Span 1098 combined Span 1099 }{ 1100 {sA, sA, sA}, 1101 {sA, sD, sAtoDNext}, 1102 {sA, sBtoD, sAtoD}, 1103 {sBtoD, sA, sAtoD}, 1104 {sD, sBtoD, sBtoDNext}, 1105 {sBtoD, sD, sBtoDNext}, 1106 {sA, sAtoC, sAtoC}, 1107 {sAtoC, sA, sAtoC}, 1108 {sAtoC, sAtoC, sAtoC}, 1109 {sAtoC, sBtoD, sAtoD}, 1110 {sBtoD, sAtoC, sAtoD}, 1111 // Invalid spans. 1112 {sAtoC, sDtoB, Span{}}, 1113 {sDtoB, sAtoC, Span{}}, 1114 {sBtoD, sCtoA, Span{}}, 1115 {sCtoA, sBtoD, Span{}}, 1116 } 1117 for i, test := range testData { 1118 if combined := test.s1.Combine(test.s2); !combined.Equal(test.combined) { 1119 t.Errorf("%d: expected combined %s; got %s between %s vs. %s", i, test.combined, combined, test.s1, test.s2) 1120 } 1121 } 1122 } 1123 1124 // TestSpanContains verifies methods to check whether a key 1125 // or key range is contained within the span. 1126 func TestSpanContains(t *testing.T) { 1127 s := Span{Key: []byte("a"), EndKey: []byte("b")} 1128 1129 testData := []struct { 1130 start, end string 1131 contains bool 1132 }{ 1133 // Single keys. 1134 {"a", "", true}, 1135 {"aa", "", true}, 1136 {"`", "", false}, 1137 {"b", "", false}, 1138 {"c", "", false}, 1139 // Key ranges. 1140 {"a", "b", true}, 1141 {"a", "aa", true}, 1142 {"aa", "b", true}, 1143 {"0", "9", false}, 1144 {"`", "a", false}, 1145 {"b", "bb", false}, 1146 {"0", "bb", false}, 1147 {"aa", "bb", false}, 1148 {"b", "a", false}, 1149 } 1150 for i, test := range testData { 1151 if s.Contains(sp(test.start, test.end)) != test.contains { 1152 t.Errorf("%d: expected span %q-%q within range to be %v", 1153 i, test.start, test.end, test.contains) 1154 } 1155 } 1156 } 1157 1158 func TestSpanSplitOnKey(t *testing.T) { 1159 s := Span{Key: []byte("b"), EndKey: []byte("c")} 1160 1161 testData := []struct { 1162 split []byte 1163 left Span 1164 right Span 1165 }{ 1166 // Split on start/end key should fail. 1167 { 1168 []byte("b"), 1169 s, 1170 Span{}, 1171 }, 1172 { 1173 []byte("c"), 1174 s, 1175 Span{}, 1176 }, 1177 1178 // Before start key. 1179 { 1180 []byte("a"), 1181 s, 1182 Span{}, 1183 }, 1184 // After end key. 1185 { 1186 []byte("d"), 1187 s, 1188 Span{}, 1189 }, 1190 1191 // Simple split. 1192 { 1193 []byte("bb"), 1194 sp("b", "bb"), 1195 sp("bb", "c"), 1196 }, 1197 } 1198 for testIdx, test := range testData { 1199 t.Run(strconv.Itoa(testIdx), func(t *testing.T) { 1200 actualL, actualR := s.SplitOnKey(test.split) 1201 if !test.left.EqualValue(actualL) { 1202 t.Fatalf("expected left span after split to be %v, got %v", test.left, actualL) 1203 } 1204 1205 if !test.right.EqualValue(actualR) { 1206 t.Fatalf("expected right span after split to be %v, got %v", test.right, actualL) 1207 } 1208 }) 1209 } 1210 } 1211 1212 func TestSpanValid(t *testing.T) { 1213 testData := []struct { 1214 start, end []byte 1215 valid bool 1216 }{ 1217 {[]byte("a"), nil, true}, 1218 {[]byte("a"), []byte("b"), true}, 1219 {[]byte(""), []byte(""), false}, 1220 {[]byte(""), []byte("a"), true}, 1221 {[]byte("a"), []byte("a"), false}, 1222 {[]byte("b"), []byte("aa"), false}, 1223 } 1224 for i, test := range testData { 1225 s := Span{Key: test.start, EndKey: test.end} 1226 if test.valid != s.Valid() { 1227 t.Errorf("%d: expected span %q-%q to return %t for Valid, instead got %t", 1228 i, test.start, test.end, test.valid, s.Valid()) 1229 } 1230 } 1231 } 1232 1233 // TestRSpanContains verifies methods to check whether a key 1234 // or key range is contained within the span. 1235 func TestRSpanContains(t *testing.T) { 1236 rs := RSpan{Key: []byte("a"), EndKey: []byte("b")} 1237 1238 testData := []struct { 1239 start, end []byte 1240 contains bool 1241 }{ 1242 // Single keys. 1243 {[]byte("a"), []byte("a"), true}, 1244 {[]byte("a"), nil, true}, 1245 {[]byte("aa"), []byte("aa"), true}, 1246 {[]byte("`"), []byte("`"), false}, 1247 {[]byte("b"), []byte("b"), false}, 1248 {[]byte("b"), nil, false}, 1249 {[]byte("c"), []byte("c"), false}, 1250 // Key ranges. 1251 {[]byte("a"), []byte("b"), true}, 1252 {[]byte("a"), []byte("aa"), true}, 1253 {[]byte("aa"), []byte("b"), true}, 1254 {[]byte("0"), []byte("9"), false}, 1255 {[]byte("`"), []byte("a"), false}, 1256 {[]byte("b"), []byte("bb"), false}, 1257 {[]byte("0"), []byte("bb"), false}, 1258 {[]byte("aa"), []byte("bb"), false}, 1259 {[]byte("b"), []byte("a"), false}, 1260 } 1261 for i, test := range testData { 1262 if bytes.Equal(test.start, test.end) { 1263 if rs.ContainsKey(test.start) != test.contains { 1264 t.Errorf("%d: expected key %q within range", i, test.start) 1265 } 1266 } 1267 if rs.ContainsKeyRange(test.start, test.end) != test.contains { 1268 t.Errorf("%d: expected key %q within range", i, test.start) 1269 } 1270 } 1271 } 1272 1273 // TestRSpanContainsKeyInverted verifies ContainsKeyInverted to check whether a key 1274 // is contained within the span. 1275 func TestRSpanContainsKeyInverted(t *testing.T) { 1276 rs := RSpan{Key: []byte("b"), EndKey: []byte("c")} 1277 1278 testData := []struct { 1279 key RKey 1280 contains bool 1281 }{ 1282 // Single keys. 1283 {RKey("a"), false}, 1284 {RKey("b"), false}, 1285 {RKey("bb"), true}, 1286 {RKey("c"), true}, 1287 {RKey("c").Next(), false}, 1288 } 1289 for i, test := range testData { 1290 if rs.ContainsKeyInverted(test.key) != test.contains { 1291 t.Errorf("%d: expected key %q within range", i, test.key) 1292 } 1293 } 1294 } 1295 1296 // TestRSpanIntersect verifies rSpan.intersect. 1297 func TestRSpanIntersect(t *testing.T) { 1298 rs := RSpan{Key: RKey("b"), EndKey: RKey("e")} 1299 1300 testData := []struct { 1301 startKey, endKey RKey 1302 expected RSpan 1303 }{ 1304 // Partially overlapping. 1305 {RKey("a"), RKey("c"), RSpan{Key: RKey("b"), EndKey: RKey("c")}}, 1306 {RKey("d"), RKey("f"), RSpan{Key: RKey("d"), EndKey: RKey("e")}}, 1307 // Descriptor surrounds the span. 1308 {RKey("a"), RKey("f"), RSpan{Key: RKey("b"), EndKey: RKey("e")}}, 1309 // Span surrounds the descriptor. 1310 {RKey("c"), RKey("d"), RSpan{Key: RKey("c"), EndKey: RKey("d")}}, 1311 // Descriptor has the same range as the span. 1312 {RKey("b"), RKey("e"), RSpan{Key: RKey("b"), EndKey: RKey("e")}}, 1313 } 1314 1315 for i, test := range testData { 1316 desc := RangeDescriptor{} 1317 desc.StartKey = test.startKey 1318 desc.EndKey = test.endKey 1319 1320 actual, err := rs.Intersect(&desc) 1321 if err != nil { 1322 t.Error(err) 1323 continue 1324 } 1325 if !actual.Equal(test.expected) { 1326 t.Errorf("%d: expected %+v but got %+v", i, test.expected, actual) 1327 } 1328 } 1329 1330 // Error scenarios 1331 errorTestData := []struct { 1332 startKey, endKey RKey 1333 }{ 1334 {RKey("a"), RKey("b")}, 1335 {RKey("e"), RKey("f")}, 1336 {RKey("f"), RKey("g")}, 1337 } 1338 for i, test := range errorTestData { 1339 desc := RangeDescriptor{} 1340 desc.StartKey = test.startKey 1341 desc.EndKey = test.endKey 1342 if _, err := rs.Intersect(&desc); err == nil { 1343 t.Errorf("%d: unexpected success", i) 1344 } 1345 } 1346 } 1347 1348 func BenchmarkValueSetBytes(b *testing.B) { 1349 v := Value{} 1350 bytes := make([]byte, 16) 1351 1352 for i := 0; i < b.N; i++ { 1353 v.SetBytes(bytes) 1354 } 1355 } 1356 1357 func BenchmarkValueSetFloat(b *testing.B) { 1358 v := Value{} 1359 f := 1.1 1360 1361 for i := 0; i < b.N; i++ { 1362 v.SetFloat(f) 1363 } 1364 } 1365 1366 func BenchmarkValueSetBool(b *testing.B) { 1367 v := Value{} 1368 bo := true 1369 1370 for i := 0; i < b.N; i++ { 1371 v.SetBool(bo) 1372 } 1373 } 1374 1375 func BenchmarkValueSetInt(b *testing.B) { 1376 v := Value{} 1377 in := int64(1) 1378 1379 for i := 0; i < b.N; i++ { 1380 v.SetInt(in) 1381 } 1382 } 1383 1384 func BenchmarkValueSetProto(b *testing.B) { 1385 v := Value{} 1386 p := &Value{} 1387 1388 for i := 0; i < b.N; i++ { 1389 if err := v.SetProto(p); err != nil { 1390 b.Fatal(err) 1391 } 1392 } 1393 } 1394 1395 func BenchmarkValueSetTime(b *testing.B) { 1396 v := Value{} 1397 ti := time.Time{} 1398 1399 for i := 0; i < b.N; i++ { 1400 v.SetTime(ti) 1401 } 1402 } 1403 1404 func BenchmarkValueSetDecimal(b *testing.B) { 1405 v := Value{} 1406 dec := apd.New(11, -1) 1407 1408 for i := 0; i < b.N; i++ { 1409 if err := v.SetDecimal(dec); err != nil { 1410 b.Fatal(err) 1411 } 1412 } 1413 } 1414 1415 func BenchmarkValueSetTuple(b *testing.B) { 1416 v := Value{} 1417 bytes := make([]byte, 16) 1418 1419 for i := 0; i < b.N; i++ { 1420 v.SetTuple(bytes) 1421 } 1422 } 1423 1424 func BenchmarkValueGetBytes(b *testing.B) { 1425 v := Value{} 1426 bytes := make([]byte, 16) 1427 v.SetBytes(bytes) 1428 1429 for i := 0; i < b.N; i++ { 1430 if _, err := v.GetBytes(); err != nil { 1431 b.Fatal(err) 1432 } 1433 } 1434 } 1435 1436 func BenchmarkValueGetFloat(b *testing.B) { 1437 v := Value{} 1438 f := 1.1 1439 v.SetFloat(f) 1440 1441 for i := 0; i < b.N; i++ { 1442 if _, err := v.GetFloat(); err != nil { 1443 b.Fatal(err) 1444 } 1445 } 1446 } 1447 1448 func BenchmarkValueGetBool(b *testing.B) { 1449 v := Value{} 1450 bo := true 1451 v.SetBool(bo) 1452 1453 for i := 0; i < b.N; i++ { 1454 if _, err := v.GetBool(); err != nil { 1455 b.Fatal(err) 1456 } 1457 } 1458 } 1459 1460 func BenchmarkValueGetInt(b *testing.B) { 1461 v := Value{} 1462 in := int64(1) 1463 v.SetInt(in) 1464 1465 for i := 0; i < b.N; i++ { 1466 if _, err := v.GetInt(); err != nil { 1467 b.Fatal(err) 1468 } 1469 } 1470 } 1471 1472 func BenchmarkValueGetProto(b *testing.B) { 1473 v := Value{} 1474 p, dst := &Value{}, &Value{} 1475 if err := v.SetProto(p); err != nil { 1476 b.Fatal(err) 1477 } 1478 1479 for i := 0; i < b.N; i++ { 1480 if err := v.GetProto(dst); err != nil { 1481 b.Fatal(err) 1482 } 1483 } 1484 } 1485 1486 func BenchmarkValueGetTime(b *testing.B) { 1487 v := Value{} 1488 ti := time.Time{} 1489 v.SetTime(ti) 1490 1491 for i := 0; i < b.N; i++ { 1492 if _, err := v.GetTime(); err != nil { 1493 b.Fatal(err) 1494 } 1495 } 1496 } 1497 1498 func BenchmarkValueGetDecimal(b *testing.B) { 1499 v := Value{} 1500 dec := apd.New(11, -1) 1501 if err := v.SetDecimal(dec); err != nil { 1502 b.Fatal(err) 1503 } 1504 1505 for i := 0; i < b.N; i++ { 1506 if _, err := v.GetDecimal(); err != nil { 1507 b.Fatal(err) 1508 } 1509 } 1510 } 1511 1512 func BenchmarkValueGetTuple(b *testing.B) { 1513 v := Value{} 1514 bytes := make([]byte, 16) 1515 v.SetTuple(bytes) 1516 1517 for i := 0; i < b.N; i++ { 1518 if _, err := v.GetTuple(); err != nil { 1519 b.Fatal(err) 1520 } 1521 } 1522 } 1523 1524 func TestValuePrettyPrint(t *testing.T) { 1525 var boolValue Value 1526 boolValue.SetBool(true) 1527 1528 var intValue Value 1529 intValue.SetInt(7) 1530 1531 var floatValue Value 1532 floatValue.SetFloat(6.28) 1533 1534 var timeValue Value 1535 timeValue.SetTime(time.Date(2016, 6, 29, 16, 2, 50, 5, time.UTC)) 1536 1537 var decimalValue Value 1538 _ = decimalValue.SetDecimal(apd.New(628, -2)) 1539 1540 var durationValue Value 1541 _ = durationValue.SetDuration(duration.DecodeDuration(1, 2, 3)) 1542 1543 var tupleValue Value 1544 tupleBytes := encoding.EncodeBytesValue(encoding.EncodeIntValue(nil, 1, 8), 2, []byte("foo")) 1545 tupleValue.SetTuple(tupleBytes) 1546 1547 var bytesValuePrintable, bytesValueNonPrintable Value 1548 bytesValuePrintable.SetBytes([]byte("abc")) 1549 bytesValueNonPrintable.SetBytes([]byte{0x89}) 1550 1551 var bitArrayValue Value 1552 ba := bitarray.MakeBitArrayFromInt64(8, 58, 7) 1553 bitArrayValue.SetBitArray(ba) 1554 1555 var errValue Value 1556 errValue.SetInt(7) 1557 errValue.setTag(ValueType_FLOAT) 1558 1559 var errTagValue Value 1560 errTagValue.SetInt(7) 1561 errTagValue.setTag(ValueType(99)) 1562 1563 tests := []struct { 1564 v Value 1565 expected string 1566 }{ 1567 {boolValue, "/INT/1"}, 1568 {intValue, "/INT/7"}, 1569 {floatValue, "/FLOAT/6.28"}, 1570 {timeValue, "/TIME/2016-06-29T16:02:50.000000005Z"}, 1571 {decimalValue, "/DECIMAL/6.28"}, 1572 {durationValue, "/DURATION/1 mon 2 days 00:00:00+3ns"}, 1573 {MakeValueFromBytes([]byte{0x1, 0x2, 0xF, 0xFF}), "/BYTES/0x01020fff"}, 1574 {MakeValueFromString("foo"), "/BYTES/foo"}, 1575 {tupleValue, "/TUPLE/1:1:Int/8/2:3:Bytes/foo"}, 1576 {bytesValuePrintable, "/BYTES/abc"}, 1577 {bytesValueNonPrintable, "/BYTES/0x89"}, 1578 {bitArrayValue, "/BITARRAY/B00111010"}, 1579 {errValue, "/<err: float64 value should be exactly 8 bytes: 1>"}, 1580 {errTagValue, "/<err: unknown tag: 99>"}, 1581 } 1582 1583 for i, test := range tests { 1584 if str := test.v.PrettyPrint(); str != test.expected { 1585 t.Errorf("%d: got %q expected %q", i, str, test.expected) 1586 } 1587 } 1588 } 1589 1590 func TestUpdateObservedTimestamps(t *testing.T) { 1591 f := func(nodeID NodeID, walltime int64) ObservedTimestamp { 1592 return ObservedTimestamp{ 1593 NodeID: nodeID, 1594 Timestamp: hlc.Timestamp{ 1595 WallTime: walltime, 1596 }, 1597 } 1598 } 1599 1600 testCases := []struct { 1601 input observedTimestampSlice 1602 expected observedTimestampSlice 1603 }{ 1604 {nil, nil}, 1605 { 1606 observedTimestampSlice{f(1, 1)}, 1607 observedTimestampSlice{f(1, 1)}, 1608 }, 1609 { 1610 observedTimestampSlice{f(1, 1), f(1, 2)}, 1611 observedTimestampSlice{f(1, 1)}, 1612 }, 1613 { 1614 observedTimestampSlice{f(1, 2), f(1, 1)}, 1615 observedTimestampSlice{f(1, 1)}, 1616 }, 1617 { 1618 observedTimestampSlice{f(1, 1), f(2, 1)}, 1619 observedTimestampSlice{f(1, 1), f(2, 1)}, 1620 }, 1621 { 1622 observedTimestampSlice{f(2, 1), f(1, 1)}, 1623 observedTimestampSlice{f(1, 1), f(2, 1)}, 1624 }, 1625 { 1626 observedTimestampSlice{f(1, 1), f(2, 1), f(3, 1)}, 1627 observedTimestampSlice{f(1, 1), f(2, 1), f(3, 1)}, 1628 }, 1629 { 1630 observedTimestampSlice{f(3, 1), f(2, 1), f(1, 1)}, 1631 observedTimestampSlice{f(1, 1), f(2, 1), f(3, 1)}, 1632 }, 1633 { 1634 observedTimestampSlice{f(2, 1), f(3, 1), f(1, 1)}, 1635 observedTimestampSlice{f(1, 1), f(2, 1), f(3, 1)}, 1636 }, 1637 } 1638 for _, c := range testCases { 1639 t.Run("", func(t *testing.T) { 1640 var s observedTimestampSlice 1641 for _, v := range c.input { 1642 s = s.update(v.NodeID, v.Timestamp) 1643 } 1644 if !reflect.DeepEqual(c.expected, s) { 1645 t.Fatalf("%s", pretty.Diff(c.expected, s)) 1646 } 1647 }) 1648 } 1649 } 1650 1651 func TestChangeReplicasTrigger_String(t *testing.T) { 1652 defer leaktest.AfterTest(t)() 1653 1654 vi := VOTER_INCOMING 1655 vo := VOTER_OUTGOING 1656 vd := VOTER_DEMOTING 1657 l := LEARNER 1658 repl1 := ReplicaDescriptor{NodeID: 1, StoreID: 2, ReplicaID: 3, Type: &vi} 1659 repl2 := ReplicaDescriptor{NodeID: 4, StoreID: 5, ReplicaID: 6, Type: &vo} 1660 learner := ReplicaDescriptor{NodeID: 7, StoreID: 8, ReplicaID: 9, Type: &l} 1661 repl3 := ReplicaDescriptor{NodeID: 10, StoreID: 11, ReplicaID: 12, Type: &vd} 1662 crt := ChangeReplicasTrigger{ 1663 InternalAddedReplicas: []ReplicaDescriptor{repl1}, 1664 InternalRemovedReplicas: []ReplicaDescriptor{repl2, repl3}, 1665 Desc: &RangeDescriptor{ 1666 RangeID: 1, 1667 StartKey: RKey("a"), 1668 EndKey: RKey("b"), 1669 InternalReplicas: []ReplicaDescriptor{ 1670 repl1, 1671 repl2, 1672 learner, 1673 repl3, 1674 }, 1675 NextReplicaID: 10, 1676 Generation: 5, 1677 }, 1678 } 1679 act := crt.String() 1680 exp := "ENTER_JOINT(r6 r12 l12 v3) ADD_REPLICA[(n1,s2):3VOTER_INCOMING], " + 1681 "REMOVE_REPLICA[(n4,s5):6VOTER_OUTGOING (n10,s11):12VOTER_DEMOTING]: " + 1682 "after=[(n1,s2):3VOTER_INCOMING (n4,s5):6VOTER_OUTGOING (n7,s8):9LEARNER " + 1683 "(n10,s11):12VOTER_DEMOTING] next=10" 1684 require.Equal(t, exp, act) 1685 1686 crt.InternalRemovedReplicas = nil 1687 crt.InternalAddedReplicas = nil 1688 repl1.Type = ReplicaTypeVoterFull() 1689 crt.Desc.SetReplicas(MakeReplicaDescriptors([]ReplicaDescriptor{repl1, learner})) 1690 act = crt.String() 1691 require.Empty(t, crt.Added()) 1692 require.Empty(t, crt.Removed()) 1693 exp = "LEAVE_JOINT: after=[(n1,s2):3 (n7,s8):9LEARNER] next=10" 1694 require.Equal(t, exp, act) 1695 } 1696 1697 type mockCRT struct { 1698 v2 bool 1699 ChangeReplicasTrigger 1700 } 1701 1702 func (m mockCRT) alwaysV2() bool { 1703 return m.v2 1704 } 1705 1706 func TestChangeReplicasTrigger_ConfChange(t *testing.T) { 1707 defer leaktest.AfterTest(t)() 1708 1709 sl := func(alt ...interface{}) []ReplicaDescriptor { 1710 t.Helper() 1711 if len(alt)%2 != 0 { 1712 t.Fatal("need pairs") 1713 } 1714 var rDescs []ReplicaDescriptor 1715 for i := 0; i < len(alt); i += 2 { 1716 typ := alt[i].(ReplicaType) 1717 id := alt[i+1].(int) 1718 rDescs = append(rDescs, ReplicaDescriptor{ 1719 Type: &typ, 1720 NodeID: NodeID(3 * id), 1721 StoreID: StoreID(2 * id), 1722 ReplicaID: ReplicaID(id), 1723 }) 1724 } 1725 return rDescs 1726 } 1727 1728 type in struct { 1729 v2 bool 1730 add, del, repls []ReplicaDescriptor 1731 } 1732 1733 mk := func(in in) mockCRT { 1734 m := mockCRT{v2: in.v2} 1735 m.ChangeReplicasTrigger.InternalAddedReplicas = in.add 1736 m.ChangeReplicasTrigger.InternalRemovedReplicas = in.del 1737 m.Desc = &RangeDescriptor{} 1738 m.Desc.SetReplicas(MakeReplicaDescriptors(in.repls)) 1739 return m 1740 } 1741 1742 vf1 := sl(VOTER_FULL, 1) 1743 vo1 := sl(VOTER_OUTGOING, 1) 1744 vi1 := sl(VOTER_INCOMING, 1) 1745 vl1 := sl(LEARNER, 1) 1746 1747 testCases := []struct { 1748 crt mockCRT 1749 exp raftpb.ConfChangeI 1750 err string 1751 }{ 1752 // A replica of type VOTER_OUTGOING being added makes no sense. 1753 {crt: mk(in{add: vo1, repls: vo1}), err: "can't add replica in state VOTER_OUTGOING"}, 1754 // But an incoming one can be added, and the result must be a joint change. 1755 {crt: mk(in{add: vi1, repls: vi1}), exp: raftpb.ConfChangeV2{ 1756 Transition: raftpb.ConfChangeTransitionJointExplicit, 1757 Changes: []raftpb.ConfChangeSingle{{Type: raftpb.ConfChangeAddNode, NodeID: 1}}, 1758 }}, 1759 // A replica of type VOTER_INCOMING being removed makes no sense. 1760 {crt: mk(in{del: vi1}), err: "can't remove replica in state VOTER_INCOMING"}, 1761 // But during a joint removal we can see VOTER_OUTGOING. 1762 {crt: mk(in{del: vo1, repls: vo1}), exp: raftpb.ConfChangeV2{ 1763 Transition: raftpb.ConfChangeTransitionJointExplicit, 1764 Changes: []raftpb.ConfChangeSingle{{Type: raftpb.ConfChangeRemoveNode, NodeID: 1}}, 1765 }}, 1766 1767 // Adding a voter via the V1 path. 1768 {crt: mk(in{add: vf1, repls: vf1}), exp: raftpb.ConfChange{ 1769 Type: raftpb.ConfChangeAddNode, 1770 NodeID: 1, 1771 }}, 1772 // Adding a learner via the V1 path. 1773 {crt: mk(in{add: vl1, repls: vl1}), exp: raftpb.ConfChange{ 1774 Type: raftpb.ConfChangeAddLearnerNode, 1775 NodeID: 1, 1776 }}, 1777 1778 // Removing a voter or learner via the V1 path but falsely the replica is still in the descriptor. 1779 {crt: mk(in{del: vf1, repls: vf1}), err: "(n3,s2):1 must no longer be present in descriptor"}, 1780 {crt: mk(in{del: vl1, repls: vl1}), err: "(n3,s2):1LEARNER must no longer be present in descriptor"}, 1781 // Well-formed examples. 1782 {crt: mk(in{del: vf1}), exp: raftpb.ConfChange{ 1783 Type: raftpb.ConfChangeRemoveNode, 1784 NodeID: 1, 1785 }}, 1786 {crt: mk(in{del: vl1}), exp: raftpb.ConfChange{ 1787 Type: raftpb.ConfChangeRemoveNode, 1788 NodeID: 1, 1789 }}, 1790 // Adding a voter via the V2 path but without joint consensus. 1791 {crt: mk(in{v2: true, add: vf1, repls: vf1}), exp: raftpb.ConfChangeV2{ 1792 Transition: raftpb.ConfChangeTransitionAuto, 1793 Changes: []raftpb.ConfChangeSingle{{ 1794 Type: raftpb.ConfChangeAddNode, 1795 NodeID: 1, 1796 }}, 1797 }}, 1798 // Ditto, but with joint consensus requested. 1799 {crt: mk(in{v2: true, add: vi1, repls: vi1}), exp: raftpb.ConfChangeV2{ 1800 Transition: raftpb.ConfChangeTransitionJointExplicit, 1801 Changes: []raftpb.ConfChangeSingle{{ 1802 Type: raftpb.ConfChangeAddNode, 1803 NodeID: 1, 1804 }}, 1805 }}, 1806 1807 // Adding a learner via the V2 path and without joint consensus. (There is currently 1808 // no way to request joint consensus when adding a single learner, but there is no 1809 // reason one would ever want that). 1810 {crt: mk(in{v2: true, add: vl1, repls: vl1}), exp: raftpb.ConfChangeV2{ 1811 Transition: raftpb.ConfChangeTransitionAuto, 1812 Changes: []raftpb.ConfChangeSingle{{ 1813 Type: raftpb.ConfChangeAddLearnerNode, 1814 NodeID: 1, 1815 }}, 1816 }}, 1817 1818 // Removing a voter or learner via the V2 path without joint consensus. 1819 // Note that this means that the replica is not in the desc any more. 1820 {crt: mk(in{v2: true, del: vf1}), exp: raftpb.ConfChangeV2{ 1821 Transition: raftpb.ConfChangeTransitionAuto, 1822 Changes: []raftpb.ConfChangeSingle{{ 1823 Type: raftpb.ConfChangeRemoveNode, 1824 NodeID: 1, 1825 }}, 1826 }}, 1827 {crt: mk(in{v2: true, del: vl1}), exp: raftpb.ConfChangeV2{ 1828 Transition: raftpb.ConfChangeTransitionAuto, 1829 Changes: []raftpb.ConfChangeSingle{{ 1830 Type: raftpb.ConfChangeRemoveNode, 1831 NodeID: 1, 1832 }}, 1833 }}, 1834 1835 // Ditto but with joint consensus. (This can happen only with a voter; 1836 // learners disappear immediately). 1837 {crt: mk(in{v2: true, del: vo1, repls: vo1}), exp: raftpb.ConfChangeV2{ 1838 Transition: raftpb.ConfChangeTransitionJointExplicit, 1839 Changes: []raftpb.ConfChangeSingle{{ 1840 Type: raftpb.ConfChangeRemoveNode, 1841 NodeID: 1, 1842 }}, 1843 }}, 1844 1845 // Run a more complex change (necessarily) via the V2 path. 1846 {crt: mk(in{ 1847 add: sl( // Additions. 1848 VOTER_INCOMING, 6, LEARNER, 4, VOTER_INCOMING, 3, 1849 ), 1850 del: sl( 1851 // Removals. 1852 LEARNER, 2, VOTER_OUTGOING, 8, VOTER_DEMOTING, 9, 1853 ), 1854 repls: sl( 1855 // Replicas. 1856 VOTER_FULL, 1, 1857 VOTER_INCOMING, 6, // added 1858 VOTER_INCOMING, 3, // added 1859 VOTER_DEMOTING, 9, // removing 1860 LEARNER, 4, // added 1861 VOTER_OUTGOING, 8, // removing 1862 VOTER_FULL, 10, 1863 )}), 1864 exp: raftpb.ConfChangeV2{ 1865 Transition: raftpb.ConfChangeTransitionJointExplicit, 1866 Changes: []raftpb.ConfChangeSingle{ 1867 {NodeID: 2, Type: raftpb.ConfChangeRemoveNode}, 1868 {NodeID: 8, Type: raftpb.ConfChangeRemoveNode}, 1869 {NodeID: 9, Type: raftpb.ConfChangeRemoveNode}, 1870 {NodeID: 9, Type: raftpb.ConfChangeAddLearnerNode}, 1871 {NodeID: 6, Type: raftpb.ConfChangeAddNode}, 1872 {NodeID: 4, Type: raftpb.ConfChangeAddLearnerNode}, 1873 {NodeID: 3, Type: raftpb.ConfChangeAddNode}, 1874 }}, 1875 }, 1876 1877 // Leave a joint config. 1878 { 1879 crt: mk(in{repls: sl(VOTER_FULL, 1)}), 1880 exp: raftpb.ConfChangeV2{}, 1881 }, 1882 // If we're asked to leave a joint state but the descriptor is still joint, 1883 // that's a problem. 1884 { 1885 crt: mk(in{v2: true, repls: sl(VOTER_INCOMING, 1)}), 1886 err: "descriptor enters joint state, but trigger is requesting to leave one", 1887 }, 1888 { 1889 crt: mk(in{v2: true, repls: sl(VOTER_OUTGOING, 1)}), 1890 err: "descriptor enters joint state, but trigger is requesting to leave one", 1891 }, 1892 } 1893 1894 for _, test := range testCases { 1895 t.Run("", func(t *testing.T) { 1896 cc, err := confChangeImpl(test.crt, nil /* payload */) 1897 if test.err == "" { 1898 require.NoError(t, err) 1899 require.Equal(t, test.exp, cc) 1900 } else { 1901 require.EqualError(t, err, test.err) 1902 } 1903 }) 1904 } 1905 } 1906 1907 // TestAsLockUpdates verifies that AsLockUpdates propagates all the important 1908 // fields from a txn to each intent. 1909 func TestAsLockUpdates(t *testing.T) { 1910 defer leaktest.AfterTest(t)() 1911 1912 ts := hlc.Timestamp{WallTime: 1} 1913 txn := MakeTransaction("hello", Key("k"), 0, ts, 0) 1914 1915 txn.Status = COMMITTED 1916 txn.IgnoredSeqNums = []enginepb.IgnoredSeqNumRange{{Start: 0, End: 0}} 1917 1918 spans := []Span{{Key: Key("a"), EndKey: Key("b")}} 1919 for _, intent := range AsLockUpdates(&txn, spans) { 1920 require.Equal(t, txn.Status, intent.Status) 1921 require.Equal(t, txn.IgnoredSeqNums, intent.IgnoredSeqNums) 1922 require.Equal(t, txn.TxnMeta, intent.Txn) 1923 } 1924 } 1925 1926 func TestAddIgnoredSeqNumRange(t *testing.T) { 1927 type r = enginepb.IgnoredSeqNumRange 1928 1929 mr := func(a, b enginepb.TxnSeq) r { 1930 return r{Start: a, End: b} 1931 } 1932 1933 testData := []struct { 1934 list []r 1935 newRange r 1936 exp []r 1937 }{ 1938 { 1939 []r{}, 1940 mr(1, 2), 1941 []r{mr(1, 2)}, 1942 }, 1943 { 1944 []r{mr(1, 2)}, 1945 mr(1, 4), 1946 []r{mr(1, 4)}, 1947 }, 1948 { 1949 []r{mr(1, 2), mr(3, 6)}, 1950 mr(8, 10), 1951 []r{mr(1, 2), mr(3, 6), mr(8, 10)}, 1952 }, 1953 { 1954 []r{mr(1, 2), mr(5, 6)}, 1955 mr(3, 8), 1956 []r{mr(1, 2), mr(3, 8)}, 1957 }, 1958 { 1959 []r{mr(1, 2), mr(5, 6)}, 1960 mr(1, 8), 1961 []r{mr(1, 8)}, 1962 }, 1963 } 1964 1965 for _, tc := range testData { 1966 txn := Transaction{ 1967 IgnoredSeqNums: tc.list, 1968 } 1969 txn.AddIgnoredSeqNumRange(tc.newRange) 1970 require.Equal(t, tc.exp, txn.IgnoredSeqNums) 1971 } 1972 }