github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/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/cockroachdb/pebble"
    12  	"github.com/cockroachdb/pebble/internal/randvar"
    13  	"github.com/pmezard/go-difflib/difflib"
    14  	"github.com/stretchr/testify/require"
    15  	"golang.org/x/exp/rand"
    16  )
    17  
    18  func TestGenerator(t *testing.T) {
    19  	rng := randvar.NewRand()
    20  	g := newGenerator(rng, defaultConfig(), newKeyManager())
    21  
    22  	g.newBatch()
    23  	g.newBatch()
    24  	g.newBatch()
    25  	require.EqualValues(t, 3, len(g.liveBatches))
    26  	require.EqualValues(t, 0, len(g.batches))
    27  
    28  	g.newIndexedBatch()
    29  	g.newIndexedBatch()
    30  	g.newIndexedBatch()
    31  	require.EqualValues(t, 6, len(g.liveBatches))
    32  	require.EqualValues(t, 3, len(g.batches))
    33  	require.EqualValues(t, 3, len(g.readers))
    34  
    35  	g.newIter()
    36  	g.newIter()
    37  	g.newIter()
    38  	require.EqualValues(t, 3, len(g.liveIters))
    39  
    40  	g.batchAbort()
    41  	g.batchAbort()
    42  	g.batchAbort()
    43  	g.batchAbort()
    44  	g.batchAbort()
    45  	g.batchAbort()
    46  
    47  	require.EqualValues(t, 0, len(g.liveBatches))
    48  	require.EqualValues(t, 0, len(g.batches))
    49  	require.EqualValues(t, 0, len(g.iters))
    50  	require.EqualValues(t, 1, len(g.liveReaders))
    51  	require.EqualValues(t, 0, len(g.readers))
    52  	require.EqualValues(t, 0, len(g.liveSnapshots))
    53  	require.EqualValues(t, 0, len(g.snapshots))
    54  	require.EqualValues(t, 1, len(g.liveWriters))
    55  
    56  	g.randIter(g.iterClose)()
    57  	g.randIter(g.iterClose)()
    58  	g.randIter(g.iterClose)()
    59  	require.EqualValues(t, 0, len(g.liveIters))
    60  
    61  	if testing.Verbose() {
    62  		t.Logf("\n%s", g)
    63  	}
    64  
    65  	g = newGenerator(rng, defaultConfig(), newKeyManager())
    66  
    67  	g.newSnapshot()
    68  	g.newSnapshot()
    69  	g.newSnapshot()
    70  	require.EqualValues(t, 3, len(g.liveSnapshots))
    71  	require.EqualValues(t, 3, len(g.snapshots))
    72  
    73  	g.newIter()
    74  	g.newIter()
    75  	g.newIter()
    76  	g.snapshotClose()
    77  	g.snapshotClose()
    78  	g.snapshotClose()
    79  
    80  	require.EqualValues(t, 0, len(g.liveBatches))
    81  	require.EqualValues(t, 0, len(g.batches))
    82  	require.EqualValues(t, 0, len(g.iters))
    83  	require.EqualValues(t, 1, len(g.liveReaders))
    84  	require.EqualValues(t, 0, len(g.readers))
    85  	require.EqualValues(t, 0, len(g.liveSnapshots))
    86  	require.EqualValues(t, 0, len(g.snapshots))
    87  	require.EqualValues(t, 1, len(g.liveWriters))
    88  
    89  	g.randIter(g.iterClose)()
    90  	g.randIter(g.iterClose)()
    91  	g.randIter(g.iterClose)()
    92  	require.EqualValues(t, 0, len(g.liveIters))
    93  
    94  	if testing.Verbose() {
    95  		t.Logf("\n%s", g)
    96  	}
    97  
    98  	g = newGenerator(rng, defaultConfig(), newKeyManager())
    99  
   100  	g.newIndexedBatch()
   101  	g.newIndexedBatch()
   102  	g.newIndexedBatch()
   103  	g.newIter()
   104  	g.newIter()
   105  	g.newIter()
   106  	g.writerApply()
   107  	g.writerApply()
   108  	g.writerApply()
   109  	g.randIter(g.iterClose)()
   110  	g.randIter(g.iterClose)()
   111  	g.randIter(g.iterClose)()
   112  
   113  	require.EqualValues(t, 0, len(g.liveBatches))
   114  	require.EqualValues(t, 0, len(g.batches))
   115  	require.EqualValues(t, 0, len(g.liveIters))
   116  	require.EqualValues(t, 0, len(g.iters))
   117  	require.EqualValues(t, 1, len(g.liveReaders))
   118  	require.EqualValues(t, 0, len(g.readers))
   119  	require.EqualValues(t, 0, len(g.liveSnapshots))
   120  	require.EqualValues(t, 0, len(g.snapshots))
   121  	require.EqualValues(t, 1, len(g.liveWriters))
   122  
   123  	if testing.Verbose() {
   124  		t.Logf("\n%s", g)
   125  	}
   126  }
   127  
   128  func TestGeneratorRandom(t *testing.T) {
   129  	seed := uint64(time.Now().UnixNano())
   130  	ops := randvar.NewUniform(1000, 10000)
   131  	generateFromSeed := func() string {
   132  		rng := rand.New(rand.NewSource(seed))
   133  		count := ops.Uint64(rng)
   134  		return formatOps(generate(rng, count, defaultConfig(), newKeyManager()))
   135  	}
   136  
   137  	// Ensure that generate doesn't use any other source of randomness other
   138  	// than rng.
   139  	referenceOps := generateFromSeed()
   140  	for i := 0; i < 10; i++ {
   141  		regeneratedOps := generateFromSeed()
   142  		diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
   143  			A:       difflib.SplitLines(referenceOps),
   144  			B:       difflib.SplitLines(regeneratedOps),
   145  			Context: 1,
   146  		})
   147  		require.NoError(t, err)
   148  		if len(diff) > 0 {
   149  			t.Fatalf("Diff:\n%s", diff)
   150  		}
   151  	}
   152  	if testing.Verbose() {
   153  		t.Logf("\nOps:\n%s", referenceOps)
   154  	}
   155  }
   156  
   157  func TestGenerateRandKeyToReadInRange(t *testing.T) {
   158  	rng := randvar.NewRand()
   159  	g := newGenerator(rng, defaultConfig(), newKeyManager())
   160  	// Seed 100 initial keys.
   161  	for i := 0; i < 100; i++ {
   162  		_ = g.randKeyToWrite(1.0)
   163  	}
   164  	for i := 0; i < 100; i++ {
   165  		a := g.randKeyToRead(0.01)
   166  		b := g.randKeyToRead(0.01)
   167  		// Ensure unique prefixes; required by randKeyToReadInRange.
   168  		for g.equal(g.prefix(a), g.prefix(b)) {
   169  			b = g.randKeyToRead(0.01)
   170  		}
   171  		if v := g.cmp(a, b); v > 0 {
   172  			a, b = b, a
   173  		}
   174  		kr := pebble.KeyRange{Start: a, End: b}
   175  		for j := 0; j < 10; j++ {
   176  			k := g.randKeyToReadInRange(0.05, kr)
   177  			if g.cmp(k, a) < 0 {
   178  				t.Errorf("generated random key %q outside range %s", k, kr)
   179  			} else if g.cmp(k, b) >= 0 {
   180  				t.Errorf("generated random key %q outside range %s", k, kr)
   181  			}
   182  		}
   183  	}
   184  }
   185  
   186  func TestGenerateDisjointKeyRanges(t *testing.T) {
   187  	rng := randvar.NewRand()
   188  	g := newGenerator(rng, defaultConfig(), newKeyManager())
   189  
   190  	for i := 0; i < 10; i++ {
   191  		keyRanges := g.generateDisjointKeyRanges(5)
   192  		for j := range keyRanges {
   193  			t.Logf("%d: %d: %s", i, j, keyRanges[j])
   194  			for k := range keyRanges {
   195  				if j == k {
   196  					continue
   197  				}
   198  				if g.cmp(keyRanges[j].End, keyRanges[k].Start) <= 0 {
   199  					require.Less(t, j, k)
   200  					continue
   201  				}
   202  				if g.cmp(keyRanges[j].Start, keyRanges[k].End) >= 0 {
   203  					require.Greater(t, j, k)
   204  					continue
   205  				}
   206  				t.Fatalf("generated key ranges %q and %q overlap", keyRanges[j], keyRanges[k])
   207  			}
   208  		}
   209  	}
   210  }