diff --git a/.golangci.yml b/.golangci.yml index 3c31b04..ab34cf7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,278 +1,176 @@ -# This code is licensed under the terms of the MIT license https://opensource.org/license/mit -# Copyright (c) 2021 Marat Reymers - -## Golden config for golangci-lint v1.61.0 -# -# This is the best config for golangci-lint based on my experience and opinion. -# It is very strict, but not extremely strict. -# Feel free to adapt and change it for your needs. - -run: - # Timeout for analysis, e.g. 30s, 5m. - # Default: 1m - timeout: 3m - - -# This file contains only configs which differ from defaults. -# All possible options can be found here https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml -linters-settings: - cyclop: - # The maximal code complexity to report. - # Default: 10 - max-complexity: 30 - # The maximal average package complexity. - # If it's higher than 0.0 (float) the check is enabled - # Default: 0.0 - package-average: 10.0 - - errcheck: - # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. - # Such cases aren't reported by default. - # Default: false - check-type-assertions: true - - exhaustive: - # Program elements to check for exhaustiveness. - # Default: [ switch ] - check: - - switch - - map - - exhaustruct: - # List of regular expressions to exclude struct packages and their names from checks. - # Regular expressions must match complete canonical struct package/name/structname. - # Default: [] - exclude: - # std libs - - "^net/http.Client$" - - "^net/http.Cookie$" - - "^net/http.Request$" - - "^net/http.Response$" - - "^net/http.Server$" - - "^net/http.Transport$" - - "^net/url.URL$" - - "^os/exec.Cmd$" - - "^reflect.StructField$" - # public libs - - "^github.com/Shopify/sarama.Config$" - - "^github.com/Shopify/sarama.ProducerMessage$" - - "^github.com/mitchellh/mapstructure.DecoderConfig$" - - "^github.com/prometheus/client_golang/.+Opts$" - - "^github.com/spf13/cobra.Command$" - - "^github.com/spf13/cobra.CompletionOptions$" - - "^github.com/stretchr/testify/mock.Mock$" - - "^github.com/testcontainers/testcontainers-go.+Request$" - - "^github.com/testcontainers/testcontainers-go.FromDockerfile$" - - "^golang.org/x/tools/go/analysis.Analyzer$" - - "^google.golang.org/protobuf/.+Options$" - - "^gopkg.in/yaml.v3.Node$" - - funlen: - # Checks the number of lines in a function. - # If lower than 0, disable the check. - # Default: 60 - lines: 100 - # Checks the number of statements in a function. - # If lower than 0, disable the check. - # Default: 40 - statements: 50 - # Ignore comments when counting lines. - # Default false - ignore-comments: true - - gocognit: - # Minimal code complexity to report. - # Default: 30 (but we recommend 10-20) - min-complexity: 30 - - gocritic: - # Settings passed to gocritic. - # The settings key is the name of a supported gocritic checker. - # The list of supported checkers can be find in https://go-critic.github.io/overview. - settings: - captLocal: - # Whether to restrict checker to params only. - # Default: true - paramsOnly: false - underef: - # Whether to skip (*x).method() calls where x is a pointer receiver. - # Default: true - skipRecvDeref: false - - gomodguard: - blocked: - # List of blocked modules. - # Default: [] - modules: - - github.com/golang/protobuf: - recommendations: - - google.golang.org/protobuf - reason: "see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules" - - github.com/satori/go.uuid: - recommendations: - - github.com/google/uuid - reason: "satori's package is not maintained" - - github.com/gofrs/uuid: - recommendations: - - github.com/gofrs/uuid/v5 - reason: "gofrs' package was not go module before v5" - - govet: - # Enable all analyzers. - # Default: false - enable-all: true - # Disable analyzers by name. - # Run `go tool vet help` to see all analyzers. - # Default: [] - disable: - - fieldalignment # too strict - - shadow - - gosec: - excludes: - - G115 - - G404 - - inamedparam: - # Skips check for interface methods with only a single parameter. - # Default: false - skip-single-param: true - - mnd: - # List of function patterns to exclude from analysis. - # Values always ignored: `time.Date`, - # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`, - # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`. - # Default: [] - ignored-functions: - - args.Error - - flag.Arg - - flag.Duration.* - - flag.Float.* - - flag.Int.* - - flag.Uint.* - - os.Chmod - - os.Mkdir.* - - os.OpenFile - - os.WriteFile - - prometheus.ExponentialBuckets.* - - prometheus.LinearBuckets - - nakedret: - # Make an issue if func has more lines of code than this setting, and it has naked returns. - # Default: 30 - max-func-lines: 0 - - nolintlint: - # Exclude following linters from requiring an explanation. - # Default: [] - allow-no-explanation: [ funlen, gocognit, lll ] - # Enable to require an explanation of nonzero length after each nolint directive. - # Default: false - require-explanation: true - # Enable to require nolint directives to mention the specific linter being suppressed. - # Default: false - require-specific: true - - perfsprint: - # Optimizes into strings concatenation. - # Default: true - strconcat: false - - rowserrcheck: - # database/sql is always checked - # Default: [] - packages: - - github.com/jmoiron/sqlx - - sloglint: - # Enforce not using global loggers. - # Values: - # - "": disabled - # - "all": report all global loggers - # - "default": report only the default slog logger - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global - # Default: "" - no-global: "all" - # Enforce using methods that accept a context. - # Values: - # - "": disabled - # - "all": report all contextless calls - # - "scope": report only if a context exists in the scope of the outermost function - # https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only - # Default: "" - context: "scope" - - tenv: - # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. - # Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. - # Default: false - all: true - - +version: "2" linters: - disable-all: true + default: none enable: - ## enabled by default - - errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases - - gosimple # specializes in simplifying a code - - govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - ineffassign # detects when assignments to existing variables are not used - - staticcheck # is a go vet on steroids, applying a ton of static analysis checks - - typecheck # like the front-end of a Go compiler, parses and type-checks Go code - - unused # checks for unused constants, variables, functions and types - ## disabled by default - - asasalint # checks for pass []any as any in variadic func(...any) - - copyloopvar # detects places where loop variables are copied (Go 1.22+) - - cyclop # checks function and package cyclomatic complexity - - dupl # tool for code clone detection - - fatcontext # detects nested contexts in loops - - funlen # tool for detection of long functions - - gocheckcompilerdirectives # validates go compiler directive comments (//go:) - - gochecknoglobals # checks that no global variables exist - - gocognit # computes and checks the cognitive complexity of functions - - goconst # finds repeated strings that could be replaced by a constant - - gocritic # provides diagnostics that check for bugs, performance and style issues - - gocyclo # computes and checks the cyclomatic complexity of functions - - goprintffuncname # checks that printf-like functions are named with f at the end - - gosec # inspects source code for security problems - - intrange # finds places where for loops could make use of an integer range - - nestif # reports deeply nested if statements - - nilerr # finds the code that returns nil even if it checks that the error is not nil - - nolintlint # reports ill-formed or insufficient nolint directives - - nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL - - perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative - - predeclared # finds code that shadows one of Go's predeclared identifiers - - reassign # checks that package variables are not reassigned - - revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint - - stylecheck # is a replacement for golint - - tenv # detects using os.Setenv instead of t.Setenv since Go1.17 - - testableexamples # checks if examples are testable (have an expected output) - - testifylint # checks usage of github.com/stretchr/testify - - tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes - - unconvert # removes unnecessary type conversions - - unparam # reports unused function parameters - - usestdlibvars # detects the possibility to use variables/constants from the Go standard library - - wastedassign # finds wasted assignment statements - - whitespace # detects leading and trailing whitespace - + - asasalint + - copyloopvar + - cyclop + - dupl + - errcheck + - fatcontext + - funlen + - gocheckcompilerdirectives + - gochecknoglobals + - gocognit + - goconst + - gocritic + - gocyclo + - goprintffuncname + - gosec + - govet + - ineffassign + - intrange + - nestif + - nilerr + - nolintlint + - nosprintfhostport + - perfsprint + - predeclared + - reassign + - revive + - staticcheck + - testableexamples + - testifylint + - tparallel + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign + - whitespace + settings: + cyclop: + max-complexity: 30 + package-average: 10 + errcheck: + check-type-assertions: true + exhaustive: + check: + - switch + - map + exhaustruct: + exclude: + - ^net/http.Client$ + - ^net/http.Cookie$ + - ^net/http.Request$ + - ^net/http.Response$ + - ^net/http.Server$ + - ^net/http.Transport$ + - ^net/url.URL$ + - ^os/exec.Cmd$ + - ^reflect.StructField$ + - ^github.com/Shopify/sarama.Config$ + - ^github.com/Shopify/sarama.ProducerMessage$ + - ^github.com/mitchellh/mapstructure.DecoderConfig$ + - ^github.com/prometheus/client_golang/.+Opts$ + - ^github.com/spf13/cobra.Command$ + - ^github.com/spf13/cobra.CompletionOptions$ + - ^github.com/stretchr/testify/mock.Mock$ + - ^github.com/testcontainers/testcontainers-go.+Request$ + - ^github.com/testcontainers/testcontainers-go.FromDockerfile$ + - ^golang.org/x/tools/go/analysis.Analyzer$ + - ^google.golang.org/protobuf/.+Options$ + - ^gopkg.in/yaml.v3.Node$ + funlen: + lines: 100 + statements: 50 + ignore-comments: true + gocognit: + min-complexity: 30 + gocritic: + settings: + captLocal: + paramsOnly: false + underef: + skipRecvDeref: false + gomodguard: + blocked: + modules: + - github.com/golang/protobuf: + recommendations: + - google.golang.org/protobuf + reason: see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules + - github.com/satori/go.uuid: + recommendations: + - github.com/google/uuid + reason: satori's package is not maintained + - github.com/gofrs/uuid: + recommendations: + - github.com/gofrs/uuid/v5 + reason: gofrs' package was not go module before v5 + gosec: + excludes: + - G115 + - G404 + govet: + disable: + - fieldalignment + - shadow + enable-all: true + inamedparam: + skip-single-param: true + mnd: + ignored-functions: + - args.Error + - flag.Arg + - flag.Duration.* + - flag.Float.* + - flag.Int.* + - flag.Uint.* + - os.Chmod + - os.Mkdir.* + - os.OpenFile + - os.WriteFile + - prometheus.ExponentialBuckets.* + - prometheus.LinearBuckets + nolintlint: + require-explanation: true + require-specific: true + allow-no-explanation: + - funlen + - gocognit + - lll + perfsprint: + strconcat: false + rowserrcheck: + packages: + - github.com/jmoiron/sqlx + sloglint: + no-global: all + context: scope + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - godot + source: (noinspection|TODO) + - linters: + - gocritic + source: //noinspection + - linters: + - bodyclose + - dupl + - funlen + - goconst + - gosec + - noctx + - wrapcheck + path: _test\.go + paths: + - third_party$ + - builtin$ + - examples$ issues: - # Maximum count of issues with the same text. - # Set to 0 to disable. - # Default: 3 max-same-issues: 50 - - exclude-rules: - - source: "(noinspection|TODO)" - linters: [ godot ] - - source: "//noinspection" - linters: [ gocritic ] - - path: "_test\\.go" - linters: - - bodyclose - - dupl - - funlen - - goconst - - gosec - - noctx - - wrapcheck \ No newline at end of file +formatters: + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile b/Makefile index 47afc47..14f631d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ .DEFAULT_GOAL := test_and_build REQUIRED_GO_VERSION := 1.23 -GOLANGCI_LINT_VERSION := v1.64.6 +GOLANGCI_LINT_VERSION := v2.0.2 # Determine the Go binary directory GOBIN_DIR := $(or $(GOBIN), $(shell go env GOBIN)) @@ -10,6 +10,9 @@ ifeq ($(GOBIN_DIR),) GOBIN_DIR := $(shell go env GOPATH)/bin endif +COMMIT := $(shell git rev-parse --short HEAD) +DATE := $(shell date +%Y-%m-%dT%H:%M:%S) + test_and_build: test build # Version check @@ -28,7 +31,10 @@ default: check_version build build: @echo "Building vt..." - @go build -o vt ./go/vt + @go build -ldflags "\ + -X github.com/vitessio/vt/go/cmd.CommitSha=$(COMMIT) \ + -X github.com/vitessio/vt/go/cmd.BuildDate=$(DATE)" \ + -o vt ./go/vt test: go test -v -count=1 ./go/... diff --git a/go/cmd/root.go b/go/cmd/root.go index 3e9a2a2..51da4ac 100644 --- a/go/cmd/root.go +++ b/go/cmd/root.go @@ -46,5 +46,6 @@ func getRootCmd() *cobra.Command { root.AddCommand(dbinfoCmd()) root.AddCommand(transactionsCmd()) root.AddCommand(planalyzeCmd()) + root.AddCommand(versionCmd()) return root } diff --git a/go/cmd/tester.go b/go/cmd/tester.go index 1e4c5fa..8ca45ac 100644 --- a/go/cmd/tester.go +++ b/go/cmd/tester.go @@ -114,4 +114,5 @@ func commonFlags(cmd *cobra.Command, cfg *vttester.Config) { cmd.Flags().StringVar(&cfg.TraceFile, "trace-file", "", "Do a vexplain trace on all queries and store the output in the given file.") cmd.Flags().BoolVar(&cfg.Sharded, "sharded", false, "Run all tests on a sharded keyspace and using auto-vschema. This cannot be used with either -vschema or -vtexplain-vschema.") cmd.Flags().StringVar(&cfg.BackupDir, "backup-path", "", "Restore from backup before running the tester") + cmd.Flags().BoolVar(&cfg.Verbose, "verbose", false, "Print to stdout the queries that are being run.") } diff --git a/go/cmd/version.go b/go/cmd/version.go new file mode 100644 index 0000000..06c26ff --- /dev/null +++ b/go/cmd/version.go @@ -0,0 +1,42 @@ +/* +Copyright 2025 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var ( + //nolint:gochecknoglobals // This is set by the linker at build time. + CommitSha = "none" // default, overridden by ldflags + + //nolint:gochecknoglobals // This is set by the linker at build time. + BuildDate = "unknown" // default, overridden by ldflags +) + +func versionCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "version", + Short: "Show the CLI version", + Run: func(_ *cobra.Command, _ []string) { + fmt.Printf("built on %s on git commit '%s'\n", BuildDate, CommitSha) + }, + } + return cmd +} diff --git a/go/dbinfo/dbinfo_test.go b/go/dbinfo/dbinfo_test.go index c0bd144..f46f709 100644 --- a/go/dbinfo/dbinfo_test.go +++ b/go/dbinfo/dbinfo_test.go @@ -61,7 +61,7 @@ func TestDBInfoLoad(t *testing.T) { "gtid_mode": "OFF", "log_bin": "ON", } - require.EqualValues(t, expected, si.GlobalVariables) + require.Equal(t, expected, si.GlobalVariables) }) } diff --git a/go/planalyze/planalyze.go b/go/planalyze/planalyze.go index 89463fd..e92fedf 100644 --- a/go/planalyze/planalyze.go +++ b/go/planalyze/planalyze.go @@ -196,7 +196,7 @@ func getPlanRes(err error, plan *engine.Plan) PlanComplexity { case *engine.Delete: rp = prim.RoutingParameters case *engine.Insert: - if prim.InsertCommon.Opcode == engine.InsertUnsharded { + if prim.Opcode == engine.InsertUnsharded { return PassThrough } return SimpleRouted diff --git a/go/tester/execute.go b/go/tester/execute.go index c4ba9d1..502a706 100644 --- a/go/tester/execute.go +++ b/go/tester/execute.go @@ -47,6 +47,9 @@ func ExecuteTests( for _, name := range cfg.Tests { errReporter := s.NewReporterForFile(name) + if cfg.Verbose { + errReporter = &loggingReporter{inner: errReporter} + } vTester := NewTester(name, errReporter, info, cfg.OLAP, info.vschema, vschemaF, factory, cfg.Loader) err := vTester.Run() if err != nil { @@ -214,10 +217,10 @@ func generateShardRanges(numberOfShards int) []string { start := i * step end := (i + 1) * step - switch { - case i == 0: + switch i { + case 0: ranges[i] = fmt.Sprintf("-%02x", end) - case i == numberOfShards-1: + case numberOfShards - 1: ranges[i] = fmt.Sprintf("%02x-", start) default: ranges[i] = fmt.Sprintf("%02x-%02x", start, end) diff --git a/go/tester/logging_reporter.go b/go/tester/logging_reporter.go new file mode 100644 index 0000000..67caea6 --- /dev/null +++ b/go/tester/logging_reporter.go @@ -0,0 +1,64 @@ +/* +Copyright 2025 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tester + +import "fmt" + +type loggingReporter struct { + inner Reporter +} + +var _ Reporter = (*loggingReporter)(nil) + +func (l *loggingReporter) Errorf(format string, args ...interface{}) { + l.inner.Errorf(format, args...) +} + +func (l *loggingReporter) FailNow() { + l.inner.FailNow() +} + +func (l *loggingReporter) Helper() { + l.inner.Helper() +} + +func (l *loggingReporter) AddTestCase(query string, lineNo int) { + fmt.Printf("Running query %q on line #%d\n", query, lineNo) + l.inner.AddTestCase(query, lineNo) +} + +func (l *loggingReporter) EndTestCase() { + l.inner.EndTestCase() +} + +func (l *loggingReporter) AddFailure(err error) { + fmt.Printf("Failure added: %s\n", err.Error()) + l.inner.AddFailure(err) +} + +func (l *loggingReporter) AddInfo(info string) { + fmt.Printf("Info: %s\n", info) + l.inner.AddInfo(info) +} + +func (l *loggingReporter) Report() string { + return l.inner.Report() +} + +func (l *loggingReporter) Failed() bool { + return l.inner.Failed() +} diff --git a/go/tester/reporter.go b/go/tester/reporter.go index 00b8493..cf55e2b 100644 --- a/go/tester/reporter.go +++ b/go/tester/reporter.go @@ -154,7 +154,7 @@ func (e *FileReporter) createErrorFileFor() *os.File { errorPath := path.Join(e.errorDir(), qc) file, err := os.Create(errorPath) exitIf(err, "creating error file") - _, err = file.WriteString(fmt.Sprintf("Error log for query on line %d:\n%s\n\n", e.currentQueryLineNum, e.currentQuery)) + _, err = fmt.Fprintf(file, "Error log for query on line %d:\n%s\n\n", e.currentQueryLineNum, e.currentQuery) exitIf(err, "writing to error file") return file diff --git a/go/tester/run.go b/go/tester/run.go index b35a186..34921f3 100644 --- a/go/tester/run.go +++ b/go/tester/run.go @@ -41,6 +41,7 @@ type Config struct { Tests []string NumberOfShards int Compare bool + Verbose bool BackupDir string Loader data.Loader @@ -77,7 +78,7 @@ func Run(cfg Config) error { return wrongUsage("specify only one of the following flags: -vschema, -vtexplain-vschema, -sharded") } - if cfg.NumberOfShards > 0 && !(cfg.Sharded || cfg.VSchemaFile != "" || cfg.VtExplainVschemaFile != "") { + if cfg.NumberOfShards > 0 && !cfg.Sharded && cfg.VSchemaFile == "" && cfg.VtExplainVschemaFile == "" { return wrongUsage("number-of-shards can only be used with -sharded, -vschema or -vtexplain-vschema") } diff --git a/go/tester/tracer.go b/go/tester/tracer.go index be1969a..645bfb9 100644 --- a/go/tester/tracer.go +++ b/go/tester/tracer.go @@ -107,7 +107,7 @@ func (t *Tracer) runQuery(q data.Query, ast sqlparser.Statement, state *state.St reference := state.IsReferenceSet() _, isSelect := ast.(sqlparser.SelectStatement) - if reference || !state.RunOnVitess() || !(isSelect || sqlparser.IsDMLStatement(ast)) { + if reference || !state.RunOnVitess() || (!isSelect && !sqlparser.IsDMLStatement(ast)) { return nil }