From 1d719d089b97c09bde2fa1bcc6c212f16e5af7aa Mon Sep 17 00:00:00 2001 From: Nathan VanBenschoten Date: Thu, 28 Sep 2023 13:37:50 -0400 Subject: [PATCH] kv: add shared, replicated, and shared-replicated locks to TestEvaluateBatch Informs #91545. Informs #100193. This commit extends TestEvaluateBatch to include shared, replicated, and shared-replicated lock acquisition using Get, Scan, and ReverseScan requests. Release note: None --- pkg/kv/kvserver/replica_evaluate_test.go | 337 ++++++++++++++++++++--- 1 file changed, 300 insertions(+), 37 deletions(-) diff --git a/pkg/kv/kvserver/replica_evaluate_test.go b/pkg/kv/kvserver/replica_evaluate_test.go index e9f165a69375..e22831aed8c8 100644 --- a/pkg/kv/kvserver/replica_evaluate_test.go +++ b/pkg/kv/kvserver/replica_evaluate_test.go @@ -52,6 +52,7 @@ func TestEvaluateBatch(t *testing.T) { require.Nil(t, r.pErr) require.NotNil(t, r.br) require.Empty(t, r.br.Responses) + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Scanning without limit should return everything. @@ -64,6 +65,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b", "c", "d", "e", "f"}) verifyResumeSpans(t, r, "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Ditto in reverse. @@ -76,6 +78,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"f", "e", "d", "c", "b", "a"}) verifyResumeSpans(t, r, "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Scanning with "giant" limit should return everything. @@ -89,6 +92,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b", "c", "d", "e", "f"}) verifyResumeSpans(t, r, "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Ditto in reverse. @@ -102,6 +106,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"f", "e", "d", "c", "b", "a"}) verifyResumeSpans(t, r, "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Similar to above, just two scans. @@ -115,6 +120,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b"}, []string{"d", "e", "f"}) verifyResumeSpans(t, r, "", "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Ditto in reverse. @@ -128,6 +134,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"f", "e", "d"}, []string{"b", "a"}) verifyResumeSpans(t, r, "", "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // A batch limited to return only one key. Throw in a Get which will come @@ -144,6 +151,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil, nil) verifyResumeSpans(t, r, "b-c", "f-", "d-f") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Ditto in reverse. @@ -158,6 +166,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"e"}, nil, nil) verifyResumeSpans(t, r, "d-d\x00", "f-", "a-c") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Similar, but this time the request allows the second scan to @@ -174,6 +183,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b"}, []string{"e"}, []string{"c"}) verifyResumeSpans(t, r, "", "", "d-e") + verifyAcquiredLocks(t, r, acquiredLocks{}) b, err := r.br.Responses[1].GetGet().Value.GetBytes() require.NoError(t, err) require.Equal(t, "value-e", string(b)) @@ -191,6 +201,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"d", "c"}, []string{"e"}, []string{"b"}) verifyResumeSpans(t, r, "", "", "a-a\x00") + verifyAcquiredLocks(t, r, acquiredLocks{}) b, err := r.br.Responses[1].GetGet().Value.GetBytes() require.NoError(t, err) require.Equal(t, "value-e", string(b)) @@ -209,6 +220,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, []string{"b"}, nil, nil) verifyResumeSpans(t, r, "", "", "c-", "d-e") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // GetRequests that come before revscans. @@ -224,6 +236,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, []string{"b"}, nil, nil) verifyResumeSpans(t, r, "", "", "c-", "d-e") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, // @@ -247,6 +260,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil, nil) verifyResumeSpans(t, r, "b-c", "e-", "c-e") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Ditto in reverse. @@ -262,6 +276,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"d"}, nil, nil) verifyResumeSpans(t, r, "c-c\x00", "e-", "a-c") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // GetRequests that come before scans. @@ -276,6 +291,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil, nil) verifyResumeSpans(t, r, "", "b-", "c-e") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // GetRequests that come before revscans. @@ -290,6 +306,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil, nil) verifyResumeSpans(t, r, "", "b-", "c-e") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, // @@ -298,21 +315,90 @@ func TestEvaluateBatch(t *testing.T) { { // Two gets, one of which finds a key, one of which does not. An // unreplicated lock should be acquired on the key that existed. - name: "gets with key locking", + name: "gets with key locking (exclusive, unreplicated)", setup: func(t *testing.T, d *data) { writeABCDEFAt(t, d, ts.Prev()) scanA := getArgsString("a") scanA.KeyLockingStrength = lock.Exclusive + scanA.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanA) scanG := getArgsString("g") scanG.KeyLockingStrength = lock.Exclusive + scanG.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanG) d.ba.Txn = &txn }, check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil) - verifyAcquiredLocks(t, r, lock.Unreplicated, "a") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"a"}}, + }) + }, + }, + { + // Same as above, but with shared locks. + name: "gets with key locking (shared, unreplicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanA := getArgsString("a") + scanA.KeyLockingStrength = lock.Shared + scanA.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanA) + scanG := getArgsString("g") + scanG.KeyLockingStrength = lock.Shared + scanG.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanG) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"a"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Shared: {lock.Unreplicated: []string{"a"}}, + }) + }, + }, + { + // Same as above, but with replicated exclusive locks. + name: "gets with key locking (exclusive, replicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanA := getArgsString("a") + scanA.KeyLockingStrength = lock.Exclusive + scanA.KeyLockingDurability = lock.Replicated + d.ba.Add(scanA) + scanG := getArgsString("g") + scanG.KeyLockingStrength = lock.Exclusive + scanG.KeyLockingDurability = lock.Replicated + d.ba.Add(scanG) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"a"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Replicated: []string{"a"}}, + }) + }, + }, + { + // Same as above, but with replicated shared locks. + name: "gets with key locking (shared, replicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanA := getArgsString("a") + scanA.KeyLockingStrength = lock.Shared + scanA.KeyLockingDurability = lock.Replicated + d.ba.Add(scanA) + scanG := getArgsString("g") + scanG.KeyLockingStrength = lock.Shared + scanG.KeyLockingDurability = lock.Replicated + d.ba.Add(scanG) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"a"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Shared: {lock.Replicated: []string{"a"}}, + }) }, }, { @@ -330,53 +416,216 @@ func TestEvaluateBatch(t *testing.T) { }, check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil) - verifyAcquiredLocks(t, r, lock.Unreplicated, []string(nil)...) - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { // Three scans that observe 3, 1, and 0 keys, respectively. An // unreplicated lock should be acquired on each key that is scanned. - name: "scans with key locking", + name: "scans with key locking (exclusive, unreplicated)", setup: func(t *testing.T, d *data) { writeABCDEFAt(t, d, ts.Prev()) scanAD := scanArgsString("a", "d") scanAD.KeyLockingStrength = lock.Exclusive + scanAD.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanAD) scanEF := scanArgsString("e", "f") scanEF.KeyLockingStrength = lock.Exclusive + scanEF.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanEF) scanHJ := scanArgsString("h", "j") scanHJ.KeyLockingStrength = lock.Exclusive + scanHJ.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanHJ) d.ba.Txn = &txn }, check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b", "c"}, []string{"e"}, nil) - verifyAcquiredLocks(t, r, lock.Unreplicated, "a", "b", "c", "e") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"a", "b", "c", "e"}}, + }) }, }, { - // Ditto in reverse. - name: "reverse scans with key locking", + // Same as above, but with shared locks. + name: "scans with key locking (shared, unreplicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanAD := scanArgsString("a", "d") + scanAD.KeyLockingStrength = lock.Shared + scanAD.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanAD) + scanEF := scanArgsString("e", "f") + scanEF.KeyLockingStrength = lock.Shared + scanEF.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanEF) + scanHJ := scanArgsString("h", "j") + scanHJ.KeyLockingStrength = lock.Shared + scanHJ.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanHJ) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"a", "b", "c"}, []string{"e"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Shared: {lock.Unreplicated: []string{"a", "b", "c", "e"}}, + }) + }, + }, + { + // Same as above, but with replicated exclusive locks. + name: "scans with key locking (exclusive, replicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanAD := scanArgsString("a", "d") + scanAD.KeyLockingStrength = lock.Exclusive + scanAD.KeyLockingDurability = lock.Replicated + d.ba.Add(scanAD) + scanEF := scanArgsString("e", "f") + scanEF.KeyLockingStrength = lock.Exclusive + scanEF.KeyLockingDurability = lock.Replicated + d.ba.Add(scanEF) + scanHJ := scanArgsString("h", "j") + scanHJ.KeyLockingStrength = lock.Exclusive + scanHJ.KeyLockingDurability = lock.Replicated + d.ba.Add(scanHJ) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"a", "b", "c"}, []string{"e"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Replicated: []string{"a", "b", "c", "e"}}, + }) + }, + }, + { + // Same as above, but with replicated shared locks. + name: "scans with key locking (shared, replicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanAD := scanArgsString("a", "d") + scanAD.KeyLockingStrength = lock.Shared + scanAD.KeyLockingDurability = lock.Replicated + d.ba.Add(scanAD) + scanEF := scanArgsString("e", "f") + scanEF.KeyLockingStrength = lock.Shared + scanEF.KeyLockingDurability = lock.Replicated + d.ba.Add(scanEF) + scanHJ := scanArgsString("h", "j") + scanHJ.KeyLockingStrength = lock.Shared + scanHJ.KeyLockingDurability = lock.Replicated + d.ba.Add(scanHJ) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"a", "b", "c"}, []string{"e"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Shared: {lock.Replicated: []string{"a", "b", "c", "e"}}, + }) + }, + }, + { + // Ditto in reverse with exclusive locks. + name: "reverse scans with key locking (exclusive, unreplicated)", setup: func(t *testing.T, d *data) { writeABCDEFAt(t, d, ts.Prev()) scanAD := revScanArgsString("a", "d") scanAD.KeyLockingStrength = lock.Exclusive + scanAD.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanAD) scanEF := revScanArgsString("e", "f") scanEF.KeyLockingStrength = lock.Exclusive + scanEF.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanEF) scanHJ := revScanArgsString("h", "j") scanHJ.KeyLockingStrength = lock.Exclusive + scanHJ.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanHJ) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"c", "b", "a"}, []string{"e"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"c", "b", "a", "e"}}, + }) + }, + }, + { + // Same as above, but with shared locks. + name: "reverse scans with key locking (shared, unreplicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanAD := revScanArgsString("a", "d") + scanAD.KeyLockingStrength = lock.Shared + scanAD.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanAD) + scanEF := revScanArgsString("e", "f") + scanEF.KeyLockingStrength = lock.Shared + scanEF.KeyLockingDurability = lock.Unreplicated + d.ba.Add(scanEF) + scanHJ := revScanArgsString("h", "j") + scanHJ.KeyLockingStrength = lock.Shared + scanHJ.KeyLockingDurability = lock.Unreplicated d.ba.Add(scanHJ) d.ba.Txn = &txn }, check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"c", "b", "a"}, []string{"e"}, nil) - verifyAcquiredLocks(t, r, lock.Unreplicated, "c", "b", "a", "e") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Shared: {lock.Unreplicated: []string{"c", "b", "a", "e"}}, + }) + }, + }, + { + // Same as above, but with replicated exclusive locks. + name: "reverse scans with key locking (exclusive, replicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanAD := revScanArgsString("a", "d") + scanAD.KeyLockingStrength = lock.Exclusive + scanAD.KeyLockingDurability = lock.Replicated + d.ba.Add(scanAD) + scanEF := revScanArgsString("e", "f") + scanEF.KeyLockingStrength = lock.Exclusive + scanEF.KeyLockingDurability = lock.Replicated + d.ba.Add(scanEF) + scanHJ := revScanArgsString("h", "j") + scanHJ.KeyLockingStrength = lock.Exclusive + scanHJ.KeyLockingDurability = lock.Replicated + d.ba.Add(scanHJ) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"c", "b", "a"}, []string{"e"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Replicated: []string{"c", "b", "a", "e"}}, + }) + }, + }, + { + // Same as above, but with replicated shared locks. + name: "reverse scans with key locking (shared, replicated)", + setup: func(t *testing.T, d *data) { + writeABCDEFAt(t, d, ts.Prev()) + scanAD := revScanArgsString("a", "d") + scanAD.KeyLockingStrength = lock.Shared + scanAD.KeyLockingDurability = lock.Replicated + d.ba.Add(scanAD) + scanEF := revScanArgsString("e", "f") + scanEF.KeyLockingStrength = lock.Shared + scanEF.KeyLockingDurability = lock.Replicated + d.ba.Add(scanEF) + scanHJ := revScanArgsString("h", "j") + scanHJ.KeyLockingStrength = lock.Shared + scanHJ.KeyLockingDurability = lock.Replicated + d.ba.Add(scanHJ) + d.ba.Txn = &txn + }, + check: func(t *testing.T, r resp) { + verifyScanResult(t, r, []string{"c", "b", "a"}, []string{"e"}, nil) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Shared: {lock.Replicated: []string{"c", "b", "a", "e"}}, + }) }, }, { @@ -397,8 +646,7 @@ func TestEvaluateBatch(t *testing.T) { }, check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b", "c"}, []string{"e"}, nil) - verifyAcquiredLocks(t, r, lock.Unreplicated, []string(nil)...) - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { @@ -418,8 +666,7 @@ func TestEvaluateBatch(t *testing.T) { }, check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"c", "b", "a"}, []string{"e"}, nil) - verifyAcquiredLocks(t, r, lock.Unreplicated, []string(nil)...) - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { @@ -439,8 +686,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b", "c"}) verifyResumeSpans(t, r, "d-e") - verifyAcquiredLocks(t, r, lock.Unreplicated, "a", "b", "c") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"a", "b", "c"}}, + }) }, }, { @@ -457,8 +705,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"d", "c", "b"}) verifyResumeSpans(t, r, "a-a\x00") - verifyAcquiredLocks(t, r, lock.Unreplicated, "d", "c", "b") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"d", "c", "b"}}, + }) }, }, { @@ -482,8 +731,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a", "b", "c"}, nil) verifyResumeSpans(t, r, "d-e", "h-j") - verifyAcquiredLocks(t, r, lock.Unreplicated, "a", "b", "c") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"a", "b", "c"}}, + }) }, }, { @@ -503,8 +753,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"d", "c", "b"}, nil) verifyResumeSpans(t, r, "a-a\x00", "h-j") - verifyAcquiredLocks(t, r, lock.Unreplicated, "d", "c", "b") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"d", "c", "b"}}, + }) }, }, { @@ -523,8 +774,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}) verifyResumeSpans(t, r, "b-e") - verifyAcquiredLocks(t, r, lock.Unreplicated, "a") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"a"}}, + }) }, }, { @@ -541,8 +793,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"d"}) verifyResumeSpans(t, r, "a-c\x00") - verifyAcquiredLocks(t, r, lock.Unreplicated, "d") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"d"}}, + }) }, }, { @@ -565,8 +818,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"a"}, nil) verifyResumeSpans(t, r, "b-e", "h-j") - verifyAcquiredLocks(t, r, lock.Unreplicated, "a") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"a"}}, + }) }, }, { @@ -586,8 +840,9 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyScanResult(t, r, []string{"d"}, nil) verifyResumeSpans(t, r, "a-c\x00", "h-j") - verifyAcquiredLocks(t, r, lock.Unreplicated, "d") - verifyAcquiredLocks(t, r, lock.Replicated, []string(nil)...) + verifyAcquiredLocks(t, r, acquiredLocks{ + lock.Exclusive: {lock.Unreplicated: []string{"d"}}, + }) }, }, // @@ -606,6 +861,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyNumKeys(t, r, 3, 1, 0) verifyResumeSpans(t, r, "", "", "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { @@ -621,6 +877,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyNumKeys(t, r, 3, 1, 0) verifyResumeSpans(t, r, "", "", "") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { @@ -637,6 +894,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyNumKeys(t, r, 2, 0, 0) verifyResumeSpans(t, r, "b\x00-d", "e-f", "h-j") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, { @@ -653,6 +911,7 @@ func TestEvaluateBatch(t *testing.T) { check: func(t *testing.T, r resp) { verifyNumKeys(t, r, 3, 0, 0) verifyResumeSpans(t, r, "", "e-f", "h-j") + verifyAcquiredLocks(t, r, acquiredLocks{}) }, }, } @@ -796,13 +1055,17 @@ func verifyResumeSpans(t *testing.T, r resp, resumeSpans ...string) { } } -func verifyAcquiredLocks(t *testing.T, r resp, dur lock.Durability, lockedKeys ...string) { +type acquiredLocks map[lock.Strength]map[lock.Durability][]string + +func verifyAcquiredLocks(t *testing.T, r resp, expLocked acquiredLocks) { t.Helper() - var foundLocked []string + foundLocked := make(acquiredLocks) for _, l := range r.res.Local.AcquiredLocks { - if l.Durability == dur { - foundLocked = append(foundLocked, string(l.Key)) + if foundLocked[l.Strength] == nil { + foundLocked[l.Strength] = make(map[lock.Durability][]string) } + cur := foundLocked[l.Strength][l.Durability] + foundLocked[l.Strength][l.Durability] = append(cur, string(l.Key)) } - require.Equal(t, lockedKeys, foundLocked) + require.Equal(t, expLocked, foundLocked) }