github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ccl/storageccl/writebatch_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Licensed as a CockroachDB Enterprise file under the Cockroach Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt 8 9 package storageccl 10 11 import ( 12 "bytes" 13 "context" 14 "reflect" 15 "testing" 16 17 "github.com/cockroachdb/cockroach/pkg/base" 18 "github.com/cockroachdb/cockroach/pkg/keys" 19 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/batcheval" 20 "github.com/cockroachdb/cockroach/pkg/roachpb" 21 "github.com/cockroachdb/cockroach/pkg/storage" 22 "github.com/cockroachdb/cockroach/pkg/storage/enginepb" 23 "github.com/cockroachdb/cockroach/pkg/testutils" 24 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 25 "github.com/cockroachdb/cockroach/pkg/util/hlc" 26 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 27 ) 28 29 func TestDBWriteBatch(t *testing.T) { 30 defer leaktest.AfterTest(t)() 31 32 s, _, db := serverutils.StartServer(t, base.TestServerArgs{Insecure: true}) 33 ctx := context.Background() 34 defer s.Stopper().Stop(ctx) 35 36 // Key range in request spans multiple ranges. 37 if err := db.WriteBatch( 38 ctx, keys.LocalMax, keys.MaxKey, nil, 39 ); !testutils.IsError(err, "data spans multiple ranges") { 40 t.Fatalf("expected multiple ranges error got: %+v", err) 41 } 42 43 { 44 var batch storage.RocksDBBatchBuilder 45 key := storage.MVCCKey{Key: []byte("bb"), Timestamp: hlc.Timestamp{WallTime: 1}} 46 batch.Put(key, roachpb.MakeValueFromString("1").RawBytes) 47 data := batch.Finish() 48 49 // Key is before the range in the request span. 50 if err := db.WriteBatch( 51 ctx, "d", "e", data, 52 ); !testutils.IsError(err, "key not in request range") { 53 t.Fatalf("expected request range error got: %+v", err) 54 } 55 // Key is after the range in the request span. 56 if err := db.WriteBatch( 57 ctx, "a", "b", data, 58 ); !testutils.IsError(err, "key not in request range") { 59 t.Fatalf("expected request range error got: %+v", err) 60 } 61 62 if err := db.WriteBatch(ctx, "b", "c", data); err != nil { 63 t.Fatalf("%+v", err) 64 } 65 if result, err := db.Get(ctx, "bb"); err != nil { 66 t.Fatalf("%+v", err) 67 } else if result := result.ValueBytes(); !bytes.Equal([]byte("1"), result) { 68 t.Errorf("expected \"%s\", got \"%s\"", []byte("1"), result) 69 } 70 } 71 72 // Key range in request span is not empty. 73 { 74 var batch storage.RocksDBBatchBuilder 75 key := storage.MVCCKey{Key: []byte("bb2"), Timestamp: hlc.Timestamp{WallTime: 1}} 76 batch.Put(key, roachpb.MakeValueFromString("2").RawBytes) 77 data := batch.Finish() 78 if err := db.WriteBatch(ctx, "b", "c", data); err != nil { 79 t.Fatalf("%+v", err) 80 } 81 82 if result, err := db.Get(ctx, "bb2"); err != nil { 83 t.Fatalf("%+v", err) 84 } else if result := result.ValueBytes(); !bytes.Equal([]byte("2"), result) { 85 t.Errorf("expected \"%s\", got \"%s\"", []byte("2"), result) 86 } 87 88 if result, err := db.Get(ctx, "bb"); err != nil { 89 t.Fatalf("%+v", err) 90 } else if result := result.ValueBytes(); result != nil { 91 t.Errorf("expected nil, got \"%s\"", result) 92 } 93 } 94 95 // Invalid key/value entry checksum. 96 { 97 var batch storage.RocksDBBatchBuilder 98 key := storage.MVCCKey{Key: []byte("bb"), Timestamp: hlc.Timestamp{WallTime: 1}} 99 value := roachpb.MakeValueFromString("1") 100 value.InitChecksum([]byte("foo")) 101 batch.Put(key, value.RawBytes) 102 data := batch.Finish() 103 104 if err := db.WriteBatch(ctx, "b", "c", data); !testutils.IsError(err, "invalid checksum") { 105 t.Fatalf("expected 'invalid checksum' error got: %+v", err) 106 } 107 } 108 } 109 110 func TestWriteBatchMVCCStats(t *testing.T) { 111 defer leaktest.AfterTest(t)() 112 113 ctx := context.Background() 114 e := storage.NewDefaultInMem() 115 defer e.Close() 116 117 var batch storage.RocksDBBatchBuilder 118 { 119 key := storage.MVCCKey{Key: []byte("bb"), Timestamp: hlc.Timestamp{WallTime: 1}} 120 batch.Put(key, roachpb.MakeValueFromString("1").RawBytes) 121 } 122 data := batch.Finish() 123 span := roachpb.Span{Key: []byte("b"), EndKey: []byte("c")} 124 125 // WriteBatch deletes any data that exists in the keyrange before applying 126 // the batch. Put something there to delete. The mvcc stats should be 127 // adjusted accordingly. 128 const numInitialEntries = 100 129 for i := 0; i < numInitialEntries; i++ { 130 if err := e.Put(storage.MVCCKey{Key: append([]byte("b"), byte(i))}, nil); err != nil { 131 t.Fatalf("%+v", err) 132 } 133 } 134 135 cArgs := batcheval.CommandArgs{ 136 Args: &roachpb.WriteBatchRequest{ 137 RequestHeader: roachpb.RequestHeaderFromSpan(span), 138 DataSpan: span, 139 Data: data, 140 }, 141 // Start with some stats to represent data throughout the replica's 142 // keyrange. 143 Stats: &enginepb.MVCCStats{ 144 LiveBytes: 10000, 145 LiveCount: 10000, 146 KeyBytes: 10000, 147 KeyCount: 10000, 148 ValBytes: 10000, 149 ValCount: 10000, 150 }, 151 } 152 if _, err := evalWriteBatch(ctx, e, cArgs, nil); err != nil { 153 t.Fatalf("%+v", err) 154 } 155 156 expectedStats := &enginepb.MVCCStats{ 157 LiveBytes: 9721, 158 LiveCount: 9901, 159 KeyBytes: 9715, 160 KeyCount: 9901, 161 ValBytes: 10006, 162 ValCount: 10001, 163 } 164 if !reflect.DeepEqual(expectedStats, cArgs.Stats) { 165 t.Errorf("mvcc stats mismatch %+v != %+v", expectedStats, cArgs.Stats) 166 } 167 168 // Run the same WriteBatch command a second time to test the idempotence. 169 if _, err := evalWriteBatch(ctx, e, cArgs, nil); err != nil { 170 t.Fatalf("%+v", err) 171 } 172 if !reflect.DeepEqual(expectedStats, cArgs.Stats) { 173 t.Errorf("mvcc stats mismatch %+v != %+v", expectedStats, cArgs.Stats) 174 } 175 }