diff --git a/.circleci/config.yml b/.circleci/config.yml index d63fb491afb..6f93ce4ec09 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -80,7 +80,7 @@ parameters: # go-cache-version can be used as a cache buster when making breaking changes to caching strategy go-cache-version: type: string - default: "v0.0" + default: "v0.1" orbs: continuation: circleci/continuation@2.0.1 diff --git a/.circleci/continue/main.yml b/.circleci/continue/main.yml index 63e552cb39d..f8c1073ae40 100644 --- a/.circleci/continue/main.yml +++ b/.circleci/continue/main.yml @@ -22,7 +22,7 @@ parameters: # go-cache-version can be used as a cache buster when making breaking changes to caching strategy c-go-cache-version: type: string - default: "v0.0" + default: "v0.1" # Workflow activation flags (set by the decision tree in config.yml) c-run_main: type: boolean @@ -896,10 +896,6 @@ jobs: command: | mkdir -p ./tmp/test-results mkdir -p ./tmp/testlogs - - run: - name: build Cannon example binaries - command: just elf # only compile ELF binaries with Go, we do not have MIPS GCC for creating the debug-dumps. - working_directory: cannon/testdata - run: name: Cannon Go lint command: | diff --git a/.circleci/continue/rust-e2e.yml b/.circleci/continue/rust-e2e.yml index dce694fb795..adc2920480f 100644 --- a/.circleci/continue/rust-e2e.yml +++ b/.circleci/continue/rust-e2e.yml @@ -16,7 +16,7 @@ parameters: default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-base-clang@sha256:852cb2dcd64eb5c039abf857a2217f341351eb7e4ef1a989ba9eefb86f158105 c-go-cache-version: type: string - default: "v0.0" + default: "v0.1" # Workflow activation flags (set by the decision tree in config.yml) c-run_rust_e2e_ci: type: boolean diff --git a/cannon/Dockerfile.diff b/cannon/Dockerfile.diff index 50d1eb9577c..82f97f4e691 100644 --- a/cannon/Dockerfile.diff +++ b/cannon/Dockerfile.diff @@ -1,4 +1,4 @@ -FROM golang:1.24.13-alpine3.22 AS builder +FROM golang:1.26.4-alpine3.22 AS builder # Install just from GitHub releases to match the version pinned in mise.toml. # The Alpine package is too old and doesn't support the [script] attribute diff --git a/cannon/Makefile b/cannon/Makefile index b944ef3a69e..7a01cb21039 100644 --- a/cannon/Makefile +++ b/cannon/Makefile @@ -1,4 +1,4 @@ -DEPRECATED_TARGETS := cannon cannon64-impl cannon-embeds clean elf elf-go-current sanitize-program contract test cannon-stf-verify fuzz lint +DEPRECATED_TARGETS := cannon cannon64-impl cannon-embeds clean diff-hello-elf sanitize-program contract test cannon-stf-verify fuzz lint include ../justfiles/deprecated.mk diff --git a/cannon/justfile b/cannon/justfile index bf3345601b7..d0928431545 100644 --- a/cannon/justfile +++ b/cannon/justfile @@ -31,13 +31,9 @@ cannon-embeds: cannon64-impl clean: rm -rf bin multicannon/embeds/cannon* -# Build ELF test binaries -elf: - just ./testdata/elf - -# Build ELF test binaries for current Go version -elf-go-current: - just ./testdata/go-1-24/elf +# Build minimal hello ELF for diff-cannon parity checks +diff-hello-elf: + just ./testdata/diff-hello-elf # Check guest program for unsupported MIPS instructions sanitize-program: @@ -56,18 +52,18 @@ contract: cd ../packages/contracts-bedrock && forge build # Run tests -test: elf contract +test: contract @just go_test "./..." # Compare cannon output against OTHER_CANNON for a given VM type -diff-cannon VM: cannon elf-go-current +diff-cannon VM: cannon diff-hello-elf #!/usr/bin/env bash set -euo pipefail VM="{{VM}}" echo "Running diff for VM type ${VM}" # Load an elf file to create a prestate, and check that both cannon versions generate the same prestate - $OTHER_CANNON load-elf --type "$VM" --path ./testdata/go-1-24/bin/hello.64.elf --out ./bin/prestate-other.bin.gz --meta "" - ./bin/cannon load-elf --type "$VM" --path ./testdata/go-1-24/bin/hello.64.elf --out ./bin/prestate.bin.gz --meta "" + $OTHER_CANNON load-elf --type "$VM" --path ./testdata/bin/hello.64.elf --out ./bin/prestate-other.bin.gz --meta "" + ./bin/cannon load-elf --type "$VM" --path ./testdata/bin/hello.64.elf --out ./bin/prestate.bin.gz --meta "" cmp ./bin/prestate-other.bin.gz ./bin/prestate.bin.gz if [ $? -eq 0 ]; then echo "Generated identical prestates" diff --git a/cannon/mipsevm/multithreaded/instrumented_test.go b/cannon/mipsevm/multithreaded/instrumented_test.go index d9d84f5b535..527dc17ee49 100644 --- a/cannon/mipsevm/multithreaded/instrumented_test.go +++ b/cannon/mipsevm/multithreaded/instrumented_test.go @@ -1,495 +1,12 @@ package multithreaded import ( - "bytes" "fmt" - "io" - "math/big" - "os" - "reflect" - "regexp" - "strconv" "testing" - "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" - "golang.org/x/crypto/sha3" - - "github.com/ethereum-optimism/optimism/cannon/mipsevm" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" ) -func TestInstrumentedState_Hello(t *testing.T) { - runTestAcrossVms(t, "Hello", func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("hello", goTarget), CreateInitialState) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := vmFactory(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - - maxSteps := 500_000 - for i := 0; i < maxSteps; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - - require.Truef(t, state.GetExited(), "must complete program. reached %d of max %d steps", state.GetStep(), maxSteps) - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - require.Equal(t, "hello world!\n", stdOutBuf.String(), "stdout says hello") - require.Equal(t, "", stdErrBuf.String(), "stderr silent") - }) -} - -func TestInstrumentedState_Claim(t *testing.T) { - runTestAcrossVms(t, "Claim", func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("claim", goTarget), CreateInitialState) - - oracle, expectedStdOut, expectedStdErr := testutil.ClaimTestOracle(t) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := vmFactory(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - - for i := 0; i < 2000_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - require.Equal(t, expectedStdOut, stdOutBuf.String(), "stdout") - require.Equal(t, expectedStdErr, stdErrBuf.String(), "stderr") - }) -} - -func TestInstrumentedState_Keccak(t *testing.T) { - runTestAcrossVms(t, "Keccak", func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("keccak", goTarget), CreateInitialState) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := vmFactory(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - - for i := 0; i < 2000_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - var result []byte - keccakState := sha3.NewLegacyKeccak256() - keccakState.Write([]byte{1, 2, 3}) - result = keccakState.Sum(result) - expectedStdOut := fmt.Sprintf("keccak program. result=%x\n", result) - require.Equal(t, expectedStdOut, stdOutBuf.String(), "stdout") - require.Equal(t, "", stdErrBuf.String(), "stderr") - }) -} - -func TestInstrumentedState_Random(t *testing.T) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("random", testutil.Go1_25), CreateInitialState) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := latestVm(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - - for i := 0; i < 500_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - t.Logf("Completed in %d steps", state.Step) - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - // Check output - // Define the regex pattern we expect to match against stdOut - pattern := `Random (hex data|int): (\w+)\s*` - re, err := regexp.Compile(pattern) - require.NoError(t, err) - - // Check that stdOut matches the expected regex - expectedMatches := 3 - output := stdOutBuf.String() - matches := re.FindAllStringSubmatch(output, -1) - require.Equal(t, expectedMatches, len(matches)) - - // Check each match and validate the random values that are printed to stdOut - for i := 0; i < expectedMatches; i++ { - match := matches[i] - require.Contains(t, match[0], "Random") - - // Check that the generated random number is not zero - dataType := match[1] - dataValue := match[2] - switch dataType { - case "hex data": - randVal, success := new(big.Int).SetString(dataValue, 16) - require.True(t, success, "should successfully set hex value") - require.NotEqual(t, 0, randVal.Sign(), "random data should be non-zero") - case "int": - randVal, err := strconv.ParseUint(dataValue, 10, 64) - require.NoError(t, err) - require.NotEqual(t, uint64(0), randVal, "random int should be non-zero") - } - } -} - -func TestInstrumentedState_SyscallEventFdProgram(t *testing.T) { - runTestAcrossVms(t, "SyscallEventFdProgram", func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("syscall-eventfd", goTarget), CreateInitialState) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := vmFactory(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - err := us.InitDebug() - require.NoError(t, err) - - for i := 0; i < 550_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - t.Logf("Completed in %d steps", state.Step) - - require.True(t, state.GetExited(), "must complete program") - if state.GetExitCode() != 0 { - us.Traceback() - } - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - // Check output - output := stdOutBuf.String() - require.Contains(t, output, "call eventfd with valid flags: '0x80080'") - require.Contains(t, output, "call eventfd with valid flags: '0xFFFFFFFFFFFFFFFF'") - require.Contains(t, output, "call eventfd with valid flags: '0x80'") - require.Contains(t, output, "call eventfd with invalid flags: '0x0'") - require.Contains(t, output, "call eventfd with invalid flags: '0xFFFFFFFFFFFFFF7F'") - require.Contains(t, output, "call eventfd with invalid flags: '0x80000'") - require.Contains(t, output, "write to eventfd object") - require.Contains(t, output, "read from eventfd object") - require.Contains(t, output, "done") - - // Check fd value - pattern := `eventfd2 fd = '(.+)'` - re, err := regexp.Compile(pattern) - require.NoError(t, err) - matches := re.FindAllStringSubmatch(output, -1) - - expectedMatches := 3 - require.Equal(t, expectedMatches, len(matches)) - for i := 0; i < expectedMatches; i++ { - require.Equal(t, "100", matches[i][1]) - } - }) -} - -func TestInstrumentedState_UtilsCheck(t *testing.T) { - // Sanity check that test running utilities will return a non-zero exit code on failure - type TestCase struct { - name string - expectedOutput string - } - - cases := []TestCase{ - {name: "utilscheck", expectedOutput: "Test failed: ShouldFail"}, - {name: "utilscheck2", expectedOutput: "Test failed: ShouldFail (subtest 2)"}, - {name: "utilscheck3", expectedOutput: "Test panicked: ShouldFail (panic test)"}, - {name: "utilscheck4", expectedOutput: "Test panicked: ShouldFail"}, - } - - testNamer := func(vm string, testCase TestCase) string { - return fmt.Sprintf("%v-%v", testCase.name, vm) - } - - runTestsAcrossVms(t, testNamer, cases, func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget, test TestCase) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath(test.name, goTarget), CreateInitialState) - oracle := testutil.StaticOracle(t, []byte{}) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := vmFactory(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - - for i := 0; i < 1_000_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - t.Logf("Completed in %d steps", state.Step) - - require.True(t, state.Exited, "must complete program") - require.Equal(t, uint8(1), state.ExitCode, "exit with 1") - require.Contains(t, stdOutBuf.String(), test.expectedOutput) - require.NotContains(t, stdOutBuf.String(), "Passed test that should have failed") - require.Equal(t, "", stdErrBuf.String(), "should not print any errors") - }) -} - -func TestInstrumentedState_MultithreadedProgram(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - type TestCase struct { - name string - expectedOutput []string - programName string - steps int - } - - cases := []TestCase{ - { - name: "general concurrency test", - expectedOutput: []string{ - "waitgroup result: 42", - "channels result: 1234", - "GC complete!", - }, - programName: "mt-general", - steps: 5_000_000, - }, - { - name: "atomic test", - expectedOutput: []string{ - "Atomic tests passed", - }, - programName: "mt-atomic", - steps: 350_000_000, - }, - { - name: "waitgroup test", - expectedOutput: []string{ - "WaitGroup tests passed", - }, - programName: "mt-wg", - steps: 15_000_000, - }, - { - name: "mutex test", - expectedOutput: []string{ - "Mutex test passed", - }, - programName: "mt-mutex", - steps: 5_000_000, - }, - { - name: "cond test", - expectedOutput: []string{ - "Cond test passed", - }, - programName: "mt-cond", - steps: 5_000_000, - }, - { - name: "rwmutex test", - expectedOutput: []string{ - "RWMutex test passed", - }, - programName: "mt-rwmutex", - steps: 5_000_000, - }, - { - name: "once test", - expectedOutput: []string{ - "Once test passed", - }, - programName: "mt-once", - steps: 5_000_000, - }, - { - name: "oncefunc test", - expectedOutput: []string{ - "OnceFunc tests passed", - }, - programName: "mt-oncefunc", - steps: 15_000_000, - }, - { - name: "map test", - expectedOutput: []string{ - "Map test passed", - }, - programName: "mt-map", - steps: 150_000_000, - }, - { - name: "pool test", - expectedOutput: []string{ - "Pool test passed", - }, - programName: "mt-pool", - steps: 50_000_000, - }, - { - name: "value test", - expectedOutput: []string{ - "Value tests passed", - }, - programName: "mt-value", - steps: 3_000_000, - }, - } - - testNamer := func(vm string, testCase TestCase) string { - return fmt.Sprintf("%v-%v", testCase.name, vm) - } - - runTestsAcrossVms(t, testNamer, cases, func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget, test TestCase) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath(test.programName, goTarget), CreateInitialState) - oracle := testutil.StaticOracle(t, []byte{}) - - var stdOutBuf, stdErrBuf bytes.Buffer - us := vmFactory(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), meta) - for i := 0; i < test.steps; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - } - t.Logf("Completed in %d steps", state.Step) - - require.True(t, state.Exited, "must complete program") - require.Equal(t, uint8(0), state.ExitCode, "exit with 0") - for _, expected := range test.expectedOutput { - require.Contains(t, stdOutBuf.String(), expected) - } - require.Equal(t, "", stdErrBuf.String(), "should not print any errors") - }) -} - -func TestInstrumentedState_Alloc(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - const MiB = 1024 * 1024 - - type TestCase struct { - name string - numAllocs int - allocSize int - maxMemoryUsageCheck int - } - - cases := []TestCase{ - {name: "10 32MiB allocations", numAllocs: 10, allocSize: 32 * MiB, maxMemoryUsageCheck: 256 * MiB}, - {name: "5 64MiB allocations", numAllocs: 5, allocSize: 64 * MiB, maxMemoryUsageCheck: 256 * MiB}, - {name: "5 128MiB allocations", numAllocs: 5, allocSize: 128 * MiB, maxMemoryUsageCheck: 128 * 3 * MiB}, - } - - testNamer := func(vm string, testCase TestCase) string { - return fmt.Sprintf("%v-%v", testCase.name, vm) - } - - runTestsAcrossVms(t, testNamer, cases, func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget, test TestCase) { - state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("alloc", goTarget), CreateInitialState) - oracle := testutil.AllocOracle(t, test.numAllocs, test.allocSize) - - us := vmFactory(state, oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), meta) - require.NoError(t, us.InitDebug()) - // emulation shouldn't take more than 20 B steps - for i := 0; i < 20_000_000_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - if state.Step%10_000_000 == 0 { - t.Logf("Completed %d steps", state.Step) - } - } - memUsage := state.Memory.PageCount() * memory.PageSize - t.Logf("Completed in %d steps. cannon memory usage: %d KiB", state.Step, memUsage/1024/1024.0) - require.True(t, state.Exited, "must complete program") - require.Equal(t, uint8(0), state.ExitCode, "exit with 0") - require.Less(t, memUsage, test.maxMemoryUsageCheck, "memory allocation is too large") - }) -} - -type VMTest func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget) -type VMTestCase[T any] func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget, testCase T) - -type TestNamer[T any] func(vmName string, testCase T) string - -func runTestAcrossVms(t *testing.T, testName string, vmTest VMTest) { - testNamer := func(vm string, _ any) string { - return fmt.Sprintf("%v-%v", testName, vm) - } - - runTestsAcrossVms[any](t, testNamer, []any{nil}, func(t *testing.T, vmFactory VMFactory[*State], goTarget testutil.GoTarget, _ any) { - vmTest(t, vmFactory, goTarget) - }) -} - -func runTestsAcrossVms[T any](t *testing.T, testNamer TestNamer[T], testCases []T, vmTestCase VMTestCase[T]) { - t.Parallel() - type VMVariations struct { - name string - goTarget testutil.GoTarget - features mipsevm.FeatureToggles - } - - variations := []VMVariations{ - {name: "Go 1.24 VM", goTarget: testutil.Go1_24, features: allFeaturesEnabled()}, - {name: "Go 1.25 VM", goTarget: testutil.Go1_25, features: allFeaturesEnabled()}, - } - - for _, testCase := range testCases { - for _, variation := range variations { - testName := testNamer(variation.name, testCase) - testCase := testCase - variation := variation - t.Run(testName, func(t *testing.T) { - t.Parallel() - vmTestCase(t, getVmFactory(variation.features), variation.goTarget, testCase) - }) - } - } -} - -func getVmFactory(featureToggles mipsevm.FeatureToggles) VMFactory[*State] { - return func(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta *program.Metadata) mipsevm.FPVM { - return NewInstrumentedState(state, po, stdOut, stdErr, log, meta, featureToggles) - } -} - -func latestVm(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta *program.Metadata) mipsevm.FPVM { - vmFactory := getVmFactory(allFeaturesEnabled()) - return vmFactory(state, po, stdOut, stdErr, log, meta) -} - -// allFeaturesEnabled returns a FeatureToggles with all toggles enabled. -func allFeaturesEnabled() mipsevm.FeatureToggles { - toggles := mipsevm.FeatureToggles{} - tRef := reflect.ValueOf(&toggles).Elem() // Get a pointer and then dereference - - for i := 0; i < tRef.NumField(); i++ { - field := tRef.Field(i) - if field.Kind() == reflect.Bool && field.CanSet() { - field.SetBool(true) - } - } - - return toggles -} - // Unit test splitmix64 based on Apache Commons RNG unit tests // See: https://github.com/apache/commons-rng/blob/df772c2f5b0644a71398e925206039a2ae516ab2/commons-rng-core/src/test/java/org/apache/commons/rng/core/source64/SplitMix64Test.java func TestSplitmix64(t *testing.T) { @@ -514,5 +31,3 @@ func TestSplitmix64(t *testing.T) { currentSeed += 0x9e3779b97f4a7c15 } } - -type VMFactory[T mipsevm.FPVMState] func(state T, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta *program.Metadata) mipsevm.FPVM diff --git a/cannon/mipsevm/multithreaded/state_test.go b/cannon/mipsevm/multithreaded/state_test.go index 3e2b4152886..5e1554ff6cf 100644 --- a/cannon/mipsevm/multithreaded/state_test.go +++ b/cannon/mipsevm/multithreaded/state_test.go @@ -2,7 +2,6 @@ package multithreaded import ( "bytes" - "debug/elf" "encoding/json" "testing" @@ -15,7 +14,6 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/arch" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" ) func setWitnessField(witness StateWitness, fieldOffset int, fieldData []byte) { @@ -100,12 +98,12 @@ func TestState_EncodeWitness(t *testing.T) { } } -func TestState_JSONCodec(t *testing.T) { - elfProgram, err := elf.Open("../../testdata/go-1-24/bin/hello.64.elf") - require.NoError(t, err, "open ELF file") - state, err := program.LoadELF(elfProgram, CreateInitialState) - require.NoError(t, err, "load ELF into state") - // Set a few additional fields +func codecTestState(t *testing.T) *State { + t.Helper() + mem := memory.NewMemory() + mem.AllocPage(0) + state := CreateEmptyState() + state.Memory = mem state.PreimageKey = crypto.Keccak256Hash([]byte{1, 2, 3, 4}) state.PreimageOffset = 4 state.Heap = 555 @@ -114,6 +112,11 @@ func TestState_JSONCodec(t *testing.T) { state.Exited = true state.ExitCode = 2 state.LastHint = []byte{11, 12, 13} + return state +} + +func TestState_JSONCodec(t *testing.T) { + state := codecTestState(t) stateJSON, err := json.Marshal(state) require.NoError(t, err) @@ -138,22 +141,10 @@ func TestState_JSONCodec(t *testing.T) { } func TestState_Binary(t *testing.T) { - elfProgram, err := elf.Open("../../testdata/go-1-24/bin/hello.64.elf") - require.NoError(t, err, "open ELF file") - state, err := program.LoadELF(elfProgram, CreateInitialState) - require.NoError(t, err, "load ELF into state") - // Set a few additional fields - state.PreimageKey = crypto.Keccak256Hash([]byte{1, 2, 3, 4}) - state.PreimageOffset = 4 - state.Heap = 555 - state.Step = 99_999 - state.StepsSinceLastContextSwitch = 123 - state.Exited = true - state.ExitCode = 2 - state.LastHint = []byte{11, 12, 13} + state := codecTestState(t) buf := new(bytes.Buffer) - err = state.Serialize(buf) + err := state.Serialize(buf) require.NoError(t, err) newState := new(State) diff --git a/cannon/mipsevm/tests/evm_common_test.go b/cannon/mipsevm/tests/evm_common_test.go index 120ce903dac..76c9e344f21 100644 --- a/cannon/mipsevm/tests/evm_common_test.go +++ b/cannon/mipsevm/tests/evm_common_test.go @@ -2,13 +2,7 @@ package tests import ( "bytes" - "io" - "math/big" - "os" - "regexp" - "strconv" "testing" - "time" "github.com/stretchr/testify/require" @@ -949,286 +943,3 @@ func TestEVM_Fault(t *testing.T) { SetExpectations(setExpectations). Run(t, cases) } - -func TestEVM_RandomProgram(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - t.Parallel() - versionCases := GetMipsVersionTestCases(t) - - for _, v := range versionCases { - v := v - t.Run(v.Name, func(t *testing.T) { - t.Parallel() - - validator := testutil.NewEvmValidator(t, v.StateHashFn, v.Contracts) - - var stdOutBuf, stdErrBuf bytes.Buffer - elfFile := testutil.ProgramPath("random", testutil.Go1_25) - goVm := v.ElfVMFactory(t, elfFile, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) - state := goVm.GetState() - - start := time.Now() - for i := 0; i < 500_000; i++ { - step := goVm.GetState().GetStep() - if goVm.GetState().GetExited() { - break - } - insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) - if i%100_000 == 0 { // avoid spamming test logs, we are executing many steps - t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) - } - - stepWitness, err := goVm.Step(true) - require.NoError(t, err) - validator.ValidateEVM(t, stepWitness, step, goVm) - } - end := time.Now() - delta := end.Sub(start) - t.Logf("test took %s, %d instructions, %s per instruction", delta, state.GetStep(), delta/time.Duration(state.GetStep())) - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - // Check output - // Define the regex pattern we expect to match against stdOut - pattern := `Random (hex data|int): (\w+)\s*` - re, err := regexp.Compile(pattern) - require.NoError(t, err) - - // Check that stdOut matches the expected regex - expectedMatches := 3 - output := stdOutBuf.String() - matches := re.FindAllStringSubmatch(output, -1) - require.Equal(t, expectedMatches, len(matches)) - - // Check each match and validate the random values that are printed to stdOut - for i := 0; i < expectedMatches; i++ { - match := matches[i] - require.Contains(t, match[0], "Random") - - // Check that the generated random number is not zero - dataType := match[1] - dataValue := match[2] - switch dataType { - case "hex data": - randVal, success := new(big.Int).SetString(dataValue, 16) - require.True(t, success, "should successfully set hex value") - require.NotEqual(t, 0, randVal.Sign(), "random data should be non-zero") - case "int": - randVal, err := strconv.ParseUint(dataValue, 10, 64) - require.NoError(t, err) - require.NotEqual(t, uint64(0), randVal, "random int should be non-zero") - } - } - }) - } -} - -func TestEVM_SyscallEventFdProgram(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - t.Parallel() - versionCases := GetMipsVersionTestCases(t) - - for _, v := range versionCases { - v := v - t.Run(v.Name, func(t *testing.T) { - t.Parallel() - - validator := testutil.NewEvmValidator(t, v.StateHashFn, v.Contracts) - - var stdOutBuf, stdErrBuf bytes.Buffer - elfFile := testutil.ProgramPath("syscall-eventfd", v.GoTarget) - goVm := v.ElfVMFactory(t, elfFile, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) - state := goVm.GetState() - - start := time.Now() - for i := 0; i < 550_000; i++ { - step := goVm.GetState().GetStep() - if goVm.GetState().GetExited() { - break - } - insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) - if i%100_000 == 0 { // avoid spamming test logs, we are executing many steps - t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) - } - - stepWitness, err := goVm.Step(true) - require.NoError(t, err) - validator.ValidateEVM(t, stepWitness, step, goVm) - } - end := time.Now() - delta := end.Sub(start) - t.Logf("test took %s, %d instructions, %s per instruction", delta, state.GetStep(), delta/time.Duration(state.GetStep())) - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - // Check output - output := stdOutBuf.String() - require.Contains(t, output, "call eventfd with valid flags: '0x80080'") - require.Contains(t, output, "call eventfd with valid flags: '0xFFFFFFFFFFFFFFFF'") - require.Contains(t, output, "call eventfd with valid flags: '0x80'") - require.Contains(t, output, "call eventfd with invalid flags: '0x0'") - require.Contains(t, output, "call eventfd with invalid flags: '0xFFFFFFFFFFFFFF7F'") - require.Contains(t, output, "call eventfd with invalid flags: '0x80000'") - require.Contains(t, output, "write to eventfd object") - require.Contains(t, output, "read from eventfd object") - require.Contains(t, output, "done") - - // Check fd value - pattern := `eventfd2 fd = '(.+)'` - re, err := regexp.Compile(pattern) - require.NoError(t, err) - matches := re.FindAllStringSubmatch(output, -1) - - expectedMatches := 3 - require.Equal(t, expectedMatches, len(matches)) - for i := 0; i < expectedMatches; i++ { - require.Equal(t, "100", matches[i][1]) - } - }) - } -} - -func TestEVM_HelloProgram(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - t.Parallel() - versions := GetMipsVersionTestCases(t) - - for _, v := range versions { - v := v - t.Run(v.Name, func(t *testing.T) { - t.Parallel() - validator := testutil.NewEvmValidator(t, v.StateHashFn, v.Contracts) - - var stdOutBuf, stdErrBuf bytes.Buffer - elfFile := testutil.ProgramPath("hello", v.GoTarget) - goVm := v.ElfVMFactory(t, elfFile, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) - state := goVm.GetState() - - start := time.Now() - for i := 0; i < 500_000; i++ { - step := goVm.GetState().GetStep() - if goVm.GetState().GetExited() { - break - } - insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) - if i%100_000 == 0 { // avoid spamming test logs, we are executing many steps - t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) - } - - stepWitness, err := goVm.Step(true) - require.NoError(t, err) - validator.ValidateEVM(t, stepWitness, step, goVm) - } - end := time.Now() - delta := end.Sub(start) - t.Logf("test took %s, %d instructions, %s per instruction", delta, state.GetStep(), delta/time.Duration(state.GetStep())) - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - require.Equal(t, "hello world!\n", stdOutBuf.String(), "stdout says hello") - require.Equal(t, "", stdErrBuf.String(), "stderr silent") - }) - } -} - -func TestEVM_ClaimProgram(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - t.Parallel() - versions := GetMipsVersionTestCases(t) - - for _, v := range versions { - v := v - t.Run(v.Name, func(t *testing.T) { - t.Parallel() - validator := testutil.NewEvmValidator(t, v.StateHashFn, v.Contracts) - oracle, expectedStdOut, expectedStdErr := testutil.ClaimTestOracle(t) - - var stdOutBuf, stdErrBuf bytes.Buffer - elfFile := testutil.ProgramPath("claim", v.GoTarget) - goVm := v.ElfVMFactory(t, elfFile, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) - state := goVm.GetState() - - for i := 0; i < 2000_000; i++ { - curStep := goVm.GetState().GetStep() - if goVm.GetState().GetExited() { - break - } - - insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) - if i%1_000_000 == 0 { // avoid spamming test logs, we are executing many steps - t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) - } - - stepWitness, err := goVm.Step(true) - require.NoError(t, err) - validator.ValidateEVM(t, stepWitness, curStep, goVm) - } - t.Logf("Completed in %d steps", state.GetStep()) - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - - require.Equal(t, expectedStdOut, stdOutBuf.String(), "stdout") - require.Equal(t, expectedStdErr, stdErrBuf.String(), "stderr") - }) - } -} - -func TestEVM_EntryProgram(t *testing.T) { - if os.Getenv("SKIP_SLOW_TESTS") == "true" { - t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") - } - - t.Parallel() - versions := GetMipsVersionTestCases(t) - - for _, v := range versions { - v := v - t.Run(v.Name, func(t *testing.T) { - t.Parallel() - validator := testutil.NewEvmValidator(t, v.StateHashFn, v.Contracts) - - var stdOutBuf, stdErrBuf bytes.Buffer - elfFile := testutil.ProgramPath("entry", v.GoTarget) - goVm := v.ElfVMFactory(t, elfFile, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) - state := goVm.GetState() - - start := time.Now() - for i := 0; i < 500_000; i++ { - curStep := goVm.GetState().GetStep() - if goVm.GetState().GetExited() { - break - } - insn := testutil.GetInstruction(state.GetMemory(), state.GetPC()) - if i%10_000 == 0 { // avoid spamming test logs, we are executing many steps - t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) - } - - stepWitness, err := goVm.Step(true) - require.NoError(t, err) - validator.ValidateEVM(t, stepWitness, curStep, goVm) - } - end := time.Now() - delta := end.Sub(start) - t.Logf("test took %s, %d instructions, %s per instruction", delta, state.GetStep(), delta/time.Duration(state.GetStep())) - - require.True(t, state.GetExited(), "must complete program") - require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") - }) - } -} diff --git a/cannon/mipsevm/tests/helpers.go b/cannon/mipsevm/tests/helpers.go index afed044e664..9c9232f2c01 100644 --- a/cannon/mipsevm/tests/helpers.go +++ b/cannon/mipsevm/tests/helpers.go @@ -26,15 +26,6 @@ func multiThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, return multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log, nil, features) } -type ElfVMFactory func(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM - -func multiThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, features mipsevm.FeatureToggles) mipsevm.FPVM { - state, meta := testutil.LoadELFProgram(t, elfFile, multithreaded.CreateInitialState) - fpvm := multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log, meta, features) - require.NoError(t, fpvm.InitDebug()) - return fpvm -} - type ProofGenerator func(t require.TestingT, state mipsevm.FPVMState, memoryProofAddresses ...arch.Word) []byte func multiThreadedProofGenerator(t require.TestingT, state mipsevm.FPVMState, memoryProofAddresses ...arch.Word) []byte { @@ -60,13 +51,11 @@ type VersionedVMTestCase struct { Contracts *testutil.ContractMetadata StateHashFn mipsevm.HashFn VMFactory VMFactory - ElfVMFactory ElfVMFactory ProofGenerator ProofGenerator Version versions.StateVersion - GoTarget testutil.GoTarget } -func GetMultiThreadedTestCase(t require.TestingT, version versions.StateVersion, goTarget testutil.GoTarget) VersionedVMTestCase { +func GetMultiThreadedTestCase(t require.TestingT, version versions.StateVersion) VersionedVMTestCase { features := versions.FeaturesForVersion(version) return VersionedVMTestCase{ Name: version.String(), @@ -75,12 +64,8 @@ func GetMultiThreadedTestCase(t require.TestingT, version versions.StateVersion, VMFactory: func(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, opts ...mtutil.StateOption) mipsevm.FPVM { return multiThreadedVmFactory(po, stdOut, stdErr, log, features, opts...) }, - ElfVMFactory: func(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM { - return multiThreadElfVmFactory(t, elfFile, po, stdOut, stdErr, log, features) - }, ProofGenerator: multiThreadedProofGenerator, Version: version, - GoTarget: goTarget, } } @@ -88,7 +73,7 @@ func GetMipsVersionTestCases(t require.TestingT) []VersionedVMTestCase { var cases []VersionedVMTestCase for _, version := range versions.StateVersionTypes { if !arch.IsMips32 && versions.IsSupportedMultiThreaded64(version) { - cases = append(cases, GetMultiThreadedTestCase(t, version, testutil.Go1_25)) + cases = append(cases, GetMultiThreadedTestCase(t, version)) } } return cases diff --git a/cannon/mipsevm/testutil/elf.go b/cannon/mipsevm/testutil/elf.go index ba12a45d330..5c7101256a2 100644 --- a/cannon/mipsevm/testutil/elf.go +++ b/cannon/mipsevm/testutil/elf.go @@ -2,7 +2,6 @@ package testutil import ( "debug/elf" - "fmt" "github.com/stretchr/testify/require" @@ -10,13 +9,6 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" ) -type GoTarget string - -const ( - Go1_24 GoTarget = "go-1-24" - Go1_25 GoTarget = "go-1-25" -) - func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T]) (T, *program.Metadata) { elfProgram, err := elf.Open(name) require.NoError(t, err, "open ELF file") @@ -29,8 +21,3 @@ func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initSt require.NoError(t, program.PatchStack(state), "add initial stack") return state, meta } - -// ProgramPath returns the appropriate ELF test program for the current architecture -func ProgramPath(programName string, goTarget GoTarget) string { - return fmt.Sprintf("../../testdata/%s/bin/%s.64.elf", goTarget, programName) -} diff --git a/cannon/mipsevm/testutil/oracle.go b/cannon/mipsevm/testutil/oracle.go index b5c4f7dce91..c2559378534 100644 --- a/cannon/mipsevm/testutil/oracle.go +++ b/cannon/mipsevm/testutil/oracle.go @@ -2,14 +2,11 @@ package testutil import ( "encoding/binary" - "encoding/hex" - "fmt" "strings" "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/cannon/mipsevm" preimage "github.com/ethereum-optimism/optimism/op-preimage" @@ -66,77 +63,6 @@ func StaticPrecompileOracle(t *testing.T, precompile common.Address, requiredGas } } -func ClaimTestOracle(t *testing.T) (po mipsevm.PreimageOracle, stdOut string, stdErr string) { - s := uint64(0x00FFFFFF_00001000) - a := uint64(3) - b := uint64(4) - - encodeU64 := func(x uint64) []byte { - return binary.BigEndian.AppendUint64(nil, x) - } - - var diff []byte - diff = append(diff, crypto.Keccak256(encodeU64(a))...) - diff = append(diff, crypto.Keccak256(encodeU64(b))...) - - preHash := crypto.Keccak256Hash(encodeU64(s)) - diffHash := crypto.Keccak256Hash(diff) - - images := make(map[[32]byte][]byte) - images[preimage.LocalIndexKey(0).PreimageKey()] = preHash[:] - images[preimage.LocalIndexKey(1).PreimageKey()] = diffHash[:] - images[preimage.LocalIndexKey(2).PreimageKey()] = encodeU64(s*a + b) - - oracle := &TestOracle{ - hint: func(v []byte) { - parts := strings.Split(string(v), " ") - require.Len(t, parts, 2) - p, err := hex.DecodeString(parts[1]) - require.NoError(t, err) - require.Len(t, p, 32) - h := common.Hash(*(*[32]byte)(p)) - switch parts[0] { - case "fetch-state": - require.Equal(t, h, preHash, "expecting request for pre-state pre-image") - images[preimage.Keccak256Key(preHash).PreimageKey()] = encodeU64(s) - case "fetch-diff": - require.Equal(t, h, diffHash, "expecting request for diff pre-images") - images[preimage.Keccak256Key(diffHash).PreimageKey()] = diff - images[preimage.Keccak256Key(crypto.Keccak256Hash(encodeU64(a))).PreimageKey()] = encodeU64(a) - images[preimage.Keccak256Key(crypto.Keccak256Hash(encodeU64(b))).PreimageKey()] = encodeU64(b) - default: - t.Fatalf("unexpected hint: %q", parts[0]) - } - }, - getPreimage: func(k [32]byte) []byte { - p, ok := images[k] - if !ok { - t.Fatalf("missing pre-image %s", k) - } - return p - }, - } - - return oracle, fmt.Sprintf("computing %d * %d + %d\nclaim %d is good!\n", s, a, b, s*a+b), "started!" -} - -func AllocOracle(t *testing.T, numAllocs int, allocSize int) *TestOracle { - return &TestOracle{ - hint: func(v []byte) {}, - getPreimage: func(k [32]byte) []byte { - switch k { - case preimage.LocalIndexKey(0).PreimageKey(): - return binary.LittleEndian.AppendUint64(nil, uint64(numAllocs)) - case preimage.LocalIndexKey(1).PreimageKey(): - return binary.LittleEndian.AppendUint64(nil, uint64(allocSize)) - default: - t.Fatalf("invalid preimage request for %x", k) - } - panic("unreachable") - }, - } -} - func SelectOracleFixture(t *testing.T, programName string) mipsevm.PreimageOracle { if strings.HasPrefix(programName, "oracle_kzg") { precompile := common.BytesToAddress([]byte{0xa}) diff --git a/cannon/testdata/Makefile b/cannon/testdata/Makefile index 6b18e6cc787..afef0642730 100644 --- a/cannon/testdata/Makefile +++ b/cannon/testdata/Makefile @@ -1,3 +1,3 @@ -DEPRECATED_TARGETS := elf go1-24 go1-25 clean +DEPRECATED_TARGETS := diff-hello-elf clean include ../../justfiles/deprecated.mk diff --git a/cannon/testdata/README.md b/cannon/testdata/README.md index 4730cac00b0..59a34d152c6 100644 --- a/cannon/testdata/README.md +++ b/cannon/testdata/README.md @@ -1,11 +1,11 @@ # Cannon testdata -These example Go programs are used in tests, -and encapsulated as their own Go modules. - -## Testdata - The `testdata` directory name (special Go exception) prevents tools like `go mod tidy` that run from the monorepo root from picking up on the test data, preventing noisy dependabot PRs. +`diff-hello/` holds a minimal MIPS guest program used only by `just diff-cannon` +and `op-challenger` cache tests. It is built with Go 1.24 so the guest binary +does not depend on Go 1.26 runtime syscalls that production Cannon no longer +implements. Legacy Go FPVM guest program fixtures were removed because +production fault proofs use the kona client instead. diff --git a/cannon/testdata/diff-hello/go.mod b/cannon/testdata/diff-hello/go.mod new file mode 100644 index 00000000000..648aad9d6b9 --- /dev/null +++ b/cannon/testdata/diff-hello/go.mod @@ -0,0 +1,3 @@ +module github.com/ethereum-optimism/optimism/cannon/testdata/diff-hello + +go 1.24.0 diff --git a/cannon/testdata/go-1-24/hello/main.go b/cannon/testdata/diff-hello/main.go similarity index 100% rename from cannon/testdata/go-1-24/hello/main.go rename to cannon/testdata/diff-hello/main.go diff --git a/cannon/testdata/go-1-24/Makefile b/cannon/testdata/go-1-24/Makefile deleted file mode 100644 index cd4c47589bd..00000000000 --- a/cannon/testdata/go-1-24/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -DEPRECATED_TARGETS := elf elf64 dump clean - -include ../../../justfiles/deprecated.mk diff --git a/cannon/testdata/go-1-24/alloc/go.mod b/cannon/testdata/go-1-24/alloc/go.mod deleted file mode 100644 index e7f536a3376..00000000000 --- a/cannon/testdata/go-1-24/alloc/go.mod +++ /dev/null @@ -1,14 +0,0 @@ -module alloc - -go 1.24.0 - -toolchain go1.24.10 - -require github.com/ethereum-optimism/optimism v0.0.0 - -require ( - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/sys v0.40.0 // indirect -) - -replace github.com/ethereum-optimism/optimism v0.0.0 => ./../../../.. diff --git a/cannon/testdata/go-1-24/alloc/go.sum b/cannon/testdata/go-1-24/alloc/go.sum deleted file mode 100644 index 2287271d512..00000000000 --- a/cannon/testdata/go-1-24/alloc/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cannon/testdata/go-1-24/alloc/main.go b/cannon/testdata/go-1-24/alloc/main.go deleted file mode 100644 index 3c7af2f165f..00000000000 --- a/cannon/testdata/go-1-24/alloc/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "encoding/binary" - "fmt" - "runtime" - - preimage "github.com/ethereum-optimism/optimism/op-preimage" -) - -func main() { - var mem []byte - po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) - numAllocs := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(0))) - allocSize := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(1))) - - fmt.Printf("alloc program. numAllocs=%d allocSize=%d\n", numAllocs, allocSize) - var alloc int - for i := 0; i < int(numAllocs); i++ { - mem = make([]byte, allocSize) - alloc += len(mem) - // touch a couple pages to prevent the runtime from overcommitting memory - for j := 0; j < len(mem); j += 1024 { - mem[j] = 0xFF - } - printGCStats(alloc) - } - - fmt.Println("alloc program exit") - printGCStats(alloc) -} - -func printGCStats(alloc int) { - var m runtime.MemStats - runtime.ReadMemStats(&m) - fmt.Printf("allocated %d bytes. memstats: heap_alloc=%d next_gc=%d frees=%d mallocs=%d num_gc=%d\n", - alloc, m.HeapAlloc, m.NextGC, m.Frees, m.Mallocs, m.NumGC) -} diff --git a/cannon/testdata/go-1-24/claim/go.mod b/cannon/testdata/go-1-24/claim/go.mod deleted file mode 100644 index 55d1bd2f452..00000000000 --- a/cannon/testdata/go-1-24/claim/go.mod +++ /dev/null @@ -1,14 +0,0 @@ -module claim - -go 1.24.0 - -toolchain go1.24.10 - -require github.com/ethereum-optimism/optimism v0.0.0 - -require ( - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/sys v0.40.0 // indirect -) - -replace github.com/ethereum-optimism/optimism v0.0.0 => ./../../../.. diff --git a/cannon/testdata/go-1-24/claim/go.sum b/cannon/testdata/go-1-24/claim/go.sum deleted file mode 100644 index 2287271d512..00000000000 --- a/cannon/testdata/go-1-24/claim/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cannon/testdata/go-1-24/claim/main.go b/cannon/testdata/go-1-24/claim/main.go deleted file mode 100644 index 72b2064dec9..00000000000 --- a/cannon/testdata/go-1-24/claim/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "encoding/binary" - "fmt" - "os" - - preimage "github.com/ethereum-optimism/optimism/op-preimage" -) - -type rawHint string - -func (rh rawHint) Hint() string { - return string(rh) -} - -func main() { - _, _ = os.Stderr.Write([]byte("started!")) - - po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) - hinter := preimage.NewHintWriter(preimage.ClientHinterChannel()) - - preHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(0))) - diffHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(1))) - claimData := *(*[8]byte)(po.Get(preimage.LocalIndexKey(2))) - - // Hints are used to indicate which things the program will access, - // so the server can be prepared to serve the corresponding pre-images. - hinter.Hint(rawHint(fmt.Sprintf("fetch-state %x", preHash))) - pre := po.Get(preimage.Keccak256Key(preHash)) - - // Multiple pre-images may be fetched based on a hint. - // E.g. when we need all values of a merkle-tree. - hinter.Hint(rawHint(fmt.Sprintf("fetch-diff %x", diffHash))) - diff := po.Get(preimage.Keccak256Key(diffHash)) - diffPartA := po.Get(preimage.Keccak256Key(*(*[32]byte)(diff[:32]))) - diffPartB := po.Get(preimage.Keccak256Key(*(*[32]byte)(diff[32:]))) - - // Example state-transition function: s' = s*a + b - s := binary.BigEndian.Uint64(pre) - a := binary.BigEndian.Uint64(diffPartA) - b := binary.BigEndian.Uint64(diffPartB) - fmt.Printf("computing %d * %d + %d\n", s, a, b) - sOut := s*a + b - - sClaim := binary.BigEndian.Uint64(claimData[:]) - if sOut != sClaim { - fmt.Printf("claim %d is bad! Correct result is %d\n", sOut, sClaim) - os.Exit(1) - } else { - fmt.Printf("claim %d is good!\n", sOut) - os.Exit(0) - } -} diff --git a/cannon/testdata/go-1-24/entry/go.mod b/cannon/testdata/go-1-24/entry/go.mod deleted file mode 100644 index 65433da8cca..00000000000 --- a/cannon/testdata/go-1-24/entry/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module entry - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/entry/main.go b/cannon/testdata/go-1-24/entry/main.go deleted file mode 100644 index 78866f88abe..00000000000 --- a/cannon/testdata/go-1-24/entry/main.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "os" - "runtime" -) - -func main() { - if len(os.Args) != 1 { - panic("expected 1 arg") - } - if os.Args[0] != "op-program" { - panic("unexpected arg0") - } - - var memProfileRate bool - env := os.Environ() - for _, env := range env { - if env != "GODEBUG=memprofilerate=0" { - panic("invalid envar") - } - memProfileRate = true - } - if !memProfileRate { - panic("memProfileRate env is not set") - } - if runtime.MemProfileRate != 0 { - panic("runtime.MemProfileRate is non-zero") - } -} diff --git a/cannon/testdata/go-1-24/hello/go.mod b/cannon/testdata/go-1-24/hello/go.mod deleted file mode 100644 index de85e6441d3..00000000000 --- a/cannon/testdata/go-1-24/hello/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module hello - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/justfile b/cannon/testdata/go-1-24/justfile deleted file mode 100644 index d606bdc6353..00000000000 --- a/cannon/testdata/go-1-24/justfile +++ /dev/null @@ -1,31 +0,0 @@ -# Build all 64-bit ELF test binaries -elf64: elf - -# Build all 64-bit ELF test binaries -[script('bash')] -elf: - set -euo pipefail - mkdir -p bin - for mod in */go.mod; do - name=$(dirname "$mod") - echo "Building bin/${name}.64.elf" - (cd "$name" && GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -o "../bin/${name}.64.elf" .) - done - -# Dump all ELF binaries -# TODO: currently have the little-endian toolchain, but should use the big-endian one. The -EB compat flag works though. -[script('bash')] -dump: - set -euo pipefail - mkdir -p bin - for mod in */go.mod; do - name=$(dirname "$mod") - elf="bin/${name}.64.elf" - dump="bin/${name}.64.dump" - echo "Dumping $elf -> $dump" - mipsel-linux-gnu-objdump -D --disassembler-options=no-aliases --wide --source -m mips:3000 -EB "$elf" > "$dump" - done - -# Clean build artifacts -clean: - @[ -d bin ] && find bin -maxdepth 1 -type f -delete || true diff --git a/cannon/testdata/go-1-24/keccak/go.mod b/cannon/testdata/go-1-24/keccak/go.mod deleted file mode 100644 index b8e5f29beef..00000000000 --- a/cannon/testdata/go-1-24/keccak/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module keccak - -go 1.24 - -toolchain go1.24.2 - -require golang.org/x/crypto v0.35.0 - -require golang.org/x/sys v0.30.0 // indirect - -replace github.com/ethereum-optimism/optimism v0.0.0 => ./../../../.. diff --git a/cannon/testdata/go-1-24/keccak/go.sum b/cannon/testdata/go-1-24/keccak/go.sum deleted file mode 100644 index 265a8fc783b..00000000000 --- a/cannon/testdata/go-1-24/keccak/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/cannon/testdata/go-1-24/keccak/main.go b/cannon/testdata/go-1-24/keccak/main.go deleted file mode 100644 index 828b1e7e665..00000000000 --- a/cannon/testdata/go-1-24/keccak/main.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "fmt" - - "golang.org/x/crypto/sha3" -) - -func main() { - var result []byte - state := sha3.NewLegacyKeccak256() - state.Write([]byte{1, 2, 3}) - result = state.Sum(result) - - fmt.Printf("keccak program. result=%x\n", result) -} diff --git a/cannon/testdata/go-1-24/mt-atomic/atomic_test_copy.go b/cannon/testdata/go-1-24/mt-atomic/atomic_test_copy.go deleted file mode 100644 index e0cd1ebd69f..00000000000 --- a/cannon/testdata/go-1-24/mt-atomic/atomic_test_copy.go +++ /dev/null @@ -1,2567 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/atomic/atomic_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "fmt" - "reflect" - "runtime" - "runtime/debug" - "strings" - . "sync/atomic" - "testing" - "unsafe" - - "utils/testutil" -) - -// Tests of correct behavior, without contention. -// (Does the function work as advertised?) -// -// Test that the Add functions add correctly. -// Test that the CompareAndSwap functions actually -// do the comparison and the swap correctly. -// -// The loop over power-of-two values is meant to -// ensure that the operations apply to the full word size. -// The struct fields x.before and x.after check that the -// operations do not extend past the full word size. - -const ( - magic32 = 0xdedbeef - magic64 = 0xdeddeadbeefbeef -) - -func TestSwapInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := SwapInt32(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := SwapUint32(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := SwapInt64(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := SwapUint64(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := SwapUintptr(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestSwapUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -var global [1024]byte - -func testPointers() []unsafe.Pointer { - var pointers []unsafe.Pointer - // globals - for i := 0; i < 10; i++ { - pointers = append(pointers, unsafe.Pointer(&global[1< delta; delta += delta { - k := AddInt32(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := AddUint32(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := AddInt64(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := AddUint64(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := AddUintptr(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestAddUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for val := int32(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapInt32(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapInt32(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for val := int32(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for val := uint32(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapUint32(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapUint32(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for val := uint32(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - for val := int64(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapInt64(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapInt64(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestCompareAndSwapInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - for val := int64(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func testCompareAndSwapUint64(t testing.TB, cas func(*uint64, uint64, uint64) bool) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - for val := uint64(1); val+val > val; val += val { - x.i = val - if !cas(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if cas(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestCompareAndSwapUint64(t *testutil.TestRunner) { - testCompareAndSwapUint64(t, CompareAndSwapUint64) -} - -func TestCompareAndSwapUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - for val := uint64(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestCompareAndSwapUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for val := uintptr(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapUintptr(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapUintptr(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for val := uintptr(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uintptr(magicptr), uintptr(magicptr)) - } -} - -func TestCompareAndSwapPointer(t *testutil.TestRunner) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - q := unsafe.Pointer(new(byte)) - for _, p := range testPointers() { - x.i = p - if !CompareAndSwapPointer(&x.i, p, q) { - t.Fatalf("should have swapped %p %p", p, q) - } - if x.i != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q) - } - if CompareAndSwapPointer(&x.i, p, nil) { - t.Fatalf("should not have swapped %p nil", p) - } - if x.i != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapPointerMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Pointer[byte] - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - q := new(byte) - for _, p := range testPointers() { - p := (*byte)(p) - x.i.Store(p) - if !x.i.CompareAndSwap(p, q) { - t.Fatalf("should have swapped %p %p", p, q) - } - if x.i.Load() != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q) - } - if x.i.CompareAndSwap(p, nil) { - t.Fatalf("should not have swapped %p nil", p) - } - if x.i.Load() != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := LoadInt32(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - want := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := LoadUint32(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - want := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := LoadInt64(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - want := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := LoadUint64(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - want := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := LoadUintptr(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - want := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadPointer(t *testutil.TestRunner) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - x.i = p - k := LoadPointer(&x.i) - if k != p { - t.Fatalf("p=%x k=%x", p, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadPointerMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Pointer[byte] - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - p := (*byte)(p) - x.i.Store(p) - k := x.i.Load() - if k != p { - t.Fatalf("p=%x k=%x", p, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStoreInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - v := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - StoreInt32(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - v := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - v := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - StoreUint32(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - v := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - v := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - StoreInt64(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - v := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - v := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - StoreUint64(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - v := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - v := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - StoreUintptr(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStoreUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - v := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStorePointer(t *testutil.TestRunner) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - StorePointer(&x.i, p) - if x.i != p { - t.Fatalf("x.i=%p p=%p", x.i, p) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStorePointerMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Pointer[byte] - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - p := (*byte)(p) - x.i.Store(p) - if x.i.Load() != p { - t.Fatalf("x.i=%p p=%p", x.i.Load(), p) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -// Tests of correct behavior, with contention. -// (Is the function atomic?) -// -// For each function, we write a "hammer" function that repeatedly -// uses the atomic operation to add 1 to a value. After running -// multiple hammers in parallel, check that we end with the correct -// total. -// Swap can't add 1, so it uses a different scheme. -// The functions repeatedly generate a pseudo-random number such that -// low bits are equal to high bits, swap, check that the old value -// has low and high bits equal. - -var hammer32 = map[string]func(*uint32, int){ - "SwapInt32": hammerSwapInt32, - "SwapUint32": hammerSwapUint32, - "SwapUintptr": hammerSwapUintptr32, - "AddInt32": hammerAddInt32, - "AddUint32": hammerAddUint32, - "AddUintptr": hammerAddUintptr32, - "CompareAndSwapInt32": hammerCompareAndSwapInt32, - "CompareAndSwapUint32": hammerCompareAndSwapUint32, - "CompareAndSwapUintptr": hammerCompareAndSwapUintptr32, - - "SwapInt32Method": hammerSwapInt32Method, - "SwapUint32Method": hammerSwapUint32Method, - "SwapUintptrMethod": hammerSwapUintptr32Method, - "AddInt32Method": hammerAddInt32Method, - "AddUint32Method": hammerAddUint32Method, - "AddUintptrMethod": hammerAddUintptr32Method, - "CompareAndSwapInt32Method": hammerCompareAndSwapInt32Method, - "CompareAndSwapUint32Method": hammerCompareAndSwapUint32Method, - "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr32Method, -} - -func init() { - var v uint64 = 1 << 50 - if uintptr(v) != 0 { - // 64-bit system; clear uintptr tests - delete(hammer32, "SwapUintptr") - delete(hammer32, "AddUintptr") - delete(hammer32, "CompareAndSwapUintptr") - delete(hammer32, "SwapUintptrMethod") - delete(hammer32, "AddUintptrMethod") - delete(hammer32, "CompareAndSwapUintptrMethod") - } -} - -func hammerSwapInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := uint32(SwapInt32(addr, int32(new))) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) - } - } -} - -func hammerSwapInt32Method(uaddr *uint32, count int) { - addr := (*Int32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := uint32(addr.Swap(int32(new))) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint32(addr *uint32, count int) { - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := SwapUint32(addr, new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint32Method(uaddr *uint32, count int) { - addr := (*Uint32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := addr.Swap(new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 - old := SwapUintptr(addr, new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old)) - } - } -} - -func hammerSwapUintptr32Method(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 - old := addr.Swap(new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("Uintptr.Swap is not atomic: %#08x", old)) - } - } -} - -func hammerAddInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddInt32(addr, 1) - } -} - -func hammerAddInt32Method(uaddr *uint32, count int) { - addr := (*Int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUint32(addr *uint32, count int) { - for i := 0; i < count; i++ { - AddUint32(addr, 1) - } -} - -func hammerAddUint32Method(uaddr *uint32, count int) { - addr := (*Uint32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddUintptr(addr, 1) - } -} - -func hammerAddUintptr32Method(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerCompareAndSwapInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadInt32(addr) - if CompareAndSwapInt32(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapInt32Method(uaddr *uint32, count int) { - addr := (*Int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint32(addr *uint32, count int) { - for i := 0; i < count; i++ { - for { - v := LoadUint32(addr) - if CompareAndSwapUint32(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint32Method(uaddr *uint32, count int) { - addr := (*Uint32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadUintptr(addr) - if CompareAndSwapUintptr(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func TestHammer32(t *testutil.TestRunner) { - const p = 4 - n := 100000 - if short { - n = 1000 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) - - for name, testf := range hammer32 { - c := make(chan int) - var val uint32 - for i := 0; i < p; i++ { - go func() { - defer func() { - if err := recover(); err != nil { - t.Error(err.(string)) - } - c <- 1 - }() - testf(&val, n) - }() - } - for i := 0; i < p; i++ { - <-c - } - if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p { - t.Fatalf("%s: val=%d want %d", name, val, n*p) - } - } -} - -var hammer64 = map[string]func(*uint64, int){ - "SwapInt64": hammerSwapInt64, - "SwapUint64": hammerSwapUint64, - "SwapUintptr": hammerSwapUintptr64, - "AddInt64": hammerAddInt64, - "AddUint64": hammerAddUint64, - "AddUintptr": hammerAddUintptr64, - "CompareAndSwapInt64": hammerCompareAndSwapInt64, - "CompareAndSwapUint64": hammerCompareAndSwapUint64, - "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64, - - "SwapInt64Method": hammerSwapInt64Method, - "SwapUint64Method": hammerSwapUint64Method, - "SwapUintptrMethod": hammerSwapUintptr64Method, - "AddInt64Method": hammerAddInt64Method, - "AddUint64Method": hammerAddUint64Method, - "AddUintptrMethod": hammerAddUintptr64Method, - "CompareAndSwapInt64Method": hammerCompareAndSwapInt64Method, - "CompareAndSwapUint64Method": hammerCompareAndSwapUint64Method, - "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr64Method, -} - -func init() { - var v uint64 = 1 << 50 - if uintptr(v) == 0 { - // 32-bit system; clear uintptr tests - delete(hammer64, "SwapUintptr") - delete(hammer64, "SwapUintptrMethod") - delete(hammer64, "AddUintptr") - delete(hammer64, "AddUintptrMethod") - delete(hammer64, "CompareAndSwapUintptr") - delete(hammer64, "CompareAndSwapUintptrMethod") - } -} - -func hammerSwapInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := uint64(SwapInt64(addr, int64(new))) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) - } - } -} - -func hammerSwapInt64Method(uaddr *uint64, count int) { - addr := (*Int64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := uint64(addr.Swap(int64(new))) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint64(addr *uint64, count int) { - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := SwapUint64(addr, new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint64Method(uaddr *uint64, count int) { - addr := (*Uint64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := addr.Swap(new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) - } - } -} - -const arch32 = unsafe.Sizeof(uintptr(0)) == 4 - -func hammerSwapUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - if !arch32 { - addr := (*uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 - old := SwapUintptr(addr, new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) - } - } - } -} - -func hammerSwapUintptr64Method(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - if !arch32 { - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 - old := addr.Swap(new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) - } - } - } -} - -func hammerAddInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddInt64(addr, 1) - } -} - -func hammerAddInt64Method(uaddr *uint64, count int) { - addr := (*Int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUint64(addr *uint64, count int) { - for i := 0; i < count; i++ { - AddUint64(addr, 1) - } -} - -func hammerAddUint64Method(uaddr *uint64, count int) { - addr := (*Uint64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddUintptr(addr, 1) - } -} - -func hammerAddUintptr64Method(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerCompareAndSwapInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadInt64(addr) - if CompareAndSwapInt64(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapInt64Method(uaddr *uint64, count int) { - addr := (*Int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint64(addr *uint64, count int) { - for i := 0; i < count; i++ { - for { - v := LoadUint64(addr) - if CompareAndSwapUint64(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint64Method(uaddr *uint64, count int) { - addr := (*Uint64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadUintptr(addr) - if CompareAndSwapUintptr(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func TestHammer64(t *testutil.TestRunner) { - const p = 4 - n := 100000 - if short { - n = 1000 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) - - for name, testf := range hammer64 { - c := make(chan int) - var val uint64 - for i := 0; i < p; i++ { - go func() { - defer func() { - if err := recover(); err != nil { - t.Error(err.(string)) - } - c <- 1 - }() - testf(&val, n) - }() - } - for i := 0; i < p; i++ { - <-c - } - if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p { - t.Fatalf("%s: val=%d want %d", name, val, n*p) - } - } -} - -func hammerStoreLoadInt32(t testing.TB, paddr unsafe.Pointer) { - addr := (*int32)(paddr) - v := LoadInt32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Int32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreInt32(addr, new) -} - -func hammerStoreLoadInt32Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*int32)(paddr) - v := LoadInt32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Int32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreInt32(addr, new) -} - -func hammerStoreLoadUint32(t testing.TB, paddr unsafe.Pointer) { - addr := (*uint32)(paddr) - v := LoadUint32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uint32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreUint32(addr, new) -} - -func hammerStoreLoadUint32Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*Uint32)(paddr) - v := addr.Load() - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uint32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - addr.Store(new) -} - -func hammerStoreLoadInt64(t testing.TB, paddr unsafe.Pointer) { - addr := (*int64)(paddr) - v := LoadInt64(addr) - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Int64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - StoreInt64(addr, new) -} - -func hammerStoreLoadInt64Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*Int64)(paddr) - v := addr.Load() - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Int64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - addr.Store(new) -} - -func hammerStoreLoadUint64(t testing.TB, paddr unsafe.Pointer) { - addr := (*uint64)(paddr) - v := LoadUint64(addr) - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uint64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - StoreUint64(addr, new) -} - -func hammerStoreLoadUint64Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*Uint64)(paddr) - v := addr.Load() - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uint64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - addr.Store(new) -} - -func hammerStoreLoadUintptr(t testing.TB, paddr unsafe.Pointer) { - addr := (*uintptr)(paddr) - v := LoadUintptr(addr) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - StoreUintptr(addr, new) -} - -//go:nocheckptr -func hammerStoreLoadUintptrMethod(t testing.TB, paddr unsafe.Pointer) { - addr := (*Uintptr)(paddr) - v := addr.Load() - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - addr.Store(new) -} - -// This code is just testing that LoadPointer/StorePointer operate -// atomically; it's not actually calculating pointers. -// -//go:nocheckptr -func hammerStoreLoadPointer(t testing.TB, paddr unsafe.Pointer) { - addr := (*unsafe.Pointer)(paddr) - v := uintptr(LoadPointer(addr)) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - StorePointer(addr, unsafe.Pointer(new)) -} - -// This code is just testing that LoadPointer/StorePointer operate -// atomically; it's not actually calculating pointers. -// -//go:nocheckptr -func hammerStoreLoadPointerMethod(t testing.TB, paddr unsafe.Pointer) { - addr := (*Pointer[byte])(paddr) - v := uintptr(unsafe.Pointer(addr.Load())) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - addr.Store((*byte)(unsafe.Pointer(new))) -} - -func TestHammerStoreLoad(t *testutil.TestRunner) { - tests := []func(testing.TB, unsafe.Pointer){ - hammerStoreLoadInt32, hammerStoreLoadUint32, - hammerStoreLoadUintptr, hammerStoreLoadPointer, - hammerStoreLoadInt32Method, hammerStoreLoadUint32Method, - hammerStoreLoadUintptrMethod, hammerStoreLoadPointerMethod, - hammerStoreLoadInt64, hammerStoreLoadUint64, - hammerStoreLoadInt64Method, hammerStoreLoadUint64Method, - } - n := int(1e6) - if short { - n = int(1e4) - } - const procs = 8 - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) - // Disable the GC because hammerStoreLoadPointer invokes - // write barriers on values that aren't real pointers. - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // Ensure any in-progress GC is finished. - runtime.GC() - for _, tt := range tests { - c := make(chan int) - var val uint64 - for p := 0; p < procs; p++ { - go func() { - for i := 0; i < n; i++ { - tt(t, unsafe.Pointer(&val)) - } - c <- 1 - }() - } - for p := 0; p < procs; p++ { - <-c - } - } -} - -func TestStoreLoadSeqCst32(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int32(1e3) - if short { - N = int32(1e2) - } - c := make(chan bool, 2) - X := [2]int32{} - ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}} - for p := 0; p < 2; p++ { - go func(me int) { - he := 1 - me - for i := int32(1); i < N; i++ { - StoreInt32(&X[me], i) - my := LoadInt32(&X[he]) - StoreInt32(&ack[me][i%3], my) - for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - his := LoadInt32(&ack[he][i%3]) - if (my != i && my != i-1) || (his != i && his != i-1) { - t.Errorf("invalid values: %d/%d (%d)", my, his, i) - break - } - if my != i && his != i { - t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) - break - } - StoreInt32(&ack[me][(i-1)%3], -1) - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadSeqCst64(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int64(1e3) - if short { - N = int64(1e2) - } - c := make(chan bool, 2) - X := [2]int64{} - ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}} - for p := 0; p < 2; p++ { - go func(me int) { - he := 1 - me - for i := int64(1); i < N; i++ { - StoreInt64(&X[me], i) - my := LoadInt64(&X[he]) - StoreInt64(&ack[me][i%3], my) - for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - his := LoadInt64(&ack[he][i%3]) - if (my != i && my != i-1) || (his != i && his != i-1) { - t.Errorf("invalid values: %d/%d (%d)", my, his, i) - break - } - if my != i && his != i { - t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) - break - } - StoreInt64(&ack[me][(i-1)%3], -1) - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadRelAcq32(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int32(1e3) - if short { - N = int32(1e2) - } - c := make(chan bool, 2) - type Data struct { - signal int32 - pad1 [128]int8 - data1 int32 - pad2 [128]int8 - data2 float32 - } - var X Data - for p := int32(0); p < 2; p++ { - go func(p int32) { - for i := int32(1); i < N; i++ { - if (i+p)%2 == 0 { - X.data1 = i - X.data2 = float32(i) - StoreInt32(&X.signal, i) - } else { - for w := 1; LoadInt32(&X.signal) != i; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - d1 := X.data1 - d2 := X.data2 - if d1 != i || d2 != float32(i) { - t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i) - break - } - } - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadRelAcq64(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int64(1e3) - if short { - N = int64(1e2) - } - c := make(chan bool, 2) - type Data struct { - signal int64 - pad1 [128]int8 - data1 int64 - pad2 [128]int8 - data2 float64 - } - var X Data - for p := int64(0); p < 2; p++ { - go func(p int64) { - for i := int64(1); i < N; i++ { - if (i+p)%2 == 0 { - X.data1 = i - X.data2 = float64(i) - StoreInt64(&X.signal, i) - } else { - for w := 1; LoadInt64(&X.signal) != i; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - d1 := X.data1 - d2 := X.data2 - if d1 != i || d2 != float64(i) { - t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i) - break - } - } - } - c <- true - }(p) - } - <-c - <-c -} - -func shouldPanic(t testing.TB, name string, f func()) { - defer func() { - // Check that all GC maps are sane. - runtime.GC() - - err := recover() - want := "unaligned 64-bit atomic operation" - if err == nil { - t.Errorf("%s did not panic", name) - } else if s, _ := err.(string); s != want { - t.Errorf("%s: wanted panic %q, got %q", name, want, err) - } - }() - f() -} - -func TestUnaligned64(t *testutil.TestRunner) { - // Unaligned 64-bit atomics on 32-bit systems are - // a continual source of pain. Test that on 32-bit systems they crash - // instead of failing silently. - if !arch32 { - t.Skip("test only runs on 32-bit systems") - } - - x := make([]uint32, 4) - p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned - - shouldPanic(t, "LoadUint64", func() { LoadUint64(p) }) - shouldPanic(t, "LoadUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Load() }) - shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) }) - shouldPanic(t, "StoreUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Store(1) }) - shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) }) - shouldPanic(t, "CompareAndSwapUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).CompareAndSwap(1, 2) }) - shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) }) - shouldPanic(t, "AddUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Add(3) }) -} - -func TestAutoAligned64(t *testutil.TestRunner) { - var signed struct { - _ uint32 - i Int64 - } - if o := reflect.TypeOf(&signed).Elem().Field(1).Offset; o != 8 { - t.Fatalf("Int64 offset = %d, want 8", o) - } - if p := reflect.ValueOf(&signed).Elem().Field(1).Addr().Pointer(); p&7 != 0 { - t.Fatalf("Int64 pointer = %#x, want 8-aligned", p) - } - - var unsigned struct { - _ uint32 - i Uint64 - } - if o := reflect.TypeOf(&unsigned).Elem().Field(1).Offset; o != 8 { - t.Fatalf("Uint64 offset = %d, want 8", o) - } - if p := reflect.ValueOf(&unsigned).Elem().Field(1).Addr().Pointer(); p&7 != 0 { - t.Fatalf("Int64 pointer = %#x, want 8-aligned", p) - } -} - -func TestNilDeref(t *testutil.TestRunner) { - funcs := [...]func(){ - func() { CompareAndSwapInt32(nil, 0, 0) }, - func() { (*Int32)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapInt64(nil, 0, 0) }, - func() { (*Int64)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapUint32(nil, 0, 0) }, - func() { (*Uint32)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapUint64(nil, 0, 0) }, - func() { (*Uint64)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapUintptr(nil, 0, 0) }, - func() { (*Uintptr)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapPointer(nil, nil, nil) }, - func() { (*Pointer[byte])(nil).CompareAndSwap(nil, nil) }, - func() { SwapInt32(nil, 0) }, - func() { (*Int32)(nil).Swap(0) }, - func() { SwapUint32(nil, 0) }, - func() { (*Uint32)(nil).Swap(0) }, - func() { SwapInt64(nil, 0) }, - func() { (*Int64)(nil).Swap(0) }, - func() { SwapUint64(nil, 0) }, - func() { (*Uint64)(nil).Swap(0) }, - func() { SwapUintptr(nil, 0) }, - func() { (*Uintptr)(nil).Swap(0) }, - func() { SwapPointer(nil, nil) }, - func() { (*Pointer[byte])(nil).Swap(nil) }, - func() { AddInt32(nil, 0) }, - func() { (*Int32)(nil).Add(0) }, - func() { AddUint32(nil, 0) }, - func() { (*Uint32)(nil).Add(0) }, - func() { AddInt64(nil, 0) }, - func() { (*Int64)(nil).Add(0) }, - func() { AddUint64(nil, 0) }, - func() { (*Uint64)(nil).Add(0) }, - func() { AddUintptr(nil, 0) }, - func() { (*Uintptr)(nil).Add(0) }, - func() { LoadInt32(nil) }, - func() { (*Int32)(nil).Load() }, - func() { LoadInt64(nil) }, - func() { (*Int64)(nil).Load() }, - func() { LoadUint32(nil) }, - func() { (*Uint32)(nil).Load() }, - func() { LoadUint64(nil) }, - func() { (*Uint64)(nil).Load() }, - func() { LoadUintptr(nil) }, - func() { (*Uintptr)(nil).Load() }, - func() { LoadPointer(nil) }, - func() { (*Pointer[byte])(nil).Load() }, - func() { StoreInt32(nil, 0) }, - func() { (*Int32)(nil).Store(0) }, - func() { StoreInt64(nil, 0) }, - func() { (*Int64)(nil).Store(0) }, - func() { StoreUint32(nil, 0) }, - func() { (*Uint32)(nil).Store(0) }, - func() { StoreUint64(nil, 0) }, - func() { (*Uint64)(nil).Store(0) }, - func() { StoreUintptr(nil, 0) }, - func() { (*Uintptr)(nil).Store(0) }, - func() { StorePointer(nil, nil) }, - func() { (*Pointer[byte])(nil).Store(nil) }, - } - for _, f := range funcs { - func() { - defer func() { - runtime.GC() - recover() - }() - f() - }() - } -} - -// Test that this compiles. -// When atomic.Pointer used _ [0]T, it did not. -type List struct { - Next Pointer[List] -} diff --git a/cannon/testdata/go-1-24/mt-atomic/go.mod b/cannon/testdata/go-1-24/mt-atomic/go.mod deleted file mode 100644 index a20fe3c9304..00000000000 --- a/cannon/testdata/go-1-24/mt-atomic/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module atomic - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/mt-atomic/main.go b/cannon/testdata/go-1-24/mt-atomic/main.go deleted file mode 100644 index 9d683c5bd59..00000000000 --- a/cannon/testdata/go-1-24/mt-atomic/main.go +++ /dev/null @@ -1,80 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestSwapInt32, "TestSwapInt32") - testutil.RunTest(TestSwapInt32Method, "TestSwapInt32Method") - testutil.RunTest(TestSwapUint32, "TestSwapUint32") - testutil.RunTest(TestSwapUint32Method, "TestSwapUint32Method") - testutil.RunTest(TestSwapInt64, "TestSwapInt64") - testutil.RunTest(TestSwapInt64Method, "TestSwapInt64Method") - testutil.RunTest(TestSwapUint64, "TestSwapUint64") - testutil.RunTest(TestSwapUint64Method, "TestSwapUint64Method") - testutil.RunTest(TestSwapUintptr, "TestSwapUintptr") - testutil.RunTest(TestSwapUintptrMethod, "TestSwapUintptrMethod") - testutil.RunTest(TestSwapPointer, "TestSwapPointer") - testutil.RunTest(TestSwapPointerMethod, "TestSwapPointerMethod") - testutil.RunTest(TestAddInt32, "TestAddInt32") - testutil.RunTest(TestAddInt32Method, "TestAddInt32Method") - testutil.RunTest(TestAddUint32, "TestAddUint32") - testutil.RunTest(TestAddUint32Method, "TestAddUint32Method") - testutil.RunTest(TestAddInt64, "TestAddInt64") - testutil.RunTest(TestAddInt64Method, "TestAddInt64Method") - testutil.RunTest(TestAddUint64, "TestAddUint64") - testutil.RunTest(TestAddUint64Method, "TestAddUint64Method") - testutil.RunTest(TestAddUintptr, "TestAddUintptr") - testutil.RunTest(TestAddUintptrMethod, "TestAddUintptrMethod") - testutil.RunTest(TestCompareAndSwapInt32, "TestCompareAndSwapInt32") - testutil.RunTest(TestCompareAndSwapInt32Method, "TestCompareAndSwapInt32Method") - testutil.RunTest(TestCompareAndSwapUint32, "TestCompareAndSwapUint32") - testutil.RunTest(TestCompareAndSwapUint32Method, "TestCompareAndSwapUint32Method") - testutil.RunTest(TestCompareAndSwapInt64, "TestCompareAndSwapInt64") - testutil.RunTest(TestCompareAndSwapInt64Method, "TestCompareAndSwapInt64Method") - testutil.RunTest(TestCompareAndSwapUint64, "TestCompareAndSwapUint64") - testutil.RunTest(TestCompareAndSwapUint64Method, "TestCompareAndSwapUint64Method") - testutil.RunTest(TestCompareAndSwapUintptr, "TestCompareAndSwapUintptr") - testutil.RunTest(TestCompareAndSwapUintptrMethod, "TestCompareAndSwapUintptrMethod") - testutil.RunTest(TestCompareAndSwapPointer, "TestCompareAndSwapPointer") - testutil.RunTest(TestCompareAndSwapPointerMethod, "TestCompareAndSwapPointerMethod") - testutil.RunTest(TestLoadInt32, "TestLoadInt32") - testutil.RunTest(TestLoadInt32Method, "TestLoadInt32Method") - testutil.RunTest(TestLoadUint32, "TestLoadUint32") - testutil.RunTest(TestLoadUint32Method, "TestLoadUint32Method") - testutil.RunTest(TestLoadInt64, "TestLoadInt64") - testutil.RunTest(TestLoadInt64Method, "TestLoadInt64Method") - testutil.RunTest(TestLoadUint64, "TestLoadUint64") - testutil.RunTest(TestLoadUint64Method, "TestLoadUint64Method") - testutil.RunTest(TestLoadUintptr, "TestLoadUintptr") - testutil.RunTest(TestLoadUintptrMethod, "TestLoadUintptrMethod") - testutil.RunTest(TestLoadPointer, "TestLoadPointer") - testutil.RunTest(TestLoadPointerMethod, "TestLoadPointerMethod") - testutil.RunTest(TestStoreInt32, "TestStoreInt32") - testutil.RunTest(TestStoreInt32Method, "TestStoreInt32Method") - testutil.RunTest(TestStoreUint32, "TestStoreUint32") - testutil.RunTest(TestStoreUint32Method, "TestStoreUint32Method") - testutil.RunTest(TestStoreInt64, "TestStoreInt64") - testutil.RunTest(TestStoreInt64Method, "TestStoreInt64Method") - testutil.RunTest(TestStoreUint64, "TestStoreUint64") - testutil.RunTest(TestStoreUint64Method, "TestStoreUint64Method") - testutil.RunTest(TestStoreUintptr, "TestStoreUintptr") - testutil.RunTest(TestStoreUintptrMethod, "TestStoreUintptrMethod") - testutil.RunTest(TestStorePointer, "TestStorePointer") - testutil.RunTest(TestStorePointerMethod, "TestStorePointerMethod") - testutil.RunTest(TestHammer32, "TestHammer32") - testutil.RunTest(TestHammer64, "TestHammer64") - testutil.RunTest(TestAutoAligned64, "TestAutoAligned64") - testutil.RunTest(TestNilDeref, "TestNilDeref") - testutil.RunTest(TestStoreLoadSeqCst32, "TestStoreLoadSeqCst32") - testutil.RunTest(TestStoreLoadSeqCst64, "TestStoreLoadSeqCst64") - testutil.RunTest(TestStoreLoadRelAcq32, "TestStoreLoadRelAcq32") - testutil.RunTest(TestStoreLoadRelAcq64, "TestStoreLoadRelAcq64") - testutil.RunTest(TestUnaligned64, "TestUnaligned64") - testutil.RunTest(TestHammerStoreLoad, "TestHammerStoreLoad") - - fmt.Println("Atomic tests passed") -} diff --git a/cannon/testdata/go-1-24/mt-cond/go.mod b/cannon/testdata/go-1-24/mt-cond/go.mod deleted file mode 100644 index 0af72c20f75..00000000000 --- a/cannon/testdata/go-1-24/mt-cond/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module cond - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/mt-cond/main.go b/cannon/testdata/go-1-24/mt-cond/main.go deleted file mode 100644 index 2b584cec999..00000000000 --- a/cannon/testdata/go-1-24/mt-cond/main.go +++ /dev/null @@ -1,302 +0,0 @@ -// Portions of this code are derived from code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/400433af3660905ecaceaf19ddad3e6c24b141df/src/sync/cond_test.go -// -// --- Original License Notice --- -// -// Copyright 2009 The Go Authors. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "fmt" - "os" - "reflect" - "runtime" - "sync" -) - -func main() { - TestCondSignal() - TestCondSignalGenerations() - TestCondBroadcast() - TestRace() - TestCondSignalStealing() - TestCondCopy() - - fmt.Println("Cond test passed") -} - -func TestCondSignal() { - var m sync.Mutex - c := sync.NewCond(&m) - n := 2 - running := make(chan bool, n) - awake := make(chan bool, n) - for i := 0; i < n; i++ { - go func() { - m.Lock() - running <- true - c.Wait() - awake <- true - m.Unlock() - }() - } - for i := 0; i < n; i++ { - <-running // Wait for everyone to run. - } - for n > 0 { - select { - case <-awake: - _, _ = fmt.Fprintln(os.Stderr, "goroutine not asleep") - os.Exit(1) - default: - } - m.Lock() - c.Signal() - m.Unlock() - <-awake // Will deadlock if no goroutine wakes up - select { - case <-awake: - _, _ = fmt.Fprintln(os.Stderr, "too many goroutines awake") - os.Exit(1) - default: - } - n-- - } - c.Signal() -} - -func TestCondSignalGenerations() { - var m sync.Mutex - c := sync.NewCond(&m) - n := 100 - running := make(chan bool, n) - awake := make(chan int, n) - for i := 0; i < n; i++ { - go func(i int) { - m.Lock() - running <- true - c.Wait() - awake <- i - m.Unlock() - }(i) - if i > 0 { - a := <-awake - if a != i-1 { - _, _ = fmt.Fprintf(os.Stderr, "wrong goroutine woke up: want %d, got %d\n", i-1, a) - os.Exit(1) - } - } - <-running - m.Lock() - c.Signal() - m.Unlock() - } -} - -func TestCondBroadcast() { - var m sync.Mutex - c := sync.NewCond(&m) - n := 5 - running := make(chan int, n) - awake := make(chan int, n) - exit := false - for i := 0; i < n; i++ { - go func(g int) { - m.Lock() - for !exit { - running <- g - c.Wait() - awake <- g - } - m.Unlock() - }(i) - } - for i := 0; i < n; i++ { - for i := 0; i < n; i++ { - <-running // Will deadlock unless n are running. - } - if i == n-1 { - m.Lock() - exit = true - m.Unlock() - } - select { - case <-awake: - _, _ = fmt.Fprintln(os.Stderr, "goroutine not asleep") - os.Exit(1) - default: - } - m.Lock() - c.Broadcast() - m.Unlock() - seen := make([]bool, n) - for i := 0; i < n; i++ { - g := <-awake - if seen[g] { - _, _ = fmt.Fprintln(os.Stderr, "goroutine woke up twice") - os.Exit(1) - } - seen[g] = true - } - } - select { - case <-running: - _, _ = fmt.Fprintln(os.Stderr, "goroutine still running") - os.Exit(1) - default: - } - c.Broadcast() -} - -func TestRace() { - x := 0 - c := sync.NewCond(&sync.Mutex{}) - done := make(chan bool) - go func() { - c.L.Lock() - x = 1 - c.Wait() - if x != 2 { - _, _ = fmt.Fprintln(os.Stderr, "want 2") - os.Exit(1) - } - x = 3 - c.Signal() - c.L.Unlock() - done <- true - }() - go func() { - c.L.Lock() - for { - if x == 1 { - x = 2 - c.Signal() - break - } - c.L.Unlock() - runtime.Gosched() - c.L.Lock() - } - c.L.Unlock() - done <- true - }() - go func() { - c.L.Lock() - for { - if x == 2 { - c.Wait() - if x != 3 { - _, _ = fmt.Fprintln(os.Stderr, "want 3") - os.Exit(1) - } - break - } - if x == 3 { - break - } - c.L.Unlock() - runtime.Gosched() - c.L.Lock() - } - c.L.Unlock() - done <- true - }() - <-done - <-done - <-done -} - -func TestCondSignalStealing() { - for iters := 0; iters < 5; iters++ { - var m sync.Mutex - cond := sync.NewCond(&m) - - // Start a waiter. - ch := make(chan struct{}) - go func() { - m.Lock() - ch <- struct{}{} - cond.Wait() - m.Unlock() - - ch <- struct{}{} - }() - - <-ch - m.Lock() - m.Unlock() - - // We know that the waiter is in the cond.Wait() call because we - // synchronized with it, then acquired/released the mutex it was - // holding when we synchronized. - // - // Start two goroutines that will race: one will broadcast on - // the cond var, the other will wait on it. - // - // The new waiter may or may not get notified, but the first one - // has to be notified. - done := false - go func() { - cond.Broadcast() - }() - - go func() { - m.Lock() - for !done { - cond.Wait() - } - m.Unlock() - }() - - // Check that the first waiter does get signaled. - <-ch - - // Release the second waiter in case it didn't get the - // broadcast. - m.Lock() - done = true - m.Unlock() - cond.Broadcast() - } -} - -func TestCondCopy() { - defer func() { - err := recover() - if err == nil || err.(string) != "sync.Cond is copied" { - _, _ = fmt.Fprintf(os.Stderr, "got %v, expect sync.Cond is copied", err) - os.Exit(1) - } - }() - c := sync.Cond{L: &sync.Mutex{}} - c.Signal() - var c2 sync.Cond - reflect.ValueOf(&c2).Elem().Set(reflect.ValueOf(&c).Elem()) // c2 := c, hidden from vet - c2.Signal() -} diff --git a/cannon/testdata/go-1-24/mt-general/go.mod b/cannon/testdata/go-1-24/mt-general/go.mod deleted file mode 100644 index 151eeeba852..00000000000 --- a/cannon/testdata/go-1-24/mt-general/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module mtgeneral - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/mt-general/main.go b/cannon/testdata/go-1-24/mt-general/main.go deleted file mode 100644 index bc871f56e52..00000000000 --- a/cannon/testdata/go-1-24/mt-general/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "fmt" - "os" - "runtime" - "sync" - "sync/atomic" -) - -func main() { - // try some concurrency! - var wg sync.WaitGroup - wg.Add(2) - var x atomic.Int32 - go func() { - x.Add(2) - wg.Done() - }() - go func() { - x.Add(40) - wg.Done() - }() - wg.Wait() - fmt.Printf("waitgroup result: %d\n", x.Load()) - - // channels - a := make(chan int, 1) - b := make(chan int) - c := make(chan int) - go func() { - t0 := <-a - b <- t0 - }() - go func() { - t1 := <-b - c <- t1 - }() - a <- 1234 - out := <-c - fmt.Printf("channels result: %d\n", out) - - // try a GC! (the runtime might not have run one yet) - runtime.GC() - _, _ = os.Stdout.Write([]byte("GC complete!\n")) -} diff --git a/cannon/testdata/go-1-24/mt-map/go.mod b/cannon/testdata/go-1-24/mt-map/go.mod deleted file mode 100644 index 37bd10adbd1..00000000000 --- a/cannon/testdata/go-1-24/mt-map/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module map - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/mt-map/main.go b/cannon/testdata/go-1-24/mt-map/main.go deleted file mode 100644 index 577a19a3ed8..00000000000 --- a/cannon/testdata/go-1-24/mt-map/main.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestMapMatchesRWMutex, "TestMapMatchesRWMutex") - testutil.RunTest(TestMapMatchesDeepCopy, "TestMapMatchesDeepCopy") - testutil.RunTest(TestConcurrentRange, "TestConcurrentRange") - testutil.RunTest(TestIssue40999, "TestIssue40999") - testutil.RunTest(TestMapRangeNestedCall, "TestMapRangeNestedCall") - testutil.RunTest(TestCompareAndSwap_NonExistingKey, "TestCompareAndSwap_NonExistingKey") - testutil.RunTest(TestMapRangeNoAllocations, "TestMapRangeNoAllocations") - - fmt.Println("Map test passed") -} diff --git a/cannon/testdata/go-1-24/mt-map/map_reference_test_copy.go b/cannon/testdata/go-1-24/mt-map/map_reference_test_copy.go deleted file mode 100644 index 3beeb1501c5..00000000000 --- a/cannon/testdata/go-1-24/mt-map/map_reference_test_copy.go +++ /dev/null @@ -1,299 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/map_reference_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "sync" - "sync/atomic" -) - -// This file contains reference map implementations for unit-tests. - -// mapInterface is the interface Map implements. -type mapInterface interface { - Load(any) (any, bool) - Store(key, value any) - LoadOrStore(key, value any) (actual any, loaded bool) - LoadAndDelete(key any) (value any, loaded bool) - Delete(any) - Swap(key, value any) (previous any, loaded bool) - CompareAndSwap(key, old, new any) (swapped bool) - CompareAndDelete(key, old any) (deleted bool) - Range(func(key, value any) (shouldContinue bool)) -} - -var ( - _ mapInterface = &RWMutexMap{} - _ mapInterface = &DeepCopyMap{} -) - -// RWMutexMap is an implementation of mapInterface using a sync.RWMutex. -type RWMutexMap struct { - mu sync.RWMutex - dirty map[any]any -} - -func (m *RWMutexMap) Load(key any) (value any, ok bool) { - m.mu.RLock() - value, ok = m.dirty[key] - m.mu.RUnlock() - return -} - -func (m *RWMutexMap) Store(key, value any) { - m.mu.Lock() - if m.dirty == nil { - m.dirty = make(map[any]any) - } - m.dirty[key] = value - m.mu.Unlock() -} - -func (m *RWMutexMap) LoadOrStore(key, value any) (actual any, loaded bool) { - m.mu.Lock() - actual, loaded = m.dirty[key] - if !loaded { - actual = value - if m.dirty == nil { - m.dirty = make(map[any]any) - } - m.dirty[key] = value - } - m.mu.Unlock() - return actual, loaded -} - -func (m *RWMutexMap) Swap(key, value any) (previous any, loaded bool) { - m.mu.Lock() - if m.dirty == nil { - m.dirty = make(map[any]any) - } - - previous, loaded = m.dirty[key] - m.dirty[key] = value - m.mu.Unlock() - return -} - -func (m *RWMutexMap) LoadAndDelete(key any) (value any, loaded bool) { - m.mu.Lock() - value, loaded = m.dirty[key] - if !loaded { - m.mu.Unlock() - return nil, false - } - delete(m.dirty, key) - m.mu.Unlock() - return value, loaded -} - -func (m *RWMutexMap) Delete(key any) { - m.mu.Lock() - delete(m.dirty, key) - m.mu.Unlock() -} - -func (m *RWMutexMap) CompareAndSwap(key, old, new any) (swapped bool) { - m.mu.Lock() - defer m.mu.Unlock() - if m.dirty == nil { - return false - } - - value, loaded := m.dirty[key] - if loaded && value == old { - m.dirty[key] = new - return true - } - return false -} - -func (m *RWMutexMap) CompareAndDelete(key, old any) (deleted bool) { - m.mu.Lock() - defer m.mu.Unlock() - if m.dirty == nil { - return false - } - - value, loaded := m.dirty[key] - if loaded && value == old { - delete(m.dirty, key) - return true - } - return false -} - -func (m *RWMutexMap) Range(f func(key, value any) (shouldContinue bool)) { - m.mu.RLock() - keys := make([]any, 0, len(m.dirty)) - for k := range m.dirty { - keys = append(keys, k) - } - m.mu.RUnlock() - - for _, k := range keys { - v, ok := m.Load(k) - if !ok { - continue - } - if !f(k, v) { - break - } - } -} - -// DeepCopyMap is an implementation of mapInterface using a Mutex and -// atomic.Value. It makes deep copies of the map on every write to avoid -// acquiring the Mutex in Load. -type DeepCopyMap struct { - mu sync.Mutex - clean atomic.Value -} - -func (m *DeepCopyMap) Load(key any) (value any, ok bool) { - clean, _ := m.clean.Load().(map[any]any) - value, ok = clean[key] - return value, ok -} - -func (m *DeepCopyMap) Store(key, value any) { - m.mu.Lock() - dirty := m.dirty() - dirty[key] = value - m.clean.Store(dirty) - m.mu.Unlock() -} - -func (m *DeepCopyMap) LoadOrStore(key, value any) (actual any, loaded bool) { - clean, _ := m.clean.Load().(map[any]any) - actual, loaded = clean[key] - if loaded { - return actual, loaded - } - - m.mu.Lock() - // Reload clean in case it changed while we were waiting on m.mu. - clean, _ = m.clean.Load().(map[any]any) - actual, loaded = clean[key] - if !loaded { - dirty := m.dirty() - dirty[key] = value - actual = value - m.clean.Store(dirty) - } - m.mu.Unlock() - return actual, loaded -} - -func (m *DeepCopyMap) Swap(key, value any) (previous any, loaded bool) { - m.mu.Lock() - dirty := m.dirty() - previous, loaded = dirty[key] - dirty[key] = value - m.clean.Store(dirty) - m.mu.Unlock() - return -} - -func (m *DeepCopyMap) LoadAndDelete(key any) (value any, loaded bool) { - m.mu.Lock() - dirty := m.dirty() - value, loaded = dirty[key] - delete(dirty, key) - m.clean.Store(dirty) - m.mu.Unlock() - return -} - -func (m *DeepCopyMap) Delete(key any) { - m.mu.Lock() - dirty := m.dirty() - delete(dirty, key) - m.clean.Store(dirty) - m.mu.Unlock() -} - -func (m *DeepCopyMap) CompareAndSwap(key, old, new any) (swapped bool) { - clean, _ := m.clean.Load().(map[any]any) - if previous, ok := clean[key]; !ok || previous != old { - return false - } - - m.mu.Lock() - defer m.mu.Unlock() - dirty := m.dirty() - value, loaded := dirty[key] - if loaded && value == old { - dirty[key] = new - m.clean.Store(dirty) - return true - } - return false -} - -func (m *DeepCopyMap) CompareAndDelete(key, old any) (deleted bool) { - clean, _ := m.clean.Load().(map[any]any) - if previous, ok := clean[key]; !ok || previous != old { - return false - } - - m.mu.Lock() - defer m.mu.Unlock() - - dirty := m.dirty() - value, loaded := dirty[key] - if loaded && value == old { - delete(dirty, key) - m.clean.Store(dirty) - return true - } - return false -} - -func (m *DeepCopyMap) Range(f func(key, value any) (shouldContinue bool)) { - clean, _ := m.clean.Load().(map[any]any) - for k, v := range clean { - if !f(k, v) { - break - } - } -} - -func (m *DeepCopyMap) dirty() map[any]any { - clean, _ := m.clean.Load().(map[any]any) - dirty := make(map[any]any, len(clean)+1) - for k, v := range clean { - dirty[k] = v - } - return dirty -} diff --git a/cannon/testdata/go-1-24/mt-map/map_test_copy.go b/cannon/testdata/go-1-24/mt-map/map_test_copy.go deleted file mode 100644 index 7b8806698f9..00000000000 --- a/cannon/testdata/go-1-24/mt-map/map_test_copy.go +++ /dev/null @@ -1,325 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/map_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "math/rand" - "reflect" - "runtime" - "sync" - "sync/atomic" - "testing" - "testing/quick" - - "utils/testutil" -) - -type mapOp string - -const ( - opLoad = mapOp("Load") - opStore = mapOp("Store") - opLoadOrStore = mapOp("LoadOrStore") - opLoadAndDelete = mapOp("LoadAndDelete") - opDelete = mapOp("Delete") - opSwap = mapOp("Swap") - opCompareAndSwap = mapOp("CompareAndSwap") - opCompareAndDelete = mapOp("CompareAndDelete") -) - -var mapOps = [...]mapOp{ - opLoad, - opStore, - opLoadOrStore, - opLoadAndDelete, - opDelete, - opSwap, - opCompareAndSwap, - opCompareAndDelete, -} - -// mapCall is a quick.Generator for calls on mapInterface. -type mapCall struct { - op mapOp - k, v any -} - -func (c mapCall) apply(m mapInterface) (any, bool) { - switch c.op { - case opLoad: - return m.Load(c.k) - case opStore: - m.Store(c.k, c.v) - return nil, false - case opLoadOrStore: - return m.LoadOrStore(c.k, c.v) - case opLoadAndDelete: - return m.LoadAndDelete(c.k) - case opDelete: - m.Delete(c.k) - return nil, false - case opSwap: - return m.Swap(c.k, c.v) - case opCompareAndSwap: - if m.CompareAndSwap(c.k, c.v, rand.Int()) { - m.Delete(c.k) - return c.v, true - } - return nil, false - case opCompareAndDelete: - if m.CompareAndDelete(c.k, c.v) { - if _, ok := m.Load(c.k); !ok { - return nil, true - } - } - return nil, false - default: - panic("invalid mapOp") - } -} - -type mapResult struct { - value any - ok bool -} - -func randValue(r *rand.Rand) any { - b := make([]byte, r.Intn(4)) - for i := range b { - b[i] = 'a' + byte(rand.Intn(26)) - } - return string(b) -} - -func (mapCall) Generate(r *rand.Rand, size int) reflect.Value { - c := mapCall{op: mapOps[rand.Intn(len(mapOps))], k: randValue(r)} - switch c.op { - case opStore, opLoadOrStore: - c.v = randValue(r) - } - return reflect.ValueOf(c) -} - -func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map[any]any) { - for _, c := range calls { - v, ok := c.apply(m) - results = append(results, mapResult{v, ok}) - } - - final = make(map[any]any) - m.Range(func(k, v any) bool { - final[k] = v - return true - }) - - return results, final -} - -func applyMap(calls []mapCall) ([]mapResult, map[any]any) { - return applyCalls(new(sync.Map), calls) -} - -func applyRWMutexMap(calls []mapCall) ([]mapResult, map[any]any) { - return applyCalls(new(RWMutexMap), calls) -} - -func applyDeepCopyMap(calls []mapCall) ([]mapResult, map[any]any) { - return applyCalls(new(DeepCopyMap), calls) -} - -func TestMapMatchesRWMutex(t *testutil.TestRunner) { - if err := quick.CheckEqual(applyMap, applyRWMutexMap, nil); err != nil { - t.Error(err) - } -} - -func TestMapMatchesDeepCopy(t *testutil.TestRunner) { - if err := quick.CheckEqual(applyMap, applyDeepCopyMap, nil); err != nil { - t.Error(err) - } -} - -func TestConcurrentRange(t *testutil.TestRunner) { - const mapSize = 1 << 10 - - m := new(sync.Map) - for n := int64(1); n <= mapSize; n++ { - m.Store(n, int64(n)) - } - - done := make(chan struct{}) - var wg sync.WaitGroup - defer func() { - close(done) - wg.Wait() - }() - for g := int64(runtime.GOMAXPROCS(0)); g > 0; g-- { - r := rand.New(rand.NewSource(g)) - wg.Add(1) - go func(g int64) { - defer wg.Done() - for i := int64(0); ; i++ { - select { - case <-done: - return - default: - } - for n := int64(1); n < mapSize; n++ { - if r.Int63n(mapSize) == 0 { - m.Store(n, n*i*g) - } else { - m.Load(n) - } - } - } - }(g) - } - - //iters := 1 << 10 - //if testing.Short() { - // iters = 16 - //} - iters := 16 - for n := iters; n > 0; n-- { - seen := make(map[int64]bool, mapSize) - - m.Range(func(ki, vi any) bool { - k, v := ki.(int64), vi.(int64) - if v%k != 0 { - t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) - } - if seen[k] { - t.Fatalf("Range visited key %v twice", k) - } - seen[k] = true - return true - }) - - if len(seen) != mapSize { - t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) - } - } -} - -func TestIssue40999(t *testutil.TestRunner) { - var m sync.Map - - // Since the miss-counting in missLocked (via Delete) - // compares the miss count with len(m.dirty), - // add an initial entry to bias len(m.dirty) above the miss count. - m.Store(nil, struct{}{}) - - var finalized uint32 - - // Set finalizers that count for collected keys. A non-zero count - // indicates that keys have not been leaked. - for atomic.LoadUint32(&finalized) == 0 { - p := new(int) - runtime.SetFinalizer(p, func(*int) { - atomic.AddUint32(&finalized, 1) - }) - m.Store(p, struct{}{}) - m.Delete(p) - runtime.GC() - } -} - -func TestMapRangeNestedCall(t *testutil.TestRunner) { // Issue 46399 - var m sync.Map - for i, v := range [3]string{"hello", "world", "Go"} { - m.Store(i, v) - } - m.Range(func(key, value any) bool { - m.Range(func(key, value any) bool { - // We should be able to load the key offered in the Range callback, - // because there are no concurrent Delete involved in this tested map. - if v, ok := m.Load(key); !ok || !reflect.DeepEqual(v, value) { - t.Fatalf("Nested Range loads unexpected value, got %+v want %+v", v, value) - } - - // We didn't keep 42 and a value into the map before, if somehow we loaded - // a value from such a key, meaning there must be an internal bug regarding - // nested range in the Map. - if _, loaded := m.LoadOrStore(42, "dummy"); loaded { - t.Fatalf("Nested Range loads unexpected value, want store a new value") - } - - // Try to Store then LoadAndDelete the corresponding value with the key - // 42 to the Map. In this case, the key 42 and associated value should be - // removed from the Map. Therefore any future range won't observe key 42 - // as we checked in above. - val := "sync.Map" - m.Store(42, val) - if v, loaded := m.LoadAndDelete(42); !loaded || !reflect.DeepEqual(v, val) { - t.Fatalf("Nested Range loads unexpected value, got %v, want %v", v, val) - } - return true - }) - - // Remove key from Map on-the-fly. - m.Delete(key) - return true - }) - - // After a Range of Delete, all keys should be removed and any - // further Range won't invoke the callback. Hence length remains 0. - length := 0 - m.Range(func(key, value any) bool { - length++ - return true - }) - - if length != 0 { - t.Fatalf("Unexpected sync.Map size, got %v want %v", length, 0) - } -} - -func TestCompareAndSwap_NonExistingKey(t *testutil.TestRunner) { - m := &sync.Map{} - if m.CompareAndSwap(m, nil, 42) { - // See https://go.dev/issue/51972#issuecomment-1126408637. - t.Fatalf("CompareAndSwap on a non-existing key succeeded") - } -} - -func TestMapRangeNoAllocations(t *testutil.TestRunner) { // Issue 62404 - var m sync.Map - allocs := testing.AllocsPerRun(10, func() { - m.Range(func(key, value any) bool { - return true - }) - }) - if allocs > 0 { - t.Errorf("AllocsPerRun of m.Range = %v; want 0", allocs) - } -} diff --git a/cannon/testdata/go-1-24/mt-mutex/go.mod b/cannon/testdata/go-1-24/mt-mutex/go.mod deleted file mode 100644 index d8ada86a86a..00000000000 --- a/cannon/testdata/go-1-24/mt-mutex/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module mutex - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/mt-mutex/main.go b/cannon/testdata/go-1-24/mt-mutex/main.go deleted file mode 100644 index 1a3b75c231b..00000000000 --- a/cannon/testdata/go-1-24/mt-mutex/main.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestSemaphore, "TestSemaphore") - testutil.RunTest(TestMutex, "TestMutex") - testutil.RunTest(TestMutexFairness, "TestMutexFairness") - - fmt.Println("Mutex test passed") -} diff --git a/cannon/testdata/go-1-24/mt-mutex/mutex_test_copy.go b/cannon/testdata/go-1-24/mt-mutex/mutex_test_copy.go deleted file mode 100644 index d3ed9343c3d..00000000000 --- a/cannon/testdata/go-1-24/mt-mutex/mutex_test_copy.go +++ /dev/null @@ -1,135 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/mutex_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "runtime" - . "sync" - "time" - - "utils/testutil" -) - -func HammerSemaphore(s *uint32, loops int, cdone chan bool) { - for i := 0; i < loops; i++ { - Runtime_Semacquire(s) - Runtime_Semrelease(s, false, 0) - } - cdone <- true -} - -func TestSemaphore(t *testutil.TestRunner) { - s := new(uint32) - *s = 1 - c := make(chan bool) - for i := 0; i < 10; i++ { - go HammerSemaphore(s, 1000, c) - } - for i := 0; i < 10; i++ { - <-c - } -} - -func HammerMutex(m *Mutex, loops int, cdone chan bool) { - for i := 0; i < loops; i++ { - if i%3 == 0 { - if m.TryLock() { - m.Unlock() - } - continue - } - m.Lock() - m.Unlock() - } - cdone <- true -} - -func TestMutex(t *testutil.TestRunner) { - if n := runtime.SetMutexProfileFraction(1); n != 0 { - t.Logf("got mutexrate %d expected 0", n) - } - defer runtime.SetMutexProfileFraction(0) - - m := new(Mutex) - - m.Lock() - if m.TryLock() { - t.Fatalf("TryLock succeeded with mutex locked") - } - m.Unlock() - if !m.TryLock() { - t.Fatalf("TryLock failed with mutex unlocked") - } - m.Unlock() - - c := make(chan bool) - for i := 0; i < 10; i++ { - go HammerMutex(m, 1000, c) - } - for i := 0; i < 10; i++ { - <-c - } -} - -func TestMutexFairness(t *testutil.TestRunner) { - var mu Mutex - stop := make(chan bool) - defer close(stop) - go func() { - for { - mu.Lock() - time.Sleep(100 * time.Microsecond) - mu.Unlock() - select { - case <-stop: - return - default: - } - } - }() - done := make(chan bool, 1) - go func() { - for i := 0; i < 10; i++ { - time.Sleep(100 * time.Microsecond) - mu.Lock() - mu.Unlock() - } - done <- true - }() - select { - case <-done: - case <-time.After(10 * time.Second): - t.Fatalf("can't acquire Mutex in 10 seconds") - } -} diff --git a/cannon/testdata/go-1-24/mt-mutex/runtime.go b/cannon/testdata/go-1-24/mt-mutex/runtime.go deleted file mode 100644 index 8d70cb10b35..00000000000 --- a/cannon/testdata/go-1-24/mt-mutex/runtime.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - _ "unsafe" // Required for go:linkname -) - -var Runtime_Semacquire = runtime_Semacquire -var Runtime_Semrelease = runtime_Semrelease - -//go:linkname runtime_Semacquire sync.runtime_Semacquire -func runtime_Semacquire(s *uint32) - -//go:linkname runtime_Semrelease sync.runtime_Semrelease -func runtime_Semrelease(s *uint32, handoff bool, skipframes int) diff --git a/cannon/testdata/go-1-24/mt-once/go.mod b/cannon/testdata/go-1-24/mt-once/go.mod deleted file mode 100644 index 4184340cb64..00000000000 --- a/cannon/testdata/go-1-24/mt-once/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module once - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/mt-once/main.go b/cannon/testdata/go-1-24/mt-once/main.go deleted file mode 100644 index 3be753e2f70..00000000000 --- a/cannon/testdata/go-1-24/mt-once/main.go +++ /dev/null @@ -1,98 +0,0 @@ -// Portions of this code are derived from code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/400433af3660905ecaceaf19ddad3e6c24b141df/src/sync/once_test.go -// -// --- Original License Notice --- -// -// Copyright 2009 The Go Authors. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "fmt" - "os" - "sync" -) - -func main() { - TestOnce() - TestOncePanic() - - fmt.Println("Once test passed") -} - -type one int - -func (o *one) Increment() { - *o++ -} - -func run(once *sync.Once, o *one, c chan bool) { - once.Do(func() { o.Increment() }) - if v := *o; v != 1 { - _, _ = fmt.Fprintf(os.Stderr, "once failed inside run: %d is not 1\n", v) - os.Exit(1) - } - c <- true -} - -func TestOnce() { - o := new(one) - once := new(sync.Once) - c := make(chan bool) - const N = 10 - for i := 0; i < N; i++ { - go run(once, o, c) - } - for i := 0; i < N; i++ { - <-c - } - if *o != 1 { - _, _ = fmt.Fprintf(os.Stderr, "once failed outside run: %d is not 1\n", *o) - os.Exit(1) - } -} - -func TestOncePanic() { - var once sync.Once - func() { - defer func() { - if r := recover(); r == nil { - _, _ = fmt.Fprintf(os.Stderr, "Once.Do did not panic") - os.Exit(1) - } - }() - once.Do(func() { - panic("failed") - }) - }() - - once.Do(func() { - _, _ = fmt.Fprintf(os.Stderr, "Once.Do called twice") - os.Exit(1) - }) -} diff --git a/cannon/testdata/go-1-24/mt-oncefunc/go.mod b/cannon/testdata/go-1-24/mt-oncefunc/go.mod deleted file mode 100644 index 55736afc7fe..00000000000 --- a/cannon/testdata/go-1-24/mt-oncefunc/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module oncefunc - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/mt-oncefunc/main.go b/cannon/testdata/go-1-24/mt-oncefunc/main.go deleted file mode 100644 index d5b0badc292..00000000000 --- a/cannon/testdata/go-1-24/mt-oncefunc/main.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestOnceFunc, "TestOnceFunc") - testutil.RunTest(TestOnceValue, "TestOnceValue") - testutil.RunTest(TestOnceValues, "TestOnceValues") - testutil.RunTest(TestOnceFuncPanic, "TestOnceFuncPanic") - testutil.RunTest(TestOnceValuePanic, "TestOnceValuePanic") - testutil.RunTest(TestOnceValuesPanic, "TestOnceValuesPanic") - testutil.RunTest(TestOnceFuncPanicNil, "TestOnceFuncPanicNil") - testutil.RunTest(TestOnceFuncGoexit, "TestOnceFuncGoexit") - testutil.RunTest(TestOnceFuncPanicTraceback, "TestOnceFuncPanicTraceback") - testutil.RunTest(TestOnceXGC, "TestOnceXGC") - - fmt.Println("OnceFunc tests passed") -} diff --git a/cannon/testdata/go-1-24/mt-oncefunc/oncefunc_test_copy.go b/cannon/testdata/go-1-24/mt-oncefunc/oncefunc_test_copy.go deleted file mode 100644 index fdbe93c260a..00000000000 --- a/cannon/testdata/go-1-24/mt-oncefunc/oncefunc_test_copy.go +++ /dev/null @@ -1,265 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/oncefunc_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "bytes" - "math" - "runtime" - "runtime/debug" - "sync" - "sync/atomic" - "testing" - _ "unsafe" - - "utils/testutil" -) - -// We assume that the Once.Do tests have already covered parallelism. - -func TestOnceFunc(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceFunc(func() { calls++ }) - allocs := testing.AllocsPerRun(10, f) - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } - if allocs != 0 { - t.Errorf("want 0 allocations per call, got %v", allocs) - } -} - -func TestOnceValue(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValue(func() int { - calls++ - return calls - }) - allocs := testing.AllocsPerRun(10, func() { f() }) - value := f() - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } - if value != 1 { - t.Errorf("want value==1, got %d", value) - } - if allocs != 0 { - t.Errorf("want 0 allocations per call, got %v", allocs) - } -} - -func TestOnceValues(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValues(func() (int, int) { - calls++ - return calls, calls + 1 - }) - allocs := testing.AllocsPerRun(10, func() { f() }) - v1, v2 := f() - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } - if v1 != 1 || v2 != 2 { - t.Errorf("want v1==1 and v2==2, got %d and %d", v1, v2) - } - if allocs != 0 { - t.Errorf("want 0 allocations per call, got %v", allocs) - } -} - -func testOncePanicX(t testing.TB, calls *int, f func()) { - testOncePanicWith(t, calls, f, func(label string, p any) { - if p != "x" { - t.Fatalf("%s: want panic %v, got %v", label, "x", p) - } - }) -} - -func testOncePanicWith(t testing.TB, calls *int, f func(), check func(label string, p any)) { - // Check that the each call to f panics with the same value, but the - // underlying function is only called once. - for _, label := range []string{"first time", "second time"} { - var p any - panicked := true - func() { - defer func() { - p = recover() - }() - f() - panicked = false - }() - if !panicked { - t.Fatalf("%s: f did not panic", label) - } - check(label, p) - } - if *calls != 1 { - t.Errorf("want calls==1, got %d", *calls) - } -} - -func TestOnceFuncPanic(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceFunc(func() { - calls++ - panic("x") - }) - testOncePanicX(t, &calls, f) -} - -func TestOnceValuePanic(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValue(func() int { - calls++ - panic("x") - }) - testOncePanicX(t, &calls, func() { f() }) -} - -func TestOnceValuesPanic(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValues(func() (int, int) { - calls++ - panic("x") - }) - testOncePanicX(t, &calls, func() { f() }) -} - -func TestOnceFuncPanicNil(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceFunc(func() { - calls++ - panic(nil) - }) - testOncePanicWith(t, &calls, f, func(label string, p any) { - switch p.(type) { - case nil, *runtime.PanicNilError: - return - } - t.Fatalf("%s: want nil panic, got %v", label, p) - }) -} - -func TestOnceFuncGoexit(t *testutil.TestRunner) { - // If f calls Goexit, the results are unspecified. But check that f doesn't - // get called twice. - calls := 0 - f := sync.OnceFunc(func() { - calls++ - runtime.Goexit() - }) - var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() - defer func() { recover() }() - f() - }() - wg.Wait() - } - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } -} - -func TestOnceFuncPanicTraceback(t *testutil.TestRunner) { - // Test that on the first invocation of a OnceFunc, the stack trace goes all - // the way to the origin of the panic. - f := sync.OnceFunc(onceFuncPanic) - - defer func() { - if p := recover(); p != "x" { - t.Fatalf("want panic %v, got %v", "x", p) - } - stack := debug.Stack() - //want := "sync_test.onceFuncPanic" - want := "main.onceFuncPanic" - if !bytes.Contains(stack, []byte(want)) { - t.Fatalf("want stack containing %v, got:\n%s", want, string(stack)) - } - }() - f() -} - -func onceFuncPanic() { - panic("x") -} - -func TestOnceXGC(t *testutil.TestRunner) { - fns := map[string]func([]byte) func(){ - "OnceFunc": func(buf []byte) func() { - return sync.OnceFunc(func() { buf[0] = 1 }) - }, - "OnceValue": func(buf []byte) func() { - f := sync.OnceValue(func() any { buf[0] = 1; return nil }) - return func() { f() } - }, - "OnceValues": func(buf []byte) func() { - f := sync.OnceValues(func() (any, any) { buf[0] = 1; return nil, nil }) - return func() { f() } - }, - } - for n, fn := range fns { - t.Run(n, func(t testing.TB) { - buf := make([]byte, 1024) - var gc atomic.Bool - runtime.SetFinalizer(&buf[0], func(_ *byte) { - gc.Store(true) - }) - f := fn(buf) - gcwaitfin() - if gc.Load() != false { - t.Fatal("wrapped function garbage collected too early") - } - f() - gcwaitfin() - if gc.Load() != true { - // Even if f is still alive, the function passed to Once(Func|Value|Values) - // is not kept alive after the first call to f. - t.Fatal("wrapped function should be garbage collected, but still live") - } - f() - }) - } -} - -// gcwaitfin performs garbage collection and waits for all finalizers to run. -func gcwaitfin() { - runtime.GC() - runtime_blockUntilEmptyFinalizerQueue(math.MaxInt64) -} - -//go:linkname runtime_blockUntilEmptyFinalizerQueue runtime.blockUntilEmptyFinalizerQueue -func runtime_blockUntilEmptyFinalizerQueue(int64) bool diff --git a/cannon/testdata/go-1-24/mt-pool/export_test_copy.go b/cannon/testdata/go-1-24/mt-pool/export_test_copy.go deleted file mode 100644 index 37b7c4a92bf..00000000000 --- a/cannon/testdata/go-1-24/mt-pool/export_test_copy.go +++ /dev/null @@ -1,86 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/export_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -// Export for testing. -// var Runtime_Semacquire = runtime_Semacquire -// var Runtime_Semrelease = runtime_Semrelease -var Runtime_procPin = runtime_procPin -var Runtime_procUnpin = runtime_procUnpin - -// poolDequeue testing. -type PoolDequeue interface { - PushHead(val any) bool - PopHead() (any, bool) - PopTail() (any, bool) -} - -func NewPoolDequeue(n int) PoolDequeue { - d := &poolDequeue{ - vals: make([]eface, n), - } - // For testing purposes, set the head and tail indexes close - // to wrapping around. - d.headTail.Store(d.pack(1< ./../../utils diff --git a/cannon/testdata/go-1-24/mt-pool/main.go b/cannon/testdata/go-1-24/mt-pool/main.go deleted file mode 100644 index 2c138b07cd9..00000000000 --- a/cannon/testdata/go-1-24/mt-pool/main.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestPool, "TestPool") - testutil.RunTest(TestPoolNew, "TestPoolNew") - testutil.RunTest(TestPoolGC, "TestPoolGC") - testutil.RunTest(TestPoolRelease, "TestPoolRelease") - testutil.RunTest(TestPoolStress, "TestPoolStress") - testutil.RunTest(TestPoolDequeue, "TestPoolDequeue") - testutil.RunTest(TestPoolChain, "TestPoolChain") - testutil.RunTest(TestNilPool, "TestNilPool") - - fmt.Println("Pool test passed") -} diff --git a/cannon/testdata/go-1-24/mt-pool/pool_test_copy.go b/cannon/testdata/go-1-24/mt-pool/pool_test_copy.go deleted file mode 100644 index 962cbfce7b5..00000000000 --- a/cannon/testdata/go-1-24/mt-pool/pool_test_copy.go +++ /dev/null @@ -1,298 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/pool_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "runtime" - "runtime/debug" - . "sync" - "sync/atomic" - "testing" - "time" - - "utils/testutil" -) - -var short bool = true - -func TestPool(t *testutil.TestRunner) { - // disable GC so we can control when it happens. - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - var p Pool - if p.Get() != nil { - t.Fatal("expected empty") - } - - // Make sure that the goroutine doesn't migrate to another P - // between Put and Get calls. - Runtime_procPin() - p.Put("a") - p.Put("b") - if g := p.Get(); g != "a" { - t.Fatalf("got %#v; want a", g) - } - if g := p.Get(); g != "b" { - t.Fatalf("got %#v; want b", g) - } - if g := p.Get(); g != nil { - t.Fatalf("got %#v; want nil", g) - } - Runtime_procUnpin() - - // Put in a large number of objects so they spill into - // stealable space. - for i := 0; i < 100; i++ { - p.Put("c") - } - // After one GC, the victim cache should keep them alive. - runtime.GC() - if g := p.Get(); g != "c" { - t.Fatalf("got %#v; want c after GC", g) - } - // A second GC should drop the victim cache. - runtime.GC() - if g := p.Get(); g != nil { - t.Fatalf("got %#v; want nil after second GC", g) - } -} - -func TestPoolNew(t *testutil.TestRunner) { - // disable GC so we can control when it happens. - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - - i := 0 - p := Pool{ - New: func() any { - i++ - return i - }, - } - if v := p.Get(); v != 1 { - t.Fatalf("got %v; want 1", v) - } - if v := p.Get(); v != 2 { - t.Fatalf("got %v; want 2", v) - } - - // Make sure that the goroutine doesn't migrate to another P - // between Put and Get calls. - Runtime_procPin() - p.Put(42) - if v := p.Get(); v != 42 { - t.Fatalf("got %v; want 42", v) - } - Runtime_procUnpin() - - if v := p.Get(); v != 3 { - t.Fatalf("got %v; want 3", v) - } -} - -// Test that Pool does not hold pointers to previously cached resources. -func TestPoolGC(t *testutil.TestRunner) { - testPool(t, true) -} - -// Test that Pool releases resources on GC. -func TestPoolRelease(t *testutil.TestRunner) { - testPool(t, false) -} - -func testPool(t testing.TB, drain bool) { - var p Pool - const N = 100 -loop: - for try := 0; try < 3; try++ { - if try == 1 && short { - break - } - var fin, fin1 uint32 - for i := 0; i < N; i++ { - v := new(string) - runtime.SetFinalizer(v, func(vv *string) { - atomic.AddUint32(&fin, 1) - }) - p.Put(v) - } - if drain { - for i := 0; i < N; i++ { - p.Get() - } - } - for i := 0; i < 5; i++ { - runtime.GC() - time.Sleep(time.Duration(i*100+10) * time.Millisecond) - // 1 pointer can remain on stack or elsewhere - if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 { - continue loop - } - } - t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try) - } -} - -func TestPoolStress(t *testutil.TestRunner) { - const P = 10 - N := int(1e6) - if short { - N /= 100 - } - var p Pool - done := make(chan bool) - for i := 0; i < P; i++ { - go func() { - var v any = 0 - for j := 0; j < N; j++ { - if v == nil { - v = 0 - } - p.Put(v) - v = p.Get() - if v != nil && v.(int) != 0 { - t.Errorf("expect 0, got %v", v) - break - } - } - done <- true - }() - } - for i := 0; i < P; i++ { - <-done - } -} - -func TestPoolDequeue(t *testutil.TestRunner) { - testPoolDequeue(t, NewPoolDequeue(16)) -} - -func TestPoolChain(t *testutil.TestRunner) { - testPoolDequeue(t, NewPoolChain()) -} - -func testPoolDequeue(t testing.TB, d PoolDequeue) { - const P = 10 - var N int = 2e6 - if short { - N = 1e3 - } - have := make([]int32, N) - var stop int32 - var wg WaitGroup - record := func(val int) { - atomic.AddInt32(&have[val], 1) - if val == N-1 { - atomic.StoreInt32(&stop, 1) - } - } - - // Start P-1 consumers. - for i := 1; i < P; i++ { - wg.Add(1) - go func() { - fail := 0 - for atomic.LoadInt32(&stop) == 0 { - val, ok := d.PopTail() - if ok { - fail = 0 - record(val.(int)) - } else { - // Speed up the test by - // allowing the pusher to run. - if fail++; fail%100 == 0 { - runtime.Gosched() - } - } - } - wg.Done() - }() - } - - // Start 1 producer. - nPopHead := 0 - wg.Add(1) - go func() { - for j := 0; j < N; j++ { - for !d.PushHead(j) { - // Allow a popper to run. - runtime.Gosched() - } - if j%10 == 0 { - val, ok := d.PopHead() - if ok { - nPopHead++ - record(val.(int)) - } - } - } - wg.Done() - }() - wg.Wait() - - // Check results. - for i, count := range have { - if count != 1 { - t.Errorf("expected have[%d] = 1, got %d", i, count) - } - } - // Check that at least some PopHeads succeeded. We skip this - // check in short mode because it's common enough that the - // queue will stay nearly empty all the time and a PopTail - // will happen during the window between every PushHead and - // PopHead. - if !short && nPopHead == 0 { - t.Errorf("popHead never succeeded") - } -} - -func TestNilPool(t *testutil.TestRunner) { - catch := func() { - if recover() == nil { - t.Error("expected panic") - } - } - - var p *Pool - t.Run("Get", func(t testing.TB) { - defer catch() - if p.Get() != nil { - t.Error("expected empty") - } - t.Error("should have panicked already") - }) - t.Run("Put", func(t testing.TB) { - defer catch() - p.Put("a") - t.Error("should have panicked already") - }) -} diff --git a/cannon/testdata/go-1-24/mt-pool/poolqueue_copy.go b/cannon/testdata/go-1-24/mt-pool/poolqueue_copy.go deleted file mode 100644 index 5aa7b1ffa7b..00000000000 --- a/cannon/testdata/go-1-24/mt-pool/poolqueue_copy.go +++ /dev/null @@ -1,338 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/poolqueue.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "sync/atomic" - "unsafe" -) - -// poolDequeue is a lock-free fixed-size single-producer, -// multi-consumer queue. The single producer can both push and pop -// from the head, and consumers can pop from the tail. -// -// It has the added feature that it nils out unused slots to avoid -// unnecessary retention of objects. This is important for sync.Pool, -// but not typically a property considered in the literature. -type poolDequeue struct { - // headTail packs together a 32-bit head index and a 32-bit - // tail index. Both are indexes into vals modulo len(vals)-1. - // - // tail = index of oldest data in queue - // head = index of next slot to fill - // - // Slots in the range [tail, head) are owned by consumers. - // A consumer continues to own a slot outside this range until - // it nils the slot, at which point ownership passes to the - // producer. - // - // The head index is stored in the most-significant bits so - // that we can atomically add to it and the overflow is - // harmless. - headTail atomic.Uint64 - - // vals is a ring buffer of interface{} values stored in this - // dequeue. The size of this must be a power of 2. - // - // vals[i].typ is nil if the slot is empty and non-nil - // otherwise. A slot is still in use until *both* the tail - // index has moved beyond it and typ has been set to nil. This - // is set to nil atomically by the consumer and read - // atomically by the producer. - vals []eface -} - -type eface struct { - typ, val unsafe.Pointer -} - -const dequeueBits = 32 - -// dequeueLimit is the maximum size of a poolDequeue. -// -// This must be at most (1<> dequeueBits) & mask) - tail = uint32(ptrs & mask) - return -} - -func (d *poolDequeue) pack(head, tail uint32) uint64 { - const mask = 1<= dequeueLimit { - // Can't make it any bigger. - newSize = dequeueLimit - } - - d2 := &poolChainElt{prev: d} - d2.vals = make([]eface, newSize) - c.head = d2 - storePoolChainElt(&d.next, d2) - d2.pushHead(val) -} - -func (c *poolChain) popHead() (any, bool) { - d := c.head - for d != nil { - if val, ok := d.popHead(); ok { - return val, ok - } - // There may still be unconsumed elements in the - // previous dequeue, so try backing up. - d = loadPoolChainElt(&d.prev) - } - return nil, false -} - -func (c *poolChain) popTail() (any, bool) { - d := loadPoolChainElt(&c.tail) - if d == nil { - return nil, false - } - - for { - // It's important that we load the next pointer - // *before* popping the tail. In general, d may be - // transiently empty, but if next is non-nil before - // the pop and the pop fails, then d is permanently - // empty, which is the only condition under which it's - // safe to drop d from the chain. - d2 := loadPoolChainElt(&d.next) - - if val, ok := d.popTail(); ok { - return val, ok - } - - if d2 == nil { - // This is the only dequeue. It's empty right - // now, but could be pushed to in the future. - return nil, false - } - - // The tail of the chain has been drained, so move on - // to the next dequeue. Try to drop it from the chain - // so the next pop doesn't have to look at the empty - // dequeue again. - if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.tail)), unsafe.Pointer(d), unsafe.Pointer(d2)) { - // We won the race. Clear the prev pointer so - // the garbage collector can collect the empty - // dequeue and so popHead doesn't back up - // further than necessary. - storePoolChainElt(&d2.prev, nil) - } - d = d2 - } -} diff --git a/cannon/testdata/go-1-24/mt-pool/runtime.go b/cannon/testdata/go-1-24/mt-pool/runtime.go deleted file mode 100644 index 1b6dbe3e6cd..00000000000 --- a/cannon/testdata/go-1-24/mt-pool/runtime.go +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import ( - _ "unsafe" // Required for go:linkname -) - -//go:linkname runtime_procPin runtime.procPin -func runtime_procPin() int - -//go:linkname runtime_procUnpin runtime.procUnpin -func runtime_procUnpin() diff --git a/cannon/testdata/go-1-24/mt-rwmutex/go.mod b/cannon/testdata/go-1-24/mt-rwmutex/go.mod deleted file mode 100644 index 08ac90dc13f..00000000000 --- a/cannon/testdata/go-1-24/mt-rwmutex/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module rwmutex - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/mt-rwmutex/main.go b/cannon/testdata/go-1-24/mt-rwmutex/main.go deleted file mode 100644 index 8553bba75ef..00000000000 --- a/cannon/testdata/go-1-24/mt-rwmutex/main.go +++ /dev/null @@ -1,226 +0,0 @@ -// Portions of this code are derived from code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/400433af3660905ecaceaf19ddad3e6c24b141df/src/sync/rwmutex_test.go -// -// --- Original License Notice --- -// -// Copyright 2009 The Go Authors. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "fmt" - "os" - "runtime" - "sync" - "sync/atomic" -) - -func main() { - TestParallelReaders() - TestRLocker() - TestRWMutex() - - fmt.Println("RWMutex test passed") -} - -func parallelReader(m *sync.RWMutex, clocked, cunlock, cdone chan bool) { - m.RLock() - clocked <- true - <-cunlock - m.RUnlock() - cdone <- true -} - -func doTestParallelReaders(numReaders, gomaxprocs int) { - runtime.GOMAXPROCS(gomaxprocs) - var m sync.RWMutex - clocked := make(chan bool) - cunlock := make(chan bool) - cdone := make(chan bool) - for i := 0; i < numReaders; i++ { - go parallelReader(&m, clocked, cunlock, cdone) - } - // Wait for all parallel RLock()s to succeed. - for i := 0; i < numReaders; i++ { - <-clocked - } - for i := 0; i < numReaders; i++ { - cunlock <- true - } - // Wait for the goroutines to finish. - for i := 0; i < numReaders; i++ { - <-cdone - } -} - -func TestParallelReaders() { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1)) - doTestParallelReaders(1, 4) - doTestParallelReaders(3, 4) - doTestParallelReaders(4, 2) -} - -func reader(rwm *sync.RWMutex, num_iterations int, activity *int32, cdone chan bool) { - for i := 0; i < num_iterations; i++ { - rwm.RLock() - n := atomic.AddInt32(activity, 1) - if n < 1 || n >= 10000 { - rwm.RUnlock() - panic(fmt.Sprintf("wlock(%d)\n", n)) - } - for i := 0; i < 100; i++ { - } - atomic.AddInt32(activity, -1) - rwm.RUnlock() - } - cdone <- true -} - -func writer(rwm *sync.RWMutex, num_iterations int, activity *int32, cdone chan bool) { - for i := 0; i < num_iterations; i++ { - rwm.Lock() - n := atomic.AddInt32(activity, 10000) - if n != 10000 { - rwm.Unlock() - panic(fmt.Sprintf("wlock(%d)\n", n)) - } - for i := 0; i < 100; i++ { - } - atomic.AddInt32(activity, -10000) - rwm.Unlock() - } - cdone <- true -} - -func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) { - runtime.GOMAXPROCS(gomaxprocs) - // Number of active readers + 10000 * number of active writers. - var activity int32 - var rwm sync.RWMutex - cdone := make(chan bool) - go writer(&rwm, num_iterations, &activity, cdone) - var i int - for i = 0; i < numReaders/2; i++ { - go reader(&rwm, num_iterations, &activity, cdone) - } - go writer(&rwm, num_iterations, &activity, cdone) - for ; i < numReaders; i++ { - go reader(&rwm, num_iterations, &activity, cdone) - } - // Wait for the 2 writers and all readers to finish. - for i := 0; i < 2+numReaders; i++ { - <-cdone - } -} - -func TestRWMutex() { - var m sync.RWMutex - - m.Lock() - if m.TryLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryLock succeeded with mutex locked") - os.Exit(1) - } - if m.TryRLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryRLock succeeded with mutex locked") - os.Exit(1) - } - m.Unlock() - - if !m.TryLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryLock failed with mutex unlocked") - os.Exit(1) - } - m.Unlock() - - if !m.TryRLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryRLock failed with mutex unlocked") - os.Exit(1) - } - if !m.TryRLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryRLock failed with mutex unlocked") - os.Exit(1) - } - if m.TryLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryLock succeeded with mutex rlocked") - os.Exit(1) - } - m.RUnlock() - m.RUnlock() - - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1)) - n := 5 - - HammerRWMutex(1, 1, n) - HammerRWMutex(1, 3, n) - HammerRWMutex(1, 10, n) - HammerRWMutex(4, 1, n) - HammerRWMutex(4, 3, n) - HammerRWMutex(4, 10, n) - HammerRWMutex(10, 1, n) - HammerRWMutex(10, 3, n) - HammerRWMutex(10, 10, n) - HammerRWMutex(10, 5, n) -} - -func TestRLocker() { - var wl sync.RWMutex - var rl sync.Locker - wlocked := make(chan bool, 1) - rlocked := make(chan bool, 1) - rl = wl.RLocker() - n := 10 - go func() { - for i := 0; i < n; i++ { - rl.Lock() - rl.Lock() - rlocked <- true - wl.Lock() - wlocked <- true - } - }() - for i := 0; i < n; i++ { - <-rlocked - rl.Unlock() - select { - case <-wlocked: - _, _ = fmt.Fprintln(os.Stderr, "RLocker() didn't read-lock it") - os.Exit(1) - default: - } - rl.Unlock() - <-wlocked - select { - case <-rlocked: - _, _ = fmt.Fprintln(os.Stderr, "RLocker() didn't respect the write lock") - os.Exit(1) - default: - } - wl.Unlock() - } -} diff --git a/cannon/testdata/go-1-24/mt-value/go.mod b/cannon/testdata/go-1-24/mt-value/go.mod deleted file mode 100644 index feeaa37da32..00000000000 --- a/cannon/testdata/go-1-24/mt-value/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module mtvalue - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/mt-value/main.go b/cannon/testdata/go-1-24/mt-value/main.go deleted file mode 100644 index 51fd1b2b730..00000000000 --- a/cannon/testdata/go-1-24/mt-value/main.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestValue, "TestValue") - testutil.RunTest(TestValueLarge, "TestValueLarge") - testutil.RunTest(TestValuePanic, "TestValuePanic") - testutil.RunTest(TestValueConcurrent, "TestValueConcurrent") - testutil.RunTest(TestValue_Swap, "TestValue_Swap") - testutil.RunTest(TestValueSwapConcurrent, "TestValueSwapConcurrent") - testutil.RunTest(TestValue_CompareAndSwap, "TestValue_CompareAndSwap") - testutil.RunTest(TestValueCompareAndSwapConcurrent, "TestValueCompareAndSwapConcurrent") - - fmt.Println("Value tests passed") -} diff --git a/cannon/testdata/go-1-24/mt-value/value_test_copy.go b/cannon/testdata/go-1-24/mt-value/value_test_copy.go deleted file mode 100644 index 32ccc006740..00000000000 --- a/cannon/testdata/go-1-24/mt-value/value_test_copy.go +++ /dev/null @@ -1,312 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/atomic/value_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "math/rand" - "runtime" - "strconv" - "sync" - "sync/atomic" - . "sync/atomic" - "testing" - - "utils/testutil" -) - -var short bool = true - -func TestValue(t *testutil.TestRunner) { - var v Value - if v.Load() != nil { - t.Fatal("initial Value is not nil") - } - v.Store(42) - x := v.Load() - if xx, ok := x.(int); !ok || xx != 42 { - t.Fatalf("wrong value: got %+v, want 42", x) - } - v.Store(84) - x = v.Load() - if xx, ok := x.(int); !ok || xx != 84 { - t.Fatalf("wrong value: got %+v, want 84", x) - } -} - -func TestValueLarge(t *testutil.TestRunner) { - var v Value - v.Store("foo") - x := v.Load() - if xx, ok := x.(string); !ok || xx != "foo" { - t.Fatalf("wrong value: got %+v, want foo", x) - } - v.Store("barbaz") - x = v.Load() - if xx, ok := x.(string); !ok || xx != "barbaz" { - t.Fatalf("wrong value: got %+v, want barbaz", x) - } -} - -func TestValuePanic(t *testutil.TestRunner) { - const nilErr = "sync/atomic: store of nil value into Value" - const badErr = "sync/atomic: store of inconsistently typed value into Value" - var v Value - func() { - defer func() { - err := recover() - if err != nilErr { - t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr) - } - }() - v.Store(nil) - }() - v.Store(42) - func() { - defer func() { - err := recover() - if err != badErr { - t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, badErr) - } - }() - v.Store("foo") - }() - func() { - defer func() { - err := recover() - if err != nilErr { - t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr) - } - }() - v.Store(nil) - }() -} - -func TestValueConcurrent(t *testutil.TestRunner) { - tests := [][]any{ - {uint16(0), ^uint16(0), uint16(1 + 2<<8), uint16(3 + 4<<8)}, - {uint32(0), ^uint32(0), uint32(1 + 2<<16), uint32(3 + 4<<16)}, - {uint64(0), ^uint64(0), uint64(1 + 2<<32), uint64(3 + 4<<32)}, - {complex(0, 0), complex(1, 2), complex(3, 4), complex(5, 6)}, - } - p := 4 * runtime.GOMAXPROCS(0) - N := int(1e5) - if short { - p /= 2 - //N = 1e3 - N = 1e2 - } - for _, test := range tests { - var v Value - done := make(chan bool, p) - for i := 0; i < p; i++ { - go func() { - r := rand.New(rand.NewSource(rand.Int63())) - expected := true - loop: - for j := 0; j < N; j++ { - x := test[r.Intn(len(test))] - v.Store(x) - x = v.Load() - for _, x1 := range test { - if x == x1 { - continue loop - } - } - t.Logf("loaded unexpected value %+v, want %+v", x, test) - expected = false - break - } - done <- expected - }() - } - for i := 0; i < p; i++ { - if !<-done { - t.FailNow() - } - } - } -} - -func BenchmarkValueRead(b *testing.B) { - var v Value - v.Store(new(int)) - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - x := v.Load().(*int) - if *x != 0 { - b.Fatalf("wrong value: got %v, want 0", *x) - } - } - }) -} - -var Value_SwapTests = []struct { - init any - new any - want any - err any -}{ - {init: nil, new: nil, err: "sync/atomic: swap of nil value into Value"}, - {init: nil, new: true, want: nil, err: nil}, - {init: true, new: "", err: "sync/atomic: swap of inconsistently typed value into Value"}, - {init: true, new: false, want: true, err: nil}, -} - -func TestValue_Swap(t *testutil.TestRunner) { - for i, tt := range Value_SwapTests { - t.Run(strconv.Itoa(i), func(t testing.TB) { - var v Value - if tt.init != nil { - v.Store(tt.init) - } - defer func() { - err := recover() - switch { - case tt.err == nil && err != nil: - t.Errorf("should not panic, got %v", err) - case tt.err != nil && err == nil: - t.Errorf("should panic %v, got ", tt.err) - } - }() - if got := v.Swap(tt.new); got != tt.want { - t.Errorf("got %v, want %v", got, tt.want) - } - if got := v.Load(); got != tt.new { - t.Errorf("got %v, want %v", got, tt.new) - } - }) - } -} - -func TestValueSwapConcurrent(t *testutil.TestRunner) { - var v Value - var count uint64 - var g sync.WaitGroup - var m, n uint64 = 10000, 10000 - if short { - //m = 1000 - //n = 1000 - m = 10 - n = 10 - } - for i := uint64(0); i < m*n; i += n { - i := i - g.Add(1) - go func() { - var c uint64 - for new := i; new < i+n; new++ { - if old := v.Swap(new); old != nil { - c += old.(uint64) - } - } - atomic.AddUint64(&count, c) - g.Done() - }() - } - g.Wait() - if want, got := (m*n-1)*(m*n)/2, count+v.Load().(uint64); got != want { - t.Errorf("sum from 0 to %d was %d, want %v", m*n-1, got, want) - } -} - -var heapA, heapB = struct{ uint }{0}, struct{ uint }{0} - -var Value_CompareAndSwapTests = []struct { - init any - new any - old any - want bool - err any -}{ - {init: nil, new: nil, old: nil, err: "sync/atomic: compare and swap of nil value into Value"}, - {init: nil, new: true, old: "", err: "sync/atomic: compare and swap of inconsistently typed values into Value"}, - {init: nil, new: true, old: true, want: false, err: nil}, - {init: nil, new: true, old: nil, want: true, err: nil}, - {init: true, new: "", err: "sync/atomic: compare and swap of inconsistently typed value into Value"}, - {init: true, new: true, old: false, want: false, err: nil}, - {init: true, new: true, old: true, want: true, err: nil}, - {init: heapA, new: struct{ uint }{1}, old: heapB, want: true, err: nil}, -} - -func TestValue_CompareAndSwap(t *testutil.TestRunner) { - for i, tt := range Value_CompareAndSwapTests { - t.Run(strconv.Itoa(i), func(t testing.TB) { - var v Value - if tt.init != nil { - v.Store(tt.init) - } - defer func() { - err := recover() - switch { - case tt.err == nil && err != nil: - t.Errorf("got %v, wanted no panic", err) - case tt.err != nil && err == nil: - t.Errorf("did not panic, want %v", tt.err) - } - }() - if got := v.CompareAndSwap(tt.old, tt.new); got != tt.want { - t.Errorf("got %v, want %v", got, tt.want) - } - }) - } -} - -func TestValueCompareAndSwapConcurrent(t *testutil.TestRunner) { - var v Value - var w sync.WaitGroup - v.Store(0) - m, n := 1000, 100 - if short { - //m = 100 - //n = 100 - m = 10 - n = 10 - } - for i := 0; i < m; i++ { - i := i - w.Add(1) - go func() { - for j := i; j < m*n; runtime.Gosched() { - if v.CompareAndSwap(j, j+1) { - j += m - } - } - w.Done() - }() - } - w.Wait() - if stop := v.Load().(int); stop != m*n { - t.Errorf("did not get to %v, stopped at %v", m*n, stop) - } -} diff --git a/cannon/testdata/go-1-24/mt-wg/go.mod b/cannon/testdata/go-1-24/mt-wg/go.mod deleted file mode 100644 index 6c98e10029f..00000000000 --- a/cannon/testdata/go-1-24/mt-wg/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module wg - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/mt-wg/main.go b/cannon/testdata/go-1-24/mt-wg/main.go deleted file mode 100644 index cfdb3e56b8e..00000000000 --- a/cannon/testdata/go-1-24/mt-wg/main.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestWaitGroup, "TestWaitGroup") - testutil.RunTest(TestWaitGroupMisuse, "TestWaitGroupMisuse") - testutil.RunTest(TestWaitGroupRace, "TestWaitGroupRace") - testutil.RunTest(TestWaitGroupAlign, "TestWaitGroupAlign") - - fmt.Println("WaitGroup tests passed") -} diff --git a/cannon/testdata/go-1-24/mt-wg/waitgroup_test_copy.go b/cannon/testdata/go-1-24/mt-wg/waitgroup_test_copy.go deleted file mode 100644 index 81f0cd0ce4c..00000000000 --- a/cannon/testdata/go-1-24/mt-wg/waitgroup_test_copy.go +++ /dev/null @@ -1,130 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/waitgroup_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - . "sync" - "sync/atomic" - "testing" - - "utils/testutil" -) - -func testWaitGroup(t testing.TB, wg1 *WaitGroup, wg2 *WaitGroup) { - n := 16 - wg1.Add(n) - wg2.Add(n) - exited := make(chan bool, n) - for i := 0; i != n; i++ { - go func() { - wg1.Done() - wg2.Wait() - exited <- true - }() - } - wg1.Wait() - for i := 0; i != n; i++ { - select { - case <-exited: - t.Fatal("WaitGroup released group too soon") - default: - } - wg2.Done() - } - for i := 0; i != n; i++ { - <-exited // Will block if barrier fails to unlock someone. - } -} - -func TestWaitGroup(t *testutil.TestRunner) { - wg1 := &WaitGroup{} - wg2 := &WaitGroup{} - - // Run the same test a few times to ensure barrier is in a proper state. - for i := 0; i != 8; i++ { - testWaitGroup(t, wg1, wg2) - } -} - -func TestWaitGroupMisuse(t *testutil.TestRunner) { - defer func() { - err := recover() - if err != "sync: negative WaitGroup counter" { - t.Fatalf("Unexpected panic: %#v", err) - } - }() - wg := &WaitGroup{} - wg.Add(1) - wg.Done() - wg.Done() - t.Fatal("Should panic") -} - -func TestWaitGroupRace(t *testutil.TestRunner) { - // Run this test for about 1ms. - for i := 0; i < 1000; i++ { - wg := &WaitGroup{} - n := new(int32) - // spawn goroutine 1 - wg.Add(1) - go func() { - atomic.AddInt32(n, 1) - wg.Done() - }() - // spawn goroutine 2 - wg.Add(1) - go func() { - atomic.AddInt32(n, 1) - wg.Done() - }() - // Wait for goroutine 1 and 2 - wg.Wait() - if atomic.LoadInt32(n) != 2 { - t.Fatal("Spurious wakeup from Wait") - } - } -} - -func TestWaitGroupAlign(t *testutil.TestRunner) { - type X struct { - x byte - wg WaitGroup - } - var x X - x.wg.Add(1) - go func(x *X) { - x.wg.Done() - }(&x) - x.wg.Wait() -} diff --git a/cannon/testdata/go-1-24/random/go.mod b/cannon/testdata/go-1-24/random/go.mod deleted file mode 100644 index de85e6441d3..00000000000 --- a/cannon/testdata/go-1-24/random/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module hello - -go 1.24 - -toolchain go1.24.2 diff --git a/cannon/testdata/go-1-24/random/main.go b/cannon/testdata/go-1-24/random/main.go deleted file mode 100644 index fbebefd8f54..00000000000 --- a/cannon/testdata/go-1-24/random/main.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - crand "crypto/rand" - "encoding/binary" - "encoding/hex" - "fmt" -) - -func main() { - // Read a uint64 - var buf = make([]byte, 8) - readRandomBytes(buf) - randomInt := binary.BigEndian.Uint64(buf) - fmt.Printf("Random int: %d\n", randomInt) - - // Read a large chunk of bytes all at once - buf = make([]byte, 25) - readRandomBytes(buf) - printRandomBuffer(buf) - - // Read a small number of bytes 1 at a time - buf = make([]byte, 5) - for i := 0; i < len(buf); i++ { - readRandomBytes(buf[i : i+1]) - } - printRandomBuffer(buf) -} - -func printRandomBuffer(buf []byte) { - hexValue := hex.EncodeToString(buf) - fmt.Printf("Random hex data: %v\n", hexValue) -} - -func readRandomBytes(buf []byte) { - n, err := crand.Read(buf) - if err != nil { - fmt.Printf("Error reading bytes: %v\n", err) - panic(err) - } - if n != len(buf) { - fmt.Printf("Read %d bytes, expected %d\n", n, len(buf)) - panic("Read wrong number of bytes") - } -} diff --git a/cannon/testdata/go-1-24/syscall-eventfd/go.mod b/cannon/testdata/go-1-24/syscall-eventfd/go.mod deleted file mode 100644 index 07d3ff2df59..00000000000 --- a/cannon/testdata/go-1-24/syscall-eventfd/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module syscalleventfd - -go 1.24 - -toolchain go1.24.2 - -require common v0.0.0 - -replace common => ./../../common diff --git a/cannon/testdata/go-1-24/syscall-eventfd/main.go b/cannon/testdata/go-1-24/syscall-eventfd/main.go deleted file mode 100644 index 07efb609324..00000000000 --- a/cannon/testdata/go-1-24/syscall-eventfd/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "common/syscalltests" -) - -func main() { - syscalltests.EventfdTest() -} diff --git a/cannon/testdata/go-1-24/utilscheck/go.mod b/cannon/testdata/go-1-24/utilscheck/go.mod deleted file mode 100644 index 0bd9df703ec..00000000000 --- a/cannon/testdata/go-1-24/utilscheck/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/utilscheck/main.go b/cannon/testdata/go-1-24/utilscheck/main.go deleted file mode 100644 index ad66a3211ad..00000000000 --- a/cannon/testdata/go-1-24/utilscheck/main.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - t.Fail() -} diff --git a/cannon/testdata/go-1-24/utilscheck2/go.mod b/cannon/testdata/go-1-24/utilscheck2/go.mod deleted file mode 100644 index 84567c65be7..00000000000 --- a/cannon/testdata/go-1-24/utilscheck2/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck2 - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/utilscheck2/main.go b/cannon/testdata/go-1-24/utilscheck2/main.go deleted file mode 100644 index 6fc619f18fe..00000000000 --- a/cannon/testdata/go-1-24/utilscheck2/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "fmt" - "testing" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - t.Run("subtest 1", func(t testing.TB) { - // Do something - }) - - t.Run("subtest 2", func(t testing.TB) { - t.Fail() - }) -} diff --git a/cannon/testdata/go-1-24/utilscheck3/go.mod b/cannon/testdata/go-1-24/utilscheck3/go.mod deleted file mode 100644 index c864546f25f..00000000000 --- a/cannon/testdata/go-1-24/utilscheck3/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck3 - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/utilscheck3/main.go b/cannon/testdata/go-1-24/utilscheck3/main.go deleted file mode 100644 index 248c891808b..00000000000 --- a/cannon/testdata/go-1-24/utilscheck3/main.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "fmt" - "testing" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - t.Run("panic test", func(t testing.TB) { - panic("oops") - }) -} diff --git a/cannon/testdata/go-1-24/utilscheck4/go.mod b/cannon/testdata/go-1-24/utilscheck4/go.mod deleted file mode 100644 index 560ee4b5a4d..00000000000 --- a/cannon/testdata/go-1-24/utilscheck4/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck4 - -go 1.24 - -toolchain go1.24.2 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-24/utilscheck4/main.go b/cannon/testdata/go-1-24/utilscheck4/main.go deleted file mode 100644 index deb78e2cb4d..00000000000 --- a/cannon/testdata/go-1-24/utilscheck4/main.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - panic("oops") -} diff --git a/cannon/testdata/go-1-25/Makefile b/cannon/testdata/go-1-25/Makefile deleted file mode 100644 index cd4c47589bd..00000000000 --- a/cannon/testdata/go-1-25/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -DEPRECATED_TARGETS := elf elf64 dump clean - -include ../../../justfiles/deprecated.mk diff --git a/cannon/testdata/go-1-25/alloc/go.mod b/cannon/testdata/go-1-25/alloc/go.mod deleted file mode 100644 index 09629e4682c..00000000000 --- a/cannon/testdata/go-1-25/alloc/go.mod +++ /dev/null @@ -1,14 +0,0 @@ -module alloc - -go 1.25 - -toolchain go1.25.4 - -require github.com/ethereum-optimism/optimism v0.0.0 - -require ( - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/sys v0.40.0 // indirect -) - -replace github.com/ethereum-optimism/optimism v0.0.0 => ./../../../.. diff --git a/cannon/testdata/go-1-25/alloc/go.sum b/cannon/testdata/go-1-25/alloc/go.sum deleted file mode 100644 index 2287271d512..00000000000 --- a/cannon/testdata/go-1-25/alloc/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cannon/testdata/go-1-25/alloc/main.go b/cannon/testdata/go-1-25/alloc/main.go deleted file mode 100644 index f4a776a0f79..00000000000 --- a/cannon/testdata/go-1-25/alloc/main.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "encoding/binary" - "fmt" - "runtime" - - preimage "github.com/ethereum-optimism/optimism/op-preimage" -) - -func main() { - var mem []byte - po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) - numAllocs := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(0))) - allocSize := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(1))) - - fmt.Printf("alloc program. numAllocs=%d allocSize=%d\n", numAllocs, allocSize) - var alloc int - for i := 0; i < int(numAllocs); i++ { - mem = make([]byte, allocSize) - alloc += len(mem) - // touch a couple pages to prevent the runtime from overcommitting memory - for j := 0; j < len(mem); j += 1024 { - mem[j] = 0xFF - } - printGCStats(alloc) - } - - fmt.Println("alloc program exit") - printGCStats(alloc) -} - -func printGCStats(alloc int) { - var m runtime.MemStats - runtime.ReadMemStats(&m) - fmt.Printf("allocated %d bytes. memstats: heap_alloc=%d next_gc=%d frees=%d mallocs=%d num_gc=%d\n", - alloc, m.HeapAlloc, m.NextGC, m.Frees, m.Mallocs, m.NumGC) -} diff --git a/cannon/testdata/go-1-25/claim/go.mod b/cannon/testdata/go-1-25/claim/go.mod deleted file mode 100644 index 5e3405d7a68..00000000000 --- a/cannon/testdata/go-1-25/claim/go.mod +++ /dev/null @@ -1,14 +0,0 @@ -module claim - -go 1.25 - -toolchain go1.25.4 - -require github.com/ethereum-optimism/optimism v0.0.0 - -require ( - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/sys v0.40.0 // indirect -) - -replace github.com/ethereum-optimism/optimism v0.0.0 => ./../../../.. diff --git a/cannon/testdata/go-1-25/claim/go.sum b/cannon/testdata/go-1-25/claim/go.sum deleted file mode 100644 index 2287271d512..00000000000 --- a/cannon/testdata/go-1-25/claim/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cannon/testdata/go-1-25/claim/main.go b/cannon/testdata/go-1-25/claim/main.go deleted file mode 100644 index 853a6f2be95..00000000000 --- a/cannon/testdata/go-1-25/claim/main.go +++ /dev/null @@ -1,55 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "encoding/binary" - "fmt" - "os" - - preimage "github.com/ethereum-optimism/optimism/op-preimage" -) - -type rawHint string - -func (rh rawHint) Hint() string { - return string(rh) -} - -func main() { - _, _ = os.Stderr.Write([]byte("started!")) - - po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) - hinter := preimage.NewHintWriter(preimage.ClientHinterChannel()) - - preHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(0))) - diffHash := *(*[32]byte)(po.Get(preimage.LocalIndexKey(1))) - claimData := *(*[8]byte)(po.Get(preimage.LocalIndexKey(2))) - - // Hints are used to indicate which things the program will access, - // so the server can be prepared to serve the corresponding pre-images. - hinter.Hint(rawHint(fmt.Sprintf("fetch-state %x", preHash))) - pre := po.Get(preimage.Keccak256Key(preHash)) - - // Multiple pre-images may be fetched based on a hint. - // E.g. when we need all values of a merkle-tree. - hinter.Hint(rawHint(fmt.Sprintf("fetch-diff %x", diffHash))) - diff := po.Get(preimage.Keccak256Key(diffHash)) - diffPartA := po.Get(preimage.Keccak256Key(*(*[32]byte)(diff[:32]))) - diffPartB := po.Get(preimage.Keccak256Key(*(*[32]byte)(diff[32:]))) - - // Example state-transition function: s' = s*a + b - s := binary.BigEndian.Uint64(pre) - a := binary.BigEndian.Uint64(diffPartA) - b := binary.BigEndian.Uint64(diffPartB) - fmt.Printf("computing %d * %d + %d\n", s, a, b) - sOut := s*a + b - - sClaim := binary.BigEndian.Uint64(claimData[:]) - if sOut != sClaim { - fmt.Printf("claim %d is bad! Correct result is %d\n", sOut, sClaim) - os.Exit(1) - } else { - fmt.Printf("claim %d is good!\n", sOut) - os.Exit(0) - } -} diff --git a/cannon/testdata/go-1-25/entry/go.mod b/cannon/testdata/go-1-25/entry/go.mod deleted file mode 100644 index 978f411adf7..00000000000 --- a/cannon/testdata/go-1-25/entry/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module entry - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/entry/main.go b/cannon/testdata/go-1-25/entry/main.go deleted file mode 100644 index 7aeb4f88e01..00000000000 --- a/cannon/testdata/go-1-25/entry/main.go +++ /dev/null @@ -1,31 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "os" - "runtime" -) - -func main() { - if len(os.Args) != 1 { - panic("expected 1 arg") - } - if os.Args[0] != "op-program" { - panic("unexpected arg0") - } - - var memProfileRate bool - env := os.Environ() - for _, env := range env { - if env != "GODEBUG=memprofilerate=0" { - panic("invalid envar") - } - memProfileRate = true - } - if !memProfileRate { - panic("memProfileRate env is not set") - } - if runtime.MemProfileRate != 0 { - panic("runtime.MemProfileRate is non-zero") - } -} diff --git a/cannon/testdata/go-1-25/hello/go.mod b/cannon/testdata/go-1-25/hello/go.mod deleted file mode 100644 index a5d20f5aa9d..00000000000 --- a/cannon/testdata/go-1-25/hello/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module hello - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/hello/main.go b/cannon/testdata/go-1-25/hello/main.go deleted file mode 100644 index 5d3fd18288d..00000000000 --- a/cannon/testdata/go-1-25/hello/main.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import "os" - -func main() { - _, _ = os.Stdout.Write([]byte("hello world!\n")) -} diff --git a/cannon/testdata/go-1-25/justfile b/cannon/testdata/go-1-25/justfile deleted file mode 100644 index d606bdc6353..00000000000 --- a/cannon/testdata/go-1-25/justfile +++ /dev/null @@ -1,31 +0,0 @@ -# Build all 64-bit ELF test binaries -elf64: elf - -# Build all 64-bit ELF test binaries -[script('bash')] -elf: - set -euo pipefail - mkdir -p bin - for mod in */go.mod; do - name=$(dirname "$mod") - echo "Building bin/${name}.64.elf" - (cd "$name" && GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -o "../bin/${name}.64.elf" .) - done - -# Dump all ELF binaries -# TODO: currently have the little-endian toolchain, but should use the big-endian one. The -EB compat flag works though. -[script('bash')] -dump: - set -euo pipefail - mkdir -p bin - for mod in */go.mod; do - name=$(dirname "$mod") - elf="bin/${name}.64.elf" - dump="bin/${name}.64.dump" - echo "Dumping $elf -> $dump" - mipsel-linux-gnu-objdump -D --disassembler-options=no-aliases --wide --source -m mips:3000 -EB "$elf" > "$dump" - done - -# Clean build artifacts -clean: - @[ -d bin ] && find bin -maxdepth 1 -type f -delete || true diff --git a/cannon/testdata/go-1-25/keccak/go.mod b/cannon/testdata/go-1-25/keccak/go.mod deleted file mode 100644 index 2d7412ddd72..00000000000 --- a/cannon/testdata/go-1-25/keccak/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module keccak - -go 1.25 - -toolchain go1.25.4 - -require golang.org/x/crypto v0.35.0 - -require golang.org/x/sys v0.30.0 // indirect - -replace github.com/ethereum-optimism/optimism v0.0.0 => ./../../../.. diff --git a/cannon/testdata/go-1-25/keccak/go.sum b/cannon/testdata/go-1-25/keccak/go.sum deleted file mode 100644 index 265a8fc783b..00000000000 --- a/cannon/testdata/go-1-25/keccak/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/cannon/testdata/go-1-25/keccak/main.go b/cannon/testdata/go-1-25/keccak/main.go deleted file mode 100644 index 4d9f6785443..00000000000 --- a/cannon/testdata/go-1-25/keccak/main.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "golang.org/x/crypto/sha3" -) - -func main() { - var result []byte - state := sha3.NewLegacyKeccak256() - state.Write([]byte{1, 2, 3}) - result = state.Sum(result) - - fmt.Printf("keccak program. result=%x\n", result) -} diff --git a/cannon/testdata/go-1-25/mt-atomic/atomic_test_copy.go b/cannon/testdata/go-1-25/mt-atomic/atomic_test_copy.go deleted file mode 100644 index e0cd1ebd69f..00000000000 --- a/cannon/testdata/go-1-25/mt-atomic/atomic_test_copy.go +++ /dev/null @@ -1,2567 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/atomic/atomic_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "fmt" - "reflect" - "runtime" - "runtime/debug" - "strings" - . "sync/atomic" - "testing" - "unsafe" - - "utils/testutil" -) - -// Tests of correct behavior, without contention. -// (Does the function work as advertised?) -// -// Test that the Add functions add correctly. -// Test that the CompareAndSwap functions actually -// do the comparison and the swap correctly. -// -// The loop over power-of-two values is meant to -// ensure that the operations apply to the full word size. -// The struct fields x.before and x.after check that the -// operations do not extend past the full word size. - -const ( - magic32 = 0xdedbeef - magic64 = 0xdeddeadbeefbeef -) - -func TestSwapInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := SwapInt32(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := SwapUint32(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := SwapInt64(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := SwapUint64(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestSwapUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := SwapUintptr(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestSwapUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := x.i.Swap(delta) - if x.i.Load() != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - j = delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -var global [1024]byte - -func testPointers() []unsafe.Pointer { - var pointers []unsafe.Pointer - // globals - for i := 0; i < 10; i++ { - pointers = append(pointers, unsafe.Pointer(&global[1< delta; delta += delta { - k := AddInt32(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := AddUint32(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := AddInt64(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := AddUint64(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestAddUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := AddUintptr(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestAddUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := x.i.Add(delta) - j += delta - if x.i.Load() != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for val := int32(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapInt32(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapInt32(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for val := int32(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for val := uint32(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapUint32(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapUint32(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for val := uint32(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - for val := int64(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapInt64(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapInt64(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestCompareAndSwapInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - for val := int64(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func testCompareAndSwapUint64(t testing.TB, cas func(*uint64, uint64, uint64) bool) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - for val := uint64(1); val+val > val; val += val { - x.i = val - if !cas(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if cas(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestCompareAndSwapUint64(t *testutil.TestRunner) { - testCompareAndSwapUint64(t, CompareAndSwapUint64) -} - -func TestCompareAndSwapUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - for val := uint64(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestCompareAndSwapUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for val := uintptr(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapUintptr(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapUintptr(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for val := uintptr(1); val+val > val; val += val { - x.i.Store(val) - if !x.i.CompareAndSwap(val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - x.i.Store(val + 1) - if x.i.CompareAndSwap(val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i.Load() != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uintptr(magicptr), uintptr(magicptr)) - } -} - -func TestCompareAndSwapPointer(t *testutil.TestRunner) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - q := unsafe.Pointer(new(byte)) - for _, p := range testPointers() { - x.i = p - if !CompareAndSwapPointer(&x.i, p, q) { - t.Fatalf("should have swapped %p %p", p, q) - } - if x.i != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q) - } - if CompareAndSwapPointer(&x.i, p, nil) { - t.Fatalf("should not have swapped %p nil", p) - } - if x.i != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapPointerMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Pointer[byte] - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - q := new(byte) - for _, p := range testPointers() { - p := (*byte)(p) - x.i.Store(p) - if !x.i.CompareAndSwap(p, q) { - t.Fatalf("should have swapped %p %p", p, q) - } - if x.i.Load() != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q) - } - if x.i.CompareAndSwap(p, nil) { - t.Fatalf("should not have swapped %p nil", p) - } - if x.i.Load() != q { - t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := LoadInt32(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - want := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := LoadUint32(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - want := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := LoadInt64(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - want := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := LoadUint64(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - want := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestLoadUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := LoadUintptr(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - want := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := x.i.Load() - if k != want { - t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) - } - x.i.Store(k + delta) - want = k + delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadPointer(t *testutil.TestRunner) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - x.i = p - k := LoadPointer(&x.i) - if k != p { - t.Fatalf("p=%x k=%x", p, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadPointerMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Pointer[byte] - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - p := (*byte)(p) - x.i.Store(p) - k := x.i.Load() - if k != p { - t.Fatalf("p=%x k=%x", p, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStoreInt32(t *testutil.TestRunner) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - v := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - StoreInt32(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreInt32Method(t *testutil.TestRunner) { - var x struct { - before int32 - i Int32 - after int32 - } - x.before = magic32 - x.after = magic32 - v := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreUint32(t *testutil.TestRunner) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - v := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - StoreUint32(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreUint32Method(t *testutil.TestRunner) { - var x struct { - before uint32 - i Uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - v := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreInt64(t *testutil.TestRunner) { - var x struct { - before int64 - i int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - v := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - StoreInt64(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreInt64Method(t *testutil.TestRunner) { - var x struct { - before int64 - i Int64 - after int64 - } - magic64 := int64(magic64) - x.before = magic64 - x.after = magic64 - v := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreUint64(t *testutil.TestRunner) { - var x struct { - before uint64 - i uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - v := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - StoreUint64(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreUint64Method(t *testutil.TestRunner) { - var x struct { - before uint64 - i Uint64 - after uint64 - } - magic64 := uint64(magic64) - x.before = magic64 - x.after = magic64 - v := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) - } -} - -func TestStoreUintptr(t *testutil.TestRunner) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - v := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - StoreUintptr(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStoreUintptrMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - v := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - x.i.Store(v) - if x.i.Load() != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) - } - v += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStorePointer(t *testutil.TestRunner) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - StorePointer(&x.i, p) - if x.i != p { - t.Fatalf("x.i=%p p=%p", x.i, p) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStorePointerMethod(t *testutil.TestRunner) { - var x struct { - before uintptr - i Pointer[byte] - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for _, p := range testPointers() { - p := (*byte)(p) - x.i.Store(p) - if x.i.Load() != p { - t.Fatalf("x.i=%p p=%p", x.i.Load(), p) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -// Tests of correct behavior, with contention. -// (Is the function atomic?) -// -// For each function, we write a "hammer" function that repeatedly -// uses the atomic operation to add 1 to a value. After running -// multiple hammers in parallel, check that we end with the correct -// total. -// Swap can't add 1, so it uses a different scheme. -// The functions repeatedly generate a pseudo-random number such that -// low bits are equal to high bits, swap, check that the old value -// has low and high bits equal. - -var hammer32 = map[string]func(*uint32, int){ - "SwapInt32": hammerSwapInt32, - "SwapUint32": hammerSwapUint32, - "SwapUintptr": hammerSwapUintptr32, - "AddInt32": hammerAddInt32, - "AddUint32": hammerAddUint32, - "AddUintptr": hammerAddUintptr32, - "CompareAndSwapInt32": hammerCompareAndSwapInt32, - "CompareAndSwapUint32": hammerCompareAndSwapUint32, - "CompareAndSwapUintptr": hammerCompareAndSwapUintptr32, - - "SwapInt32Method": hammerSwapInt32Method, - "SwapUint32Method": hammerSwapUint32Method, - "SwapUintptrMethod": hammerSwapUintptr32Method, - "AddInt32Method": hammerAddInt32Method, - "AddUint32Method": hammerAddUint32Method, - "AddUintptrMethod": hammerAddUintptr32Method, - "CompareAndSwapInt32Method": hammerCompareAndSwapInt32Method, - "CompareAndSwapUint32Method": hammerCompareAndSwapUint32Method, - "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr32Method, -} - -func init() { - var v uint64 = 1 << 50 - if uintptr(v) != 0 { - // 64-bit system; clear uintptr tests - delete(hammer32, "SwapUintptr") - delete(hammer32, "AddUintptr") - delete(hammer32, "CompareAndSwapUintptr") - delete(hammer32, "SwapUintptrMethod") - delete(hammer32, "AddUintptrMethod") - delete(hammer32, "CompareAndSwapUintptrMethod") - } -} - -func hammerSwapInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := uint32(SwapInt32(addr, int32(new))) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) - } - } -} - -func hammerSwapInt32Method(uaddr *uint32, count int) { - addr := (*Int32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := uint32(addr.Swap(int32(new))) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint32(addr *uint32, count int) { - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := SwapUint32(addr, new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint32Method(uaddr *uint32, count int) { - addr := (*Uint32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := addr.Swap(new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 - old := SwapUintptr(addr, new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old)) - } - } -} - -func hammerSwapUintptr32Method(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 - old := addr.Swap(new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("Uintptr.Swap is not atomic: %#08x", old)) - } - } -} - -func hammerAddInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddInt32(addr, 1) - } -} - -func hammerAddInt32Method(uaddr *uint32, count int) { - addr := (*Int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUint32(addr *uint32, count int) { - for i := 0; i < count; i++ { - AddUint32(addr, 1) - } -} - -func hammerAddUint32Method(uaddr *uint32, count int) { - addr := (*Uint32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddUintptr(addr, 1) - } -} - -func hammerAddUintptr32Method(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerCompareAndSwapInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadInt32(addr) - if CompareAndSwapInt32(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapInt32Method(uaddr *uint32, count int) { - addr := (*Int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint32(addr *uint32, count int) { - for i := 0; i < count; i++ { - for { - v := LoadUint32(addr) - if CompareAndSwapUint32(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint32Method(uaddr *uint32, count int) { - addr := (*Uint32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadUintptr(addr) - if CompareAndSwapUintptr(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func TestHammer32(t *testutil.TestRunner) { - const p = 4 - n := 100000 - if short { - n = 1000 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) - - for name, testf := range hammer32 { - c := make(chan int) - var val uint32 - for i := 0; i < p; i++ { - go func() { - defer func() { - if err := recover(); err != nil { - t.Error(err.(string)) - } - c <- 1 - }() - testf(&val, n) - }() - } - for i := 0; i < p; i++ { - <-c - } - if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p { - t.Fatalf("%s: val=%d want %d", name, val, n*p) - } - } -} - -var hammer64 = map[string]func(*uint64, int){ - "SwapInt64": hammerSwapInt64, - "SwapUint64": hammerSwapUint64, - "SwapUintptr": hammerSwapUintptr64, - "AddInt64": hammerAddInt64, - "AddUint64": hammerAddUint64, - "AddUintptr": hammerAddUintptr64, - "CompareAndSwapInt64": hammerCompareAndSwapInt64, - "CompareAndSwapUint64": hammerCompareAndSwapUint64, - "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64, - - "SwapInt64Method": hammerSwapInt64Method, - "SwapUint64Method": hammerSwapUint64Method, - "SwapUintptrMethod": hammerSwapUintptr64Method, - "AddInt64Method": hammerAddInt64Method, - "AddUint64Method": hammerAddUint64Method, - "AddUintptrMethod": hammerAddUintptr64Method, - "CompareAndSwapInt64Method": hammerCompareAndSwapInt64Method, - "CompareAndSwapUint64Method": hammerCompareAndSwapUint64Method, - "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr64Method, -} - -func init() { - var v uint64 = 1 << 50 - if uintptr(v) == 0 { - // 32-bit system; clear uintptr tests - delete(hammer64, "SwapUintptr") - delete(hammer64, "SwapUintptrMethod") - delete(hammer64, "AddUintptr") - delete(hammer64, "AddUintptrMethod") - delete(hammer64, "CompareAndSwapUintptr") - delete(hammer64, "CompareAndSwapUintptrMethod") - } -} - -func hammerSwapInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := uint64(SwapInt64(addr, int64(new))) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) - } - } -} - -func hammerSwapInt64Method(uaddr *uint64, count int) { - addr := (*Int64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := uint64(addr.Swap(int64(new))) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint64(addr *uint64, count int) { - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := SwapUint64(addr, new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint64Method(uaddr *uint64, count int) { - addr := (*Uint64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := addr.Swap(new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) - } - } -} - -const arch32 = unsafe.Sizeof(uintptr(0)) == 4 - -func hammerSwapUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - if !arch32 { - addr := (*uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 - old := SwapUintptr(addr, new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) - } - } - } -} - -func hammerSwapUintptr64Method(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - if !arch32 { - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 - old := addr.Swap(new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) - } - } - } -} - -func hammerAddInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddInt64(addr, 1) - } -} - -func hammerAddInt64Method(uaddr *uint64, count int) { - addr := (*Int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUint64(addr *uint64, count int) { - for i := 0; i < count; i++ { - AddUint64(addr, 1) - } -} - -func hammerAddUint64Method(uaddr *uint64, count int) { - addr := (*Uint64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerAddUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddUintptr(addr, 1) - } -} - -func hammerAddUintptr64Method(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - addr.Add(1) - } -} - -func hammerCompareAndSwapInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadInt64(addr) - if CompareAndSwapInt64(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapInt64Method(uaddr *uint64, count int) { - addr := (*Int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint64(addr *uint64, count int) { - for i := 0; i < count; i++ { - for { - v := LoadUint64(addr) - if CompareAndSwapUint64(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint64Method(uaddr *uint64, count int) { - addr := (*Uint64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := LoadUintptr(addr) - if CompareAndSwapUintptr(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*Uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := addr.Load() - if addr.CompareAndSwap(v, v+1) { - break - } - } - } -} - -func TestHammer64(t *testutil.TestRunner) { - const p = 4 - n := 100000 - if short { - n = 1000 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) - - for name, testf := range hammer64 { - c := make(chan int) - var val uint64 - for i := 0; i < p; i++ { - go func() { - defer func() { - if err := recover(); err != nil { - t.Error(err.(string)) - } - c <- 1 - }() - testf(&val, n) - }() - } - for i := 0; i < p; i++ { - <-c - } - if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p { - t.Fatalf("%s: val=%d want %d", name, val, n*p) - } - } -} - -func hammerStoreLoadInt32(t testing.TB, paddr unsafe.Pointer) { - addr := (*int32)(paddr) - v := LoadInt32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Int32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreInt32(addr, new) -} - -func hammerStoreLoadInt32Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*int32)(paddr) - v := LoadInt32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Int32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreInt32(addr, new) -} - -func hammerStoreLoadUint32(t testing.TB, paddr unsafe.Pointer) { - addr := (*uint32)(paddr) - v := LoadUint32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uint32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreUint32(addr, new) -} - -func hammerStoreLoadUint32Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*Uint32)(paddr) - v := addr.Load() - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uint32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - addr.Store(new) -} - -func hammerStoreLoadInt64(t testing.TB, paddr unsafe.Pointer) { - addr := (*int64)(paddr) - v := LoadInt64(addr) - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Int64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - StoreInt64(addr, new) -} - -func hammerStoreLoadInt64Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*Int64)(paddr) - v := addr.Load() - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Int64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - addr.Store(new) -} - -func hammerStoreLoadUint64(t testing.TB, paddr unsafe.Pointer) { - addr := (*uint64)(paddr) - v := LoadUint64(addr) - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uint64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - StoreUint64(addr, new) -} - -func hammerStoreLoadUint64Method(t testing.TB, paddr unsafe.Pointer) { - addr := (*Uint64)(paddr) - v := addr.Load() - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uint64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - addr.Store(new) -} - -func hammerStoreLoadUintptr(t testing.TB, paddr unsafe.Pointer) { - addr := (*uintptr)(paddr) - v := LoadUintptr(addr) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - StoreUintptr(addr, new) -} - -//go:nocheckptr -func hammerStoreLoadUintptrMethod(t testing.TB, paddr unsafe.Pointer) { - addr := (*Uintptr)(paddr) - v := addr.Load() - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - addr.Store(new) -} - -// This code is just testing that LoadPointer/StorePointer operate -// atomically; it's not actually calculating pointers. -// -//go:nocheckptr -func hammerStoreLoadPointer(t testing.TB, paddr unsafe.Pointer) { - addr := (*unsafe.Pointer)(paddr) - v := uintptr(LoadPointer(addr)) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - StorePointer(addr, unsafe.Pointer(new)) -} - -// This code is just testing that LoadPointer/StorePointer operate -// atomically; it's not actually calculating pointers. -// -//go:nocheckptr -func hammerStoreLoadPointerMethod(t testing.TB, paddr unsafe.Pointer) { - addr := (*Pointer[byte])(paddr) - v := uintptr(unsafe.Pointer(addr.Load())) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - addr.Store((*byte)(unsafe.Pointer(new))) -} - -func TestHammerStoreLoad(t *testutil.TestRunner) { - tests := []func(testing.TB, unsafe.Pointer){ - hammerStoreLoadInt32, hammerStoreLoadUint32, - hammerStoreLoadUintptr, hammerStoreLoadPointer, - hammerStoreLoadInt32Method, hammerStoreLoadUint32Method, - hammerStoreLoadUintptrMethod, hammerStoreLoadPointerMethod, - hammerStoreLoadInt64, hammerStoreLoadUint64, - hammerStoreLoadInt64Method, hammerStoreLoadUint64Method, - } - n := int(1e6) - if short { - n = int(1e4) - } - const procs = 8 - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) - // Disable the GC because hammerStoreLoadPointer invokes - // write barriers on values that aren't real pointers. - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - // Ensure any in-progress GC is finished. - runtime.GC() - for _, tt := range tests { - c := make(chan int) - var val uint64 - for p := 0; p < procs; p++ { - go func() { - for i := 0; i < n; i++ { - tt(t, unsafe.Pointer(&val)) - } - c <- 1 - }() - } - for p := 0; p < procs; p++ { - <-c - } - } -} - -func TestStoreLoadSeqCst32(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int32(1e3) - if short { - N = int32(1e2) - } - c := make(chan bool, 2) - X := [2]int32{} - ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}} - for p := 0; p < 2; p++ { - go func(me int) { - he := 1 - me - for i := int32(1); i < N; i++ { - StoreInt32(&X[me], i) - my := LoadInt32(&X[he]) - StoreInt32(&ack[me][i%3], my) - for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - his := LoadInt32(&ack[he][i%3]) - if (my != i && my != i-1) || (his != i && his != i-1) { - t.Errorf("invalid values: %d/%d (%d)", my, his, i) - break - } - if my != i && his != i { - t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) - break - } - StoreInt32(&ack[me][(i-1)%3], -1) - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadSeqCst64(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int64(1e3) - if short { - N = int64(1e2) - } - c := make(chan bool, 2) - X := [2]int64{} - ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}} - for p := 0; p < 2; p++ { - go func(me int) { - he := 1 - me - for i := int64(1); i < N; i++ { - StoreInt64(&X[me], i) - my := LoadInt64(&X[he]) - StoreInt64(&ack[me][i%3], my) - for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - his := LoadInt64(&ack[he][i%3]) - if (my != i && my != i-1) || (his != i && his != i-1) { - t.Errorf("invalid values: %d/%d (%d)", my, his, i) - break - } - if my != i && his != i { - t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) - break - } - StoreInt64(&ack[me][(i-1)%3], -1) - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadRelAcq32(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int32(1e3) - if short { - N = int32(1e2) - } - c := make(chan bool, 2) - type Data struct { - signal int32 - pad1 [128]int8 - data1 int32 - pad2 [128]int8 - data2 float32 - } - var X Data - for p := int32(0); p < 2; p++ { - go func(p int32) { - for i := int32(1); i < N; i++ { - if (i+p)%2 == 0 { - X.data1 = i - X.data2 = float32(i) - StoreInt32(&X.signal, i) - } else { - for w := 1; LoadInt32(&X.signal) != i; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - d1 := X.data1 - d2 := X.data2 - if d1 != i || d2 != float32(i) { - t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i) - break - } - } - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadRelAcq64(t *testutil.TestRunner) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int64(1e3) - if short { - N = int64(1e2) - } - c := make(chan bool, 2) - type Data struct { - signal int64 - pad1 [128]int8 - data1 int64 - pad2 [128]int8 - data2 float64 - } - var X Data - for p := int64(0); p < 2; p++ { - go func(p int64) { - for i := int64(1); i < N; i++ { - if (i+p)%2 == 0 { - X.data1 = i - X.data2 = float64(i) - StoreInt64(&X.signal, i) - } else { - for w := 1; LoadInt64(&X.signal) != i; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - d1 := X.data1 - d2 := X.data2 - if d1 != i || d2 != float64(i) { - t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i) - break - } - } - } - c <- true - }(p) - } - <-c - <-c -} - -func shouldPanic(t testing.TB, name string, f func()) { - defer func() { - // Check that all GC maps are sane. - runtime.GC() - - err := recover() - want := "unaligned 64-bit atomic operation" - if err == nil { - t.Errorf("%s did not panic", name) - } else if s, _ := err.(string); s != want { - t.Errorf("%s: wanted panic %q, got %q", name, want, err) - } - }() - f() -} - -func TestUnaligned64(t *testutil.TestRunner) { - // Unaligned 64-bit atomics on 32-bit systems are - // a continual source of pain. Test that on 32-bit systems they crash - // instead of failing silently. - if !arch32 { - t.Skip("test only runs on 32-bit systems") - } - - x := make([]uint32, 4) - p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned - - shouldPanic(t, "LoadUint64", func() { LoadUint64(p) }) - shouldPanic(t, "LoadUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Load() }) - shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) }) - shouldPanic(t, "StoreUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Store(1) }) - shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) }) - shouldPanic(t, "CompareAndSwapUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).CompareAndSwap(1, 2) }) - shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) }) - shouldPanic(t, "AddUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Add(3) }) -} - -func TestAutoAligned64(t *testutil.TestRunner) { - var signed struct { - _ uint32 - i Int64 - } - if o := reflect.TypeOf(&signed).Elem().Field(1).Offset; o != 8 { - t.Fatalf("Int64 offset = %d, want 8", o) - } - if p := reflect.ValueOf(&signed).Elem().Field(1).Addr().Pointer(); p&7 != 0 { - t.Fatalf("Int64 pointer = %#x, want 8-aligned", p) - } - - var unsigned struct { - _ uint32 - i Uint64 - } - if o := reflect.TypeOf(&unsigned).Elem().Field(1).Offset; o != 8 { - t.Fatalf("Uint64 offset = %d, want 8", o) - } - if p := reflect.ValueOf(&unsigned).Elem().Field(1).Addr().Pointer(); p&7 != 0 { - t.Fatalf("Int64 pointer = %#x, want 8-aligned", p) - } -} - -func TestNilDeref(t *testutil.TestRunner) { - funcs := [...]func(){ - func() { CompareAndSwapInt32(nil, 0, 0) }, - func() { (*Int32)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapInt64(nil, 0, 0) }, - func() { (*Int64)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapUint32(nil, 0, 0) }, - func() { (*Uint32)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapUint64(nil, 0, 0) }, - func() { (*Uint64)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapUintptr(nil, 0, 0) }, - func() { (*Uintptr)(nil).CompareAndSwap(0, 0) }, - func() { CompareAndSwapPointer(nil, nil, nil) }, - func() { (*Pointer[byte])(nil).CompareAndSwap(nil, nil) }, - func() { SwapInt32(nil, 0) }, - func() { (*Int32)(nil).Swap(0) }, - func() { SwapUint32(nil, 0) }, - func() { (*Uint32)(nil).Swap(0) }, - func() { SwapInt64(nil, 0) }, - func() { (*Int64)(nil).Swap(0) }, - func() { SwapUint64(nil, 0) }, - func() { (*Uint64)(nil).Swap(0) }, - func() { SwapUintptr(nil, 0) }, - func() { (*Uintptr)(nil).Swap(0) }, - func() { SwapPointer(nil, nil) }, - func() { (*Pointer[byte])(nil).Swap(nil) }, - func() { AddInt32(nil, 0) }, - func() { (*Int32)(nil).Add(0) }, - func() { AddUint32(nil, 0) }, - func() { (*Uint32)(nil).Add(0) }, - func() { AddInt64(nil, 0) }, - func() { (*Int64)(nil).Add(0) }, - func() { AddUint64(nil, 0) }, - func() { (*Uint64)(nil).Add(0) }, - func() { AddUintptr(nil, 0) }, - func() { (*Uintptr)(nil).Add(0) }, - func() { LoadInt32(nil) }, - func() { (*Int32)(nil).Load() }, - func() { LoadInt64(nil) }, - func() { (*Int64)(nil).Load() }, - func() { LoadUint32(nil) }, - func() { (*Uint32)(nil).Load() }, - func() { LoadUint64(nil) }, - func() { (*Uint64)(nil).Load() }, - func() { LoadUintptr(nil) }, - func() { (*Uintptr)(nil).Load() }, - func() { LoadPointer(nil) }, - func() { (*Pointer[byte])(nil).Load() }, - func() { StoreInt32(nil, 0) }, - func() { (*Int32)(nil).Store(0) }, - func() { StoreInt64(nil, 0) }, - func() { (*Int64)(nil).Store(0) }, - func() { StoreUint32(nil, 0) }, - func() { (*Uint32)(nil).Store(0) }, - func() { StoreUint64(nil, 0) }, - func() { (*Uint64)(nil).Store(0) }, - func() { StoreUintptr(nil, 0) }, - func() { (*Uintptr)(nil).Store(0) }, - func() { StorePointer(nil, nil) }, - func() { (*Pointer[byte])(nil).Store(nil) }, - } - for _, f := range funcs { - func() { - defer func() { - runtime.GC() - recover() - }() - f() - }() - } -} - -// Test that this compiles. -// When atomic.Pointer used _ [0]T, it did not. -type List struct { - Next Pointer[List] -} diff --git a/cannon/testdata/go-1-25/mt-atomic/go.mod b/cannon/testdata/go-1-25/mt-atomic/go.mod deleted file mode 100644 index 6f16f7245e1..00000000000 --- a/cannon/testdata/go-1-25/mt-atomic/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module atomic - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/mt-atomic/main.go b/cannon/testdata/go-1-25/mt-atomic/main.go deleted file mode 100644 index 91f875fbe1e..00000000000 --- a/cannon/testdata/go-1-25/mt-atomic/main.go +++ /dev/null @@ -1,81 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestSwapInt32, "TestSwapInt32") - testutil.RunTest(TestSwapInt32Method, "TestSwapInt32Method") - testutil.RunTest(TestSwapUint32, "TestSwapUint32") - testutil.RunTest(TestSwapUint32Method, "TestSwapUint32Method") - testutil.RunTest(TestSwapInt64, "TestSwapInt64") - testutil.RunTest(TestSwapInt64Method, "TestSwapInt64Method") - testutil.RunTest(TestSwapUint64, "TestSwapUint64") - testutil.RunTest(TestSwapUint64Method, "TestSwapUint64Method") - testutil.RunTest(TestSwapUintptr, "TestSwapUintptr") - testutil.RunTest(TestSwapUintptrMethod, "TestSwapUintptrMethod") - testutil.RunTest(TestSwapPointer, "TestSwapPointer") - testutil.RunTest(TestSwapPointerMethod, "TestSwapPointerMethod") - testutil.RunTest(TestAddInt32, "TestAddInt32") - testutil.RunTest(TestAddInt32Method, "TestAddInt32Method") - testutil.RunTest(TestAddUint32, "TestAddUint32") - testutil.RunTest(TestAddUint32Method, "TestAddUint32Method") - testutil.RunTest(TestAddInt64, "TestAddInt64") - testutil.RunTest(TestAddInt64Method, "TestAddInt64Method") - testutil.RunTest(TestAddUint64, "TestAddUint64") - testutil.RunTest(TestAddUint64Method, "TestAddUint64Method") - testutil.RunTest(TestAddUintptr, "TestAddUintptr") - testutil.RunTest(TestAddUintptrMethod, "TestAddUintptrMethod") - testutil.RunTest(TestCompareAndSwapInt32, "TestCompareAndSwapInt32") - testutil.RunTest(TestCompareAndSwapInt32Method, "TestCompareAndSwapInt32Method") - testutil.RunTest(TestCompareAndSwapUint32, "TestCompareAndSwapUint32") - testutil.RunTest(TestCompareAndSwapUint32Method, "TestCompareAndSwapUint32Method") - testutil.RunTest(TestCompareAndSwapInt64, "TestCompareAndSwapInt64") - testutil.RunTest(TestCompareAndSwapInt64Method, "TestCompareAndSwapInt64Method") - testutil.RunTest(TestCompareAndSwapUint64, "TestCompareAndSwapUint64") - testutil.RunTest(TestCompareAndSwapUint64Method, "TestCompareAndSwapUint64Method") - testutil.RunTest(TestCompareAndSwapUintptr, "TestCompareAndSwapUintptr") - testutil.RunTest(TestCompareAndSwapUintptrMethod, "TestCompareAndSwapUintptrMethod") - testutil.RunTest(TestCompareAndSwapPointer, "TestCompareAndSwapPointer") - testutil.RunTest(TestCompareAndSwapPointerMethod, "TestCompareAndSwapPointerMethod") - testutil.RunTest(TestLoadInt32, "TestLoadInt32") - testutil.RunTest(TestLoadInt32Method, "TestLoadInt32Method") - testutil.RunTest(TestLoadUint32, "TestLoadUint32") - testutil.RunTest(TestLoadUint32Method, "TestLoadUint32Method") - testutil.RunTest(TestLoadInt64, "TestLoadInt64") - testutil.RunTest(TestLoadInt64Method, "TestLoadInt64Method") - testutil.RunTest(TestLoadUint64, "TestLoadUint64") - testutil.RunTest(TestLoadUint64Method, "TestLoadUint64Method") - testutil.RunTest(TestLoadUintptr, "TestLoadUintptr") - testutil.RunTest(TestLoadUintptrMethod, "TestLoadUintptrMethod") - testutil.RunTest(TestLoadPointer, "TestLoadPointer") - testutil.RunTest(TestLoadPointerMethod, "TestLoadPointerMethod") - testutil.RunTest(TestStoreInt32, "TestStoreInt32") - testutil.RunTest(TestStoreInt32Method, "TestStoreInt32Method") - testutil.RunTest(TestStoreUint32, "TestStoreUint32") - testutil.RunTest(TestStoreUint32Method, "TestStoreUint32Method") - testutil.RunTest(TestStoreInt64, "TestStoreInt64") - testutil.RunTest(TestStoreInt64Method, "TestStoreInt64Method") - testutil.RunTest(TestStoreUint64, "TestStoreUint64") - testutil.RunTest(TestStoreUint64Method, "TestStoreUint64Method") - testutil.RunTest(TestStoreUintptr, "TestStoreUintptr") - testutil.RunTest(TestStoreUintptrMethod, "TestStoreUintptrMethod") - testutil.RunTest(TestStorePointer, "TestStorePointer") - testutil.RunTest(TestStorePointerMethod, "TestStorePointerMethod") - testutil.RunTest(TestHammer32, "TestHammer32") - testutil.RunTest(TestHammer64, "TestHammer64") - testutil.RunTest(TestAutoAligned64, "TestAutoAligned64") - testutil.RunTest(TestNilDeref, "TestNilDeref") - testutil.RunTest(TestStoreLoadSeqCst32, "TestStoreLoadSeqCst32") - testutil.RunTest(TestStoreLoadSeqCst64, "TestStoreLoadSeqCst64") - testutil.RunTest(TestStoreLoadRelAcq32, "TestStoreLoadRelAcq32") - testutil.RunTest(TestStoreLoadRelAcq64, "TestStoreLoadRelAcq64") - testutil.RunTest(TestUnaligned64, "TestUnaligned64") - testutil.RunTest(TestHammerStoreLoad, "TestHammerStoreLoad") - - fmt.Println("Atomic tests passed") -} diff --git a/cannon/testdata/go-1-25/mt-cond/go.mod b/cannon/testdata/go-1-25/mt-cond/go.mod deleted file mode 100644 index 3968aa9d126..00000000000 --- a/cannon/testdata/go-1-25/mt-cond/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module cond - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/mt-cond/main.go b/cannon/testdata/go-1-25/mt-cond/main.go deleted file mode 100644 index a6c93e5084a..00000000000 --- a/cannon/testdata/go-1-25/mt-cond/main.go +++ /dev/null @@ -1,304 +0,0 @@ -// Portions of this code are derived from code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/400433af3660905ecaceaf19ddad3e6c24b141df/src/sync/cond_test.go -// -// --- Original License Notice --- -// -// Copyright 2009 The Go Authors. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - "os" - "reflect" - "runtime" - "sync" -) - -func main() { - TestCondSignal() - TestCondSignalGenerations() - TestCondBroadcast() - TestRace() - TestCondSignalStealing() - TestCondCopy() - - fmt.Println("Cond test passed") -} - -func TestCondSignal() { - var m sync.Mutex - c := sync.NewCond(&m) - n := 2 - running := make(chan bool, n) - awake := make(chan bool, n) - for i := 0; i < n; i++ { - go func() { - m.Lock() - running <- true - c.Wait() - awake <- true - m.Unlock() - }() - } - for i := 0; i < n; i++ { - <-running // Wait for everyone to run. - } - for n > 0 { - select { - case <-awake: - _, _ = fmt.Fprintln(os.Stderr, "goroutine not asleep") - os.Exit(1) - default: - } - m.Lock() - c.Signal() - m.Unlock() - <-awake // Will deadlock if no goroutine wakes up - select { - case <-awake: - _, _ = fmt.Fprintln(os.Stderr, "too many goroutines awake") - os.Exit(1) - default: - } - n-- - } - c.Signal() -} - -func TestCondSignalGenerations() { - var m sync.Mutex - c := sync.NewCond(&m) - n := 100 - running := make(chan bool, n) - awake := make(chan int, n) - for i := 0; i < n; i++ { - go func(i int) { - m.Lock() - running <- true - c.Wait() - awake <- i - m.Unlock() - }(i) - if i > 0 { - a := <-awake - if a != i-1 { - _, _ = fmt.Fprintf(os.Stderr, "wrong goroutine woke up: want %d, got %d\n", i-1, a) - os.Exit(1) - } - } - <-running - m.Lock() - c.Signal() - m.Unlock() - } -} - -func TestCondBroadcast() { - var m sync.Mutex - c := sync.NewCond(&m) - n := 5 - running := make(chan int, n) - awake := make(chan int, n) - exit := false - for i := 0; i < n; i++ { - go func(g int) { - m.Lock() - for !exit { - running <- g - c.Wait() - awake <- g - } - m.Unlock() - }(i) - } - for i := 0; i < n; i++ { - for i := 0; i < n; i++ { - <-running // Will deadlock unless n are running. - } - if i == n-1 { - m.Lock() - exit = true - m.Unlock() - } - select { - case <-awake: - _, _ = fmt.Fprintln(os.Stderr, "goroutine not asleep") - os.Exit(1) - default: - } - m.Lock() - c.Broadcast() - m.Unlock() - seen := make([]bool, n) - for i := 0; i < n; i++ { - g := <-awake - if seen[g] { - _, _ = fmt.Fprintln(os.Stderr, "goroutine woke up twice") - os.Exit(1) - } - seen[g] = true - } - } - select { - case <-running: - _, _ = fmt.Fprintln(os.Stderr, "goroutine still running") - os.Exit(1) - default: - } - c.Broadcast() -} - -func TestRace() { - x := 0 - c := sync.NewCond(&sync.Mutex{}) - done := make(chan bool) - go func() { - c.L.Lock() - x = 1 - c.Wait() - if x != 2 { - _, _ = fmt.Fprintln(os.Stderr, "want 2") - os.Exit(1) - } - x = 3 - c.Signal() - c.L.Unlock() - done <- true - }() - go func() { - c.L.Lock() - for { - if x == 1 { - x = 2 - c.Signal() - break - } - c.L.Unlock() - runtime.Gosched() - c.L.Lock() - } - c.L.Unlock() - done <- true - }() - go func() { - c.L.Lock() - for { - if x == 2 { - c.Wait() - if x != 3 { - _, _ = fmt.Fprintln(os.Stderr, "want 3") - os.Exit(1) - } - break - } - if x == 3 { - break - } - c.L.Unlock() - runtime.Gosched() - c.L.Lock() - } - c.L.Unlock() - done <- true - }() - <-done - <-done - <-done -} - -func TestCondSignalStealing() { - for iters := 0; iters < 5; iters++ { - var m sync.Mutex - cond := sync.NewCond(&m) - - // Start a waiter. - ch := make(chan struct{}) - go func() { - m.Lock() - ch <- struct{}{} - cond.Wait() - m.Unlock() - - ch <- struct{}{} - }() - - <-ch - m.Lock() - m.Unlock() - - // We know that the waiter is in the cond.Wait() call because we - // synchronized with it, then acquired/released the mutex it was - // holding when we synchronized. - // - // Start two goroutines that will race: one will broadcast on - // the cond var, the other will wait on it. - // - // The new waiter may or may not get notified, but the first one - // has to be notified. - done := false - go func() { - cond.Broadcast() - }() - - go func() { - m.Lock() - for !done { - cond.Wait() - } - m.Unlock() - }() - - // Check that the first waiter does get signaled. - <-ch - - // Release the second waiter in case it didn't get the - // broadcast. - m.Lock() - done = true - m.Unlock() - cond.Broadcast() - } -} - -func TestCondCopy() { - defer func() { - err := recover() - if err == nil || err.(string) != "sync.Cond is copied" { - _, _ = fmt.Fprintf(os.Stderr, "got %v, expect sync.Cond is copied", err) - os.Exit(1) - } - }() - c := sync.Cond{L: &sync.Mutex{}} - c.Signal() - var c2 sync.Cond - reflect.ValueOf(&c2).Elem().Set(reflect.ValueOf(&c).Elem()) // c2 := c, hidden from vet - c2.Signal() -} diff --git a/cannon/testdata/go-1-25/mt-general/go.mod b/cannon/testdata/go-1-25/mt-general/go.mod deleted file mode 100644 index 21da495482b..00000000000 --- a/cannon/testdata/go-1-25/mt-general/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module mtgeneral - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/mt-general/main.go b/cannon/testdata/go-1-25/mt-general/main.go deleted file mode 100644 index 085b7a1fd72..00000000000 --- a/cannon/testdata/go-1-25/mt-general/main.go +++ /dev/null @@ -1,47 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - "os" - "runtime" - "sync" - "sync/atomic" -) - -func main() { - // try some concurrency! - var wg sync.WaitGroup - wg.Add(2) - var x atomic.Int32 - go func() { - x.Add(2) - wg.Done() - }() - go func() { - x.Add(40) - wg.Done() - }() - wg.Wait() - fmt.Printf("waitgroup result: %d\n", x.Load()) - - // channels - a := make(chan int, 1) - b := make(chan int) - c := make(chan int) - go func() { - t0 := <-a - b <- t0 - }() - go func() { - t1 := <-b - c <- t1 - }() - a <- 1234 - out := <-c - fmt.Printf("channels result: %d\n", out) - - // try a GC! (the runtime might not have run one yet) - runtime.GC() - _, _ = os.Stdout.Write([]byte("GC complete!\n")) -} diff --git a/cannon/testdata/go-1-25/mt-map/go.mod b/cannon/testdata/go-1-25/mt-map/go.mod deleted file mode 100644 index 80dcbdafdea..00000000000 --- a/cannon/testdata/go-1-25/mt-map/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module map - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/mt-map/main.go b/cannon/testdata/go-1-25/mt-map/main.go deleted file mode 100644 index ab35ee97b63..00000000000 --- a/cannon/testdata/go-1-25/mt-map/main.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestMapMatchesRWMutex, "TestMapMatchesRWMutex") - testutil.RunTest(TestMapMatchesDeepCopy, "TestMapMatchesDeepCopy") - testutil.RunTest(TestConcurrentRange, "TestConcurrentRange") - testutil.RunTest(TestIssue40999, "TestIssue40999") - testutil.RunTest(TestMapRangeNestedCall, "TestMapRangeNestedCall") - testutil.RunTest(TestCompareAndSwap_NonExistingKey, "TestCompareAndSwap_NonExistingKey") - testutil.RunTest(TestMapRangeNoAllocations, "TestMapRangeNoAllocations") - - fmt.Println("Map test passed") -} diff --git a/cannon/testdata/go-1-25/mt-map/map_reference_test_copy.go b/cannon/testdata/go-1-25/mt-map/map_reference_test_copy.go deleted file mode 100644 index 3beeb1501c5..00000000000 --- a/cannon/testdata/go-1-25/mt-map/map_reference_test_copy.go +++ /dev/null @@ -1,299 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/map_reference_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "sync" - "sync/atomic" -) - -// This file contains reference map implementations for unit-tests. - -// mapInterface is the interface Map implements. -type mapInterface interface { - Load(any) (any, bool) - Store(key, value any) - LoadOrStore(key, value any) (actual any, loaded bool) - LoadAndDelete(key any) (value any, loaded bool) - Delete(any) - Swap(key, value any) (previous any, loaded bool) - CompareAndSwap(key, old, new any) (swapped bool) - CompareAndDelete(key, old any) (deleted bool) - Range(func(key, value any) (shouldContinue bool)) -} - -var ( - _ mapInterface = &RWMutexMap{} - _ mapInterface = &DeepCopyMap{} -) - -// RWMutexMap is an implementation of mapInterface using a sync.RWMutex. -type RWMutexMap struct { - mu sync.RWMutex - dirty map[any]any -} - -func (m *RWMutexMap) Load(key any) (value any, ok bool) { - m.mu.RLock() - value, ok = m.dirty[key] - m.mu.RUnlock() - return -} - -func (m *RWMutexMap) Store(key, value any) { - m.mu.Lock() - if m.dirty == nil { - m.dirty = make(map[any]any) - } - m.dirty[key] = value - m.mu.Unlock() -} - -func (m *RWMutexMap) LoadOrStore(key, value any) (actual any, loaded bool) { - m.mu.Lock() - actual, loaded = m.dirty[key] - if !loaded { - actual = value - if m.dirty == nil { - m.dirty = make(map[any]any) - } - m.dirty[key] = value - } - m.mu.Unlock() - return actual, loaded -} - -func (m *RWMutexMap) Swap(key, value any) (previous any, loaded bool) { - m.mu.Lock() - if m.dirty == nil { - m.dirty = make(map[any]any) - } - - previous, loaded = m.dirty[key] - m.dirty[key] = value - m.mu.Unlock() - return -} - -func (m *RWMutexMap) LoadAndDelete(key any) (value any, loaded bool) { - m.mu.Lock() - value, loaded = m.dirty[key] - if !loaded { - m.mu.Unlock() - return nil, false - } - delete(m.dirty, key) - m.mu.Unlock() - return value, loaded -} - -func (m *RWMutexMap) Delete(key any) { - m.mu.Lock() - delete(m.dirty, key) - m.mu.Unlock() -} - -func (m *RWMutexMap) CompareAndSwap(key, old, new any) (swapped bool) { - m.mu.Lock() - defer m.mu.Unlock() - if m.dirty == nil { - return false - } - - value, loaded := m.dirty[key] - if loaded && value == old { - m.dirty[key] = new - return true - } - return false -} - -func (m *RWMutexMap) CompareAndDelete(key, old any) (deleted bool) { - m.mu.Lock() - defer m.mu.Unlock() - if m.dirty == nil { - return false - } - - value, loaded := m.dirty[key] - if loaded && value == old { - delete(m.dirty, key) - return true - } - return false -} - -func (m *RWMutexMap) Range(f func(key, value any) (shouldContinue bool)) { - m.mu.RLock() - keys := make([]any, 0, len(m.dirty)) - for k := range m.dirty { - keys = append(keys, k) - } - m.mu.RUnlock() - - for _, k := range keys { - v, ok := m.Load(k) - if !ok { - continue - } - if !f(k, v) { - break - } - } -} - -// DeepCopyMap is an implementation of mapInterface using a Mutex and -// atomic.Value. It makes deep copies of the map on every write to avoid -// acquiring the Mutex in Load. -type DeepCopyMap struct { - mu sync.Mutex - clean atomic.Value -} - -func (m *DeepCopyMap) Load(key any) (value any, ok bool) { - clean, _ := m.clean.Load().(map[any]any) - value, ok = clean[key] - return value, ok -} - -func (m *DeepCopyMap) Store(key, value any) { - m.mu.Lock() - dirty := m.dirty() - dirty[key] = value - m.clean.Store(dirty) - m.mu.Unlock() -} - -func (m *DeepCopyMap) LoadOrStore(key, value any) (actual any, loaded bool) { - clean, _ := m.clean.Load().(map[any]any) - actual, loaded = clean[key] - if loaded { - return actual, loaded - } - - m.mu.Lock() - // Reload clean in case it changed while we were waiting on m.mu. - clean, _ = m.clean.Load().(map[any]any) - actual, loaded = clean[key] - if !loaded { - dirty := m.dirty() - dirty[key] = value - actual = value - m.clean.Store(dirty) - } - m.mu.Unlock() - return actual, loaded -} - -func (m *DeepCopyMap) Swap(key, value any) (previous any, loaded bool) { - m.mu.Lock() - dirty := m.dirty() - previous, loaded = dirty[key] - dirty[key] = value - m.clean.Store(dirty) - m.mu.Unlock() - return -} - -func (m *DeepCopyMap) LoadAndDelete(key any) (value any, loaded bool) { - m.mu.Lock() - dirty := m.dirty() - value, loaded = dirty[key] - delete(dirty, key) - m.clean.Store(dirty) - m.mu.Unlock() - return -} - -func (m *DeepCopyMap) Delete(key any) { - m.mu.Lock() - dirty := m.dirty() - delete(dirty, key) - m.clean.Store(dirty) - m.mu.Unlock() -} - -func (m *DeepCopyMap) CompareAndSwap(key, old, new any) (swapped bool) { - clean, _ := m.clean.Load().(map[any]any) - if previous, ok := clean[key]; !ok || previous != old { - return false - } - - m.mu.Lock() - defer m.mu.Unlock() - dirty := m.dirty() - value, loaded := dirty[key] - if loaded && value == old { - dirty[key] = new - m.clean.Store(dirty) - return true - } - return false -} - -func (m *DeepCopyMap) CompareAndDelete(key, old any) (deleted bool) { - clean, _ := m.clean.Load().(map[any]any) - if previous, ok := clean[key]; !ok || previous != old { - return false - } - - m.mu.Lock() - defer m.mu.Unlock() - - dirty := m.dirty() - value, loaded := dirty[key] - if loaded && value == old { - delete(dirty, key) - m.clean.Store(dirty) - return true - } - return false -} - -func (m *DeepCopyMap) Range(f func(key, value any) (shouldContinue bool)) { - clean, _ := m.clean.Load().(map[any]any) - for k, v := range clean { - if !f(k, v) { - break - } - } -} - -func (m *DeepCopyMap) dirty() map[any]any { - clean, _ := m.clean.Load().(map[any]any) - dirty := make(map[any]any, len(clean)+1) - for k, v := range clean { - dirty[k] = v - } - return dirty -} diff --git a/cannon/testdata/go-1-25/mt-map/map_test_copy.go b/cannon/testdata/go-1-25/mt-map/map_test_copy.go deleted file mode 100644 index 7b8806698f9..00000000000 --- a/cannon/testdata/go-1-25/mt-map/map_test_copy.go +++ /dev/null @@ -1,325 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/map_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -package main - -import ( - "math/rand" - "reflect" - "runtime" - "sync" - "sync/atomic" - "testing" - "testing/quick" - - "utils/testutil" -) - -type mapOp string - -const ( - opLoad = mapOp("Load") - opStore = mapOp("Store") - opLoadOrStore = mapOp("LoadOrStore") - opLoadAndDelete = mapOp("LoadAndDelete") - opDelete = mapOp("Delete") - opSwap = mapOp("Swap") - opCompareAndSwap = mapOp("CompareAndSwap") - opCompareAndDelete = mapOp("CompareAndDelete") -) - -var mapOps = [...]mapOp{ - opLoad, - opStore, - opLoadOrStore, - opLoadAndDelete, - opDelete, - opSwap, - opCompareAndSwap, - opCompareAndDelete, -} - -// mapCall is a quick.Generator for calls on mapInterface. -type mapCall struct { - op mapOp - k, v any -} - -func (c mapCall) apply(m mapInterface) (any, bool) { - switch c.op { - case opLoad: - return m.Load(c.k) - case opStore: - m.Store(c.k, c.v) - return nil, false - case opLoadOrStore: - return m.LoadOrStore(c.k, c.v) - case opLoadAndDelete: - return m.LoadAndDelete(c.k) - case opDelete: - m.Delete(c.k) - return nil, false - case opSwap: - return m.Swap(c.k, c.v) - case opCompareAndSwap: - if m.CompareAndSwap(c.k, c.v, rand.Int()) { - m.Delete(c.k) - return c.v, true - } - return nil, false - case opCompareAndDelete: - if m.CompareAndDelete(c.k, c.v) { - if _, ok := m.Load(c.k); !ok { - return nil, true - } - } - return nil, false - default: - panic("invalid mapOp") - } -} - -type mapResult struct { - value any - ok bool -} - -func randValue(r *rand.Rand) any { - b := make([]byte, r.Intn(4)) - for i := range b { - b[i] = 'a' + byte(rand.Intn(26)) - } - return string(b) -} - -func (mapCall) Generate(r *rand.Rand, size int) reflect.Value { - c := mapCall{op: mapOps[rand.Intn(len(mapOps))], k: randValue(r)} - switch c.op { - case opStore, opLoadOrStore: - c.v = randValue(r) - } - return reflect.ValueOf(c) -} - -func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map[any]any) { - for _, c := range calls { - v, ok := c.apply(m) - results = append(results, mapResult{v, ok}) - } - - final = make(map[any]any) - m.Range(func(k, v any) bool { - final[k] = v - return true - }) - - return results, final -} - -func applyMap(calls []mapCall) ([]mapResult, map[any]any) { - return applyCalls(new(sync.Map), calls) -} - -func applyRWMutexMap(calls []mapCall) ([]mapResult, map[any]any) { - return applyCalls(new(RWMutexMap), calls) -} - -func applyDeepCopyMap(calls []mapCall) ([]mapResult, map[any]any) { - return applyCalls(new(DeepCopyMap), calls) -} - -func TestMapMatchesRWMutex(t *testutil.TestRunner) { - if err := quick.CheckEqual(applyMap, applyRWMutexMap, nil); err != nil { - t.Error(err) - } -} - -func TestMapMatchesDeepCopy(t *testutil.TestRunner) { - if err := quick.CheckEqual(applyMap, applyDeepCopyMap, nil); err != nil { - t.Error(err) - } -} - -func TestConcurrentRange(t *testutil.TestRunner) { - const mapSize = 1 << 10 - - m := new(sync.Map) - for n := int64(1); n <= mapSize; n++ { - m.Store(n, int64(n)) - } - - done := make(chan struct{}) - var wg sync.WaitGroup - defer func() { - close(done) - wg.Wait() - }() - for g := int64(runtime.GOMAXPROCS(0)); g > 0; g-- { - r := rand.New(rand.NewSource(g)) - wg.Add(1) - go func(g int64) { - defer wg.Done() - for i := int64(0); ; i++ { - select { - case <-done: - return - default: - } - for n := int64(1); n < mapSize; n++ { - if r.Int63n(mapSize) == 0 { - m.Store(n, n*i*g) - } else { - m.Load(n) - } - } - } - }(g) - } - - //iters := 1 << 10 - //if testing.Short() { - // iters = 16 - //} - iters := 16 - for n := iters; n > 0; n-- { - seen := make(map[int64]bool, mapSize) - - m.Range(func(ki, vi any) bool { - k, v := ki.(int64), vi.(int64) - if v%k != 0 { - t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) - } - if seen[k] { - t.Fatalf("Range visited key %v twice", k) - } - seen[k] = true - return true - }) - - if len(seen) != mapSize { - t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) - } - } -} - -func TestIssue40999(t *testutil.TestRunner) { - var m sync.Map - - // Since the miss-counting in missLocked (via Delete) - // compares the miss count with len(m.dirty), - // add an initial entry to bias len(m.dirty) above the miss count. - m.Store(nil, struct{}{}) - - var finalized uint32 - - // Set finalizers that count for collected keys. A non-zero count - // indicates that keys have not been leaked. - for atomic.LoadUint32(&finalized) == 0 { - p := new(int) - runtime.SetFinalizer(p, func(*int) { - atomic.AddUint32(&finalized, 1) - }) - m.Store(p, struct{}{}) - m.Delete(p) - runtime.GC() - } -} - -func TestMapRangeNestedCall(t *testutil.TestRunner) { // Issue 46399 - var m sync.Map - for i, v := range [3]string{"hello", "world", "Go"} { - m.Store(i, v) - } - m.Range(func(key, value any) bool { - m.Range(func(key, value any) bool { - // We should be able to load the key offered in the Range callback, - // because there are no concurrent Delete involved in this tested map. - if v, ok := m.Load(key); !ok || !reflect.DeepEqual(v, value) { - t.Fatalf("Nested Range loads unexpected value, got %+v want %+v", v, value) - } - - // We didn't keep 42 and a value into the map before, if somehow we loaded - // a value from such a key, meaning there must be an internal bug regarding - // nested range in the Map. - if _, loaded := m.LoadOrStore(42, "dummy"); loaded { - t.Fatalf("Nested Range loads unexpected value, want store a new value") - } - - // Try to Store then LoadAndDelete the corresponding value with the key - // 42 to the Map. In this case, the key 42 and associated value should be - // removed from the Map. Therefore any future range won't observe key 42 - // as we checked in above. - val := "sync.Map" - m.Store(42, val) - if v, loaded := m.LoadAndDelete(42); !loaded || !reflect.DeepEqual(v, val) { - t.Fatalf("Nested Range loads unexpected value, got %v, want %v", v, val) - } - return true - }) - - // Remove key from Map on-the-fly. - m.Delete(key) - return true - }) - - // After a Range of Delete, all keys should be removed and any - // further Range won't invoke the callback. Hence length remains 0. - length := 0 - m.Range(func(key, value any) bool { - length++ - return true - }) - - if length != 0 { - t.Fatalf("Unexpected sync.Map size, got %v want %v", length, 0) - } -} - -func TestCompareAndSwap_NonExistingKey(t *testutil.TestRunner) { - m := &sync.Map{} - if m.CompareAndSwap(m, nil, 42) { - // See https://go.dev/issue/51972#issuecomment-1126408637. - t.Fatalf("CompareAndSwap on a non-existing key succeeded") - } -} - -func TestMapRangeNoAllocations(t *testutil.TestRunner) { // Issue 62404 - var m sync.Map - allocs := testing.AllocsPerRun(10, func() { - m.Range(func(key, value any) bool { - return true - }) - }) - if allocs > 0 { - t.Errorf("AllocsPerRun of m.Range = %v; want 0", allocs) - } -} diff --git a/cannon/testdata/go-1-25/mt-mutex/go.mod b/cannon/testdata/go-1-25/mt-mutex/go.mod deleted file mode 100644 index 2be3cac451c..00000000000 --- a/cannon/testdata/go-1-25/mt-mutex/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module mutex - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/mt-mutex/main.go b/cannon/testdata/go-1-25/mt-mutex/main.go deleted file mode 100644 index 7c24f560af4..00000000000 --- a/cannon/testdata/go-1-25/mt-mutex/main.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestSemaphore, "TestSemaphore") - testutil.RunTest(TestMutex, "TestMutex") - testutil.RunTest(TestMutexFairness, "TestMutexFairness") - - fmt.Println("Mutex test passed") -} diff --git a/cannon/testdata/go-1-25/mt-mutex/mutex_test_copy.go b/cannon/testdata/go-1-25/mt-mutex/mutex_test_copy.go deleted file mode 100644 index d3ed9343c3d..00000000000 --- a/cannon/testdata/go-1-25/mt-mutex/mutex_test_copy.go +++ /dev/null @@ -1,135 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/mutex_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "runtime" - . "sync" - "time" - - "utils/testutil" -) - -func HammerSemaphore(s *uint32, loops int, cdone chan bool) { - for i := 0; i < loops; i++ { - Runtime_Semacquire(s) - Runtime_Semrelease(s, false, 0) - } - cdone <- true -} - -func TestSemaphore(t *testutil.TestRunner) { - s := new(uint32) - *s = 1 - c := make(chan bool) - for i := 0; i < 10; i++ { - go HammerSemaphore(s, 1000, c) - } - for i := 0; i < 10; i++ { - <-c - } -} - -func HammerMutex(m *Mutex, loops int, cdone chan bool) { - for i := 0; i < loops; i++ { - if i%3 == 0 { - if m.TryLock() { - m.Unlock() - } - continue - } - m.Lock() - m.Unlock() - } - cdone <- true -} - -func TestMutex(t *testutil.TestRunner) { - if n := runtime.SetMutexProfileFraction(1); n != 0 { - t.Logf("got mutexrate %d expected 0", n) - } - defer runtime.SetMutexProfileFraction(0) - - m := new(Mutex) - - m.Lock() - if m.TryLock() { - t.Fatalf("TryLock succeeded with mutex locked") - } - m.Unlock() - if !m.TryLock() { - t.Fatalf("TryLock failed with mutex unlocked") - } - m.Unlock() - - c := make(chan bool) - for i := 0; i < 10; i++ { - go HammerMutex(m, 1000, c) - } - for i := 0; i < 10; i++ { - <-c - } -} - -func TestMutexFairness(t *testutil.TestRunner) { - var mu Mutex - stop := make(chan bool) - defer close(stop) - go func() { - for { - mu.Lock() - time.Sleep(100 * time.Microsecond) - mu.Unlock() - select { - case <-stop: - return - default: - } - } - }() - done := make(chan bool, 1) - go func() { - for i := 0; i < 10; i++ { - time.Sleep(100 * time.Microsecond) - mu.Lock() - mu.Unlock() - } - done <- true - }() - select { - case <-done: - case <-time.After(10 * time.Second): - t.Fatalf("can't acquire Mutex in 10 seconds") - } -} diff --git a/cannon/testdata/go-1-25/mt-mutex/runtime.go b/cannon/testdata/go-1-25/mt-mutex/runtime.go deleted file mode 100644 index 8d70cb10b35..00000000000 --- a/cannon/testdata/go-1-25/mt-mutex/runtime.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - _ "unsafe" // Required for go:linkname -) - -var Runtime_Semacquire = runtime_Semacquire -var Runtime_Semrelease = runtime_Semrelease - -//go:linkname runtime_Semacquire sync.runtime_Semacquire -func runtime_Semacquire(s *uint32) - -//go:linkname runtime_Semrelease sync.runtime_Semrelease -func runtime_Semrelease(s *uint32, handoff bool, skipframes int) diff --git a/cannon/testdata/go-1-25/mt-once/go.mod b/cannon/testdata/go-1-25/mt-once/go.mod deleted file mode 100644 index 7d487d3f37c..00000000000 --- a/cannon/testdata/go-1-25/mt-once/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module once - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/mt-once/main.go b/cannon/testdata/go-1-25/mt-once/main.go deleted file mode 100644 index c53af95d3d7..00000000000 --- a/cannon/testdata/go-1-25/mt-once/main.go +++ /dev/null @@ -1,100 +0,0 @@ -// Portions of this code are derived from code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/400433af3660905ecaceaf19ddad3e6c24b141df/src/sync/once_test.go -// -// --- Original License Notice --- -// -// Copyright 2009 The Go Authors. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - "os" - "sync" -) - -func main() { - TestOnce() - TestOncePanic() - - fmt.Println("Once test passed") -} - -type one int - -func (o *one) Increment() { - *o++ -} - -func run(once *sync.Once, o *one, c chan bool) { - once.Do(func() { o.Increment() }) - if v := *o; v != 1 { - _, _ = fmt.Fprintf(os.Stderr, "once failed inside run: %d is not 1\n", v) - os.Exit(1) - } - c <- true -} - -func TestOnce() { - o := new(one) - once := new(sync.Once) - c := make(chan bool) - const N = 10 - for i := 0; i < N; i++ { - go run(once, o, c) - } - for i := 0; i < N; i++ { - <-c - } - if *o != 1 { - _, _ = fmt.Fprintf(os.Stderr, "once failed outside run: %d is not 1\n", *o) - os.Exit(1) - } -} - -func TestOncePanic() { - var once sync.Once - func() { - defer func() { - if r := recover(); r == nil { - _, _ = fmt.Fprintf(os.Stderr, "Once.Do did not panic") - os.Exit(1) - } - }() - once.Do(func() { - panic("failed") - }) - }() - - once.Do(func() { - _, _ = fmt.Fprintf(os.Stderr, "Once.Do called twice") - os.Exit(1) - }) -} diff --git a/cannon/testdata/go-1-25/mt-oncefunc/go.mod b/cannon/testdata/go-1-25/mt-oncefunc/go.mod deleted file mode 100644 index 5a6c1763b06..00000000000 --- a/cannon/testdata/go-1-25/mt-oncefunc/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module oncefunc - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/mt-oncefunc/main.go b/cannon/testdata/go-1-25/mt-oncefunc/main.go deleted file mode 100644 index a004621d5be..00000000000 --- a/cannon/testdata/go-1-25/mt-oncefunc/main.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestOnceFunc, "TestOnceFunc") - testutil.RunTest(TestOnceValue, "TestOnceValue") - testutil.RunTest(TestOnceValues, "TestOnceValues") - testutil.RunTest(TestOnceFuncPanic, "TestOnceFuncPanic") - testutil.RunTest(TestOnceValuePanic, "TestOnceValuePanic") - testutil.RunTest(TestOnceValuesPanic, "TestOnceValuesPanic") - testutil.RunTest(TestOnceFuncPanicNil, "TestOnceFuncPanicNil") - testutil.RunTest(TestOnceFuncGoexit, "TestOnceFuncGoexit") - testutil.RunTest(TestOnceFuncPanicTraceback, "TestOnceFuncPanicTraceback") - testutil.RunTest(TestOnceXGC, "TestOnceXGC") - - fmt.Println("OnceFunc tests passed") -} diff --git a/cannon/testdata/go-1-25/mt-oncefunc/oncefunc_test_copy.go b/cannon/testdata/go-1-25/mt-oncefunc/oncefunc_test_copy.go deleted file mode 100644 index fdbe93c260a..00000000000 --- a/cannon/testdata/go-1-25/mt-oncefunc/oncefunc_test_copy.go +++ /dev/null @@ -1,265 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/oncefunc_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "bytes" - "math" - "runtime" - "runtime/debug" - "sync" - "sync/atomic" - "testing" - _ "unsafe" - - "utils/testutil" -) - -// We assume that the Once.Do tests have already covered parallelism. - -func TestOnceFunc(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceFunc(func() { calls++ }) - allocs := testing.AllocsPerRun(10, f) - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } - if allocs != 0 { - t.Errorf("want 0 allocations per call, got %v", allocs) - } -} - -func TestOnceValue(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValue(func() int { - calls++ - return calls - }) - allocs := testing.AllocsPerRun(10, func() { f() }) - value := f() - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } - if value != 1 { - t.Errorf("want value==1, got %d", value) - } - if allocs != 0 { - t.Errorf("want 0 allocations per call, got %v", allocs) - } -} - -func TestOnceValues(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValues(func() (int, int) { - calls++ - return calls, calls + 1 - }) - allocs := testing.AllocsPerRun(10, func() { f() }) - v1, v2 := f() - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } - if v1 != 1 || v2 != 2 { - t.Errorf("want v1==1 and v2==2, got %d and %d", v1, v2) - } - if allocs != 0 { - t.Errorf("want 0 allocations per call, got %v", allocs) - } -} - -func testOncePanicX(t testing.TB, calls *int, f func()) { - testOncePanicWith(t, calls, f, func(label string, p any) { - if p != "x" { - t.Fatalf("%s: want panic %v, got %v", label, "x", p) - } - }) -} - -func testOncePanicWith(t testing.TB, calls *int, f func(), check func(label string, p any)) { - // Check that the each call to f panics with the same value, but the - // underlying function is only called once. - for _, label := range []string{"first time", "second time"} { - var p any - panicked := true - func() { - defer func() { - p = recover() - }() - f() - panicked = false - }() - if !panicked { - t.Fatalf("%s: f did not panic", label) - } - check(label, p) - } - if *calls != 1 { - t.Errorf("want calls==1, got %d", *calls) - } -} - -func TestOnceFuncPanic(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceFunc(func() { - calls++ - panic("x") - }) - testOncePanicX(t, &calls, f) -} - -func TestOnceValuePanic(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValue(func() int { - calls++ - panic("x") - }) - testOncePanicX(t, &calls, func() { f() }) -} - -func TestOnceValuesPanic(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceValues(func() (int, int) { - calls++ - panic("x") - }) - testOncePanicX(t, &calls, func() { f() }) -} - -func TestOnceFuncPanicNil(t *testutil.TestRunner) { - calls := 0 - f := sync.OnceFunc(func() { - calls++ - panic(nil) - }) - testOncePanicWith(t, &calls, f, func(label string, p any) { - switch p.(type) { - case nil, *runtime.PanicNilError: - return - } - t.Fatalf("%s: want nil panic, got %v", label, p) - }) -} - -func TestOnceFuncGoexit(t *testutil.TestRunner) { - // If f calls Goexit, the results are unspecified. But check that f doesn't - // get called twice. - calls := 0 - f := sync.OnceFunc(func() { - calls++ - runtime.Goexit() - }) - var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() - defer func() { recover() }() - f() - }() - wg.Wait() - } - if calls != 1 { - t.Errorf("want calls==1, got %d", calls) - } -} - -func TestOnceFuncPanicTraceback(t *testutil.TestRunner) { - // Test that on the first invocation of a OnceFunc, the stack trace goes all - // the way to the origin of the panic. - f := sync.OnceFunc(onceFuncPanic) - - defer func() { - if p := recover(); p != "x" { - t.Fatalf("want panic %v, got %v", "x", p) - } - stack := debug.Stack() - //want := "sync_test.onceFuncPanic" - want := "main.onceFuncPanic" - if !bytes.Contains(stack, []byte(want)) { - t.Fatalf("want stack containing %v, got:\n%s", want, string(stack)) - } - }() - f() -} - -func onceFuncPanic() { - panic("x") -} - -func TestOnceXGC(t *testutil.TestRunner) { - fns := map[string]func([]byte) func(){ - "OnceFunc": func(buf []byte) func() { - return sync.OnceFunc(func() { buf[0] = 1 }) - }, - "OnceValue": func(buf []byte) func() { - f := sync.OnceValue(func() any { buf[0] = 1; return nil }) - return func() { f() } - }, - "OnceValues": func(buf []byte) func() { - f := sync.OnceValues(func() (any, any) { buf[0] = 1; return nil, nil }) - return func() { f() } - }, - } - for n, fn := range fns { - t.Run(n, func(t testing.TB) { - buf := make([]byte, 1024) - var gc atomic.Bool - runtime.SetFinalizer(&buf[0], func(_ *byte) { - gc.Store(true) - }) - f := fn(buf) - gcwaitfin() - if gc.Load() != false { - t.Fatal("wrapped function garbage collected too early") - } - f() - gcwaitfin() - if gc.Load() != true { - // Even if f is still alive, the function passed to Once(Func|Value|Values) - // is not kept alive after the first call to f. - t.Fatal("wrapped function should be garbage collected, but still live") - } - f() - }) - } -} - -// gcwaitfin performs garbage collection and waits for all finalizers to run. -func gcwaitfin() { - runtime.GC() - runtime_blockUntilEmptyFinalizerQueue(math.MaxInt64) -} - -//go:linkname runtime_blockUntilEmptyFinalizerQueue runtime.blockUntilEmptyFinalizerQueue -func runtime_blockUntilEmptyFinalizerQueue(int64) bool diff --git a/cannon/testdata/go-1-25/mt-pool/export_test_copy.go b/cannon/testdata/go-1-25/mt-pool/export_test_copy.go deleted file mode 100644 index 37b7c4a92bf..00000000000 --- a/cannon/testdata/go-1-25/mt-pool/export_test_copy.go +++ /dev/null @@ -1,86 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/export_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -// Export for testing. -// var Runtime_Semacquire = runtime_Semacquire -// var Runtime_Semrelease = runtime_Semrelease -var Runtime_procPin = runtime_procPin -var Runtime_procUnpin = runtime_procUnpin - -// poolDequeue testing. -type PoolDequeue interface { - PushHead(val any) bool - PopHead() (any, bool) - PopTail() (any, bool) -} - -func NewPoolDequeue(n int) PoolDequeue { - d := &poolDequeue{ - vals: make([]eface, n), - } - // For testing purposes, set the head and tail indexes close - // to wrapping around. - d.headTail.Store(d.pack(1< ./../../utils diff --git a/cannon/testdata/go-1-25/mt-pool/main.go b/cannon/testdata/go-1-25/mt-pool/main.go deleted file mode 100644 index 632ec662242..00000000000 --- a/cannon/testdata/go-1-25/mt-pool/main.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestPool, "TestPool") - testutil.RunTest(TestPoolNew, "TestPoolNew") - testutil.RunTest(TestPoolGC, "TestPoolGC") - testutil.RunTest(TestPoolRelease, "TestPoolRelease") - testutil.RunTest(TestPoolStress, "TestPoolStress") - testutil.RunTest(TestPoolDequeue, "TestPoolDequeue") - testutil.RunTest(TestPoolChain, "TestPoolChain") - testutil.RunTest(TestNilPool, "TestNilPool") - - fmt.Println("Pool test passed") -} diff --git a/cannon/testdata/go-1-25/mt-pool/pool_test_copy.go b/cannon/testdata/go-1-25/mt-pool/pool_test_copy.go deleted file mode 100644 index 962cbfce7b5..00000000000 --- a/cannon/testdata/go-1-25/mt-pool/pool_test_copy.go +++ /dev/null @@ -1,298 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/pool_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "runtime" - "runtime/debug" - . "sync" - "sync/atomic" - "testing" - "time" - - "utils/testutil" -) - -var short bool = true - -func TestPool(t *testutil.TestRunner) { - // disable GC so we can control when it happens. - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - var p Pool - if p.Get() != nil { - t.Fatal("expected empty") - } - - // Make sure that the goroutine doesn't migrate to another P - // between Put and Get calls. - Runtime_procPin() - p.Put("a") - p.Put("b") - if g := p.Get(); g != "a" { - t.Fatalf("got %#v; want a", g) - } - if g := p.Get(); g != "b" { - t.Fatalf("got %#v; want b", g) - } - if g := p.Get(); g != nil { - t.Fatalf("got %#v; want nil", g) - } - Runtime_procUnpin() - - // Put in a large number of objects so they spill into - // stealable space. - for i := 0; i < 100; i++ { - p.Put("c") - } - // After one GC, the victim cache should keep them alive. - runtime.GC() - if g := p.Get(); g != "c" { - t.Fatalf("got %#v; want c after GC", g) - } - // A second GC should drop the victim cache. - runtime.GC() - if g := p.Get(); g != nil { - t.Fatalf("got %#v; want nil after second GC", g) - } -} - -func TestPoolNew(t *testutil.TestRunner) { - // disable GC so we can control when it happens. - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - - i := 0 - p := Pool{ - New: func() any { - i++ - return i - }, - } - if v := p.Get(); v != 1 { - t.Fatalf("got %v; want 1", v) - } - if v := p.Get(); v != 2 { - t.Fatalf("got %v; want 2", v) - } - - // Make sure that the goroutine doesn't migrate to another P - // between Put and Get calls. - Runtime_procPin() - p.Put(42) - if v := p.Get(); v != 42 { - t.Fatalf("got %v; want 42", v) - } - Runtime_procUnpin() - - if v := p.Get(); v != 3 { - t.Fatalf("got %v; want 3", v) - } -} - -// Test that Pool does not hold pointers to previously cached resources. -func TestPoolGC(t *testutil.TestRunner) { - testPool(t, true) -} - -// Test that Pool releases resources on GC. -func TestPoolRelease(t *testutil.TestRunner) { - testPool(t, false) -} - -func testPool(t testing.TB, drain bool) { - var p Pool - const N = 100 -loop: - for try := 0; try < 3; try++ { - if try == 1 && short { - break - } - var fin, fin1 uint32 - for i := 0; i < N; i++ { - v := new(string) - runtime.SetFinalizer(v, func(vv *string) { - atomic.AddUint32(&fin, 1) - }) - p.Put(v) - } - if drain { - for i := 0; i < N; i++ { - p.Get() - } - } - for i := 0; i < 5; i++ { - runtime.GC() - time.Sleep(time.Duration(i*100+10) * time.Millisecond) - // 1 pointer can remain on stack or elsewhere - if fin1 = atomic.LoadUint32(&fin); fin1 >= N-1 { - continue loop - } - } - t.Fatalf("only %v out of %v resources are finalized on try %v", fin1, N, try) - } -} - -func TestPoolStress(t *testutil.TestRunner) { - const P = 10 - N := int(1e6) - if short { - N /= 100 - } - var p Pool - done := make(chan bool) - for i := 0; i < P; i++ { - go func() { - var v any = 0 - for j := 0; j < N; j++ { - if v == nil { - v = 0 - } - p.Put(v) - v = p.Get() - if v != nil && v.(int) != 0 { - t.Errorf("expect 0, got %v", v) - break - } - } - done <- true - }() - } - for i := 0; i < P; i++ { - <-done - } -} - -func TestPoolDequeue(t *testutil.TestRunner) { - testPoolDequeue(t, NewPoolDequeue(16)) -} - -func TestPoolChain(t *testutil.TestRunner) { - testPoolDequeue(t, NewPoolChain()) -} - -func testPoolDequeue(t testing.TB, d PoolDequeue) { - const P = 10 - var N int = 2e6 - if short { - N = 1e3 - } - have := make([]int32, N) - var stop int32 - var wg WaitGroup - record := func(val int) { - atomic.AddInt32(&have[val], 1) - if val == N-1 { - atomic.StoreInt32(&stop, 1) - } - } - - // Start P-1 consumers. - for i := 1; i < P; i++ { - wg.Add(1) - go func() { - fail := 0 - for atomic.LoadInt32(&stop) == 0 { - val, ok := d.PopTail() - if ok { - fail = 0 - record(val.(int)) - } else { - // Speed up the test by - // allowing the pusher to run. - if fail++; fail%100 == 0 { - runtime.Gosched() - } - } - } - wg.Done() - }() - } - - // Start 1 producer. - nPopHead := 0 - wg.Add(1) - go func() { - for j := 0; j < N; j++ { - for !d.PushHead(j) { - // Allow a popper to run. - runtime.Gosched() - } - if j%10 == 0 { - val, ok := d.PopHead() - if ok { - nPopHead++ - record(val.(int)) - } - } - } - wg.Done() - }() - wg.Wait() - - // Check results. - for i, count := range have { - if count != 1 { - t.Errorf("expected have[%d] = 1, got %d", i, count) - } - } - // Check that at least some PopHeads succeeded. We skip this - // check in short mode because it's common enough that the - // queue will stay nearly empty all the time and a PopTail - // will happen during the window between every PushHead and - // PopHead. - if !short && nPopHead == 0 { - t.Errorf("popHead never succeeded") - } -} - -func TestNilPool(t *testutil.TestRunner) { - catch := func() { - if recover() == nil { - t.Error("expected panic") - } - } - - var p *Pool - t.Run("Get", func(t testing.TB) { - defer catch() - if p.Get() != nil { - t.Error("expected empty") - } - t.Error("should have panicked already") - }) - t.Run("Put", func(t testing.TB) { - defer catch() - p.Put("a") - t.Error("should have panicked already") - }) -} diff --git a/cannon/testdata/go-1-25/mt-pool/poolqueue_copy.go b/cannon/testdata/go-1-25/mt-pool/poolqueue_copy.go deleted file mode 100644 index 5aa7b1ffa7b..00000000000 --- a/cannon/testdata/go-1-25/mt-pool/poolqueue_copy.go +++ /dev/null @@ -1,338 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/poolqueue.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "sync/atomic" - "unsafe" -) - -// poolDequeue is a lock-free fixed-size single-producer, -// multi-consumer queue. The single producer can both push and pop -// from the head, and consumers can pop from the tail. -// -// It has the added feature that it nils out unused slots to avoid -// unnecessary retention of objects. This is important for sync.Pool, -// but not typically a property considered in the literature. -type poolDequeue struct { - // headTail packs together a 32-bit head index and a 32-bit - // tail index. Both are indexes into vals modulo len(vals)-1. - // - // tail = index of oldest data in queue - // head = index of next slot to fill - // - // Slots in the range [tail, head) are owned by consumers. - // A consumer continues to own a slot outside this range until - // it nils the slot, at which point ownership passes to the - // producer. - // - // The head index is stored in the most-significant bits so - // that we can atomically add to it and the overflow is - // harmless. - headTail atomic.Uint64 - - // vals is a ring buffer of interface{} values stored in this - // dequeue. The size of this must be a power of 2. - // - // vals[i].typ is nil if the slot is empty and non-nil - // otherwise. A slot is still in use until *both* the tail - // index has moved beyond it and typ has been set to nil. This - // is set to nil atomically by the consumer and read - // atomically by the producer. - vals []eface -} - -type eface struct { - typ, val unsafe.Pointer -} - -const dequeueBits = 32 - -// dequeueLimit is the maximum size of a poolDequeue. -// -// This must be at most (1<> dequeueBits) & mask) - tail = uint32(ptrs & mask) - return -} - -func (d *poolDequeue) pack(head, tail uint32) uint64 { - const mask = 1<= dequeueLimit { - // Can't make it any bigger. - newSize = dequeueLimit - } - - d2 := &poolChainElt{prev: d} - d2.vals = make([]eface, newSize) - c.head = d2 - storePoolChainElt(&d.next, d2) - d2.pushHead(val) -} - -func (c *poolChain) popHead() (any, bool) { - d := c.head - for d != nil { - if val, ok := d.popHead(); ok { - return val, ok - } - // There may still be unconsumed elements in the - // previous dequeue, so try backing up. - d = loadPoolChainElt(&d.prev) - } - return nil, false -} - -func (c *poolChain) popTail() (any, bool) { - d := loadPoolChainElt(&c.tail) - if d == nil { - return nil, false - } - - for { - // It's important that we load the next pointer - // *before* popping the tail. In general, d may be - // transiently empty, but if next is non-nil before - // the pop and the pop fails, then d is permanently - // empty, which is the only condition under which it's - // safe to drop d from the chain. - d2 := loadPoolChainElt(&d.next) - - if val, ok := d.popTail(); ok { - return val, ok - } - - if d2 == nil { - // This is the only dequeue. It's empty right - // now, but could be pushed to in the future. - return nil, false - } - - // The tail of the chain has been drained, so move on - // to the next dequeue. Try to drop it from the chain - // so the next pop doesn't have to look at the empty - // dequeue again. - if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.tail)), unsafe.Pointer(d), unsafe.Pointer(d2)) { - // We won the race. Clear the prev pointer so - // the garbage collector can collect the empty - // dequeue and so popHead doesn't back up - // further than necessary. - storePoolChainElt(&d2.prev, nil) - } - d = d2 - } -} diff --git a/cannon/testdata/go-1-25/mt-pool/runtime.go b/cannon/testdata/go-1-25/mt-pool/runtime.go deleted file mode 100644 index 1b6dbe3e6cd..00000000000 --- a/cannon/testdata/go-1-25/mt-pool/runtime.go +++ /dev/null @@ -1,11 +0,0 @@ -package main - -import ( - _ "unsafe" // Required for go:linkname -) - -//go:linkname runtime_procPin runtime.procPin -func runtime_procPin() int - -//go:linkname runtime_procUnpin runtime.procUnpin -func runtime_procUnpin() diff --git a/cannon/testdata/go-1-25/mt-rwmutex/go.mod b/cannon/testdata/go-1-25/mt-rwmutex/go.mod deleted file mode 100644 index d92b7de4ee6..00000000000 --- a/cannon/testdata/go-1-25/mt-rwmutex/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module rwmutex - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/mt-rwmutex/main.go b/cannon/testdata/go-1-25/mt-rwmutex/main.go deleted file mode 100644 index 998a80e5eda..00000000000 --- a/cannon/testdata/go-1-25/mt-rwmutex/main.go +++ /dev/null @@ -1,228 +0,0 @@ -// Portions of this code are derived from code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/400433af3660905ecaceaf19ddad3e6c24b141df/src/sync/rwmutex_test.go -// -// --- Original License Notice --- -// -// Copyright 2009 The Go Authors. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - "os" - "runtime" - "sync" - "sync/atomic" -) - -func main() { - TestParallelReaders() - TestRLocker() - TestRWMutex() - - fmt.Println("RWMutex test passed") -} - -func parallelReader(m *sync.RWMutex, clocked, cunlock, cdone chan bool) { - m.RLock() - clocked <- true - <-cunlock - m.RUnlock() - cdone <- true -} - -func doTestParallelReaders(numReaders, gomaxprocs int) { - runtime.GOMAXPROCS(gomaxprocs) - var m sync.RWMutex - clocked := make(chan bool) - cunlock := make(chan bool) - cdone := make(chan bool) - for i := 0; i < numReaders; i++ { - go parallelReader(&m, clocked, cunlock, cdone) - } - // Wait for all parallel RLock()s to succeed. - for i := 0; i < numReaders; i++ { - <-clocked - } - for i := 0; i < numReaders; i++ { - cunlock <- true - } - // Wait for the goroutines to finish. - for i := 0; i < numReaders; i++ { - <-cdone - } -} - -func TestParallelReaders() { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1)) - doTestParallelReaders(1, 4) - doTestParallelReaders(3, 4) - doTestParallelReaders(4, 2) -} - -func reader(rwm *sync.RWMutex, num_iterations int, activity *int32, cdone chan bool) { - for i := 0; i < num_iterations; i++ { - rwm.RLock() - n := atomic.AddInt32(activity, 1) - if n < 1 || n >= 10000 { - rwm.RUnlock() - panic(fmt.Sprintf("wlock(%d)\n", n)) - } - for i := 0; i < 100; i++ { - } - atomic.AddInt32(activity, -1) - rwm.RUnlock() - } - cdone <- true -} - -func writer(rwm *sync.RWMutex, num_iterations int, activity *int32, cdone chan bool) { - for i := 0; i < num_iterations; i++ { - rwm.Lock() - n := atomic.AddInt32(activity, 10000) - if n != 10000 { - rwm.Unlock() - panic(fmt.Sprintf("wlock(%d)\n", n)) - } - for i := 0; i < 100; i++ { - } - atomic.AddInt32(activity, -10000) - rwm.Unlock() - } - cdone <- true -} - -func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) { - runtime.GOMAXPROCS(gomaxprocs) - // Number of active readers + 10000 * number of active writers. - var activity int32 - var rwm sync.RWMutex - cdone := make(chan bool) - go writer(&rwm, num_iterations, &activity, cdone) - var i int - for i = 0; i < numReaders/2; i++ { - go reader(&rwm, num_iterations, &activity, cdone) - } - go writer(&rwm, num_iterations, &activity, cdone) - for ; i < numReaders; i++ { - go reader(&rwm, num_iterations, &activity, cdone) - } - // Wait for the 2 writers and all readers to finish. - for i := 0; i < 2+numReaders; i++ { - <-cdone - } -} - -func TestRWMutex() { - var m sync.RWMutex - - m.Lock() - if m.TryLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryLock succeeded with mutex locked") - os.Exit(1) - } - if m.TryRLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryRLock succeeded with mutex locked") - os.Exit(1) - } - m.Unlock() - - if !m.TryLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryLock failed with mutex unlocked") - os.Exit(1) - } - m.Unlock() - - if !m.TryRLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryRLock failed with mutex unlocked") - os.Exit(1) - } - if !m.TryRLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryRLock failed with mutex unlocked") - os.Exit(1) - } - if m.TryLock() { - _, _ = fmt.Fprintln(os.Stderr, "TryLock succeeded with mutex rlocked") - os.Exit(1) - } - m.RUnlock() - m.RUnlock() - - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1)) - n := 5 - - HammerRWMutex(1, 1, n) - HammerRWMutex(1, 3, n) - HammerRWMutex(1, 10, n) - HammerRWMutex(4, 1, n) - HammerRWMutex(4, 3, n) - HammerRWMutex(4, 10, n) - HammerRWMutex(10, 1, n) - HammerRWMutex(10, 3, n) - HammerRWMutex(10, 10, n) - HammerRWMutex(10, 5, n) -} - -func TestRLocker() { - var wl sync.RWMutex - var rl sync.Locker - wlocked := make(chan bool, 1) - rlocked := make(chan bool, 1) - rl = wl.RLocker() - n := 10 - go func() { - for i := 0; i < n; i++ { - rl.Lock() - rl.Lock() - rlocked <- true - wl.Lock() - wlocked <- true - } - }() - for i := 0; i < n; i++ { - <-rlocked - rl.Unlock() - select { - case <-wlocked: - _, _ = fmt.Fprintln(os.Stderr, "RLocker() didn't read-lock it") - os.Exit(1) - default: - } - rl.Unlock() - <-wlocked - select { - case <-rlocked: - _, _ = fmt.Fprintln(os.Stderr, "RLocker() didn't respect the write lock") - os.Exit(1) - default: - } - wl.Unlock() - } -} diff --git a/cannon/testdata/go-1-25/mt-value/go.mod b/cannon/testdata/go-1-25/mt-value/go.mod deleted file mode 100644 index 2bdfccdf22d..00000000000 --- a/cannon/testdata/go-1-25/mt-value/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module mtvalue - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/mt-value/main.go b/cannon/testdata/go-1-25/mt-value/main.go deleted file mode 100644 index 87ba3173099..00000000000 --- a/cannon/testdata/go-1-25/mt-value/main.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestValue, "TestValue") - testutil.RunTest(TestValueLarge, "TestValueLarge") - testutil.RunTest(TestValuePanic, "TestValuePanic") - testutil.RunTest(TestValueConcurrent, "TestValueConcurrent") - testutil.RunTest(TestValue_Swap, "TestValue_Swap") - testutil.RunTest(TestValueSwapConcurrent, "TestValueSwapConcurrent") - testutil.RunTest(TestValue_CompareAndSwap, "TestValue_CompareAndSwap") - testutil.RunTest(TestValueCompareAndSwapConcurrent, "TestValueCompareAndSwapConcurrent") - - fmt.Println("Value tests passed") -} diff --git a/cannon/testdata/go-1-25/mt-value/value_test_copy.go b/cannon/testdata/go-1-25/mt-value/value_test_copy.go deleted file mode 100644 index 32ccc006740..00000000000 --- a/cannon/testdata/go-1-25/mt-value/value_test_copy.go +++ /dev/null @@ -1,312 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/atomic/value_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - "math/rand" - "runtime" - "strconv" - "sync" - "sync/atomic" - . "sync/atomic" - "testing" - - "utils/testutil" -) - -var short bool = true - -func TestValue(t *testutil.TestRunner) { - var v Value - if v.Load() != nil { - t.Fatal("initial Value is not nil") - } - v.Store(42) - x := v.Load() - if xx, ok := x.(int); !ok || xx != 42 { - t.Fatalf("wrong value: got %+v, want 42", x) - } - v.Store(84) - x = v.Load() - if xx, ok := x.(int); !ok || xx != 84 { - t.Fatalf("wrong value: got %+v, want 84", x) - } -} - -func TestValueLarge(t *testutil.TestRunner) { - var v Value - v.Store("foo") - x := v.Load() - if xx, ok := x.(string); !ok || xx != "foo" { - t.Fatalf("wrong value: got %+v, want foo", x) - } - v.Store("barbaz") - x = v.Load() - if xx, ok := x.(string); !ok || xx != "barbaz" { - t.Fatalf("wrong value: got %+v, want barbaz", x) - } -} - -func TestValuePanic(t *testutil.TestRunner) { - const nilErr = "sync/atomic: store of nil value into Value" - const badErr = "sync/atomic: store of inconsistently typed value into Value" - var v Value - func() { - defer func() { - err := recover() - if err != nilErr { - t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr) - } - }() - v.Store(nil) - }() - v.Store(42) - func() { - defer func() { - err := recover() - if err != badErr { - t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, badErr) - } - }() - v.Store("foo") - }() - func() { - defer func() { - err := recover() - if err != nilErr { - t.Fatalf("inconsistent store panic: got '%v', want '%v'", err, nilErr) - } - }() - v.Store(nil) - }() -} - -func TestValueConcurrent(t *testutil.TestRunner) { - tests := [][]any{ - {uint16(0), ^uint16(0), uint16(1 + 2<<8), uint16(3 + 4<<8)}, - {uint32(0), ^uint32(0), uint32(1 + 2<<16), uint32(3 + 4<<16)}, - {uint64(0), ^uint64(0), uint64(1 + 2<<32), uint64(3 + 4<<32)}, - {complex(0, 0), complex(1, 2), complex(3, 4), complex(5, 6)}, - } - p := 4 * runtime.GOMAXPROCS(0) - N := int(1e5) - if short { - p /= 2 - //N = 1e3 - N = 1e2 - } - for _, test := range tests { - var v Value - done := make(chan bool, p) - for i := 0; i < p; i++ { - go func() { - r := rand.New(rand.NewSource(rand.Int63())) - expected := true - loop: - for j := 0; j < N; j++ { - x := test[r.Intn(len(test))] - v.Store(x) - x = v.Load() - for _, x1 := range test { - if x == x1 { - continue loop - } - } - t.Logf("loaded unexpected value %+v, want %+v", x, test) - expected = false - break - } - done <- expected - }() - } - for i := 0; i < p; i++ { - if !<-done { - t.FailNow() - } - } - } -} - -func BenchmarkValueRead(b *testing.B) { - var v Value - v.Store(new(int)) - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - x := v.Load().(*int) - if *x != 0 { - b.Fatalf("wrong value: got %v, want 0", *x) - } - } - }) -} - -var Value_SwapTests = []struct { - init any - new any - want any - err any -}{ - {init: nil, new: nil, err: "sync/atomic: swap of nil value into Value"}, - {init: nil, new: true, want: nil, err: nil}, - {init: true, new: "", err: "sync/atomic: swap of inconsistently typed value into Value"}, - {init: true, new: false, want: true, err: nil}, -} - -func TestValue_Swap(t *testutil.TestRunner) { - for i, tt := range Value_SwapTests { - t.Run(strconv.Itoa(i), func(t testing.TB) { - var v Value - if tt.init != nil { - v.Store(tt.init) - } - defer func() { - err := recover() - switch { - case tt.err == nil && err != nil: - t.Errorf("should not panic, got %v", err) - case tt.err != nil && err == nil: - t.Errorf("should panic %v, got ", tt.err) - } - }() - if got := v.Swap(tt.new); got != tt.want { - t.Errorf("got %v, want %v", got, tt.want) - } - if got := v.Load(); got != tt.new { - t.Errorf("got %v, want %v", got, tt.new) - } - }) - } -} - -func TestValueSwapConcurrent(t *testutil.TestRunner) { - var v Value - var count uint64 - var g sync.WaitGroup - var m, n uint64 = 10000, 10000 - if short { - //m = 1000 - //n = 1000 - m = 10 - n = 10 - } - for i := uint64(0); i < m*n; i += n { - i := i - g.Add(1) - go func() { - var c uint64 - for new := i; new < i+n; new++ { - if old := v.Swap(new); old != nil { - c += old.(uint64) - } - } - atomic.AddUint64(&count, c) - g.Done() - }() - } - g.Wait() - if want, got := (m*n-1)*(m*n)/2, count+v.Load().(uint64); got != want { - t.Errorf("sum from 0 to %d was %d, want %v", m*n-1, got, want) - } -} - -var heapA, heapB = struct{ uint }{0}, struct{ uint }{0} - -var Value_CompareAndSwapTests = []struct { - init any - new any - old any - want bool - err any -}{ - {init: nil, new: nil, old: nil, err: "sync/atomic: compare and swap of nil value into Value"}, - {init: nil, new: true, old: "", err: "sync/atomic: compare and swap of inconsistently typed values into Value"}, - {init: nil, new: true, old: true, want: false, err: nil}, - {init: nil, new: true, old: nil, want: true, err: nil}, - {init: true, new: "", err: "sync/atomic: compare and swap of inconsistently typed value into Value"}, - {init: true, new: true, old: false, want: false, err: nil}, - {init: true, new: true, old: true, want: true, err: nil}, - {init: heapA, new: struct{ uint }{1}, old: heapB, want: true, err: nil}, -} - -func TestValue_CompareAndSwap(t *testutil.TestRunner) { - for i, tt := range Value_CompareAndSwapTests { - t.Run(strconv.Itoa(i), func(t testing.TB) { - var v Value - if tt.init != nil { - v.Store(tt.init) - } - defer func() { - err := recover() - switch { - case tt.err == nil && err != nil: - t.Errorf("got %v, wanted no panic", err) - case tt.err != nil && err == nil: - t.Errorf("did not panic, want %v", tt.err) - } - }() - if got := v.CompareAndSwap(tt.old, tt.new); got != tt.want { - t.Errorf("got %v, want %v", got, tt.want) - } - }) - } -} - -func TestValueCompareAndSwapConcurrent(t *testutil.TestRunner) { - var v Value - var w sync.WaitGroup - v.Store(0) - m, n := 1000, 100 - if short { - //m = 100 - //n = 100 - m = 10 - n = 10 - } - for i := 0; i < m; i++ { - i := i - w.Add(1) - go func() { - for j := i; j < m*n; runtime.Gosched() { - if v.CompareAndSwap(j, j+1) { - j += m - } - } - w.Done() - }() - } - w.Wait() - if stop := v.Load().(int); stop != m*n { - t.Errorf("did not get to %v, stopped at %v", m*n, stop) - } -} diff --git a/cannon/testdata/go-1-25/mt-wg/go.mod b/cannon/testdata/go-1-25/mt-wg/go.mod deleted file mode 100644 index d09007abb48..00000000000 --- a/cannon/testdata/go-1-25/mt-wg/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module wg - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/mt-wg/main.go b/cannon/testdata/go-1-25/mt-wg/main.go deleted file mode 100644 index 702ebe38fdc..00000000000 --- a/cannon/testdata/go-1-25/mt-wg/main.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(TestWaitGroup, "TestWaitGroup") - testutil.RunTest(TestWaitGroupMisuse, "TestWaitGroupMisuse") - testutil.RunTest(TestWaitGroupRace, "TestWaitGroupRace") - testutil.RunTest(TestWaitGroupAlign, "TestWaitGroupAlign") - - fmt.Println("WaitGroup tests passed") -} diff --git a/cannon/testdata/go-1-25/mt-wg/waitgroup_test_copy.go b/cannon/testdata/go-1-25/mt-wg/waitgroup_test_copy.go deleted file mode 100644 index 81f0cd0ce4c..00000000000 --- a/cannon/testdata/go-1-25/mt-wg/waitgroup_test_copy.go +++ /dev/null @@ -1,130 +0,0 @@ -// This file is based on code written by The Go Authors. -// See original source: https://github.com/golang/go/blob/go1.22.7/src/sync/waitgroup_test.go -// -// --- Original License Notice --- -// -// Copyright (c) 2009 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package main - -import ( - . "sync" - "sync/atomic" - "testing" - - "utils/testutil" -) - -func testWaitGroup(t testing.TB, wg1 *WaitGroup, wg2 *WaitGroup) { - n := 16 - wg1.Add(n) - wg2.Add(n) - exited := make(chan bool, n) - for i := 0; i != n; i++ { - go func() { - wg1.Done() - wg2.Wait() - exited <- true - }() - } - wg1.Wait() - for i := 0; i != n; i++ { - select { - case <-exited: - t.Fatal("WaitGroup released group too soon") - default: - } - wg2.Done() - } - for i := 0; i != n; i++ { - <-exited // Will block if barrier fails to unlock someone. - } -} - -func TestWaitGroup(t *testutil.TestRunner) { - wg1 := &WaitGroup{} - wg2 := &WaitGroup{} - - // Run the same test a few times to ensure barrier is in a proper state. - for i := 0; i != 8; i++ { - testWaitGroup(t, wg1, wg2) - } -} - -func TestWaitGroupMisuse(t *testutil.TestRunner) { - defer func() { - err := recover() - if err != "sync: negative WaitGroup counter" { - t.Fatalf("Unexpected panic: %#v", err) - } - }() - wg := &WaitGroup{} - wg.Add(1) - wg.Done() - wg.Done() - t.Fatal("Should panic") -} - -func TestWaitGroupRace(t *testutil.TestRunner) { - // Run this test for about 1ms. - for i := 0; i < 1000; i++ { - wg := &WaitGroup{} - n := new(int32) - // spawn goroutine 1 - wg.Add(1) - go func() { - atomic.AddInt32(n, 1) - wg.Done() - }() - // spawn goroutine 2 - wg.Add(1) - go func() { - atomic.AddInt32(n, 1) - wg.Done() - }() - // Wait for goroutine 1 and 2 - wg.Wait() - if atomic.LoadInt32(n) != 2 { - t.Fatal("Spurious wakeup from Wait") - } - } -} - -func TestWaitGroupAlign(t *testutil.TestRunner) { - type X struct { - x byte - wg WaitGroup - } - var x X - x.wg.Add(1) - go func(x *X) { - x.wg.Done() - }(&x) - x.wg.Wait() -} diff --git a/cannon/testdata/go-1-25/random/go.mod b/cannon/testdata/go-1-25/random/go.mod deleted file mode 100644 index a5d20f5aa9d..00000000000 --- a/cannon/testdata/go-1-25/random/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module hello - -go 1.25 - -toolchain go1.25.4 - -godebug decoratemappings=0 diff --git a/cannon/testdata/go-1-25/random/main.go b/cannon/testdata/go-1-25/random/main.go deleted file mode 100644 index 575f16b73f2..00000000000 --- a/cannon/testdata/go-1-25/random/main.go +++ /dev/null @@ -1,46 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - crand "crypto/rand" - "encoding/binary" - "encoding/hex" - "fmt" -) - -func main() { - // Read a uint64 - var buf = make([]byte, 8) - readRandomBytes(buf) - randomInt := binary.BigEndian.Uint64(buf) - fmt.Printf("Random int: %d\n", randomInt) - - // Read a large chunk of bytes all at once - buf = make([]byte, 25) - readRandomBytes(buf) - printRandomBuffer(buf) - - // Read a small number of bytes 1 at a time - buf = make([]byte, 5) - for i := 0; i < len(buf); i++ { - readRandomBytes(buf[i : i+1]) - } - printRandomBuffer(buf) -} - -func printRandomBuffer(buf []byte) { - hexValue := hex.EncodeToString(buf) - fmt.Printf("Random hex data: %v\n", hexValue) -} - -func readRandomBytes(buf []byte) { - n, err := crand.Read(buf) - if err != nil { - fmt.Printf("Error reading bytes: %v\n", err) - panic(err) - } - if n != len(buf) { - fmt.Printf("Read %d bytes, expected %d\n", n, len(buf)) - panic("Read wrong number of bytes") - } -} diff --git a/cannon/testdata/go-1-25/syscall-eventfd/go.mod b/cannon/testdata/go-1-25/syscall-eventfd/go.mod deleted file mode 100644 index 6c1c0d35b45..00000000000 --- a/cannon/testdata/go-1-25/syscall-eventfd/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module syscalleventfd - -go 1.25 - -toolchain go1.25.4 - -require common v0.0.0 - -replace common => ./../../common diff --git a/cannon/testdata/go-1-25/syscall-eventfd/main.go b/cannon/testdata/go-1-25/syscall-eventfd/main.go deleted file mode 100644 index a05345c662b..00000000000 --- a/cannon/testdata/go-1-25/syscall-eventfd/main.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "common/syscalltests" -) - -func main() { - syscalltests.EventfdTest() -} diff --git a/cannon/testdata/go-1-25/utilscheck/go.mod b/cannon/testdata/go-1-25/utilscheck/go.mod deleted file mode 100644 index e04e9120f4f..00000000000 --- a/cannon/testdata/go-1-25/utilscheck/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/utilscheck/main.go b/cannon/testdata/go-1-25/utilscheck/main.go deleted file mode 100644 index 1d7c06736be..00000000000 --- a/cannon/testdata/go-1-25/utilscheck/main.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - t.Fail() -} diff --git a/cannon/testdata/go-1-25/utilscheck2/go.mod b/cannon/testdata/go-1-25/utilscheck2/go.mod deleted file mode 100644 index 556c3507569..00000000000 --- a/cannon/testdata/go-1-25/utilscheck2/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck2 - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/utilscheck2/main.go b/cannon/testdata/go-1-25/utilscheck2/main.go deleted file mode 100644 index 24932d89883..00000000000 --- a/cannon/testdata/go-1-25/utilscheck2/main.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - "testing" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - t.Run("subtest 1", func(t testing.TB) { - // Do something - }) - - t.Run("subtest 2", func(t testing.TB) { - t.Fail() - }) -} diff --git a/cannon/testdata/go-1-25/utilscheck3/go.mod b/cannon/testdata/go-1-25/utilscheck3/go.mod deleted file mode 100644 index b292bc4e72c..00000000000 --- a/cannon/testdata/go-1-25/utilscheck3/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck3 - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/utilscheck3/main.go b/cannon/testdata/go-1-25/utilscheck3/main.go deleted file mode 100644 index e09944999ee..00000000000 --- a/cannon/testdata/go-1-25/utilscheck3/main.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - "testing" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - t.Run("panic test", func(t testing.TB) { - panic("oops") - }) -} diff --git a/cannon/testdata/go-1-25/utilscheck4/go.mod b/cannon/testdata/go-1-25/utilscheck4/go.mod deleted file mode 100644 index 012d1ef4b6b..00000000000 --- a/cannon/testdata/go-1-25/utilscheck4/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module utilscheck4 - -go 1.25 - -toolchain go1.25.4 - -require utils v0.0.0 - -replace utils => ./../../utils diff --git a/cannon/testdata/go-1-25/utilscheck4/main.go b/cannon/testdata/go-1-25/utilscheck4/main.go deleted file mode 100644 index d5a3d4210d8..00000000000 --- a/cannon/testdata/go-1-25/utilscheck4/main.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:debug decoratemappings=0 -package main - -import ( - "fmt" - - "utils/testutil" -) - -func main() { - testutil.RunTest(ShouldFail, "ShouldFail") - - fmt.Println("Passed test that should have failed") -} - -func ShouldFail(t *testutil.TestRunner) { - panic("oops") -} diff --git a/cannon/testdata/justfile b/cannon/testdata/justfile index 8eda5295052..5fa9d68502b 100644 --- a/cannon/testdata/justfile +++ b/cannon/testdata/justfile @@ -1,15 +1,6 @@ -# Build all ELF test binaries -elf: go1-24 go1-25 - -# Build go-1-24 ELF binaries -go1-24: - just ./go-1-24/elf - -# Build go-1-25 ELF binaries -go1-25: - just ./go-1-25/elf - -# Clean all build artifacts -clean: - just ./go-1-24/clean - just ./go-1-25/clean +# Build minimal hello ELF used by diff-cannon parity checks and op-challenger +# provider tests. Built with Go 1.24 so the guest avoids Go 1.26 runtime +# syscalls (e.g. prctl) that production Cannon no longer tracks. +diff-hello-elf: + mkdir -p bin + cd diff-hello && GOTOOLCHAIN=go1.24.13 GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -o ../bin/hello.64.elf . diff --git a/cannon/testdata/utils/go.mod b/cannon/testdata/utils/go.mod deleted file mode 100644 index b4742f67277..00000000000 --- a/cannon/testdata/utils/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module utils - -go 1.24 - -toolchain go1.24.10 diff --git a/cannon/testdata/utils/testutil/testing.go b/cannon/testdata/utils/testutil/testing.go deleted file mode 100644 index f6c79c63655..00000000000 --- a/cannon/testdata/utils/testutil/testing.go +++ /dev/null @@ -1,170 +0,0 @@ -package testutil - -import ( - "fmt" - "os" - "runtime" - "sync" - "testing" -) - -func RunTest(testFunc func(*TestRunner), name string) { - goRunTest(name, testFunc, newTestRunner(name)) -} - -type TestRunner struct { - *mockT - baseName string -} - -func newTestRunner(baseName string) *TestRunner { - return &TestRunner{mockT: newMockT(), baseName: baseName} -} - -func (r *TestRunner) Run(name string, testFunc func(t testing.TB)) bool { - testName := r.baseName - if name != "" { - testName = fmt.Sprintf("%v (%v)", r.baseName, name) - } - - var tester testing.TB = r - goRunTest(testName, testFunc, tester) - return !r.Failed() -} - -func goRunTest[T testing.TB](testName string, testFunc func(t T), t T) { - var wg sync.WaitGroup - wg.Add(1) - - go func() { - defer func() { - if err := recover(); err != nil { - fmt.Printf("Test panicked: %v\n\t%v", testName, err) - os.Exit(1) - } - - if t.Failed() { - fmt.Printf("Test failed: %v\n", testName) - os.Exit(1) - } else if t.Skipped() { - fmt.Printf("Test skipped: %v\n", testName) - } else { - fmt.Printf("Test passed: %v\n", testName) - } - - wg.Done() - }() - - testFunc(t) - }() - - wg.Wait() -} - -type mockT struct { - *testing.T - mu sync.Mutex - failed bool - skipped bool -} - -var _ testing.TB = (*mockT)(nil) - -func newMockT() *mockT { - return &mockT{} -} - -func (t *mockT) Cleanup(func()) { - t.Fatalf("Cleanup not supported") -} - -func (t *mockT) Error(args ...any) { - fmt.Print(args...) - t.fail() -} - -func (t *mockT) Errorf(format string, args ...any) { - fmt.Printf(format, args...) - t.fail() -} - -func (t *mockT) Fail() { - t.fail() -} - -func (t *mockT) FailNow() { - fmt.Println("Fatal") - t.fail() -} - -func (t *mockT) Failed() bool { - t.mu.Lock() - defer t.mu.Unlock() - return t.failed -} - -func (t *mockT) Fatal(args ...any) { - fmt.Print(args...) - t.fail() -} - -func (t *mockT) Fatalf(format string, args ...any) { - fmt.Printf(format, args...) - t.fail() -} - -func (t *mockT) Helper() {} - -func (t *mockT) Log(args ...any) { - fmt.Print(args...) -} - -func (t *mockT) Logf(format string, args ...any) { - fmt.Printf(format, args...) -} - -func (t *mockT) Name() string { - return "" -} - -func (t *mockT) Setenv(key, value string) { - t.Fatalf("Setenv not supported") -} - -func (t *mockT) Skip(args ...any) { - fmt.Println(args...) - t.skip() -} - -func (t *mockT) SkipNow() { - t.skip() -} - -func (t *mockT) Skipf(format string, args ...any) { - fmt.Printf(format, args...) - t.skip() -} -func (t *mockT) Skipped() bool { - t.mu.Lock() - defer t.mu.Unlock() - return t.skipped -} - -func (t *mockT) skip() { - t.mu.Lock() - defer t.mu.Unlock() - t.skipped = true - runtime.Goexit() -} - -func (t *mockT) fail() { - t.mu.Lock() - defer t.mu.Unlock() - t.failed = true - runtime.Goexit() -} - -func (t *mockT) TempDir() string { - t.Fatalf("TempDir not supported") - return "" -} diff --git a/go.mod b/go.mod index a51b969a148..5b5e06e1d1d 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/ethereum-optimism/optimism -go 1.24.0 +go 1.26.0 -toolchain go1.24.13 +toolchain go1.26.4 require ( github.com/BurntSushi/toml v1.5.0 @@ -59,11 +59,11 @@ require ( go.etcd.io/bbolt v1.3.6 go.opentelemetry.io/otel v1.40.0 go.opentelemetry.io/otel/trace v1.40.0 - golang.org/x/crypto v0.46.0 - golang.org/x/mod v0.30.0 - golang.org/x/sync v0.19.0 - golang.org/x/term v0.38.0 - golang.org/x/text v0.32.0 + golang.org/x/crypto v0.50.0 + golang.org/x/mod v0.34.0 + golang.org/x/sync v0.20.0 + golang.org/x/term v0.42.0 + golang.org/x/text v0.36.0 golang.org/x/time v0.14.0 gonum.org/v1/plot v0.16.0 gopkg.in/yaml.v3 v3.0.1 @@ -82,7 +82,7 @@ require ( github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect github.com/pkg/errors v0.9.1 // indirect golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect - golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 // indirect + golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c // indirect ) require ( @@ -271,9 +271,9 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/image v0.25.0 // indirect - golang.org/x/net v0.48.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/tools v0.39.0 + golang.org/x/net v0.53.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/tools v0.43.0 google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect google.golang.org/grpc v1.79.3 // indirect diff --git a/go.sum b/go.sum index e3f1c2994ab..256a319f210 100644 --- a/go.sum +++ b/go.sum @@ -944,8 +944,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= @@ -963,8 +963,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -998,8 +998,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1016,8 +1016,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1078,10 +1078,10 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo= -golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c h1:6a8FdnNk6bTXBjR4AGKFgUKuo+7GnR3FX5L7CbveeZc= +golang.org/x/telemetry v0.0.0-20260311193753-579e4da9a98c/go.mod h1:TpUTTEp9frx7rTdLpC9gFG9kdI7zVLFTFFlqaH2Cncw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1090,8 +1090,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -1104,8 +1104,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1132,8 +1132,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/justfile b/justfile index 347286a7c81..47fd442c3e1 100644 --- a/justfile +++ b/justfile @@ -183,7 +183,10 @@ reproducible-prestate: pid1=$! (cd rust && just build-kona-reproducible-prestate) & pid2=$! - wait "$pid1" "$pid2" + # wait with multiple PIDs only propagates the last PID's exit status; wait + # separately so an op-program build failure can't be masked by a kona success. + wait "$pid1" + wait "$pid2" (cd op-program && just output-prestate-hash) (cd rust && just output-kona-prestate-hash) @@ -263,7 +266,7 @@ go-tests-short: op-program-client op-program-host cannon build-contracts cannon- [script('bash')] _go-tests-ci-internal go_test_flags="": sync-superchain set -euo pipefail - (cd cannon && just cannon elf) + (cd cannon && just diff-hello-elf) echo "Setting up test directories..." mkdir -p ./tmp/test-results ./tmp/testlogs echo "Running Go tests with gotestsum..." diff --git a/mise.toml b/mise.toml index 02833905769..f6dd5993ebe 100644 --- a/mise.toml +++ b/mise.toml @@ -2,10 +2,10 @@ # Core dependencies bun = "1.2.5" -go = "1.24.13" +go = "1.26.4" golangci-lint = "2.8.0" gotestsum = "1.12.3" -mockery = "2.53.3" +mockery = "2.53.6" rust = [ { version = "1.94.0", components = "clippy,rustfmt,llvm-tools-preview", targets = "riscv32imac-unknown-none-elf,wasm32-unknown-unknown,wasm32-wasip1" }, { version = "nightly-2026-02-20", components = "rustfmt" }, diff --git a/op-chain-ops/justfile b/op-chain-ops/justfile index 9c232a6ae24..f760e0c03f7 100644 --- a/op-chain-ops/justfile +++ b/op-chain-ops/justfile @@ -30,7 +30,6 @@ fuzz_task FUZZ TIME='10s': (go_fuzz FUZZ TIME "./crossdomain") fuzz: printf "%s\n" \ "FuzzEncodeDecodeWithdrawal" \ - "FuzzEncodeDecodeLegacyWithdrawal" \ "FuzzAliasing" \ "FuzzVersionedNonce" \ | parallel --tag -j {{PARALLEL_JOBS}} {{just_executable()}} fuzz_task {} diff --git a/op-chain-ops/script/cheatcodes_external.go b/op-chain-ops/script/cheatcodes_external.go index d2714473e1b..f64adff248f 100644 --- a/op-chain-ops/script/cheatcodes_external.go +++ b/op-chain-ops/script/cheatcodes_external.go @@ -414,7 +414,7 @@ func lookupKeys(v any, query string) ([]string, error) { return lookupKeys(x[index], trailing) case map[string]any: if stringKey == "" { - return nil, fmt.Errorf("expected string key, but got index in path: %q", index) + return nil, fmt.Errorf("expected string key, but got index in path: %d", index) } if stringKey == "$" { if trailing != "" { diff --git a/op-challenger/game/fault/trace/cannon/provider_test.go b/op-challenger/game/fault/trace/cannon/provider_test.go index 3980eb500da..49794634bb1 100644 --- a/op-challenger/game/fault/trace/cannon/provider_test.go +++ b/op-challenger/game/fault/trace/cannon/provider_test.go @@ -248,8 +248,8 @@ func TestLastStepCacheAccuracy(t *testing.T) { } prestate := filepath.Join(dir, "prestate.bin.gz") - // This requires cannon and its testdata to be built: cd cannon && make cannon elf - state, _ := testutil.LoadELFProgram(t, filepath.Join(monorepoRoot, "cannon/testdata/go-1-24/bin/hello.64.elf"), multithreaded.CreateInitialState) + // This requires the diff-hello guest ELF: cd cannon && just diff-hello-elf + state, _ := testutil.LoadELFProgram(t, filepath.Join(monorepoRoot, "cannon/testdata/bin/hello.64.elf"), multithreaded.CreateInitialState) versionedState, err := versions.NewFromState(versions.GetCurrentVersion(), state) require.NoError(t, err) err = serialize.Write(prestate, versionedState, os.FileMode(0o755)) diff --git a/op-challenger/justfile b/op-challenger/justfile index e8718a64baf..1a60f942284 100644 --- a/op-challenger/justfile +++ b/op-challenger/justfile @@ -24,5 +24,5 @@ clean: # Run tests test: # Required for cannon/provider_test TestLastStepCacheAccuracy - cd ../cannon && make cannon elf + cd ../cannon && just diff-hello-elf @just go_test "./..." diff --git a/op-node/p2p/gating/mocks/BlockingConnectionGater.go b/op-node/p2p/gating/mocks/BlockingConnectionGater.go index f0df92f8560..47be198bc80 100644 --- a/op-node/p2p/gating/mocks/BlockingConnectionGater.go +++ b/op-node/p2p/gating/mocks/BlockingConnectionGater.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/gating/mocks/ExpiryStore.go b/op-node/p2p/gating/mocks/ExpiryStore.go index 1d736043d88..bda4193151f 100644 --- a/op-node/p2p/gating/mocks/ExpiryStore.go +++ b/op-node/p2p/gating/mocks/ExpiryStore.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/gating/mocks/Scores.go b/op-node/p2p/gating/mocks/Scores.go index 2b78a741596..0662fe94d02 100644 --- a/op-node/p2p/gating/mocks/Scores.go +++ b/op-node/p2p/gating/mocks/Scores.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/mocks/GossipMetricer.go b/op-node/p2p/mocks/GossipMetricer.go index 03a87b71312..9228fc4a74e 100644 --- a/op-node/p2p/mocks/GossipMetricer.go +++ b/op-node/p2p/mocks/GossipMetricer.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/mocks/Peerstore.go b/op-node/p2p/mocks/Peerstore.go index c395e8c2dcb..f1885630fd6 100644 --- a/op-node/p2p/mocks/Peerstore.go +++ b/op-node/p2p/mocks/Peerstore.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/mocks/ScoreMetrics.go b/op-node/p2p/mocks/ScoreMetrics.go index a5012c9798a..c262d03836c 100644 --- a/op-node/p2p/mocks/ScoreMetrics.go +++ b/op-node/p2p/mocks/ScoreMetrics.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/monitor/mocks/PeerManager.go b/op-node/p2p/monitor/mocks/PeerManager.go index eb66083319d..a4d9fc26997 100644 --- a/op-node/p2p/monitor/mocks/PeerManager.go +++ b/op-node/p2p/monitor/mocks/PeerManager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-node/p2p/peer_scores_test.go b/op-node/p2p/peer_scores_test.go index 33263c285a2..c6b9b861d87 100644 --- a/op-node/p2p/peer_scores_test.go +++ b/op-node/p2p/peer_scores_test.go @@ -71,7 +71,7 @@ func getNetHosts(testSuite *PeerScoresTestSuite, ctx context.Context, n int) []h var out []host.Host log := testlog.Logger(testSuite.T(), log.LevelError) for i := 0; i < n; i++ { - swarm := tswarm.GenSwarm(testSuite.T()) + swarm := tswarm.GenSwarm(testSuite.T(), tswarm.OptDisableQUIC) eps, err := store.NewExtendedPeerstore(ctx, log, clock.SystemClock, swarm.Peerstore(), sync.MutexWrap(ds.NewMapDatastore()), 1*time.Hour) netw := &customPeerstoreNetwork{swarm, eps} require.NoError(testSuite.T(), err) diff --git a/op-node/rollup/derive/mocks/next_data_provider.go b/op-node/rollup/derive/mocks/next_data_provider.go index cb3ef5f50fa..48df65d2fae 100644 --- a/op-node/rollup/derive/mocks/next_data_provider.go +++ b/op-node/rollup/derive/mocks/next_data_provider.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-program/Dockerfile.repro b/op-program/Dockerfile.repro index 64450e15fa6..601dcf7be46 100644 --- a/op-program/Dockerfile.repro +++ b/op-program/Dockerfile.repro @@ -1,4 +1,4 @@ -ARG GO_VERSION=1.24.10-alpine3.21 +ARG GO_VERSION=1.26.4-alpine3.22 ARG EXPORT_TARGET=current FROM golang:${GO_VERSION} AS src diff --git a/op-program/client/interopcmd/godebug.go b/op-program/client/interopcmd/godebug.go new file mode 100644 index 00000000000..47bda43fa4a --- /dev/null +++ b/op-program/client/interopcmd/godebug.go @@ -0,0 +1,8 @@ +// Disable annotating anonymous memory mappings. Cannon doesn't support this syscall +// The directive (and functionality) only exists on go1.25 and above so this file is conditionally included. + +//go:build go1.25 + +//go:debug decoratemappings=0 + +package main diff --git a/op-program/justfile b/op-program/justfile index dc2694e2dcb..6f7ddedd0cc 100644 --- a/op-program/justfile +++ b/op-program/justfile @@ -26,24 +26,27 @@ op-program: op-program-host op-program-client op-program-client-mips op-program-host: (go_build "./bin/op-program" "./host/cmd/main.go" "-ldflags" _HOST_LDFLAGS) # Build op-program client binaries (client + interop) +# Build the package dir, not main.go alone: a single-file build drops the other +# files in the package, including godebug.go (//go:debug decoratemappings=0), +# which the MIPS clients need so cannon never sees a prctl syscall. op-program-client: - env GO111MODULE=on GOOS={{TARGETOS}} GOARCH={{TARGETARCH}} go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client ./client/cmd/main.go - env GO111MODULE=on GOOS={{TARGETOS}} GOARCH={{TARGETARCH}} go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client-interop ./client/interopcmd/main.go + env GO111MODULE=on GOOS={{TARGETOS}} GOARCH={{TARGETARCH}} go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client ./client/cmd + env GO111MODULE=on GOOS={{TARGETOS}} GOARCH={{TARGETARCH}} go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client-interop ./client/interopcmd # Build MIPS client binaries op-program-client-mips: op-program-client-mips64 op-program-client-mips64-interop # Build MIPS64 client binary op-program-client-mips64: - env GO111MODULE=on GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client64.elf ./client/cmd/main.go + env GO111MODULE=on GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client64.elf ./client/cmd # Build MIPS64 interop client binary op-program-client-mips64-interop: - env GO111MODULE=on GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client-interop.elf ./client/interopcmd/main.go + env GO111MODULE=on GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -v -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client-interop.elf ./client/interopcmd # Build RISC-V client binary op-program-client-riscv: - env GO111MODULE=on GOOS=linux GOARCH=riscv64 go build -v -gcflags="all=-d=softfloat" -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client-riscv.elf ./client/cmd/main.go + env GO111MODULE=on GOOS=linux GOARCH=riscv64 go build -v -gcflags="all=-d=softfloat" -ldflags {{_CLIENT_LDFLAGS}} -o ./bin/op-program-client-riscv.elf ./client/cmd # Check custom chain configurations check-custom-chains: op-program-host @@ -51,8 +54,8 @@ check-custom-chains: op-program-host # Build reproducible prestates via Docker build-reproducible-prestate: check-custom-chains - docker build --build-arg GO_VERSION=1.24.2-alpine3.21 --build-arg EXPORT_TARGET=next --output ./bin/ --progress plain -f Dockerfile.repro ../ - docker build --build-arg GO_VERSION=1.24.2-alpine3.21 --build-arg EXPORT_TARGET=current --output ./bin/ --progress plain -f Dockerfile.repro ../ + docker build --build-arg GO_VERSION=1.26.4-alpine3.22 --build-arg EXPORT_TARGET=next --output ./bin/ --progress plain -f Dockerfile.repro ../ + docker build --build-arg GO_VERSION=1.26.4-alpine3.22 --build-arg EXPORT_TARGET=current --output ./bin/ --progress plain -f Dockerfile.repro ../ # Print prestate hashes output-prestate-hash: diff --git a/op-service/sources/mocks/BeaconClient.go b/op-service/sources/mocks/BeaconClient.go index fb4b8cea209..cd19f1dfb23 100644 --- a/op-service/sources/mocks/BeaconClient.go +++ b/op-service/sources/mocks/BeaconClient.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/op-service/txmgr/mocks/TxManager.go b/op-service/txmgr/mocks/TxManager.go index 0f282b9abb9..abb651dfb95 100644 --- a/op-service/txmgr/mocks/TxManager.go +++ b/op-service/txmgr/mocks/TxManager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.3. DO NOT EDIT. +// Code generated by mockery v2.53.6. DO NOT EDIT. package mocks diff --git a/ops/docker/deployment-utils/Dockerfile b/ops/docker/deployment-utils/Dockerfile index aff7ffc6991..6574b06dca7 100644 --- a/ops/docker/deployment-utils/Dockerfile +++ b/ops/docker/deployment-utils/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.13-bookworm AS go-base +FROM golang:1.26.4-bookworm AS go-base RUN go install github.com/tomwright/dasel/v2/cmd/dasel@master diff --git a/ops/docker/op-stack-go/Dockerfile b/ops/docker/op-stack-go/Dockerfile index ba9a36e44a0..72b26b8c913 100644 --- a/ops/docker/op-stack-go/Dockerfile +++ b/ops/docker/op-stack-go/Dockerfile @@ -49,7 +49,7 @@ EOF RUN forge --version # We may be cross-building for another platform. Specify which platform we need as builder. -FROM --platform=$BUILDPLATFORM golang:1.24.13-alpine3.22 AS builder +FROM --platform=$BUILDPLATFORM golang:1.26.4-alpine3.22 AS builder RUN apk add --no-cache curl tar gzip make gcc musl-dev linux-headers git jq yq-go bash just @@ -178,7 +178,7 @@ RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache # Compile contracts in a glibc-based image (solc requires glibc, crashes on Alpine musl). # Uses BUILDPLATFORM so it runs natively (no QEMU). Contract artifacts are platform-independent. -FROM --platform=$BUILDPLATFORM golang:1.24.13-bookworm AS op-deployer-contracts +FROM --platform=$BUILDPLATFORM golang:1.26.4-bookworm AS op-deployer-contracts ARG BUILDARCH RUN apt-get update && apt-get install -y --no-install-recommends curl jq git && rm -rf /var/lib/apt/lists/* COPY ./go.mod /app/go.mod diff --git a/rust/kona/docker/fpvm-prestates/cannon-repro.dockerfile b/rust/kona/docker/fpvm-prestates/cannon-repro.dockerfile index d805fc92b65..b729cc0384c 100644 --- a/rust/kona/docker/fpvm-prestates/cannon-repro.dockerfile +++ b/rust/kona/docker/fpvm-prestates/cannon-repro.dockerfile @@ -9,7 +9,7 @@ # Build Cannon from local monorepo # ################################################################ -FROM golang:1.24.13-alpine3.22 AS cannon-build +FROM golang:1.26.4-alpine3.22 AS cannon-build RUN apk add --no-cache bash just