github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/metamorphic/meta_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  	"path/filepath"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/cockroachdb/pebble/internal/metamorphic/metaflags"
    13  	"github.com/cockroachdb/pebble/metamorphic"
    14  )
    15  
    16  // TODO(peter):
    17  //
    18  // Miscellaneous:
    19  // - Add support for different comparers. In particular, allow reverse
    20  //   comparers and a comparer which supports Comparer.Split (by splitting off
    21  //   a variable length suffix).
    22  // - Add support for Writer.LogData
    23  
    24  var runOnceFlags, runFlags = metaflags.InitAllFlags()
    25  
    26  // TestMeta generates a random set of operations to run, then runs multiple
    27  // instances of the test with varying options. See standardOptions() for the set
    28  // of options that are always run, and randomOptions() for the randomly
    29  // generated options. The number of operations to generate is determined by the
    30  // `--ops` flag. If a failure occurs, the output is kept in `_meta/<test>`,
    31  // though note that a subsequent invocation will overwrite that output. A test
    32  // can be re-run by using the `--run-dir` flag. For example:
    33  //
    34  //	go test -v -run TestMeta --run-dir _meta/standard-017
    35  //
    36  // This will reuse the existing operations present in _meta/ops, rather than
    37  // generating a new set.
    38  //
    39  // The generated operations and options are generated deterministically from a
    40  // pseudorandom number generator seed. If a failure occurs, the seed is
    41  // printed, and the full suite of tests may be re-run using the `--seed` flag:
    42  //
    43  //	go test -v -run TestMeta --seed 1594395154492165000
    44  //
    45  // This will generate a new `_meta/<test>` directory, with the same operations
    46  // and options. This must be run on the same commit SHA as the original
    47  // failure, otherwise changes to the metamorphic tests may cause the generated
    48  // operations and options to differ.
    49  //
    50  // Each instance of the test is run in a different process, by executing the
    51  // same binary (i.e. os.Args[0]) and passing `--run_dir`; the "inner" binary can
    52  // be customized via the --inner-binary flag (used for code coverage
    53  // instrumentation).
    54  func TestMeta(t *testing.T) {
    55  	switch {
    56  	case runOnceFlags.Compare != "":
    57  		runDirs := strings.Split(runOnceFlags.Compare, ",")
    58  		onceOpts := runOnceFlags.MakeRunOnceOptions()
    59  		metamorphic.Compare(t, runOnceFlags.Dir, runOnceFlags.Seed, runDirs, onceOpts...)
    60  
    61  	case runOnceFlags.RunDir != "":
    62  		// The --run-dir flag is specified either in the child process (see
    63  		// runOptions() below) or the user specified it manually in order to re-run
    64  		// a test.
    65  		onceOpts := runOnceFlags.MakeRunOnceOptions()
    66  		metamorphic.RunOnce(t, runOnceFlags.RunDir, runOnceFlags.Seed, filepath.Join(runOnceFlags.RunDir, "history"), onceOpts...)
    67  
    68  	default:
    69  		opts := runFlags.MakeRunOptions()
    70  		metamorphic.RunAndCompare(t, runFlags.Dir, opts...)
    71  	}
    72  }
    73  
    74  func TestMetaTwoInstance(t *testing.T) {
    75  	switch {
    76  	case runOnceFlags.Compare != "":
    77  		runDirs := strings.Split(runOnceFlags.Compare, ",")
    78  		onceOpts := runOnceFlags.MakeRunOnceOptions()
    79  		onceOpts = append(onceOpts, metamorphic.MultiInstance(2))
    80  		metamorphic.Compare(t, runOnceFlags.Dir, runOnceFlags.Seed, runDirs, onceOpts...)
    81  
    82  	case runOnceFlags.RunDir != "":
    83  		// The --run-dir flag is specified either in the child process (see
    84  		// runOptions() below) or the user specified it manually in order to re-run
    85  		// a test.
    86  		onceOpts := runOnceFlags.MakeRunOnceOptions()
    87  		onceOpts = append(onceOpts, metamorphic.MultiInstance(2))
    88  		metamorphic.RunOnce(t, runOnceFlags.RunDir, runOnceFlags.Seed, filepath.Join(runOnceFlags.RunDir, "history"), onceOpts...)
    89  
    90  	default:
    91  		opts := runFlags.MakeRunOptions()
    92  		opts = append(opts, metamorphic.MultiInstance(2))
    93  		metamorphic.RunAndCompare(t, runFlags.Dir, opts...)
    94  	}
    95  }