github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachtest/orm_helpers.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 main
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"sort"
    17  	"strings"
    18  )
    19  
    20  // alterZoneConfigAndClusterSettings changes the zone configurations so that GC
    21  // occurs more quickly and jobs are retained for less time. This is useful for
    22  // most ORM tests because they create/drop/alter tables frequently, which can
    23  // cause thousands of table descriptors and schema change jobs to accumulate
    24  // rapidly, thereby decreasing performance.
    25  func alterZoneConfigAndClusterSettings(
    26  	ctx context.Context, version string, c *cluster, nodeIdx int,
    27  ) error {
    28  	db, err := c.ConnE(ctx, nodeIdx)
    29  	if err != nil {
    30  		return err
    31  	}
    32  	defer db.Close()
    33  
    34  	if _, err := db.ExecContext(
    35  		ctx, `ALTER RANGE default CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 120;`,
    36  	); err != nil {
    37  		return err
    38  	}
    39  
    40  	if _, err := db.ExecContext(
    41  		ctx, `ALTER DATABASE system CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 120;`,
    42  	); err != nil {
    43  		return err
    44  	}
    45  
    46  	if _, err := db.ExecContext(
    47  		ctx, `ALTER TABLE system.public.jobs CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 120;`,
    48  	); err != nil {
    49  		return err
    50  	}
    51  
    52  	if _, err := db.ExecContext(
    53  		ctx, `ALTER RANGE meta CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 120;`,
    54  	); err != nil {
    55  		return err
    56  	}
    57  
    58  	if _, err := db.ExecContext(
    59  		ctx, `ALTER RANGE system CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 120;`,
    60  	); err != nil {
    61  		return err
    62  	}
    63  
    64  	if _, err := db.ExecContext(
    65  		ctx, `ALTER RANGE liveness CONFIGURE ZONE USING num_replicas = 1, gc.ttlseconds = 120;`,
    66  	); err != nil {
    67  		return err
    68  	}
    69  
    70  	// TODO(rafi): remove this check once we stop testing against 2.0 and 2.1
    71  	if strings.HasPrefix(version, "v2.0") || strings.HasPrefix(version, "v2.1") {
    72  		return nil
    73  	}
    74  
    75  	if _, err := db.ExecContext(
    76  		ctx, `SET CLUSTER SETTING jobs.retention_time = '180s';`,
    77  	); err != nil {
    78  		return err
    79  	}
    80  
    81  	// Enable temp tables for v20.1
    82  	if strings.HasPrefix(version, "v20.") {
    83  		if _, err := db.ExecContext(
    84  			ctx, `SET CLUSTER SETTING sql.defaults.experimental_temporary_tables.enabled = 'true';`,
    85  		); err != nil {
    86  			return err
    87  		}
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  // ormTestsResults is a helper struct to be used in all roachtests for ORMs and
    94  // drivers' compatibility.
    95  type ormTestsResults struct {
    96  	currentFailures, allTests                    []string
    97  	failUnexpectedCount, failExpectedCount       int
    98  	ignoredCount, skipCount, unexpectedSkipCount int
    99  	passUnexpectedCount, passExpectedCount       int
   100  	// Put all the results in a giant map of [testname]result.
   101  	results map[string]string
   102  	// Put all issue hints in a map of [testname]issue.
   103  	allIssueHints map[string]string
   104  	runTests      map[string]struct{}
   105  }
   106  
   107  func newORMTestsResults() *ormTestsResults {
   108  	return &ormTestsResults{
   109  		results:       make(map[string]string),
   110  		allIssueHints: make(map[string]string),
   111  		runTests:      make(map[string]struct{}),
   112  	}
   113  }
   114  
   115  // summarizeAll summarizes the result of running an ORM or a driver test suite
   116  // against a cockroach node. If an unexpected result is observed (for example,
   117  // a test unexpectedly failed or passed), a new blacklist is populated.
   118  func (r *ormTestsResults) summarizeAll(
   119  	t *test, ormName, blacklistName string, expectedFailures blacklist, version, latestTag string,
   120  ) {
   121  	// Collect all the tests that were not run.
   122  	notRunCount := 0
   123  	for test, issue := range expectedFailures {
   124  		if _, ok := r.runTests[test]; ok {
   125  			continue
   126  		}
   127  		r.allTests = append(r.allTests, test)
   128  		r.results[test] = fmt.Sprintf("--- FAIL: %s - %s (not run)", test, maybeAddGithubLink(issue))
   129  		notRunCount++
   130  	}
   131  
   132  	// Log all the test results. We re-order the tests alphabetically here.
   133  	sort.Strings(r.allTests)
   134  	for _, test := range r.allTests {
   135  		result, ok := r.results[test]
   136  		if !ok {
   137  			t.Fatalf("can't find %s in test result list", test)
   138  		}
   139  		t.l.Printf("%s\n", result)
   140  	}
   141  
   142  	t.l.Printf("------------------------\n")
   143  
   144  	r.summarizeFailed(
   145  		t, ormName, blacklistName, expectedFailures, version, latestTag, notRunCount,
   146  	)
   147  }
   148  
   149  // summarizeFailed prints out the results of running an ORM or a driver test
   150  // suite against a cockroach node. It is similar to summarizeAll except that it
   151  // doesn't pay attention to all the tests - only to the failed ones.
   152  // If a test suite outputs only the failures, then this method should be used.
   153  func (r *ormTestsResults) summarizeFailed(
   154  	t *test,
   155  	ormName, blacklistName string,
   156  	expectedFailures blacklist,
   157  	version, latestTag string,
   158  	notRunCount int,
   159  ) {
   160  	var bResults strings.Builder
   161  	fmt.Fprintf(&bResults, "Tests run on Cockroach %s\n", version)
   162  	fmt.Fprintf(&bResults, "Tests run against %s %s\n", ormName, latestTag)
   163  	fmt.Fprintf(&bResults, "%d Total Tests Run\n",
   164  		r.passExpectedCount+r.passUnexpectedCount+r.failExpectedCount+r.failUnexpectedCount,
   165  	)
   166  
   167  	p := func(msg string, count int) {
   168  		testString := "tests"
   169  		if count == 1 {
   170  			testString = "test"
   171  		}
   172  		fmt.Fprintf(&bResults, "%d %s %s\n", count, testString, msg)
   173  	}
   174  	p("passed", r.passUnexpectedCount+r.passExpectedCount)
   175  	p("failed", r.failUnexpectedCount+r.failExpectedCount)
   176  	p("skipped", r.skipCount)
   177  	p("ignored", r.ignoredCount)
   178  	p("passed unexpectedly", r.passUnexpectedCount)
   179  	p("failed unexpectedly", r.failUnexpectedCount)
   180  	p("expected failed but skipped", r.unexpectedSkipCount)
   181  	p("expected failed but not run", notRunCount)
   182  
   183  	fmt.Fprintf(&bResults, "---\n")
   184  	for _, result := range r.results {
   185  		if strings.Contains(result, "unexpected") {
   186  			fmt.Fprintf(&bResults, "%s\n", result)
   187  		}
   188  	}
   189  
   190  	fmt.Fprintf(&bResults, "For a full summary look at the %s artifacts \n", ormName)
   191  	t.l.Printf("%s\n", bResults.String())
   192  	t.l.Printf("------------------------\n")
   193  
   194  	if r.failUnexpectedCount > 0 || r.passUnexpectedCount > 0 ||
   195  		notRunCount > 0 || r.unexpectedSkipCount > 0 {
   196  		// Create a new blacklist so we can easily update this test.
   197  		sort.Strings(r.currentFailures)
   198  		var b strings.Builder
   199  		fmt.Fprintf(&b, "Here is new %s blacklist that can be used to update the test:\n\n", ormName)
   200  		fmt.Fprintf(&b, "var %s = blacklist{\n", blacklistName)
   201  		for _, test := range r.currentFailures {
   202  			issue := expectedFailures[test]
   203  			if len(issue) == 0 || issue == "unknown" {
   204  				issue = r.allIssueHints[test]
   205  			}
   206  			if len(issue) == 0 {
   207  				issue = "unknown"
   208  			}
   209  			fmt.Fprintf(&b, "  \"%s\": \"%s\",\n", test, issue)
   210  		}
   211  		fmt.Fprintf(&b, "}\n\n")
   212  		t.l.Printf("\n\n%s\n\n", b.String())
   213  		t.l.Printf("------------------------\n")
   214  		t.Fatalf("\n%s\nAn updated blacklist (%s) is available in the artifacts' %s log\n",
   215  			bResults.String(),
   216  			blacklistName,
   217  			ormName,
   218  		)
   219  	}
   220  }