github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/internal/metamorphic/generator_test.go (about) 1 // Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package metamorphic 6 7 import ( 8 "testing" 9 "time" 10 11 "github.com/pmezard/go-difflib/difflib" 12 "github.com/stretchr/testify/require" 13 "github.com/zuoyebang/bitalostable/internal/randvar" 14 "golang.org/x/exp/rand" 15 ) 16 17 func TestGenerator(t *testing.T) { 18 rng := randvar.NewRand() 19 g := newGenerator(rng, defaultConfig(), newKeyManager()) 20 21 g.newBatch() 22 g.newBatch() 23 g.newBatch() 24 require.EqualValues(t, 3, len(g.liveBatches)) 25 require.EqualValues(t, 0, len(g.batches)) 26 27 g.newIndexedBatch() 28 g.newIndexedBatch() 29 g.newIndexedBatch() 30 require.EqualValues(t, 6, len(g.liveBatches)) 31 require.EqualValues(t, 3, len(g.batches)) 32 require.EqualValues(t, 3, len(g.readers)) 33 34 g.newIter() 35 g.newIter() 36 g.newIter() 37 require.EqualValues(t, 3, len(g.liveIters)) 38 39 g.batchAbort() 40 g.batchAbort() 41 g.batchAbort() 42 g.batchAbort() 43 g.batchAbort() 44 g.batchAbort() 45 46 require.EqualValues(t, 0, len(g.liveBatches)) 47 require.EqualValues(t, 0, len(g.batches)) 48 require.EqualValues(t, 0, len(g.iters)) 49 require.EqualValues(t, 1, len(g.liveReaders)) 50 require.EqualValues(t, 0, len(g.readers)) 51 require.EqualValues(t, 0, len(g.liveSnapshots)) 52 require.EqualValues(t, 0, len(g.snapshots)) 53 require.EqualValues(t, 1, len(g.liveWriters)) 54 55 g.randIter(g.iterClose)() 56 g.randIter(g.iterClose)() 57 g.randIter(g.iterClose)() 58 require.EqualValues(t, 0, len(g.liveIters)) 59 60 if testing.Verbose() { 61 t.Logf("\n%s", g) 62 } 63 64 g = newGenerator(rng, defaultConfig(), newKeyManager()) 65 66 g.newSnapshot() 67 g.newSnapshot() 68 g.newSnapshot() 69 require.EqualValues(t, 3, len(g.liveSnapshots)) 70 require.EqualValues(t, 3, len(g.snapshots)) 71 72 g.newIter() 73 g.newIter() 74 g.newIter() 75 g.snapshotClose() 76 g.snapshotClose() 77 g.snapshotClose() 78 79 require.EqualValues(t, 0, len(g.liveBatches)) 80 require.EqualValues(t, 0, len(g.batches)) 81 require.EqualValues(t, 0, len(g.iters)) 82 require.EqualValues(t, 1, len(g.liveReaders)) 83 require.EqualValues(t, 0, len(g.readers)) 84 require.EqualValues(t, 0, len(g.liveSnapshots)) 85 require.EqualValues(t, 0, len(g.snapshots)) 86 require.EqualValues(t, 1, len(g.liveWriters)) 87 88 g.randIter(g.iterClose)() 89 g.randIter(g.iterClose)() 90 g.randIter(g.iterClose)() 91 require.EqualValues(t, 0, len(g.liveIters)) 92 93 if testing.Verbose() { 94 t.Logf("\n%s", g) 95 } 96 97 g = newGenerator(rng, defaultConfig(), newKeyManager()) 98 99 g.newIndexedBatch() 100 g.newIndexedBatch() 101 g.newIndexedBatch() 102 g.newIter() 103 g.newIter() 104 g.newIter() 105 g.writerApply() 106 g.writerApply() 107 g.writerApply() 108 g.randIter(g.iterClose)() 109 g.randIter(g.iterClose)() 110 g.randIter(g.iterClose)() 111 112 require.EqualValues(t, 0, len(g.liveBatches)) 113 require.EqualValues(t, 0, len(g.batches)) 114 require.EqualValues(t, 0, len(g.liveIters)) 115 require.EqualValues(t, 0, len(g.iters)) 116 require.EqualValues(t, 1, len(g.liveReaders)) 117 require.EqualValues(t, 0, len(g.readers)) 118 require.EqualValues(t, 0, len(g.liveSnapshots)) 119 require.EqualValues(t, 0, len(g.snapshots)) 120 require.EqualValues(t, 1, len(g.liveWriters)) 121 122 if testing.Verbose() { 123 t.Logf("\n%s", g) 124 } 125 } 126 127 func TestGeneratorRandom(t *testing.T) { 128 seed := uint64(time.Now().UnixNano()) 129 generateFromSeed := func() string { 130 rng := rand.New(rand.NewSource(seed)) 131 count := ops.Uint64(rng) 132 return formatOps(generate(rng, count, defaultConfig(), newKeyManager())) 133 } 134 135 // Ensure that generate doesn't use any other source of randomness other 136 // than rng. 137 referenceOps := generateFromSeed() 138 for i := 0; i < 10; i++ { 139 regeneratedOps := generateFromSeed() 140 diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ 141 A: difflib.SplitLines(referenceOps), 142 B: difflib.SplitLines(regeneratedOps), 143 Context: 1, 144 }) 145 require.NoError(t, err) 146 if len(diff) > 0 { 147 t.Fatalf("Diff:\n%s", diff) 148 } 149 } 150 if testing.Verbose() { 151 t.Logf("\nOps:\n%s", referenceOps) 152 } 153 }