diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile new file mode 100644 index 0000000000000..25b655544265a --- /dev/null +++ b/.clusterfuzzlite/Dockerfile @@ -0,0 +1,7 @@ +# Copyright (c) Tailscale Inc & AUTHORS +# SPDX-License-Identifier: BSD-3-Clause + +FROM gcr.io/oss-fuzz-base/base-builder-go +COPY . $SRC/tailscale +WORKDIR $SRC/tailscale +COPY .clusterfuzzlite/build.sh $SRC/ diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh new file mode 100755 index 0000000000000..299930fc3bfa8 --- /dev/null +++ b/.clusterfuzzlite/build.sh @@ -0,0 +1,21 @@ +#!/bin/bash -eu +# Copyright (c) Tailscale Inc & AUTHORS +# SPDX-License-Identifier: BSD-3-Clause + +tool=github.com/AdamKorcz/go-118-fuzz-build +ref=fc5dc53b9db8a38c394c53d6e439a1410cf8fc19 +work=$(mktemp -d) +version=$(awk '/^go / { print $2 }' go.mod) +goroot=$(GOTOOLCHAIN="go$version" go env GOROOT) +# The v2 builder modifies testing internals and must match the Go toolchain. +cp -a "$goroot/." "$work/goroot" +chmod -R u+w "$work/goroot" +export GOROOT="$work/goroot" GOTOOLCHAIN=local +export PATH="$work/bin:$GOROOT/bin:$PATH" +GOBIN="$work/bin" go install "$tool@$ref" +mv "$work/bin/go-118-fuzz-build" "$work/bin/go-118-fuzz-build_v2" +go get "$tool/testing@$ref" +compile_native_go_fuzzer_v2 tailscale.com/net/dns/resolver FuzzClampEDNSSize clamp_edns_size +compile_native_go_fuzzer_v2 tailscale.com/util/hashx Fuzz hashx +compile_native_go_fuzzer_v2 tailscale.com/util/deephash FuzzTime deephash_time +compile_native_go_fuzzer_v2 tailscale.com/util/deephash FuzzAddr deephash_addr diff --git a/.clusterfuzzlite/project.yaml b/.clusterfuzzlite/project.yaml new file mode 100644 index 0000000000000..4f2ee4d973389 --- /dev/null +++ b/.clusterfuzzlite/project.yaml @@ -0,0 +1 @@ +language: go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6e3d8fa18a1f5..4a275b6e04d74 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,19 +2,7 @@ # both PRs and merged commits, and for the latter reports failures to slack. name: CI -env: - # Our fuzz job, powered by OSS-Fuzz, fails periodically because we upgrade to - # new Go versions very eagerly. OSS-Fuzz is a little more conservative, and - # ends up being unable to compile our code. - # - # When this happens, we want to disable the fuzz target until OSS-Fuzz catches - # up. However, we also don't want to forget to turn it back on when OSS-Fuzz - # can once again build our code. - # - # This variable toggles the fuzz job between two modes: - # - false: we expect fuzzing to be happy, and should report failure if it's not. - # - true: we expect fuzzing is broken, and should report failure if it start working. - TS_FUZZ_CURRENTLY_BROKEN: false +permissions: {} on: push: @@ -40,6 +28,8 @@ concurrency: jobs: test: + permissions: + contents: read strategy: fail-fast: false # don't abort the entire matrix if one element fails matrix: @@ -116,6 +106,8 @@ jobs: fi windows: + permissions: + contents: read runs-on: windows-2022 steps: - name: checkout @@ -148,9 +140,12 @@ jobs: # Don't use -bench=. -benchtime=1x. # Somewhere in the layers (powershell?) # the equals signs cause great confusion. - run: go test -bench . -benchtime 1x ./... + # testwrapper retries tests marked with flakytest.Mark. + run: go run ./cmd/testwrapper ./... -bench . -benchtime 1x vm: + permissions: + contents: read runs-on: ["self-hosted", "linux", "vm"] # VM tests run with some privileges, don't let them run on 3p PRs. if: github.repository == 'tailscale/tailscale' @@ -171,6 +166,8 @@ jobs: XDB_CACHE_HOME: "/var/lib/ghrunner/cache" cross: # cross-compile checks, build only. + permissions: + contents: read strategy: fail-fast: false # don't abort the entire matrix if one element fails matrix: @@ -248,6 +245,8 @@ jobs: ios: # similar to cross above, but iOS can't build most of the repo. So, just #make it build a few smoke packages. + permissions: + contents: read runs-on: ubuntu-22.04 steps: - name: checkout @@ -259,6 +258,8 @@ jobs: GOARCH: arm64 android: + permissions: + contents: read # similar to cross above, but android fails to build a few pieces of the # repo. We should fix those pieces, they're small, but as a stepping stone, # only test the subset of android that our past smoke test checked. @@ -281,65 +282,33 @@ jobs: GOARCH: arm64 fuzz: - # This target periodically breaks (see TS_FUZZ_CURRENTLY_BROKEN at the top - # of the file), so it's more complex than usual: the 'build fuzzers' step - # might fail, and depending on the value of 'TS_FUZZ_CURRENTLY_BROKEN', that - # might or might not be fine. The steps after the build figure out whether - # the success/failure is expected, and appropriately pass/fail the job - # overall accordingly. - # - # Practically, this means that all steps after 'build fuzzers' must have an - # explicit 'if' condition, because the default condition for steps is - # 'success()', meaning "only run this if no previous steps failed". + permissions: + contents: read if: github.event_name == 'pull_request' runs-on: ubuntu-22.04 steps: - name: build fuzzers - id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - # continue-on-error makes steps.build.conclusion be 'success' even if - # steps.build.outcome is 'failure'. This means this step does not - # contribute to the job's overall pass/fail evaluation. - continue-on-error: true + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: - oss-fuzz-project-name: "tailscale" - dry-run: false language: go - - name: report unexpectedly broken fuzz build - if: steps.build.outcome == 'failure' && env.TS_FUZZ_CURRENTLY_BROKEN != 'true' - run: | - echo "fuzzer build failed, see above for why" - echo "if the failure is due to OSS-Fuzz not being on the latest Go yet," - echo "set TS_FUZZ_CURRENTLY_BROKEN=true in .github/workflows/test.yml" - echo "to temporarily disable fuzzing until OSS-Fuzz works again." - exit 1 - - name: report unexpectedly working fuzz build - if: steps.build.outcome == 'success' && env.TS_FUZZ_CURRENTLY_BROKEN == 'true' - run: | - echo "fuzzer build succeeded, but we expect it to be broken" - echo "please set TS_FUZZ_CURRENTLY_BROKEN=false in .github/workflows/test.yml" - echo "to reenable fuzz testing" - exit 1 + keep-unaffected-fuzz-targets: true - name: run fuzzers id: run - # Run the fuzzers whenever they're able to build, even if we're going to - # report a failure because TS_FUZZ_CURRENTLY_BROKEN is set to the wrong - # value. - if: steps.build.outcome == 'success' - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: - oss-fuzz-project-name: "tailscale" fuzz-seconds: 300 - dry-run: false language: go + github-token: ${{ secrets.GITHUB_TOKEN }} - name: upload crash - uses: actions/upload-artifact@v3 - if: steps.run.outcome != 'success' && steps.build.outcome == 'success' + uses: actions/upload-artifact@v4 + if: failure() && steps.run.outcome == 'failure' with: name: artifacts path: ./out/artifacts depaware: + permissions: + contents: read runs-on: ubuntu-22.04 steps: - name: checkout @@ -354,6 +323,8 @@ jobs: find . -name 'depaware.txt' | xargs -n1 dirname | xargs ./tool/go run github.com/tailscale/depaware --check go_generate: + permissions: + contents: read runs-on: ubuntu-22.04 steps: - name: checkout @@ -371,6 +342,8 @@ jobs: git diff --name-only --exit-code || (echo "The files above need updating. Please run 'go generate'."; exit 1) go_mod_tidy: + permissions: + contents: read runs-on: ubuntu-22.04 steps: - name: checkout @@ -387,6 +360,8 @@ jobs: git diff --name-only --exit-code || (echo "Please run 'go mod tidy'."; exit 1) licenses: + permissions: + contents: read runs-on: ubuntu-22.04 steps: - name: checkout @@ -395,6 +370,8 @@ jobs: run: ./scripts/check_license_headers.sh . staticcheck: + permissions: + contents: read runs-on: ubuntu-22.04 strategy: fail-fast: false # don't abort the entire matrix if one element fails @@ -483,4 +460,5 @@ jobs: if: github.event_name != 'push' uses: re-actors/alls-green@release/v1 with: + allowed-skips: ${{ github.repository != 'tailscale/tailscale' && 'vm' || '' }} jobs: ${{ toJSON(needs) }} diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index 46fbbfdc9db01..f4aeffbdf2cb5 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -168,7 +168,6 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa golang.org/x/crypto/nacl/box from tailscale.com/types/key+ golang.org/x/crypto/nacl/secretbox from golang.org/x/crypto/nacl/box golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+ - golang.org/x/exp/constraints from golang.org/x/exp/slices golang.org/x/exp/maps from tailscale.com/types/views golang.org/x/exp/slices from tailscale.com/net/tsaddr+ L golang.org/x/net/bpf from github.com/mdlayher/netlink+ diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 0b9729a78d8b3..1f91a41c153a0 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -163,7 +163,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/crypto/nacl/secretbox from golang.org/x/crypto/nacl/box golang.org/x/crypto/pbkdf2 from software.sslmate.com/src/go-pkcs12 golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+ - golang.org/x/exp/constraints from golang.org/x/exp/slices+ + golang.org/x/exp/constraints from github.com/dblohm7/wingoes/pe+ golang.org/x/exp/maps from tailscale.com/types/views+ golang.org/x/exp/slices from tailscale.com/net/tsaddr+ golang.org/x/net/bpf from github.com/mdlayher/netlink+ @@ -213,6 +213,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep crypto/hkdf from crypto/internal/hpke+ crypto/hmac from crypto/tls+ crypto/md5 from crypto/tls+ + crypto/pbkdf2 from golang.org/x/crypto/pbkdf2 crypto/rand from crypto/ed25519+ crypto/rc4 from crypto/tls crypto/rsa from crypto/tls+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index c065d6129b9c6..787ea1689989c 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -11,7 +11,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate W 💣 github.com/alexbrainman/sspi/negotiate from tailscale.com/net/tshttpproxy LD github.com/anmitsu/go-shlex from tailscale.com/tempfork/gliderlabs/ssh - L github.com/aws/aws-sdk-go-v2 from github.com/aws/aws-sdk-go-v2/internal/ini L github.com/aws/aws-sdk-go-v2/aws from github.com/aws/aws-sdk-go-v2/aws/middleware+ L github.com/aws/aws-sdk-go-v2/aws/arn from tailscale.com/ipn/store/awsstore L github.com/aws/aws-sdk-go-v2/aws/defaults from github.com/aws/aws-sdk-go-v2/service/ssm+ @@ -29,12 +28,18 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/credentials/endpointcreds from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client from github.com/aws/aws-sdk-go-v2/credentials/endpointcreds + L github.com/aws/aws-sdk-go-v2/credentials/logincreds from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/credentials/processcreds from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/credentials/ssocreds from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/credentials/stscreds from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/feature/ec2/imds from github.com/aws/aws-sdk-go-v2/config+ L github.com/aws/aws-sdk-go-v2/feature/ec2/imds/internal/config from github.com/aws/aws-sdk-go-v2/feature/ec2/imds + L github.com/aws/aws-sdk-go-v2/internal/auth from github.com/aws/aws-sdk-go-v2/aws/signer/v4+ + L github.com/aws/aws-sdk-go-v2/internal/auth/smithy from github.com/aws/aws-sdk-go-v2/service/signin+ L github.com/aws/aws-sdk-go-v2/internal/configsources from github.com/aws/aws-sdk-go-v2/service/ssm+ + L github.com/aws/aws-sdk-go-v2/internal/context from github.com/aws/aws-sdk-go-v2/aws/retry+ + L github.com/aws/aws-sdk-go-v2/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/signin+ + L github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn from github.com/aws/aws-sdk-go-v2/service/signin+ L github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 from github.com/aws/aws-sdk-go-v2/service/ssm/internal/endpoints+ L github.com/aws/aws-sdk-go-v2/internal/ini from github.com/aws/aws-sdk-go-v2/config L github.com/aws/aws-sdk-go-v2/internal/rand from github.com/aws/aws-sdk-go-v2/aws+ @@ -44,7 +49,11 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/aws-sdk-go-v2/internal/strings from github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4 L github.com/aws/aws-sdk-go-v2/internal/sync/singleflight from github.com/aws/aws-sdk-go-v2/aws L github.com/aws/aws-sdk-go-v2/internal/timeconv from github.com/aws/aws-sdk-go-v2/aws/retry + L github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding from github.com/aws/aws-sdk-go-v2/service/sts L github.com/aws/aws-sdk-go-v2/service/internal/presigned-url from github.com/aws/aws-sdk-go-v2/service/sts + L github.com/aws/aws-sdk-go-v2/service/signin from github.com/aws/aws-sdk-go-v2/config+ + L github.com/aws/aws-sdk-go-v2/service/signin/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/signin + L github.com/aws/aws-sdk-go-v2/service/signin/types from github.com/aws/aws-sdk-go-v2/credentials/logincreds+ L github.com/aws/aws-sdk-go-v2/service/ssm from tailscale.com/ipn/store/awsstore L github.com/aws/aws-sdk-go-v2/service/ssm/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/ssm L github.com/aws/aws-sdk-go-v2/service/ssm/types from github.com/aws/aws-sdk-go-v2/service/ssm+ @@ -58,6 +67,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/sts L github.com/aws/aws-sdk-go-v2/service/sts/types from github.com/aws/aws-sdk-go-v2/credentials/stscreds+ L github.com/aws/smithy-go from github.com/aws/aws-sdk-go-v2/aws/protocol/restjson+ + L github.com/aws/smithy-go/auth from github.com/aws/aws-sdk-go-v2/internal/auth+ L github.com/aws/smithy-go/auth/bearer from github.com/aws/aws-sdk-go-v2/aws+ L github.com/aws/smithy-go/context from github.com/aws/smithy-go/auth/bearer L github.com/aws/smithy-go/document from github.com/aws/aws-sdk-go-v2/service/ssm+ @@ -65,13 +75,18 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/smithy-go/encoding/httpbinding from github.com/aws/aws-sdk-go-v2/aws/protocol/query+ L github.com/aws/smithy-go/encoding/json from github.com/aws/aws-sdk-go-v2/service/ssm+ L github.com/aws/smithy-go/encoding/xml from github.com/aws/aws-sdk-go-v2/service/sts + L github.com/aws/smithy-go/endpoints from github.com/aws/aws-sdk-go-v2/service/signin+ + L github.com/aws/smithy-go/endpoints/private/rulesfn from github.com/aws/aws-sdk-go-v2/service/signin+ L github.com/aws/smithy-go/internal/sync/singleflight from github.com/aws/smithy-go/auth/bearer L github.com/aws/smithy-go/io from github.com/aws/aws-sdk-go-v2/feature/ec2/imds+ L github.com/aws/smithy-go/logging from github.com/aws/aws-sdk-go-v2/aws+ + L github.com/aws/smithy-go/metrics from github.com/aws/aws-sdk-go-v2/aws/retry+ L github.com/aws/smithy-go/middleware from github.com/aws/aws-sdk-go-v2/aws+ + L github.com/aws/smithy-go/private/requestcompression from github.com/aws/aws-sdk-go-v2/config L github.com/aws/smithy-go/ptr from github.com/aws/aws-sdk-go-v2/aws+ L github.com/aws/smithy-go/rand from github.com/aws/aws-sdk-go-v2/aws/middleware+ L github.com/aws/smithy-go/time from github.com/aws/aws-sdk-go-v2/service/ssm+ + L github.com/aws/smithy-go/tracing from github.com/aws/aws-sdk-go-v2/aws/middleware+ L github.com/aws/smithy-go/transport/http from github.com/aws/aws-sdk-go-v2/aws/middleware+ L github.com/aws/smithy-go/transport/http/internal/io from github.com/aws/smithy-go/transport/http L github.com/aws/smithy-go/waiter from github.com/aws/aws-sdk-go-v2/service/ssm @@ -376,7 +391,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de golang.org/x/crypto/poly1305 from github.com/tailscale/golang-x-crypto/ssh+ golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+ LD golang.org/x/crypto/ssh from tailscale.com/ssh/tailssh+ - golang.org/x/exp/constraints from golang.org/x/exp/slices+ + golang.org/x/exp/constraints from github.com/dblohm7/wingoes/pe+ golang.org/x/exp/maps from tailscale.com/wgengine+ golang.org/x/exp/slices from tailscale.com/ipn/ipnlocal+ golang.org/x/net/bpf from github.com/mdlayher/genetlink+ diff --git a/cmd/testwrapper/testwrapper.go b/cmd/testwrapper/testwrapper.go index c9790aafcd32b..5bfaea3512b43 100644 --- a/cmd/testwrapper/testwrapper.go +++ b/cmd/testwrapper/testwrapper.go @@ -33,6 +33,7 @@ type testAttempt struct { outcome string // "pass", "fail", "skip" logs bytes.Buffer isMarkedFlaky bool // set if the test is marked as flaky + ended bool // set after the test's "--- PASS" or "--- SKIP" line pkgFinished bool } @@ -61,11 +62,9 @@ type goTestOutput struct { var debug = os.Getenv("TS_TESTWRAPPER_DEBUG") != "" -// runTests runs the tests in pt and sends the results on ch. It sends a -// testAttempt for each test and a final testAttempt per pkg with pkgFinished -// set to true. -// It calls close(ch) when it's done. -func runTests(ctx context.Context, attempt int, pt *packageTests, otherArgs []string, ch chan<- *testAttempt) { +// runTests sends per-test and package outcomes to ch, then closes ch. +// It returns startup errors or the go test subprocess's exit error. +func runTests(ctx context.Context, attempt int, pt *packageTests, otherArgs []string, ch chan<- *testAttempt) error { defer close(ch) args := []string{"test", "-json", pt.pattern} args = append(args, otherArgs...) @@ -79,7 +78,7 @@ func runTests(ctx context.Context, attempt int, pt *packageTests, otherArgs []st cmd := exec.CommandContext(ctx, "go", args...) r, err := cmd.StdoutPipe() if err != nil { - log.Printf("error creating stdout pipe: %v", err) + return fmt.Errorf("creating stdout pipe: %w", err) } defer r.Close() cmd.Stderr = os.Stderr @@ -88,14 +87,8 @@ func runTests(ctx context.Context, attempt int, pt *packageTests, otherArgs []st cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%d", flakytest.FlakeAttemptEnv, attempt)) if err := cmd.Start(); err != nil { - log.Printf("error starting test: %v", err) - os.Exit(1) + return fmt.Errorf("starting test: %w", err) } - done := make(chan struct{}) - go func() { - defer close(done) - cmd.Wait() - }() jd := json.NewDecoder(r) resultMap := make(map[testName]*testAttempt) @@ -118,7 +111,22 @@ func runTests(ctx context.Context, attempt int, pt *packageTests, otherArgs []st } if goOutput.Test == "" { switch goOutput.Action { + case "output": + if !isPkgSummary(goOutput.Output, goOutput.Package) { + fmt.Print(goOutput.Output) + } + case "build-output": + fmt.Print(goOutput.Output) case "fail", "pass", "skip": + if goOutput.Action == "fail" { + // Timeouts omit the final per-test event; report those tests as failed. + for name, test := range resultMap { + if name.pkg == goOutput.Package && test.outcome == "" { + test.outcome = "fail" + ch <- test + } + } + } ch <- &testAttempt{ name: testName{ pkg: goOutput.Package, @@ -151,14 +159,32 @@ func runTests(ctx context.Context, attempt int, pt *packageTests, otherArgs []st resultMap[name].outcome = goOutput.Action ch <- resultMap[name] case "output": - if strings.TrimSpace(goOutput.Output) == flakytest.FlakyTestLogMessage { - resultMap[name].isMarkedFlaky = true - } else { - resultMap[name].logs.WriteString(goOutput.Output) + test := resultMap[name] + switch { + case test.ended: + // go test attributes a timeout panic to the last resumed + // test, even if it already passed. Print it so it isn't lost. + fmt.Print(goOutput.Output) + case strings.TrimSpace(goOutput.Output) == flakytest.FlakyTestLogMessage: + test.isMarkedFlaky = true + default: + test.logs.WriteString(goOutput.Output) + test.ended = strings.HasPrefix(goOutput.Output, "--- PASS: "+name.name+" ") || + strings.HasPrefix(goOutput.Output, "--- SKIP: "+name.name+" ") } } } - <-done + return cmd.Wait() +} + +// isPkgSummary reports whether line is a go test result line for pkg, such as +// "ok \tpkg\t0.1s". main prints its own summary with the attempt number. +func isPkgSummary(line, pkg string) bool { + if line == "PASS\n" || line == "FAIL\n" { + return true + } + f := strings.Fields(line) + return len(f) >= 2 && f[1] == pkg && (f[0] == "ok" || f[0] == "FAIL" || f[0] == "?") } func main() { @@ -244,9 +270,16 @@ func main() { toRetry := make(map[string][]string) // pkg -> tests to retry for _, pt := range thisRun.tests { ch := make(chan *testAttempt) - go runTests(ctx, thisRun.attempt, pt, otherArgs, ch) + runErr := make(chan error, 1) + go func() { + runErr <- runTests(ctx, thisRun.attempt, pt, otherArgs, ch) + }() + retryable := false for tr := range ch { if tr.pkgFinished { + if tr.outcome == "fail" && len(toRetry[tr.name.pkg]) == 0 { + failed = true + } printPkgOutcome(tr.name.pkg, tr.outcome, thisRun.attempt) continue } @@ -257,11 +290,16 @@ func main() { continue } if tr.isMarkedFlaky { + retryable = true toRetry[tr.name.pkg] = append(toRetry[tr.name.pkg], tr.name.name) } else { failed = true } } + if err := <-runErr; err != nil && !retryable { + log.Printf("go test: %v", err) + failed = true + } } if failed { fmt.Println("\n\nNot retrying flaky tests because non-flaky tests failed.") diff --git a/cmd/testwrapper/testwrapper_test.go b/cmd/testwrapper/testwrapper_test.go new file mode 100644 index 0000000000000..a69d95ad23fa3 --- /dev/null +++ b/cmd/testwrapper/testwrapper_test.go @@ -0,0 +1,213 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package main_test + +import ( + "context" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" + "time" + + "golang.org/x/mod/modfile" +) + +const ( + okTest = "package ok\n\nimport \"testing\"\n\nfunc TestOK(t *testing.T) {}\n" + + flakyTest = `package flaky + +import ( + "os" + "testing" + + "tailscale.com/cmd/testwrapper/flakytest" +) + +func TestOK(t *testing.T) {} + +func TestFlaky(t *testing.T) { + flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/0") + if os.Getenv(flakytest.FlakeAttemptEnv) == "1" { + t.Fatal("failing first attempt") + } +} +` + + flakyThenHangTest = `package flakyhang + +import ( + "os" + "testing" + + "tailscale.com/cmd/testwrapper/flakytest" +) + +func TestFlaky(t *testing.T) { + flakytest.Mark(t, "https://github.com/tailscale/tailscale/issues/0") + if os.Getenv(flakytest.FlakeAttemptEnv) == "1" { + t.Fatal("failing first attempt") + } +} + +func TestHang(t *testing.T) { <-make(chan struct{}) } +` + + compileErrorTest = "package broken\n\nimport \"testing\"\n\nfunc TestBroken(t *testing.T) { undefinedSymbol() }\n" +) + +func TestCLI(t *testing.T) { + t.Parallel() + repo, err := filepath.Abs(filepath.Join("..", "..")) + if err != nil { + t.Fatal(err) + } + repoMod, err := os.ReadFile(filepath.Join(repo, "go.mod")) + if err != nil { + t.Fatal(err) + } + mf, err := modfile.ParseLax("go.mod", repoMod, nil) + if err != nil || mf.Go == nil { + t.Fatalf("reading repo go version: %v", err) + } + bin := filepath.Join(t.TempDir(), "testwrapper") + if runtime.GOOS == "windows" { + bin += ".exe" + } + buildCtx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + if out, err := exec.CommandContext(buildCtx, "go", "build", "-o", bin, ".").CombinedOutput(); err != nil { + t.Fatalf("building testwrapper: %v\n%s", err, out) + } + + tests := []struct { + name string + files map[string]string + args []string + quiet bool // run without -v, as CI does + wantCode int + want []string + // wantCount maps output substrings to their exact number of occurrences. + wantCount map[string]int + }{ + {name: "Pass", files: map[string]string{"ok/ok_test.go": okTest}, wantCode: 0, wantCount: map[string]int{"fixture/ok": 1}}, + {name: "InvalidGoFlags", files: map[string]string{"ok/ok_test.go": okTest}, args: []string{"-p=invalid"}, wantCode: 1, want: []string{"invalid value"}}, + {name: "CompileError", files: map[string]string{"broken/broken_test.go": compileErrorTest}, wantCode: 1, want: []string{"undefinedSymbol"}, wantCount: map[string]int{"FAIL\tfixture/broken": 1}}, + { + name: "MarkedFlakeThenPass", + files: map[string]string{"flaky/flaky_test.go": flakyTest}, + wantCode: 0, + want: []string{"[attempt=2]"}, + wantCount: map[string]int{"=== RUN TestOK\n": 1, "=== RUN TestFlaky\n": 2}, + }, + { + name: "MixedFlakeAndCompileError", + files: map[string]string{ + "flaky/flaky_test.go": flakyTest, + "broken/broken_test.go": compileErrorTest, + }, + wantCode: 1, + want: []string{"undefinedSymbol"}, + }, + { + name: "NonFlakyFailure", + files: map[string]string{"fail/fail_test.go": "package fail\n\nimport \"testing\"\n\nfunc TestFail(t *testing.T) { t.Error(\"expected failure\") }\n"}, + wantCode: 1, + want: []string{"expected failure"}, + }, + { + name: "Timeout", + files: map[string]string{"hang/hang_test.go": "package hang\n\nimport \"testing\"\n\nfunc TestHang(t *testing.T) { <-make(chan struct{}) }\n"}, + args: []string{"-timeout=1s"}, + wantCode: 1, + want: []string{"timed out"}, + }, + { + name: "TimeoutAfterParallelPass", + files: map[string]string{"hang/hang_test.go": `package hang + +import ( + "testing" + "time" +) + +func TestHang(t *testing.T) { t.Parallel(); <-make(chan struct{}) } + +func TestQuick(t *testing.T) { t.Parallel(); time.Sleep(100 * time.Millisecond) } +`}, + args: []string{"-timeout=2s"}, + quiet: true, + wantCode: 1, + want: []string{"panic: test timed out", "running tests:"}, + }, + { + name: "FlakeThenTimeout", + files: map[string]string{"flakyhang/flakyhang_test.go": flakyThenHangTest}, + args: []string{"-timeout=1s"}, + wantCode: 1, + want: []string{"timed out", "Not retrying flaky tests"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + dir := t.TempDir() + gomod := fmt.Sprintf("module fixture\n\ngo %s\n\nrequire tailscale.com v0.0.0\n\nreplace tailscale.com => %q\n", mf.Go.Version, filepath.ToSlash(repo)) + if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte(gomod), 0o644); err != nil { + t.Fatal(err) + } + for name, content := range tt.files { + path := filepath.Join(dir, filepath.FromSlash(name)) + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + } + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + args := []string{"./..."} + if !tt.quiet { + args = append([]string{"-v"}, args...) + } + cmd := exec.CommandContext(ctx, bin, append(args, tt.args...)...) + cmd.Dir = dir + cmd.Env = append(os.Environ(), "GOWORK=off", "GOFLAGS=-mod=mod", "GOPROXY=off") + outBytes, err := cmd.CombinedOutput() + out := string(outBytes) + if ctx.Err() != nil { + t.Fatalf("testwrapper did not finish: %v\n%s", ctx.Err(), out) + } + code := 0 + if exitErr := (*exec.ExitError)(nil); errors.As(err, &exitErr) { + code = exitErr.ExitCode() + } else if err != nil { + t.Fatalf("running testwrapper: %v", err) + } + if code != tt.wantCode { + t.Errorf("exit code = %d, want %d", code, tt.wantCode) + } + for _, want := range tt.want { + if !strings.Contains(out, want) { + t.Errorf("output missing %q", want) + } + } + for sub, want := range tt.wantCount { + if got := strings.Count(out, sub); got != want { + t.Errorf("output has %q %d times, want %d", sub, got, want) + } + } + if t.Failed() { + t.Logf("output:\n%s", out) + } + }) + } +} diff --git a/derp/dropreason_string.go b/derp/dropreason_string.go index 5ba500ab20530..6bfa6817d5d38 100644 --- a/derp/dropreason_string.go +++ b/derp/dropreason_string.go @@ -25,8 +25,9 @@ const _dropReason_name = "UnknownDestUnknownDestOnFwdGoneDisconnectedQueueHeadQu var _dropReason_index = [...]uint8{0, 11, 27, 43, 52, 61, 71, 80} func (i dropReason) String() string { - if i < 0 || i >= dropReason(len(_dropReason_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_dropReason_index)-1 { return "dropReason(" + strconv.FormatInt(int64(i), 10) + ")" } - return _dropReason_name[_dropReason_index[i]:_dropReason_index[i+1]] + return _dropReason_name[_dropReason_index[idx]:_dropReason_index[idx+1]] } diff --git a/go.mod b/go.mod index 6d37f6075e7f5..3464aa1ddca1c 100644 --- a/go.mod +++ b/go.mod @@ -15,8 +15,8 @@ require ( github.com/andybalholm/brotli v1.0.5 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be github.com/aws/aws-sdk-go-v2 v1.41.5 - github.com/aws/aws-sdk-go-v2/config v1.18.22 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64 + github.com/aws/aws-sdk-go-v2/config v1.32.13 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.10 github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 github.com/coder/websocket v1.8.12 @@ -95,7 +95,7 @@ require ( golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 golang.zx2c4.com/wireguard/windows v0.5.3 gvisor.dev/gvisor v0.0.0-20240509041132-65b30f7869dc - honnef.co/go/tools v0.5.1 + honnef.co/go/tools v0.7.0 k8s.io/api v0.27.2 k8s.io/apimachinery v0.27.2 k8s.io/client-go v0.27.2 @@ -126,19 +126,20 @@ require ( github.com/ashanbrown/forbidigo v1.5.1 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.21 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.13 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.9 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.18.10 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.14 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.18 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect github.com/aws/smithy-go v1.24.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.0 // indirect diff --git a/go.sum b/go.sum index 681c57976b8d1..33f2874dd8bb1 100644 --- a/go.sum +++ b/go.sum @@ -124,51 +124,46 @@ github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvx github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= -github.com/aws/aws-sdk-go-v2/config v1.18.22 h1:7vkUEmjjv+giht4wIROqLs+49VWmiQMMHSduxmoNKLU= -github.com/aws/aws-sdk-go-v2/config v1.18.22/go.mod h1:mN7Li1wxaPxSSy4Xkr6stFuinJGf3VZW3ZSNvO0q6sI= -github.com/aws/aws-sdk-go-v2/credentials v1.13.21 h1:VRiXnPEaaPeGeoFcXvMZOB5K/yfIXOYE3q97Kgb0zbU= -github.com/aws/aws-sdk-go-v2/credentials v1.13.21/go.mod h1:90Dk1lJoMyspa/EDUrldTxsPns0wn6+KpRKpdAWc0uA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64 h1:9QJQs36z61YB8nxGwRDfWXEDYbU6H7jdI6zFiAX1vag= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64/go.mod h1:4Q7R9MFpXRdjO3YnAfUTdnuENs32WzBkASt6VxSYDYQ= +github.com/aws/aws-sdk-go-v2/config v1.32.13 h1:5KgbxMaS2coSWRrx9TX/QtWbqzgQkOdEa3sZPhBhCSg= +github.com/aws/aws-sdk-go-v2/config v1.32.13/go.mod h1:8zz7wedqtCbw5e9Mi2doEwDyEgHcEE9YOJp6a8jdSMY= +github.com/aws/aws-sdk-go-v2/credentials v1.19.13 h1:mA59E3fokBvyEGHKFdnpNNrvaR351cqiHgRg+JzOSRI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.13/go.mod h1:yoTXOQKea18nrM69wGF9jBdG4WocSZA1h38A+t/MAsk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.10 h1:GHKiUsNpMVIrrf4v+IvC56VfCB0LeZ6FUFpMUDIckSI= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.22.10/go.mod h1:wGl2ts9ULQknI/BNi3VzcRFv3ebvOViQdtyxaMpBzzI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25/go.mod h1:SUbB4wcbSEyCvqBxv/O/IBf93RbEze7U7OnoTlpPB+g= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28/go.mod h1:spfrICMD6wCAhjhzHuy6DOZZ+LAIY10UxhUmLzpJTTs= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2/go.mod h1:4tfW5l4IAB32VWCDEBxCRtR9T4BWy4I4kr1spr8NgZM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= -github.com/aws/aws-sdk-go-v2/service/s3 v1.33.0/go.mod h1:J9kLNzEiHSeGMyN7238EjJmBpCniVzFda75Gxl/NqB8= github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 h1:HwxWTbTrIHm5qY+CAEur0s/figc3qwvLWsNkF4RPToo= github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 h1:TQZH0Djie8VVgTBDOQ02M4zVHJFrNzLMsYMbNfRitVM= github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3/go.mod h1:p6MaesK9061w6NTiFmZpUzEkKUY5blKlwD2zYyErxKA= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.9 h1:GAiaQWuQhQQui76KjuXeShmyXqECwQ0mGRMc/rwsL+c= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.9/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9 h1:TraLwncRJkWqtIBVKI/UqBymq4+hL+3MzUOtUATuzkA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.10 h1:6UbNM/KJhMBfOI5+lpVcJ/8OA7cBSz0O6OX37SRKlSw= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.10/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.14 h1:GcLE9ba5ehAQma6wlopUesYg/hbcOhFNWTjELkiWkh4= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.14/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.18 h1:mP49nTpfKtpXLt5SLn8Uv8z6W+03jYVoOSAl/c02nog= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.18/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= @@ -1713,8 +1708,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= -honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= -honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= +honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU= +honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= diff --git a/net/connstats/stats_test.go b/net/connstats/stats_test.go index 0db7996f4072b..20b019370786a 100644 --- a/net/connstats/stats_test.go +++ b/net/connstats/stats_test.go @@ -87,6 +87,11 @@ func TestConcurrent(t *testing.T) { const maxConns = 10 virtualAggregate := make(map[netlogtype.Connection]netlogtype.Counts) stats := NewStatistics(maxPeriod, maxConns, func(start, end time.Time, virtual, physical map[netlogtype.Connection]netlogtype.Counts) { + // Empty intervals have no timestamps. + if len(virtual)+len(physical) == 0 { + c.Assert(start.IsZero() && end.IsZero(), qt.IsTrue) + return + } c.Assert(start.IsZero(), qt.IsFalse) c.Assert(end.IsZero(), qt.IsFalse) c.Assert(end.Before(start), qt.IsFalse) diff --git a/net/portmapper/pmpresultcode_string.go b/net/portmapper/pmpresultcode_string.go index 603636adec044..18d911d944126 100644 --- a/net/portmapper/pmpresultcode_string.go +++ b/net/portmapper/pmpresultcode_string.go @@ -24,8 +24,9 @@ const _pmpResultCode_name = "OKUnsupportedVersionNotAuthorizedNetworkFailureOutO var _pmpResultCode_index = [...]uint8{0, 2, 20, 33, 47, 61, 78} func (i pmpResultCode) String() string { - if i >= pmpResultCode(len(_pmpResultCode_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_pmpResultCode_index)-1 { return "pmpResultCode(" + strconv.FormatInt(int64(i), 10) + ")" } - return _pmpResultCode_name[_pmpResultCode_index[i]:_pmpResultCode_index[i+1]] + return _pmpResultCode_name[_pmpResultCode_index[idx]:_pmpResultCode_index[idx+1]] } diff --git a/net/sockstats/label_string.go b/net/sockstats/label_string.go index 2c3fb6bd7b2e8..9a07718617079 100644 --- a/net/sockstats/label_string.go +++ b/net/sockstats/label_string.go @@ -27,8 +27,9 @@ const _Label_name = "ControlClientAutoControlClientDialerDERPHTTPClientLogtailLo var _Label_index = [...]uint8{0, 17, 36, 50, 63, 78, 93, 107, 123, 140, 157, 169, 186} func (i Label) String() string { - if i >= Label(len(_Label_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_Label_index)-1 { return "Label(" + strconv.FormatInt(int64(i), 10) + ")" } - return _Label_name[_Label_index[i]:_Label_index[i+1]] + return _Label_name[_Label_index[idx]:_Label_index[idx+1]] } diff --git a/net/tshttpproxy/zsyscall_windows.go b/net/tshttpproxy/zsyscall_windows.go index c07e9ee03a69e..5dcfae83ea1a4 100644 --- a/net/tshttpproxy/zsyscall_windows.go +++ b/net/tshttpproxy/zsyscall_windows.go @@ -48,7 +48,7 @@ var ( ) func globalFree(hglobal winHGlobal) (err error) { - r1, _, e1 := syscall.Syscall(procGlobalFree.Addr(), 1, uintptr(hglobal), 0, 0) + r1, _, e1 := syscall.SyscallN(procGlobalFree.Addr(), uintptr(hglobal)) if r1 == 0 { err = errnoErr(e1) } @@ -56,7 +56,7 @@ func globalFree(hglobal winHGlobal) (err error) { } func winHTTPCloseHandle(whi winHTTPInternet) (err error) { - r1, _, e1 := syscall.Syscall(procWinHttpCloseHandle.Addr(), 1, uintptr(whi), 0, 0) + r1, _, e1 := syscall.SyscallN(procWinHttpCloseHandle.Addr(), uintptr(whi)) if r1 == 0 { err = errnoErr(e1) } @@ -64,7 +64,7 @@ func winHTTPCloseHandle(whi winHTTPInternet) (err error) { } func winHTTPGetProxyForURL(whi winHTTPInternet, url *uint16, options *winHTTPAutoProxyOptions, proxyInfo *winHTTPProxyInfo) (err error) { - r1, _, e1 := syscall.Syscall6(procWinHttpGetProxyForUrl.Addr(), 4, uintptr(whi), uintptr(unsafe.Pointer(url)), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(proxyInfo)), 0, 0) + r1, _, e1 := syscall.SyscallN(procWinHttpGetProxyForUrl.Addr(), uintptr(whi), uintptr(unsafe.Pointer(url)), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(proxyInfo))) if r1 == 0 { err = errnoErr(e1) } @@ -72,7 +72,7 @@ func winHTTPGetProxyForURL(whi winHTTPInternet, url *uint16, options *winHTTPAut } func winHTTPOpen(agent *uint16, accessType uint32, proxy *uint16, proxyBypass *uint16, flags uint32) (whi winHTTPInternet, err error) { - r0, _, e1 := syscall.Syscall6(procWinHttpOpen.Addr(), 5, uintptr(unsafe.Pointer(agent)), uintptr(accessType), uintptr(unsafe.Pointer(proxy)), uintptr(unsafe.Pointer(proxyBypass)), uintptr(flags), 0) + r0, _, e1 := syscall.SyscallN(procWinHttpOpen.Addr(), uintptr(unsafe.Pointer(agent)), uintptr(accessType), uintptr(unsafe.Pointer(proxy)), uintptr(unsafe.Pointer(proxyBypass)), uintptr(flags)) whi = winHTTPInternet(r0) if whi == 0 { err = errnoErr(e1) diff --git a/util/osdiag/zsyscall_windows.go b/util/osdiag/zsyscall_windows.go index caeb245d2974f..570d298d9d469 100644 --- a/util/osdiag/zsyscall_windows.go +++ b/util/osdiag/zsyscall_windows.go @@ -45,7 +45,7 @@ var ( ) func regEnumValue(key registry.Key, index uint32, valueName *uint16, valueNameLen *uint32, reserved *uint32, valueType *uint32, pData *byte, cbData *uint32) (ret error) { - r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(valueName)), uintptr(unsafe.Pointer(valueNameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valueType)), uintptr(unsafe.Pointer(pData)), uintptr(unsafe.Pointer(cbData)), 0) + r0, _, _ := syscall.SyscallN(procRegEnumValueW.Addr(), uintptr(key), uintptr(index), uintptr(unsafe.Pointer(valueName)), uintptr(unsafe.Pointer(valueNameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valueType)), uintptr(unsafe.Pointer(pData)), uintptr(unsafe.Pointer(cbData))) if r0 != 0 { ret = syscall.Errno(r0) } diff --git a/util/winutil/authenticode/zsyscall_windows.go b/util/winutil/authenticode/zsyscall_windows.go index 643721e06aad5..f1fba2828713c 100644 --- a/util/winutil/authenticode/zsyscall_windows.go +++ b/util/winutil/authenticode/zsyscall_windows.go @@ -56,7 +56,7 @@ var ( ) func cryptMsgClose(cryptMsg windows.Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCryptMsgClose.Addr(), 1, uintptr(cryptMsg), 0, 0) + r1, _, e1 := syscall.SyscallN(procCryptMsgClose.Addr(), uintptr(cryptMsg)) if int32(r1) == 0 { err = errnoErr(e1) } @@ -64,7 +64,7 @@ func cryptMsgClose(cryptMsg windows.Handle) (err error) { } func cryptMsgGetParam(cryptMsg windows.Handle, paramType uint32, index uint32, data unsafe.Pointer, dataLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCryptMsgGetParam.Addr(), 5, uintptr(cryptMsg), uintptr(paramType), uintptr(index), uintptr(data), uintptr(unsafe.Pointer(dataLen)), 0) + r1, _, e1 := syscall.SyscallN(procCryptMsgGetParam.Addr(), uintptr(cryptMsg), uintptr(paramType), uintptr(index), uintptr(data), uintptr(unsafe.Pointer(dataLen))) if int32(r1) == 0 { err = errnoErr(e1) } @@ -72,7 +72,7 @@ func cryptMsgGetParam(cryptMsg windows.Handle, paramType uint32, index uint32, d } func cryptVerifyMessageSignature(pVerifyPara *_CRYPT_VERIFY_MESSAGE_PARA, signerIndex uint32, pbSignedBlob *byte, cbSignedBlob uint32, pbDecoded *byte, pdbDecoded *uint32, ppSignerCert **windows.CertContext) (err error) { - r1, _, e1 := syscall.Syscall9(procCryptVerifyMessageSignature.Addr(), 7, uintptr(unsafe.Pointer(pVerifyPara)), uintptr(signerIndex), uintptr(unsafe.Pointer(pbSignedBlob)), uintptr(cbSignedBlob), uintptr(unsafe.Pointer(pbDecoded)), uintptr(unsafe.Pointer(pdbDecoded)), uintptr(unsafe.Pointer(ppSignerCert)), 0, 0) + r1, _, e1 := syscall.SyscallN(procCryptVerifyMessageSignature.Addr(), uintptr(unsafe.Pointer(pVerifyPara)), uintptr(signerIndex), uintptr(unsafe.Pointer(pbSignedBlob)), uintptr(cbSignedBlob), uintptr(unsafe.Pointer(pbDecoded)), uintptr(unsafe.Pointer(pdbDecoded)), uintptr(unsafe.Pointer(ppSignerCert))) if int32(r1) == 0 { err = errnoErr(e1) } @@ -80,13 +80,13 @@ func cryptVerifyMessageSignature(pVerifyPara *_CRYPT_VERIFY_MESSAGE_PARA, signer } func msiGetFileSignatureInformation(signedObjectPath *uint16, flags uint32, certCtx **windows.CertContext, pbHashData *byte, cbHashData *uint32) (ret wingoes.HRESULT) { - r0, _, _ := syscall.Syscall6(procMsiGetFileSignatureInformationW.Addr(), 5, uintptr(unsafe.Pointer(signedObjectPath)), uintptr(flags), uintptr(unsafe.Pointer(certCtx)), uintptr(unsafe.Pointer(pbHashData)), uintptr(unsafe.Pointer(cbHashData)), 0) + r0, _, _ := syscall.SyscallN(procMsiGetFileSignatureInformationW.Addr(), uintptr(unsafe.Pointer(signedObjectPath)), uintptr(flags), uintptr(unsafe.Pointer(certCtx)), uintptr(unsafe.Pointer(pbHashData)), uintptr(unsafe.Pointer(cbHashData))) ret = wingoes.HRESULT(r0) return } func cryptCATAdminAcquireContext2(hCatAdmin *_HCATADMIN, pgSubsystem *windows.GUID, hashAlgorithm *uint16, strongHashPolicy *windows.CertStrongSignPara, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCryptCATAdminAcquireContext2.Addr(), 5, uintptr(unsafe.Pointer(hCatAdmin)), uintptr(unsafe.Pointer(pgSubsystem)), uintptr(unsafe.Pointer(hashAlgorithm)), uintptr(unsafe.Pointer(strongHashPolicy)), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procCryptCATAdminAcquireContext2.Addr(), uintptr(unsafe.Pointer(hCatAdmin)), uintptr(unsafe.Pointer(pgSubsystem)), uintptr(unsafe.Pointer(hashAlgorithm)), uintptr(unsafe.Pointer(strongHashPolicy)), uintptr(flags)) if int32(r1) == 0 { err = errnoErr(e1) } @@ -94,7 +94,7 @@ func cryptCATAdminAcquireContext2(hCatAdmin *_HCATADMIN, pgSubsystem *windows.GU } func cryptCATAdminCalcHashFromFileHandle2(hCatAdmin _HCATADMIN, file windows.Handle, pcbHash *uint32, pbHash *byte, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCryptCATAdminCalcHashFromFileHandle2.Addr(), 5, uintptr(hCatAdmin), uintptr(file), uintptr(unsafe.Pointer(pcbHash)), uintptr(unsafe.Pointer(pbHash)), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procCryptCATAdminCalcHashFromFileHandle2.Addr(), uintptr(hCatAdmin), uintptr(file), uintptr(unsafe.Pointer(pcbHash)), uintptr(unsafe.Pointer(pbHash)), uintptr(flags)) if int32(r1) == 0 { err = errnoErr(e1) } @@ -102,7 +102,7 @@ func cryptCATAdminCalcHashFromFileHandle2(hCatAdmin _HCATADMIN, file windows.Han } func cryptCATAdminEnumCatalogFromHash(hCatAdmin _HCATADMIN, pbHash *byte, cbHash uint32, flags uint32, prevCatInfo *_HCATINFO) (ret _HCATINFO, err error) { - r0, _, e1 := syscall.Syscall6(procCryptCATAdminEnumCatalogFromHash.Addr(), 5, uintptr(hCatAdmin), uintptr(unsafe.Pointer(pbHash)), uintptr(cbHash), uintptr(flags), uintptr(unsafe.Pointer(prevCatInfo)), 0) + r0, _, e1 := syscall.SyscallN(procCryptCATAdminEnumCatalogFromHash.Addr(), uintptr(hCatAdmin), uintptr(unsafe.Pointer(pbHash)), uintptr(cbHash), uintptr(flags), uintptr(unsafe.Pointer(prevCatInfo))) ret = _HCATINFO(r0) if ret == 0 { err = errnoErr(e1) @@ -111,7 +111,7 @@ func cryptCATAdminEnumCatalogFromHash(hCatAdmin _HCATADMIN, pbHash *byte, cbHash } func cryptCATAdminReleaseCatalogContext(hCatAdmin _HCATADMIN, hCatInfo _HCATINFO, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCryptCATAdminReleaseCatalogContext.Addr(), 3, uintptr(hCatAdmin), uintptr(hCatInfo), uintptr(flags)) + r1, _, e1 := syscall.SyscallN(procCryptCATAdminReleaseCatalogContext.Addr(), uintptr(hCatAdmin), uintptr(hCatInfo), uintptr(flags)) if int32(r1) == 0 { err = errnoErr(e1) } @@ -119,7 +119,7 @@ func cryptCATAdminReleaseCatalogContext(hCatAdmin _HCATADMIN, hCatInfo _HCATINFO } func cryptCATAdminReleaseContext(hCatAdmin _HCATADMIN, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCryptCATAdminReleaseContext.Addr(), 2, uintptr(hCatAdmin), uintptr(flags), 0) + r1, _, e1 := syscall.SyscallN(procCryptCATAdminReleaseContext.Addr(), uintptr(hCatAdmin), uintptr(flags)) if int32(r1) == 0 { err = errnoErr(e1) } @@ -127,7 +127,7 @@ func cryptCATAdminReleaseContext(hCatAdmin _HCATADMIN, flags uint32) (err error) } func cryptCATAdminCatalogInfoFromContext(hCatInfo _HCATINFO, catInfo *_CATALOG_INFO, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCryptCATCatalogInfoFromContext.Addr(), 3, uintptr(hCatInfo), uintptr(unsafe.Pointer(catInfo)), uintptr(flags)) + r1, _, e1 := syscall.SyscallN(procCryptCATCatalogInfoFromContext.Addr(), uintptr(hCatInfo), uintptr(unsafe.Pointer(catInfo)), uintptr(flags)) if int32(r1) == 0 { err = errnoErr(e1) } diff --git a/util/winutil/zsyscall_windows.go b/util/winutil/zsyscall_windows.go index 8c899232f3431..fc9b8274f7c3e 100644 --- a/util/winutil/zsyscall_windows.go +++ b/util/winutil/zsyscall_windows.go @@ -44,7 +44,7 @@ var ( ) func queryServiceConfig2(hService windows.Handle, infoLevel uint32, buf *byte, bufLen uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceConfig2W.Addr(), 5, uintptr(hService), uintptr(infoLevel), uintptr(unsafe.Pointer(buf)), uintptr(bufLen), uintptr(unsafe.Pointer(bytesNeeded)), 0) + r1, _, e1 := syscall.SyscallN(procQueryServiceConfig2W.Addr(), uintptr(hService), uintptr(infoLevel), uintptr(unsafe.Pointer(buf)), uintptr(bufLen), uintptr(unsafe.Pointer(bytesNeeded))) if r1 == 0 { err = errnoErr(e1) } diff --git a/wgengine/magicsock/discopingpurpose_string.go b/wgengine/magicsock/discopingpurpose_string.go index 6329172dccc2e..803dfce5980b9 100644 --- a/wgengine/magicsock/discopingpurpose_string.go +++ b/wgengine/magicsock/discopingpurpose_string.go @@ -21,8 +21,9 @@ const _discoPingPurpose_name = "DiscoveryHeartbeatCLI" var _discoPingPurpose_index = [...]uint8{0, 9, 18, 21} func (i discoPingPurpose) String() string { - if i < 0 || i >= discoPingPurpose(len(_discoPingPurpose_index)-1) { + idx := int(i) - 0 + if i < 0 || idx >= len(_discoPingPurpose_index)-1 { return "discoPingPurpose(" + strconv.FormatInt(int64(i), 10) + ")" } - return _discoPingPurpose_name[_discoPingPurpose_index[i]:_discoPingPurpose_index[i+1]] + return _discoPingPurpose_name[_discoPingPurpose_index[idx]:_discoPingPurpose_index[idx+1]] } diff --git a/wgengine/magicsock/magicsock_darwin.go b/wgengine/magicsock/magicsock_darwin.go index f3b32959f5ba8..dbc3a45a1c1c8 100644 --- a/wgengine/magicsock/magicsock_darwin.go +++ b/wgengine/magicsock/magicsock_darwin.go @@ -1,3 +1,6 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + package magicsock import ( diff --git a/wgengine/magicsock/magicsock_windows.go b/wgengine/magicsock/magicsock_windows.go index 0206fbc47c896..cef7ee48e67b1 100644 --- a/wgengine/magicsock/magicsock_windows.go +++ b/wgengine/magicsock/magicsock_windows.go @@ -1,3 +1,6 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + package magicsock import (