func TestBatchBuilderStress(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() e := NewInMem(roachpb.Attributes{}, 1<<20, stopper) rng, _ := randutil.NewPseudoRand() for i := 0; i < 1000; i++ { count := 1 + rng.Intn(1000) func() { batch := e.NewBatch().(*rocksDBBatch) defer batch.Close() builder := &rocksDBBatchBuilder{} for j := 0; j < count; j++ { var ts roachpb.Timestamp if rng.Float32() <= 0.9 { // Give 90% of keys timestamps. ts.WallTime = rng.Int63() if rng.Float32() <= 0.1 { // Give 10% of timestamps a non-zero logical component. ts.Logical = rng.Int31() } } key := MVCCKey{ Key: []byte(fmt.Sprintf("%d", rng.Intn(10000))), Timestamp: ts, } // Generate a random mixture of puts, deletes and merges. switch rng.Intn(3) { case 0: if err := dbPut(batch.batch, key, []byte("value")); err != nil { t.Fatal(err) } builder.Put(key, []byte("value")) case 1: if err := dbClear(batch.batch, key); err != nil { t.Fatal(err) } builder.Clear(key) case 2: if err := dbMerge(batch.batch, key, appender("bar")); err != nil { t.Fatal(err) } builder.Merge(key, appender("bar")) } } batchRepr := batch.Repr() builderRepr := builder.Finish() if !bytes.Equal(batchRepr, builderRepr) { t.Fatalf("expected [% x], but got [% x]", batchRepr, builderRepr) } }() } }