@@ -8,11 +8,11 @@ package tests
8
8
import (
9
9
"context"
10
10
"fmt"
11
- "hash"
12
11
"hash/fnv"
13
12
"math/rand"
14
13
"os"
15
14
"path/filepath"
15
+ "regexp"
16
16
"strings"
17
17
"testing"
18
18
"time"
@@ -35,8 +35,10 @@ import (
35
35
"github.com/cockroachdb/cockroach/pkg/util/humanizeutil"
36
36
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
37
37
"github.com/cockroachdb/cockroach/pkg/util/log"
38
+ "github.com/cockroachdb/cockroach/pkg/util/tracing/tracingpb"
38
39
"github.com/cockroachdb/datadriven"
39
40
"github.com/cockroachdb/logtags"
41
+ "github.com/stretchr/testify/assert"
40
42
"github.com/stretchr/testify/require"
41
43
)
42
44
@@ -165,6 +167,12 @@ var runAsimTests = envutil.EnvOrDefaultBool("COCKROACH_RUN_ASIM_TESTS", false)
165
167
// random number generator that creates the seed used to generate each
166
168
// simulation sample. The default values are: duration=30m (30 minutes)
167
169
// samples=1 seed=random.
170
+ //
171
+ // To run all tests and rewrite the testdata files as well as generate the
172
+ // artifacts in `testdata/generated`, you can use:
173
+ /*
174
+ ./dev test pkg/kv/kvserver/asim/tests --ignore-cache --rewrite -v -f TestDataDriven -- --test_env COCKROACH_RUN_ASIM_TESTS=true --test_env COCKROACH_ALWAYS_KEEP_TEST_LOGS=true
175
+ */
168
176
func TestDataDriven (t * testing.T ) {
169
177
skip .UnderDuressWithIssue (t , 149875 )
170
178
leakTestAfter := leaktest .AfterTest (t )
@@ -531,7 +539,34 @@ func TestDataDriven(t *testing.T) {
531
539
require .NotNil (t , set , "unknown mode value: %s" , mv )
532
540
set (& eventGen )
533
541
542
+ // TODO(tbg): need to decide whether multiple evals in a single file
543
+ // is a feature or an anti-pattern. If it's a feature, we should let
544
+ // the `name` part below be adjustable (but not the plotDir) via a
545
+ // parameter to the `eval` command.
546
+ testName := name + "_" + mv
547
+
534
548
for sample := 0 ; sample < samples ; sample ++ {
549
+ recIdx := map [int64 ]int {}
550
+ settingsGen .Settings .OnRecording = func (storeID int64 , rec tracingpb.Recording ) {
551
+ if ! rewrite || len (rec [0 ].Logs ) == 0 {
552
+ return
553
+ }
554
+ traceDir := filepath .Join (plotDir , "traces" , fmt .Sprintf ("s%d" , storeID ))
555
+ if recIdx [storeID ] == 0 {
556
+ require .NoError (t , os .MkdirAll (traceDir , 0755 ))
557
+ }
558
+ re := regexp .MustCompile (`[^a-zA-Z0-9]+` )
559
+ outName := fmt .Sprintf ("%s_%s_s%d" , mv , re .ReplaceAllString (rec [0 ].Operation , "_" ), storeID )
560
+ if sample > 0 {
561
+ outName += fmt .Sprintf ("_sample%d" , sample + 1 )
562
+ }
563
+ outName += "_" + fmt .Sprintf ("%03d.txt" , recIdx [storeID ])
564
+ assert .NoError (t , os .WriteFile (
565
+ filepath .Join (traceDir , outName ),
566
+ []byte (rec .String ()), 0644 ))
567
+ recIdx [storeID ] += 1
568
+ }
569
+
535
570
assertionFailures := []string {}
536
571
var tmpStrB * strings.Builder = nil
537
572
if stateStrForOnce == "" {
@@ -561,17 +596,10 @@ func TestDataDriven(t *testing.T) {
561
596
// Generate artifacts. Hash artifact input data to ensure they are
562
597
// up to date.
563
598
hasher := fnv .New64a ()
564
- // TODO(tbg): need to decide whether multiple evals in a single file
565
- // is a feature or an anti-pattern. If it's a feature, we should let
566
- // the `name` part below be adjustable (but not the plotDir) via a
567
- // parameter to the `eval` command.
568
- testName := name + "_" + mv
599
+
569
600
for sample , h := range run .hs {
570
- generateAllPlots (t , & buf , h , testName , sample + 1 , plotDir , hasher , rewrite ,
601
+ printStatsAndGenerateJSON (t , & buf , h , testName , sample + 1 , plotDir , hasher , rewrite ,
571
602
settingsGen .Settings .TickInterval , metricsMap )
572
- generateTopology (t , h ,
573
- filepath .Join (plotDir , fmt .Sprintf ("%s_%d_topology.txt" , testName , sample + 1 )),
574
- hasher , rewrite )
575
603
}
576
604
artifactsHash := hasher .Sum64 ()
577
605
@@ -707,22 +735,6 @@ type modeHistory struct {
707
735
hs []history.History
708
736
}
709
737
710
- func generateTopology (
711
- t * testing.T , h history.History , topFile string , hasher hash.Hash , rewrite bool ,
712
- ) {
713
- // TODO(tbg): this can in principle be printed without even
714
- // evaluating the test, and in particular it's independent of
715
- // settings. It seems like an artifact of the implementation
716
- // that we can only access the structured topology after the
717
- // simulation has run.
718
- top := h .S .Topology ()
719
- s := top .String ()
720
- _ , _ = fmt .Fprint (hasher , s )
721
- if rewrite {
722
- require .NoError (t , os .WriteFile (topFile , []byte (s ), 0644 ))
723
- }
724
- }
725
-
726
738
// writeStateStrToFile writes the state string to the given file.
727
739
func writeStateStrToFile (t * testing.T , topFile string , stateStr string , rewrite bool ) {
728
740
if rewrite {
0 commit comments