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  }