github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cli/debug_check_store_test.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package cli
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"path/filepath"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/cockroachdb/cockroach/pkg/base"
    22  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/stateloader"
    23  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    24  	"github.com/cockroachdb/cockroach/pkg/storage"
    25  	"github.com/cockroachdb/cockroach/pkg/testutils"
    26  	"github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
    27  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestDebugCheckStore(t *testing.T) {
    32  	defer leaktest.AfterTest(t)()
    33  
    34  	ctx := context.Background()
    35  
    36  	baseDir, dirCleanupFn := testutils.TempDir(t)
    37  	defer dirCleanupFn()
    38  
    39  	// Number of nodes. Increasing this will make the test flaky as written
    40  	// because it relies on finding r1 on n1.
    41  	const n = 3
    42  
    43  	clusterArgs := base.TestClusterArgs{
    44  		ServerArgsPerNode: map[int]base.TestServerArgs{},
    45  	}
    46  	var storePaths []string
    47  	for i := 0; i < n; i++ {
    48  		args := base.TestServerArgs{}
    49  		args.ScanMaxIdleTime = time.Millisecond
    50  		args.ScanMaxIdleTime = time.Millisecond
    51  		storeID := roachpb.StoreID(i + 1)
    52  		path := filepath.Join(baseDir, fmt.Sprintf("s%d", storeID))
    53  		storePaths = append(storePaths, path)
    54  		args.StoreSpecs = []base.StoreSpec{{Path: path}}
    55  		clusterArgs.ServerArgsPerNode[i] = args
    56  	}
    57  
    58  	// Start the cluster, wait for full replication, stop the cluster.
    59  	func() {
    60  		tc := testcluster.StartTestCluster(t, n, clusterArgs)
    61  		defer tc.Stopper().Stop(ctx)
    62  		require.NoError(t, tc.WaitForFullReplication())
    63  	}()
    64  
    65  	check := func(dir string) (string, error) {
    66  		var buf strings.Builder
    67  		err := checkStoreRangeStats(ctx, dir, func(args ...interface{}) {
    68  			fmt.Fprintln(&buf, args...)
    69  		})
    70  		return buf.String(), err
    71  	}
    72  
    73  	// Should not error out randomly.
    74  	for _, dir := range storePaths {
    75  		out, err := check(dir)
    76  		require.NoError(t, err, dir)
    77  		require.Contains(t, out, "total stats", dir)
    78  	}
    79  
    80  	// Introduce a stats divergence on s1.
    81  	func() {
    82  		eng, err := storage.NewDefaultEngine(
    83  			10<<20, /* 10mb */
    84  			base.StorageConfig{
    85  				Dir:       storePaths[0],
    86  				MustExist: true,
    87  			})
    88  		require.NoError(t, err)
    89  		defer eng.Close()
    90  		sl := stateloader.Make(1)
    91  		ms, err := sl.LoadMVCCStats(ctx, eng)
    92  		require.NoError(t, err)
    93  		ms.ContainsEstimates = 0
    94  		ms.LiveBytes++
    95  		require.NoError(t, sl.SetMVCCStats(ctx, eng, &ms))
    96  	}()
    97  
    98  	// The check should now fail on s1.
    99  	{
   100  		const s = "stats inconsistency"
   101  		out, err := check(storePaths[0])
   102  		require.Error(t, err)
   103  		require.Contains(t, out, s)
   104  		require.Contains(t, out, "total stats")
   105  	}
   106  }