github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/storage/batch_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 storage
    12  
    13  import (
    14  	"bytes"
    15  	"context"
    16  	"fmt"
    17  	"reflect"
    18  	"sync/atomic"
    19  	"testing"
    20  
    21  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    22  	"github.com/cockroachdb/cockroach/pkg/storage/enginepb"
    23  	"github.com/cockroachdb/cockroach/pkg/testutils"
    24  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    25  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    26  	"github.com/cockroachdb/cockroach/pkg/util/protoutil"
    27  	"github.com/cockroachdb/cockroach/pkg/util/randutil"
    28  	"github.com/cockroachdb/cockroach/pkg/util/stop"
    29  	"github.com/cockroachdb/errors"
    30  	"github.com/gogo/protobuf/proto"
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  func mvccKey(k interface{}) MVCCKey {
    35  	switch k := k.(type) {
    36  	case string:
    37  		return MakeMVCCMetadataKey(roachpb.Key(k))
    38  	case []byte:
    39  		return MakeMVCCMetadataKey(roachpb.Key(k))
    40  	case roachpb.Key:
    41  		return MakeMVCCMetadataKey(k)
    42  	case roachpb.RKey:
    43  		return MakeMVCCMetadataKey(roachpb.Key(k))
    44  	default:
    45  		panic(fmt.Sprintf("unsupported type: %T", k))
    46  	}
    47  }
    48  
    49  func testBatchBasics(t *testing.T, writeOnly bool, commit func(e Engine, b Batch) error) {
    50  	for _, engineImpl := range mvccEngineImpls {
    51  		t.Run(engineImpl.name, func(t *testing.T) {
    52  			e := engineImpl.create()
    53  			defer e.Close()
    54  
    55  			var b Batch
    56  			if writeOnly {
    57  				b = e.NewWriteOnlyBatch()
    58  			} else {
    59  				b = e.NewBatch()
    60  			}
    61  			defer b.Close()
    62  
    63  			if err := b.Put(mvccKey("a"), []byte("value")); err != nil {
    64  				t.Fatal(err)
    65  			}
    66  			// Write an engine value to be deleted.
    67  			if err := e.Put(mvccKey("b"), []byte("value")); err != nil {
    68  				t.Fatal(err)
    69  			}
    70  			if err := b.Clear(mvccKey("b")); err != nil {
    71  				t.Fatal(err)
    72  			}
    73  			// Write an engine value to be merged.
    74  			if err := e.Put(mvccKey("c"), appender("foo")); err != nil {
    75  				t.Fatal(err)
    76  			}
    77  			if err := b.Merge(mvccKey("c"), appender("bar")); err != nil {
    78  				t.Fatal(err)
    79  			}
    80  			// Write a key with an empty value.
    81  			if err := b.Put(mvccKey("e"), nil); err != nil {
    82  				t.Fatal(err)
    83  			}
    84  			// Write an engine value to be single deleted.
    85  			if err := e.Put(mvccKey("d"), []byte("before")); err != nil {
    86  				t.Fatal(err)
    87  			}
    88  			if err := b.SingleClear(mvccKey("d")); err != nil {
    89  				t.Fatal(err)
    90  			}
    91  
    92  			// Check all keys are in initial state (nothing from batch has gone
    93  			// through to engine until commit).
    94  			expValues := []MVCCKeyValue{
    95  				{Key: mvccKey("b"), Value: []byte("value")},
    96  				{Key: mvccKey("c"), Value: appender("foo")},
    97  				{Key: mvccKey("d"), Value: []byte("before")},
    98  			}
    99  			kvs, err := Scan(e, roachpb.KeyMin, roachpb.KeyMax, 0)
   100  			if err != nil {
   101  				t.Fatal(err)
   102  			}
   103  			if !reflect.DeepEqual(expValues, kvs) {
   104  				t.Fatalf("%v != %v", kvs, expValues)
   105  			}
   106  
   107  			// Now, merged values should be:
   108  			expValues = []MVCCKeyValue{
   109  				{Key: mvccKey("a"), Value: []byte("value")},
   110  				{Key: mvccKey("c"), Value: appender("foobar")},
   111  				{Key: mvccKey("e"), Value: []byte{}},
   112  			}
   113  			if !writeOnly {
   114  				// Scan values from batch directly.
   115  				kvs, err = Scan(b, roachpb.KeyMin, roachpb.KeyMax, 0)
   116  				if err != nil {
   117  					t.Fatal(err)
   118  				}
   119  				if !reflect.DeepEqual(expValues, kvs) {
   120  					t.Errorf("%v != %v", kvs, expValues)
   121  				}
   122  			}
   123  
   124  			// Commit batch and verify direct engine scan yields correct values.
   125  			if err := commit(e, b); err != nil {
   126  				t.Fatal(err)
   127  			}
   128  			kvs, err = Scan(e, roachpb.KeyMin, roachpb.KeyMax, 0)
   129  			if err != nil {
   130  				t.Fatal(err)
   131  			}
   132  			if !reflect.DeepEqual(expValues, kvs) {
   133  				t.Errorf("%v != %v", kvs, expValues)
   134  			}
   135  		})
   136  	}
   137  }
   138  
   139  // TestBatchBasics verifies that all commands work in a batch, aren't
   140  // visible until commit, and then are all visible after commit.
   141  func TestBatchBasics(t *testing.T) {
   142  	defer leaktest.AfterTest(t)()
   143  	testBatchBasics(t, false /* writeOnly */, func(e Engine, b Batch) error {
   144  		return b.Commit(false /* sync */)
   145  	})
   146  }
   147  
   148  func shouldPanic(t *testing.T, f func(), funcName string, expectedPanicStr string) {
   149  	defer func() {
   150  		if r := recover(); r == nil {
   151  			t.Fatalf("%v: test did not panic", funcName)
   152  		} else if r != expectedPanicStr {
   153  			t.Fatalf("%v: unexpected panic: %v", funcName, r)
   154  		}
   155  	}()
   156  	f()
   157  }
   158  
   159  func shouldNotPanic(t *testing.T, f func(), funcName string) {
   160  	defer func() {
   161  		if r := recover(); r != nil {
   162  			t.Fatalf("%v: unexpected panic: %v", funcName, r)
   163  		}
   164  	}()
   165  	f()
   166  }
   167  
   168  // TestReadOnlyBasics verifies that for a read-only ReadWriter (obtained via
   169  // engine.NewReadOnly()) all Reader methods work, and all Writer methods panic
   170  // as "not implemented". Also basic iterating functionality is verified.
   171  func TestReadOnlyBasics(t *testing.T) {
   172  	defer leaktest.AfterTest(t)()
   173  
   174  	for _, engineImpl := range mvccEngineImpls {
   175  		t.Run(engineImpl.name, func(t *testing.T) {
   176  			e := engineImpl.create()
   177  			defer e.Close()
   178  
   179  			ro := e.NewReadOnly()
   180  			if ro.Closed() {
   181  				t.Fatal("read-only is expectedly found to be closed")
   182  			}
   183  			a := mvccKey("a")
   184  			getVal := &roachpb.Value{}
   185  			successTestCases := []func(){
   186  				func() { _, _ = ro.Get(a) },
   187  				func() { _, _, _, _ = ro.GetProto(a, getVal) },
   188  				func() { _ = ro.Iterate(a.Key, a.Key, func(MVCCKeyValue) (bool, error) { return true, nil }) },
   189  				func() { ro.NewIterator(IterOptions{UpperBound: roachpb.KeyMax}).Close() },
   190  				func() {
   191  					ro.NewIterator(IterOptions{
   192  						MinTimestampHint: hlc.MinTimestamp,
   193  						MaxTimestampHint: hlc.MaxTimestamp,
   194  						UpperBound:       roachpb.KeyMax,
   195  					}).Close()
   196  				},
   197  			}
   198  			defer func() {
   199  				ro.Close()
   200  				if !ro.Closed() {
   201  					t.Fatal("even after calling Close, a read-only should not be closed")
   202  				}
   203  				name := "rocksDBReadOnly"
   204  				if engineImpl.name == "pebble" {
   205  					name = "pebbleReadOnly"
   206  				}
   207  				shouldPanic(t, func() { ro.Close() }, "Close", "closing an already-closed "+name)
   208  				for i, f := range successTestCases {
   209  					shouldPanic(t, f, string(i), "using a closed "+name)
   210  				}
   211  			}()
   212  
   213  			for i, f := range successTestCases {
   214  				shouldNotPanic(t, f, string(i))
   215  			}
   216  
   217  			// For a read-only ReadWriter, all Writer methods should panic.
   218  			failureTestCases := []func(){
   219  				func() { _ = ro.ApplyBatchRepr(nil, false) },
   220  				func() { _ = ro.Clear(a) },
   221  				func() { _ = ro.SingleClear(a) },
   222  				func() { _ = ro.ClearRange(a, a) },
   223  				func() { _ = ro.Merge(a, nil) },
   224  				func() { _ = ro.Put(a, nil) },
   225  			}
   226  			for i, f := range failureTestCases {
   227  				shouldPanic(t, f, string(i), "not implemented")
   228  			}
   229  
   230  			if err := e.Put(mvccKey("a"), []byte("value")); err != nil {
   231  				t.Fatal(err)
   232  			}
   233  			if err := e.Put(mvccKey("b"), []byte("value")); err != nil {
   234  				t.Fatal(err)
   235  			}
   236  			if err := e.Clear(mvccKey("b")); err != nil {
   237  				t.Fatal(err)
   238  			}
   239  			if err := e.Put(mvccKey("c"), appender("foo")); err != nil {
   240  				t.Fatal(err)
   241  			}
   242  			if err := e.Merge(mvccKey("c"), appender("bar")); err != nil {
   243  				t.Fatal(err)
   244  			}
   245  			if err := e.Put(mvccKey("d"), []byte("value")); err != nil {
   246  				t.Fatal(err)
   247  			}
   248  			if err := e.SingleClear(mvccKey("d")); err != nil {
   249  				t.Fatal(err)
   250  			}
   251  
   252  			// Now, merged values should be:
   253  			expValues := []MVCCKeyValue{
   254  				{Key: mvccKey("a"), Value: []byte("value")},
   255  				{Key: mvccKey("c"), Value: appender("foobar")},
   256  			}
   257  
   258  			kvs, err := Scan(e, roachpb.KeyMin, roachpb.KeyMax, 0)
   259  			if err != nil {
   260  				t.Fatal(err)
   261  			}
   262  			if !reflect.DeepEqual(expValues, kvs) {
   263  				t.Errorf("%v != %v", kvs, expValues)
   264  			}
   265  		})
   266  	}
   267  }
   268  
   269  func TestBatchRepr(t *testing.T) {
   270  	defer leaktest.AfterTest(t)()
   271  	testBatchBasics(t, false /* writeOnly */, func(e Engine, b Batch) error {
   272  		repr := b.Repr()
   273  
   274  		r, err := NewRocksDBBatchReader(repr)
   275  		if err != nil {
   276  			t.Fatalf("%+v", err)
   277  		}
   278  		const expectedCount = 5
   279  		if count := r.Count(); count != expectedCount {
   280  			t.Fatalf("bad count: RocksDBBatchReader.Count expected %d, but found %d", expectedCount, count)
   281  		}
   282  		if count, err := RocksDBBatchCount(repr); err != nil {
   283  			t.Fatal(err)
   284  		} else if count != expectedCount {
   285  			t.Fatalf("bad count: RocksDBBatchCount expected %d, but found %d", expectedCount, count)
   286  		}
   287  
   288  		var ops []string
   289  		for i := 0; i < r.Count(); i++ {
   290  			if ok := r.Next(); !ok {
   291  				t.Fatalf("%d: unexpected end of batch", i)
   292  			}
   293  			switch r.BatchType() {
   294  			case BatchTypeDeletion:
   295  				ops = append(ops, fmt.Sprintf("delete(%s)", string(r.Key())))
   296  			case BatchTypeValue:
   297  				ops = append(ops, fmt.Sprintf("put(%s,%s)", string(r.Key()), string(r.Value())))
   298  			case BatchTypeMerge:
   299  				// The merge value is a protobuf and not easily displayable.
   300  				ops = append(ops, fmt.Sprintf("merge(%s)", string(r.Key())))
   301  			case BatchTypeSingleDeletion:
   302  				ops = append(ops, fmt.Sprintf("single_delete(%s)", string(r.Key())))
   303  			}
   304  		}
   305  		if err != nil {
   306  			t.Fatalf("unexpected err during iteration: %+v", err)
   307  		}
   308  		if ok := r.Next(); ok {
   309  			t.Errorf("expected end of batch")
   310  		}
   311  
   312  		// The keys in the batch have the internal MVCC encoding applied which for
   313  		// this test implies an appended 0 byte.
   314  		expOps := []string{
   315  			"put(a\x00,value)",
   316  			"delete(b\x00)",
   317  			"merge(c\x00)",
   318  			"put(e\x00,)",
   319  			"single_delete(d\x00)",
   320  		}
   321  		if !reflect.DeepEqual(expOps, ops) {
   322  			t.Fatalf("expected %v, but found %v", expOps, ops)
   323  		}
   324  
   325  		return e.ApplyBatchRepr(repr, false /* sync */)
   326  	})
   327  }
   328  
   329  func TestWriteBatchBasics(t *testing.T) {
   330  	defer leaktest.AfterTest(t)()
   331  	testBatchBasics(t, true /* writeOnly */, func(e Engine, b Batch) error {
   332  		return b.Commit(false /* sync */)
   333  	})
   334  }
   335  
   336  // Regression test for flush issue which caused
   337  // b2.ApplyBatchRepr(b1.Repr()).Repr() to not equal a noop.
   338  func TestApplyBatchRepr(t *testing.T) {
   339  	defer leaktest.AfterTest(t)()
   340  
   341  	for _, engineImpl := range mvccEngineImpls {
   342  		t.Run(engineImpl.name, func(t *testing.T) {
   343  			e := engineImpl.create()
   344  			defer e.Close()
   345  
   346  			// Failure to represent the absorbed Batch again.
   347  			{
   348  				b1 := e.NewBatch()
   349  				defer b1.Close()
   350  
   351  				if err := b1.Put(mvccKey("lost"), []byte("update")); err != nil {
   352  					t.Fatal(err)
   353  				}
   354  
   355  				repr1 := b1.Repr()
   356  
   357  				b2 := e.NewBatch()
   358  				defer b2.Close()
   359  				if err := b2.ApplyBatchRepr(repr1, false /* sync */); err != nil {
   360  					t.Fatal(err)
   361  				}
   362  				repr2 := b2.Repr()
   363  
   364  				if !reflect.DeepEqual(repr1, repr2) {
   365  					t.Fatalf("old batch represents to:\n%q\nrestored batch to:\n%q", repr1, repr2)
   366  				}
   367  			}
   368  
   369  			// Failure to commit what was absorbed.
   370  			{
   371  				b3 := e.NewBatch()
   372  				defer b3.Close()
   373  
   374  				key := mvccKey("phantom")
   375  				val := []byte("phantom")
   376  
   377  				if err := b3.Put(key, val); err != nil {
   378  					t.Fatal(err)
   379  				}
   380  
   381  				repr := b3.Repr()
   382  
   383  				b4 := e.NewBatch()
   384  				defer b4.Close()
   385  				if err := b4.ApplyBatchRepr(repr, false /* sync */); err != nil {
   386  					t.Fatal(err)
   387  				}
   388  				// Intentionally don't call Repr() because the expected user wouldn't.
   389  				if err := b4.Commit(false /* sync */); err != nil {
   390  					t.Fatal(err)
   391  				}
   392  
   393  				if b, err := e.Get(key); err != nil {
   394  					t.Fatal(err)
   395  				} else if !reflect.DeepEqual(b, val) {
   396  					t.Fatalf("read %q from engine, expected %q", b, val)
   397  				}
   398  			}
   399  		})
   400  	}
   401  }
   402  
   403  func TestBatchGet(t *testing.T) {
   404  	defer leaktest.AfterTest(t)()
   405  
   406  	for _, engineImpl := range mvccEngineImpls {
   407  		t.Run(engineImpl.name, func(t *testing.T) {
   408  			e := engineImpl.create()
   409  			defer e.Close()
   410  
   411  			b := e.NewBatch()
   412  			defer b.Close()
   413  
   414  			// Write initial values, then write to batch.
   415  			if err := e.Put(mvccKey("b"), []byte("value")); err != nil {
   416  				t.Fatal(err)
   417  			}
   418  			if err := e.Put(mvccKey("c"), appender("foo")); err != nil {
   419  				t.Fatal(err)
   420  			}
   421  			// Write batch values.
   422  			if err := b.Put(mvccKey("a"), []byte("value")); err != nil {
   423  				t.Fatal(err)
   424  			}
   425  			if err := b.Clear(mvccKey("b")); err != nil {
   426  				t.Fatal(err)
   427  			}
   428  			if err := b.Merge(mvccKey("c"), appender("bar")); err != nil {
   429  				t.Fatal(err)
   430  			}
   431  			if err := b.Put(mvccKey("d"), []byte("before")); err != nil {
   432  				t.Fatal(err)
   433  			}
   434  			if err := b.SingleClear(mvccKey("d")); err != nil {
   435  				t.Fatal(err)
   436  			}
   437  			if err := b.Put(mvccKey("d"), []byte("after")); err != nil {
   438  				t.Fatal(err)
   439  			}
   440  
   441  			expValues := []MVCCKeyValue{
   442  				{Key: mvccKey("a"), Value: []byte("value")},
   443  				{Key: mvccKey("b"), Value: nil},
   444  				{Key: mvccKey("c"), Value: appender("foobar")},
   445  				{Key: mvccKey("d"), Value: []byte("after")},
   446  			}
   447  			for i, expKV := range expValues {
   448  				kv, err := b.Get(expKV.Key)
   449  				if err != nil {
   450  					t.Fatal(err)
   451  				}
   452  				if !bytes.Equal(kv, expKV.Value) {
   453  					t.Errorf("%d: expected \"value\", got %q", i, kv)
   454  				}
   455  			}
   456  		})
   457  	}
   458  }
   459  
   460  func compareMergedValues(t *testing.T, result, expected []byte) bool {
   461  	var resultV, expectedV enginepb.MVCCMetadata
   462  	if err := protoutil.Unmarshal(result, &resultV); err != nil {
   463  		t.Fatal(err)
   464  	}
   465  	if err := protoutil.Unmarshal(expected, &expectedV); err != nil {
   466  		t.Fatal(err)
   467  	}
   468  	return reflect.DeepEqual(resultV, expectedV)
   469  }
   470  
   471  func TestBatchMerge(t *testing.T) {
   472  	defer leaktest.AfterTest(t)()
   473  
   474  	for _, engineImpl := range mvccEngineImpls {
   475  		t.Run(engineImpl.name, func(t *testing.T) {
   476  			e := engineImpl.create()
   477  			defer e.Close()
   478  
   479  			b := e.NewBatch()
   480  			defer b.Close()
   481  
   482  			// Write batch put, delete & merge.
   483  			if err := b.Put(mvccKey("a"), appender("a-value")); err != nil {
   484  				t.Fatal(err)
   485  			}
   486  			if err := b.Clear(mvccKey("b")); err != nil {
   487  				t.Fatal(err)
   488  			}
   489  			if err := b.Merge(mvccKey("c"), appender("c-value")); err != nil {
   490  				t.Fatal(err)
   491  			}
   492  
   493  			// Now, merge to all three keys.
   494  			if err := b.Merge(mvccKey("a"), appender("append")); err != nil {
   495  				t.Fatal(err)
   496  			}
   497  			if err := b.Merge(mvccKey("b"), appender("append")); err != nil {
   498  				t.Fatal(err)
   499  			}
   500  			if err := b.Merge(mvccKey("c"), appender("append")); err != nil {
   501  				t.Fatal(err)
   502  			}
   503  
   504  			// Verify values.
   505  			val, err := b.Get(mvccKey("a"))
   506  			if err != nil {
   507  				t.Fatal(err)
   508  			}
   509  			if !compareMergedValues(t, val, appender("a-valueappend")) {
   510  				t.Error("mismatch of \"a\"")
   511  			}
   512  
   513  			val, err = b.Get(mvccKey("b"))
   514  			if err != nil {
   515  				t.Fatal(err)
   516  			}
   517  			if !compareMergedValues(t, val, appender("append")) {
   518  				t.Error("mismatch of \"b\"")
   519  			}
   520  
   521  			val, err = b.Get(mvccKey("c"))
   522  			if err != nil {
   523  				t.Fatal(err)
   524  			}
   525  			if !compareMergedValues(t, val, appender("c-valueappend")) {
   526  				t.Error("mismatch of \"c\"")
   527  			}
   528  		})
   529  	}
   530  }
   531  
   532  func TestBatchProto(t *testing.T) {
   533  	defer leaktest.AfterTest(t)()
   534  
   535  	for _, engineImpl := range mvccEngineImpls {
   536  		t.Run(engineImpl.name, func(t *testing.T) {
   537  			e := engineImpl.create()
   538  			defer e.Close()
   539  
   540  			b := e.NewBatch()
   541  			defer b.Close()
   542  
   543  			val := roachpb.MakeValueFromString("value")
   544  			if _, _, err := PutProto(b, mvccKey("proto"), &val); err != nil {
   545  				t.Fatal(err)
   546  			}
   547  			getVal := &roachpb.Value{}
   548  			ok, keySize, valSize, err := b.GetProto(mvccKey("proto"), getVal)
   549  			if !ok || err != nil {
   550  				t.Fatalf("expected GetProto to success ok=%t: %+v", ok, err)
   551  			}
   552  			if keySize != 6 {
   553  				t.Errorf("expected key size 6; got %d", keySize)
   554  			}
   555  			data, err := protoutil.Marshal(&val)
   556  			if err != nil {
   557  				t.Fatal(err)
   558  			}
   559  			if valSize != int64(len(data)) {
   560  				t.Errorf("expected value size %d; got %d", len(data), valSize)
   561  			}
   562  			if !proto.Equal(getVal, &val) {
   563  				t.Errorf("expected %v; got %v", &val, getVal)
   564  			}
   565  			// Before commit, proto will not be available via engine.
   566  			fmt.Printf("before\n")
   567  			if ok, _, _, err := e.GetProto(mvccKey("proto"), getVal); ok || err != nil {
   568  				fmt.Printf("after\n")
   569  				t.Fatalf("expected GetProto to fail ok=%t: %+v", ok, err)
   570  			}
   571  			// Commit and verify the proto can be read directly from the engine.
   572  			if err := b.Commit(false /* sync */); err != nil {
   573  				t.Fatal(err)
   574  			}
   575  			if ok, _, _, err := e.GetProto(mvccKey("proto"), getVal); !ok || err != nil {
   576  				t.Fatalf("expected GetProto to success ok=%t: %+v", ok, err)
   577  			}
   578  			if !proto.Equal(getVal, &val) {
   579  				t.Errorf("expected %v; got %v", &val, getVal)
   580  			}
   581  		})
   582  	}
   583  }
   584  
   585  func TestBatchScan(t *testing.T) {
   586  	defer leaktest.AfterTest(t)()
   587  
   588  	for _, engineImpl := range mvccEngineImpls {
   589  		t.Run(engineImpl.name, func(t *testing.T) {
   590  			e := engineImpl.create()
   591  			defer e.Close()
   592  
   593  			b := e.NewBatch()
   594  			defer b.Close()
   595  
   596  			existingVals := []MVCCKeyValue{
   597  				{Key: mvccKey("a"), Value: []byte("1")},
   598  				{Key: mvccKey("b"), Value: []byte("2")},
   599  				{Key: mvccKey("c"), Value: []byte("3")},
   600  				{Key: mvccKey("d"), Value: []byte("4")},
   601  				{Key: mvccKey("e"), Value: []byte("5")},
   602  				{Key: mvccKey("f"), Value: []byte("6")},
   603  				{Key: mvccKey("g"), Value: []byte("7")},
   604  				{Key: mvccKey("h"), Value: []byte("8")},
   605  				{Key: mvccKey("i"), Value: []byte("9")},
   606  				{Key: mvccKey("j"), Value: []byte("10")},
   607  				{Key: mvccKey("k"), Value: []byte("11")},
   608  				{Key: mvccKey("l"), Value: []byte("12")},
   609  				{Key: mvccKey("m"), Value: []byte("13")},
   610  			}
   611  			for _, kv := range existingVals {
   612  				if err := e.Put(kv.Key, kv.Value); err != nil {
   613  					t.Fatal(err)
   614  				}
   615  			}
   616  
   617  			batchVals := []MVCCKeyValue{
   618  				{Key: mvccKey("a"), Value: []byte("b1")},
   619  				{Key: mvccKey("bb"), Value: []byte("b2")},
   620  				{Key: mvccKey("c"), Value: []byte("b3")},
   621  				{Key: mvccKey("dd"), Value: []byte("b4")},
   622  				{Key: mvccKey("e"), Value: []byte("b5")},
   623  				{Key: mvccKey("ff"), Value: []byte("b6")},
   624  				{Key: mvccKey("g"), Value: []byte("b7")},
   625  				{Key: mvccKey("hh"), Value: []byte("b8")},
   626  				{Key: mvccKey("i"), Value: []byte("b9")},
   627  				{Key: mvccKey("jj"), Value: []byte("b10")},
   628  			}
   629  			for _, kv := range batchVals {
   630  				if err := b.Put(kv.Key, kv.Value); err != nil {
   631  					t.Fatal(err)
   632  				}
   633  			}
   634  
   635  			scans := []struct {
   636  				start, end roachpb.Key
   637  				max        int64
   638  			}{
   639  				// Full monty.
   640  				{start: roachpb.Key("a"), end: roachpb.Key("z"), max: 0},
   641  				// Select ~half.
   642  				{start: roachpb.Key("a"), end: roachpb.Key("z"), max: 9},
   643  				// Select one.
   644  				{start: roachpb.Key("a"), end: roachpb.Key("z"), max: 1},
   645  				// Select half by end key.
   646  				{start: roachpb.Key("a"), end: roachpb.Key("f0"), max: 0},
   647  				// Start at half and select rest.
   648  				{start: roachpb.Key("f"), end: roachpb.Key("z"), max: 0},
   649  				// Start at last and select max=10.
   650  				{start: roachpb.Key("m"), end: roachpb.Key("z"), max: 10},
   651  			}
   652  
   653  			// Scan each case using the batch and store the results.
   654  			results := map[int][]MVCCKeyValue{}
   655  			for i, scan := range scans {
   656  				kvs, err := Scan(b, scan.start, scan.end, scan.max)
   657  				if err != nil {
   658  					t.Fatal(err)
   659  				}
   660  				results[i] = kvs
   661  			}
   662  
   663  			// Now, commit batch and re-scan using engine direct to compare results.
   664  			if err := b.Commit(false /* sync */); err != nil {
   665  				t.Fatal(err)
   666  			}
   667  			for i, scan := range scans {
   668  				kvs, err := Scan(e, scan.start, scan.end, scan.max)
   669  				if err != nil {
   670  					t.Fatal(err)
   671  				}
   672  				if !reflect.DeepEqual(kvs, results[i]) {
   673  					t.Errorf("%d: expected %v; got %v", i, results[i], kvs)
   674  				}
   675  			}
   676  		})
   677  	}
   678  }
   679  
   680  // TestBatchScanWithDelete verifies that a scan containing
   681  // a single deleted value returns nothing.
   682  func TestBatchScanWithDelete(t *testing.T) {
   683  	defer leaktest.AfterTest(t)()
   684  
   685  	for _, engineImpl := range mvccEngineImpls {
   686  		t.Run(engineImpl.name, func(t *testing.T) {
   687  			e := engineImpl.create()
   688  			defer e.Close()
   689  
   690  			b := e.NewBatch()
   691  			defer b.Close()
   692  
   693  			// Write initial value, then delete via batch.
   694  			if err := e.Put(mvccKey("a"), []byte("value")); err != nil {
   695  				t.Fatal(err)
   696  			}
   697  			if err := b.Clear(mvccKey("a")); err != nil {
   698  				t.Fatal(err)
   699  			}
   700  			kvs, err := Scan(b, roachpb.KeyMin, roachpb.KeyMax, 0)
   701  			if err != nil {
   702  				t.Fatal(err)
   703  			}
   704  			if len(kvs) != 0 {
   705  				t.Errorf("expected empty scan with batch-deleted value; got %v", kvs)
   706  			}
   707  		})
   708  	}
   709  }
   710  
   711  // TestBatchScanMaxWithDeleted verifies that if a deletion
   712  // in the updates map shadows an entry from the engine, the
   713  // max on a scan is still reached.
   714  func TestBatchScanMaxWithDeleted(t *testing.T) {
   715  	defer leaktest.AfterTest(t)()
   716  
   717  	for _, engineImpl := range mvccEngineImpls {
   718  		t.Run(engineImpl.name, func(t *testing.T) {
   719  			e := engineImpl.create()
   720  			defer e.Close()
   721  
   722  			b := e.NewBatch()
   723  			defer b.Close()
   724  
   725  			// Write two values.
   726  			if err := e.Put(mvccKey("a"), []byte("value1")); err != nil {
   727  				t.Fatal(err)
   728  			}
   729  			if err := e.Put(mvccKey("b"), []byte("value2")); err != nil {
   730  				t.Fatal(err)
   731  			}
   732  			// Now, delete "a" in batch.
   733  			if err := b.Clear(mvccKey("a")); err != nil {
   734  				t.Fatal(err)
   735  			}
   736  			// A scan with max=1 should scan "b".
   737  			kvs, err := Scan(b, roachpb.KeyMin, roachpb.KeyMax, 1)
   738  			if err != nil {
   739  				t.Fatal(err)
   740  			}
   741  			if len(kvs) != 1 || !bytes.Equal(kvs[0].Key.Key, []byte("b")) {
   742  				t.Errorf("expected scan of \"b\"; got %v", kvs)
   743  			}
   744  		})
   745  	}
   746  }
   747  
   748  // TestBatchConcurrency verifies operation of batch when the
   749  // underlying engine has concurrent modifications to overlapping
   750  // keys. This should never happen with the way Cockroach uses
   751  // batches, but worth verifying.
   752  func TestBatchConcurrency(t *testing.T) {
   753  	defer leaktest.AfterTest(t)()
   754  
   755  	for _, engineImpl := range mvccEngineImpls {
   756  		t.Run(engineImpl.name, func(t *testing.T) {
   757  			e := engineImpl.create()
   758  			defer e.Close()
   759  
   760  			b := e.NewBatch()
   761  			defer b.Close()
   762  
   763  			// Write a merge to the batch.
   764  			if err := b.Merge(mvccKey("a"), appender("bar")); err != nil {
   765  				t.Fatal(err)
   766  			}
   767  			val, err := b.Get(mvccKey("a"))
   768  			if err != nil {
   769  				t.Fatal(err)
   770  			}
   771  			if !compareMergedValues(t, val, appender("bar")) {
   772  				t.Error("mismatch of \"a\"")
   773  			}
   774  			// Write an engine value.
   775  			if err := e.Put(mvccKey("a"), appender("foo")); err != nil {
   776  				t.Fatal(err)
   777  			}
   778  			// Now, read again and verify that the merge happens on top of the mod.
   779  			val, err = b.Get(mvccKey("a"))
   780  			if err != nil {
   781  				t.Fatal(err)
   782  			}
   783  			if !bytes.Equal(val, appender("foobar")) {
   784  				t.Error("mismatch of \"a\"")
   785  			}
   786  		})
   787  	}
   788  }
   789  
   790  func TestBatchBuilder(t *testing.T) {
   791  	defer leaktest.AfterTest(t)()
   792  
   793  	stopper := stop.NewStopper()
   794  	defer stopper.Stop(context.Background())
   795  	e := newRocksDBInMem(roachpb.Attributes{}, 1<<20)
   796  	stopper.AddCloser(e)
   797  
   798  	batch := e.NewBatch().(*rocksDBBatch)
   799  	batch.ensureBatch()
   800  	// Ensure that, even though we reach into the batch's internals with
   801  	// dbPut etc, asking for the batch's Repr will get data from C++ and
   802  	// not its unused builder.
   803  	batch.flushes++
   804  	defer batch.Close()
   805  
   806  	builder := &RocksDBBatchBuilder{}
   807  
   808  	testData := []struct {
   809  		key string
   810  		ts  hlc.Timestamp
   811  	}{
   812  		{"a", hlc.Timestamp{}},
   813  		{"b", hlc.Timestamp{WallTime: 1}},
   814  		{"c", hlc.Timestamp{WallTime: 1, Logical: 1}},
   815  	}
   816  	for _, data := range testData {
   817  		key := MVCCKey{roachpb.Key(data.key), data.ts}
   818  		if err := dbPut(batch.batch, key, []byte("value")); err != nil {
   819  			t.Fatal(err)
   820  		}
   821  		if err := dbClear(batch.batch, key); err != nil {
   822  			t.Fatal(err)
   823  		}
   824  		// TODO(itsbilal): Uncomment this when pebble.Batch supports SingleDeletion.
   825  		//if err := dbSingleClear(batch.batch, key); err != nil {
   826  		//	t.Fatal(err)
   827  		//}
   828  		if err := dbMerge(batch.batch, key, appender("bar")); err != nil {
   829  			t.Fatal(err)
   830  		}
   831  
   832  		builder.Put(key, []byte("value"))
   833  		builder.Clear(key)
   834  		// TODO(itsbilal): Uncomment this when pebble.Batch supports SingleDeletion.
   835  		//builder.SingleClear(key)
   836  		builder.Merge(key, appender("bar"))
   837  	}
   838  
   839  	batchRepr := batch.Repr()
   840  	builderRepr := builder.Finish()
   841  	if !bytes.Equal(batchRepr, builderRepr) {
   842  		t.Fatalf("expected [% x], but got [% x]", batchRepr, builderRepr)
   843  	}
   844  }
   845  
   846  func TestBatchBuilderStress(t *testing.T) {
   847  	defer leaktest.AfterTest(t)()
   848  
   849  	stopper := stop.NewStopper()
   850  	defer stopper.Stop(context.Background())
   851  	e := newRocksDBInMem(roachpb.Attributes{}, 1<<20)
   852  	stopper.AddCloser(e)
   853  
   854  	rng, _ := randutil.NewPseudoRand()
   855  
   856  	for i := 0; i < 1000; i++ {
   857  		count := 1 + rng.Intn(1000)
   858  
   859  		func() {
   860  			batch := e.NewBatch().(*rocksDBBatch)
   861  			batch.ensureBatch()
   862  			// Ensure that, even though we reach into the batch's internals with
   863  			// dbPut etc, asking for the batch's Repr will get data from C++ and
   864  			// not its unused builder.
   865  			batch.flushes++
   866  			defer batch.Close()
   867  
   868  			builder := &RocksDBBatchBuilder{}
   869  
   870  			for j := 0; j < count; j++ {
   871  				var ts hlc.Timestamp
   872  				if rng.Float32() <= 0.9 {
   873  					// Give 90% of keys timestamps.
   874  					ts.WallTime = rng.Int63()
   875  					if rng.Float32() <= 0.1 {
   876  						// Give 10% of timestamps a non-zero logical component.
   877  						ts.Logical = rng.Int31()
   878  					}
   879  				}
   880  				key := MVCCKey{
   881  					Key:       []byte(fmt.Sprintf("%d", rng.Intn(10000))),
   882  					Timestamp: ts,
   883  				}
   884  				// Generate a random mixture of puts, deletes, single deletes, and merges.
   885  				switch rng.Intn(3) {
   886  				case 0:
   887  					if err := dbPut(batch.batch, key, []byte("value")); err != nil {
   888  						t.Fatal(err)
   889  					}
   890  					builder.Put(key, []byte("value"))
   891  				case 1:
   892  					if err := dbClear(batch.batch, key); err != nil {
   893  						t.Fatal(err)
   894  					}
   895  					builder.Clear(key)
   896  				case 2:
   897  					// TODO(itsbilal): Don't test SingleClears matching up until
   898  					// pebble.Batch supports them.
   899  					//if err := dbSingleClear(batch.batch, key); err != nil {
   900  					//	t.Fatal(err)
   901  					//}
   902  					//builder.SingleClear(key)
   903  				case 3:
   904  					if err := dbMerge(batch.batch, key, appender("bar")); err != nil {
   905  						t.Fatal(err)
   906  					}
   907  					builder.Merge(key, appender("bar"))
   908  				}
   909  			}
   910  
   911  			batchRepr := batch.Repr()
   912  			builderRepr := builder.Finish()
   913  			if !bytes.Equal(batchRepr, builderRepr) {
   914  				t.Fatalf("expected [% x], but got [% x]", batchRepr, builderRepr)
   915  			}
   916  		}()
   917  	}
   918  }
   919  
   920  func TestBatchDistinctAfterApplyBatchRepr(t *testing.T) {
   921  	defer leaktest.AfterTest(t)()
   922  
   923  	for _, engineImpl := range mvccEngineImpls {
   924  		t.Run(engineImpl.name, func(t *testing.T) {
   925  			e := engineImpl.create()
   926  			defer e.Close()
   927  
   928  			wb := func() []byte {
   929  				batch := e.NewBatch()
   930  				defer batch.Close()
   931  
   932  				if err := batch.Put(mvccKey("batchkey"), []byte("b")); err != nil {
   933  					t.Fatal(err)
   934  				}
   935  
   936  				return batch.Repr()
   937  			}()
   938  
   939  			batch := e.NewBatch()
   940  			defer batch.Close()
   941  
   942  			assert.NoError(t, batch.ApplyBatchRepr(wb, false /* sync */))
   943  
   944  			distinct := batch.Distinct()
   945  			defer distinct.Close()
   946  
   947  			// The distinct batch can see the earlier write to the batch.
   948  			v, err := distinct.Get(mvccKey("batchkey"))
   949  			if err != nil {
   950  				t.Fatal(err)
   951  			}
   952  			assert.Equal(t, []byte("b"), v)
   953  		})
   954  	}
   955  }
   956  
   957  func TestBatchDistinct(t *testing.T) {
   958  	defer leaktest.AfterTest(t)()
   959  
   960  	for _, engineImpl := range mvccEngineImpls {
   961  		t.Run(engineImpl.name, func(t *testing.T) {
   962  			e := engineImpl.create()
   963  			defer e.Close()
   964  
   965  			if err := e.Put(mvccKey("b"), []byte("b")); err != nil {
   966  				t.Fatal(err)
   967  			}
   968  
   969  			batch := e.NewBatch()
   970  			defer batch.Close()
   971  
   972  			if err := batch.Put(mvccKey("a"), []byte("a")); err != nil {
   973  				t.Fatal(err)
   974  			}
   975  			if err := batch.Clear(mvccKey("b")); err != nil {
   976  				t.Fatal(err)
   977  			}
   978  
   979  			// The original batch can see the writes to the batch.
   980  			if v, err := batch.Get(mvccKey("a")); err != nil {
   981  				t.Fatal(err)
   982  			} else if string(v) != "a" {
   983  				t.Fatalf("expected a, but got %s", v)
   984  			}
   985  
   986  			// The distinct batch will see previous writes to the batch.
   987  			distinct := batch.Distinct()
   988  			if v, err := distinct.Get(mvccKey("a")); err != nil {
   989  				t.Fatal(err)
   990  			} else if string(v) != "a" {
   991  				t.Fatalf("expected a, but got %s", v)
   992  			}
   993  			if v, err := distinct.Get(mvccKey("b")); err != nil {
   994  				t.Fatal(err)
   995  			} else if v != nil {
   996  				t.Fatalf("expected nothing, but got %s", v)
   997  			}
   998  
   999  			// Similarly, for distinct batch iterators we will see previous writes to the
  1000  			// batch.
  1001  			iter := distinct.NewIterator(IterOptions{UpperBound: roachpb.KeyMax})
  1002  			iter.SeekGE(mvccKey("a"))
  1003  			if ok, err := iter.Valid(); !ok {
  1004  				t.Fatalf("expected iterator to be valid; err=%v", err)
  1005  			}
  1006  			if string(iter.Key().Key) != "a" {
  1007  				t.Fatalf("expected a, but got %s", iter.Key())
  1008  			}
  1009  			iter.Close()
  1010  
  1011  			if err := distinct.Put(mvccKey("c"), []byte("c")); err != nil {
  1012  				t.Fatal(err)
  1013  			}
  1014  			if v, err := distinct.Get(mvccKey("c")); err != nil {
  1015  				t.Fatal(err)
  1016  			} else {
  1017  				switch engineImpl.name {
  1018  				case "pebble":
  1019  					// With Pebble, writes to the distinct batch are readable by the
  1020  					// distinct batch. This semantic difference is due to not buffering
  1021  					// writes in a builder.
  1022  					if v == nil {
  1023  						t.Fatalf("expected success, but got %s", v)
  1024  					}
  1025  				default:
  1026  					// Writes to the distinct batch are not readable by the distinct
  1027  					// batch.
  1028  					if v != nil {
  1029  						t.Fatalf("expected nothing, but got %s", v)
  1030  					}
  1031  				}
  1032  			}
  1033  			distinct.Close()
  1034  
  1035  			// Writes to the distinct batch are reflected in the original batch.
  1036  			if v, err := batch.Get(mvccKey("c")); err != nil {
  1037  				t.Fatal(err)
  1038  			} else if string(v) != "c" {
  1039  				t.Fatalf("expected c, but got %s", v)
  1040  			}
  1041  		})
  1042  	}
  1043  }
  1044  
  1045  func TestWriteOnlyBatchDistinct(t *testing.T) {
  1046  	defer leaktest.AfterTest(t)()
  1047  
  1048  	for _, engineImpl := range mvccEngineImpls {
  1049  		t.Run(engineImpl.name, func(t *testing.T) {
  1050  			e := engineImpl.create()
  1051  			defer e.Close()
  1052  
  1053  			if err := e.Put(mvccKey("b"), []byte("b")); err != nil {
  1054  				t.Fatal(err)
  1055  			}
  1056  			if _, _, err := PutProto(e, mvccKey("c"), &roachpb.Value{}); err != nil {
  1057  				t.Fatal(err)
  1058  			}
  1059  
  1060  			b := e.NewWriteOnlyBatch()
  1061  			defer b.Close()
  1062  
  1063  			distinct := b.Distinct()
  1064  			defer distinct.Close()
  1065  
  1066  			// Verify that reads on the distinct batch go to the underlying engine, not
  1067  			// to the write-only batch.
  1068  			iter := distinct.NewIterator(IterOptions{UpperBound: roachpb.KeyMax})
  1069  			iter.SeekGE(mvccKey("a"))
  1070  			if ok, err := iter.Valid(); !ok {
  1071  				t.Fatalf("expected iterator to be valid, err=%v", err)
  1072  			}
  1073  			if string(iter.Key().Key) != "b" {
  1074  				t.Fatalf("expected b, but got %s", iter.Key())
  1075  			}
  1076  			iter.Close()
  1077  
  1078  			if v, err := distinct.Get(mvccKey("b")); err != nil {
  1079  				t.Fatal(err)
  1080  			} else if string(v) != "b" {
  1081  				t.Fatalf("expected b, but got %s", v)
  1082  			}
  1083  
  1084  			val := &roachpb.Value{}
  1085  			if _, _, _, err := distinct.GetProto(mvccKey("c"), val); err != nil {
  1086  				t.Fatal(err)
  1087  			}
  1088  		})
  1089  	}
  1090  }
  1091  
  1092  func TestBatchDistinctPanics(t *testing.T) {
  1093  	defer leaktest.AfterTest(t)()
  1094  
  1095  	for _, engineImpl := range mvccEngineImpls {
  1096  		t.Run(engineImpl.name, func(t *testing.T) {
  1097  			e := engineImpl.create()
  1098  			defer e.Close()
  1099  
  1100  			batch := e.NewBatch()
  1101  			defer batch.Close()
  1102  
  1103  			distinct := batch.Distinct()
  1104  			defer distinct.Close()
  1105  
  1106  			// The various Reader and Writer methods on the original batch should panic
  1107  			// while the distinct batch is open.
  1108  			a := mvccKey("a")
  1109  			testCases := []func(){
  1110  				func() { _ = batch.Put(a, nil) },
  1111  				func() { _ = batch.Merge(a, nil) },
  1112  				func() { _ = batch.Clear(a) },
  1113  				func() { _ = batch.SingleClear(a) },
  1114  				func() { _ = batch.ApplyBatchRepr(nil, false) },
  1115  				func() { _, _ = batch.Get(a) },
  1116  				func() { _, _, _, _ = batch.GetProto(a, nil) },
  1117  				func() { _ = batch.Iterate(a.Key, a.Key, nil) },
  1118  				func() { _ = batch.NewIterator(IterOptions{UpperBound: roachpb.KeyMax}) },
  1119  			}
  1120  			for i, f := range testCases {
  1121  				func() {
  1122  					defer func() {
  1123  						if r := recover(); r == nil {
  1124  							t.Fatalf("%d: test did not panic", i)
  1125  						} else if r != "distinct batch open" {
  1126  							t.Fatalf("%d: unexpected panic: %v", i, r)
  1127  						}
  1128  					}()
  1129  					f()
  1130  				}()
  1131  			}
  1132  		})
  1133  	}
  1134  }
  1135  
  1136  func TestBatchIteration(t *testing.T) {
  1137  	defer leaktest.AfterTest(t)()
  1138  
  1139  	for _, engineImpl := range mvccEngineImpls {
  1140  		t.Run(engineImpl.name, func(t *testing.T) {
  1141  			e := engineImpl.create()
  1142  			defer e.Close()
  1143  
  1144  			b := e.NewBatch()
  1145  			defer b.Close()
  1146  
  1147  			k1 := MakeMVCCMetadataKey(roachpb.Key("c"))
  1148  			k2 := MakeMVCCMetadataKey(roachpb.Key("d"))
  1149  			k3 := MakeMVCCMetadataKey(roachpb.Key("e"))
  1150  			v1 := []byte("value1")
  1151  			v2 := []byte("value2")
  1152  
  1153  			if err := b.Put(k1, v1); err != nil {
  1154  				t.Fatal(err)
  1155  			}
  1156  			if err := b.Put(k2, v2); err != nil {
  1157  				t.Fatal(err)
  1158  			}
  1159  			if err := b.Put(k3, []byte("doesn't matter")); err != nil {
  1160  				t.Fatal(err)
  1161  			}
  1162  
  1163  			iterOpts := IterOptions{UpperBound: k3.Key}
  1164  			iter := b.NewIterator(iterOpts)
  1165  			defer iter.Close()
  1166  
  1167  			// Forward iteration,
  1168  			iter.SeekGE(k1)
  1169  			if ok, err := iter.Valid(); !ok {
  1170  				t.Fatal(err)
  1171  			}
  1172  			if !reflect.DeepEqual(iter.Key(), k1) {
  1173  				t.Fatalf("expected %s, got %s", k1, iter.Key())
  1174  			}
  1175  			if !reflect.DeepEqual(iter.Value(), v1) {
  1176  				t.Fatalf("expected %s, got %s", v1, iter.Value())
  1177  			}
  1178  			iter.Next()
  1179  			if ok, err := iter.Valid(); !ok {
  1180  				t.Fatal(err)
  1181  			}
  1182  			if !reflect.DeepEqual(iter.Key(), k2) {
  1183  				t.Fatalf("expected %s, got %s", k2, iter.Key())
  1184  			}
  1185  			if !reflect.DeepEqual(iter.Value(), v2) {
  1186  				t.Fatalf("expected %s, got %s", v2, iter.Value())
  1187  			}
  1188  			iter.Next()
  1189  			if ok, err := iter.Valid(); err != nil {
  1190  				t.Fatal(err)
  1191  			} else if ok {
  1192  				t.Fatalf("expected invalid, got valid at key %s", iter.Key())
  1193  			}
  1194  
  1195  			// Reverse iteration.
  1196  			switch engineImpl.name {
  1197  			case "pebble":
  1198  				// Reverse iteration in batches works on Pebble.
  1199  				iter.SeekLT(k3)
  1200  				if ok, err := iter.Valid(); !ok {
  1201  					t.Fatal(err)
  1202  				}
  1203  				if !reflect.DeepEqual(iter.Key(), k2) {
  1204  					t.Fatalf("expected %s, got %s", k2, iter.Key())
  1205  				}
  1206  				if !reflect.DeepEqual(iter.Value(), v2) {
  1207  					t.Fatalf("expected %s, got %s", v2, iter.Value())
  1208  				}
  1209  
  1210  				iter.Prev()
  1211  				if ok, err := iter.Valid(); !ok || err != nil {
  1212  					t.Fatalf("expected success, but got invalid: %v", err)
  1213  				}
  1214  				if !reflect.DeepEqual(iter.Key(), k1) {
  1215  					t.Fatalf("expected %s, got %s", k1, iter.Key())
  1216  				}
  1217  				if !reflect.DeepEqual(iter.Value(), v1) {
  1218  					t.Fatalf("expected %s, got %s", v1, iter.Value())
  1219  				}
  1220  			default:
  1221  				// Reverse iteration in batches is not supported with RocksDB.
  1222  				iter.SeekLT(k3)
  1223  				if ok, err := iter.Valid(); ok {
  1224  					t.Fatalf("expected invalid, got valid at key %s", iter.Key())
  1225  				} else if !testutils.IsError(err, "SeekForPrev\\(\\) not supported") {
  1226  					t.Fatalf("expected 'SeekForPrev() not supported', got %s", err)
  1227  				}
  1228  
  1229  				iter.Prev()
  1230  				if ok, err := iter.Valid(); ok {
  1231  					t.Fatalf("expected invalid, got valid at key %s", iter.Key())
  1232  				} else if !testutils.IsError(err, "Prev\\(\\) not supported") {
  1233  					t.Fatalf("expected 'Prev() not supported', got %s", err)
  1234  				}
  1235  			}
  1236  		})
  1237  	}
  1238  }
  1239  
  1240  // Test combining of concurrent commits of write-only batches, verifying that
  1241  // all of the keys written by the individual batches are subsequently readable.
  1242  func TestBatchCombine(t *testing.T) {
  1243  	defer leaktest.AfterTest(t)()
  1244  
  1245  	for _, engineImpl := range mvccEngineImpls {
  1246  		t.Run(engineImpl.name, func(t *testing.T) {
  1247  			e := engineImpl.create()
  1248  			defer e.Close()
  1249  
  1250  			var n uint32
  1251  			const count = 10000
  1252  
  1253  			errs := make(chan error, 10)
  1254  			for i := 0; i < cap(errs); i++ {
  1255  				go func() {
  1256  					for {
  1257  						v := atomic.AddUint32(&n, 1) - 1
  1258  						if v >= count {
  1259  							break
  1260  						}
  1261  						k := fmt.Sprint(v)
  1262  
  1263  						b := e.NewWriteOnlyBatch()
  1264  						if err := b.Put(mvccKey(k), []byte(k)); err != nil {
  1265  							errs <- errors.Wrap(err, "put failed")
  1266  							return
  1267  						}
  1268  						if err := b.Commit(false); err != nil {
  1269  							errs <- errors.Wrap(err, "commit failed")
  1270  							return
  1271  						}
  1272  
  1273  						// Verify we can read the key we just wrote immediately.
  1274  						if v, err := e.Get(mvccKey(k)); err != nil {
  1275  							errs <- errors.Wrap(err, "get failed")
  1276  							return
  1277  						} else if string(v) != k {
  1278  							errs <- errors.Errorf("read %q from engine, expected %q", v, k)
  1279  							return
  1280  						}
  1281  					}
  1282  					errs <- nil
  1283  				}()
  1284  			}
  1285  
  1286  			for i := 0; i < cap(errs); i++ {
  1287  				if err := <-errs; err != nil {
  1288  					t.Error(err)
  1289  				}
  1290  			}
  1291  		})
  1292  	}
  1293  }
  1294  
  1295  func TestDecodeKey(t *testing.T) {
  1296  	defer leaktest.AfterTest(t)()
  1297  
  1298  	e := newRocksDBInMem(roachpb.Attributes{}, 1<<20)
  1299  	defer e.Close()
  1300  
  1301  	tests := []MVCCKey{
  1302  		{Key: []byte{}},
  1303  		{Key: []byte("foo")},
  1304  		{Key: []byte("foo"), Timestamp: hlc.Timestamp{WallTime: 1}},
  1305  		{Key: []byte("foo"), Timestamp: hlc.Timestamp{WallTime: 1, Logical: 1}},
  1306  	}
  1307  	for _, test := range tests {
  1308  		t.Run(test.String(), func(t *testing.T) {
  1309  			b := e.NewBatch()
  1310  			defer b.Close()
  1311  			if err := b.Put(test, nil); err != nil {
  1312  				t.Fatalf("%+v", err)
  1313  			}
  1314  			repr := b.Repr()
  1315  
  1316  			r, err := NewRocksDBBatchReader(repr)
  1317  			if err != nil {
  1318  				t.Fatalf("%+v", err)
  1319  			}
  1320  			if !r.Next() {
  1321  				t.Fatalf("could not get the first entry: %+v", r.Error())
  1322  			}
  1323  			decodedKey, err := DecodeMVCCKey(r.Key())
  1324  			if err != nil {
  1325  				t.Fatalf("unexpected err: %+v", err)
  1326  			}
  1327  			if !reflect.DeepEqual(test, decodedKey) {
  1328  				t.Errorf("expected %+v got %+v", test, decodedKey)
  1329  			}
  1330  		})
  1331  	}
  1332  }