From fc9dc76b82a79be80c185fb8f65d787a8048cbdd Mon Sep 17 00:00:00 2001 From: Federico <14293929+falcorocks@users.noreply.github.com> Date: Mon, 22 Jun 2026 16:54:14 +0200 Subject: [PATCH 1/5] chore: bump Go to 1.26.4 for image CVE fixes (#21452) * chore(docker): bump Go builder image to 1.26.4 Rebuild OP Stack release images on golang:1.26.4 to pick up stdlib security fixes. Docker builder pins only; go.mod and CI Go version unchanged. * chore: bump Go toolchain pins to 1.26.4 Align mise.toml and go.mod with the Docker builder image bump so CircleCI tests and shipped images use the same Go version. * fix: unblock CI for Go 1.26.4 toolchain bump Bump mockery to 2.53.6 for Go 1.26 AST parsing, regen mocks, fix govet format string, tidy cannon testdata go.mod files, and raise Random cannon test step budget (~510k needed vs 500k cap). * fix(cannon): noop Go 1.26 prctl syscall in mips64 VM Go 1.26 claim binaries call prctl (5153). Handle it as a guest noop in the Go VM, onchain MIPS64, and cannon EVM syscall tests. * chore(op-chain-ops): drop removed legacy withdrawal fuzz target FuzzEncodeDecodeLegacyWithdrawal no longer exists; remove from just fuzz list to avoid noisy parallel worker. * ci: bust Go build cache for 1.26.4 toolchain bump Stale go-build cache from Go 1.24 can break fuzz/tests under 1.26. * ci: sync go-cache-version defaults to v0.1 * fix(op-node): disable QUIC in peer score test for Go 1.26 quic-go v0.46 panics on Go 1.26 TLS session ticket behavior; test only needs TCP gossipsub so use OptDisableQUIC in swarm setup. * fix(cannon): drop Go FPVM fixtures and revert prctl VM bump Production FPVM runs kona, not Go claim programs. Revert MIPS64 prctl noop and semver bump per review feedback, remove legacy go-1-24/1-25 guest fixtures and tests that forced Go-runtime syscall tracking, and keep a minimal diff-hello ELF only for diff-cannon parity checks. * fix(cannon): update CI test prep for diff-hello-elf recipe go-tests-short still invoked removed `just elf` when building Cannon guest binaries. Point root and op-challenger test prep at diff-hello-elf. * fix(cannon): build diff-hello guest with Go 1.24 toolchain Go 1.26-linked hello binaries call prctl in the FPVM, which we intentionally do not implement after dropping legacy Go guest fixtures. Pin diff-hello to Go 1.24 in an isolated module so provider and diff-cannon tests keep working. --- .circleci/config.yml | 2 +- .circleci/continue/main.yml | 6 +- .circleci/continue/rust-e2e.yml | 2 +- cannon/Dockerfile.diff | 2 +- cannon/Makefile | 2 +- cannon/justfile | 18 +- .../multithreaded/instrumented_test.go | 485 ---- cannon/mipsevm/multithreaded/state_test.go | 35 +- cannon/mipsevm/tests/evm_common_test.go | 289 -- cannon/mipsevm/tests/helpers.go | 19 +- cannon/mipsevm/testutil/elf.go | 13 - cannon/mipsevm/testutil/oracle.go | 74 - cannon/testdata/Makefile | 2 +- cannon/testdata/README.md | 10 +- cannon/testdata/diff-hello/go.mod | 3 + .../{go-1-24/hello => diff-hello}/main.go | 0 cannon/testdata/go-1-24/Makefile | 3 - cannon/testdata/go-1-24/alloc/go.mod | 14 - cannon/testdata/go-1-24/alloc/go.sum | 12 - cannon/testdata/go-1-24/alloc/main.go | 38 - cannon/testdata/go-1-24/claim/go.mod | 14 - cannon/testdata/go-1-24/claim/go.sum | 12 - cannon/testdata/go-1-24/claim/main.go | 54 - cannon/testdata/go-1-24/entry/go.mod | 5 - cannon/testdata/go-1-24/entry/main.go | 30 - cannon/testdata/go-1-24/hello/go.mod | 5 - cannon/testdata/go-1-24/justfile | 31 - cannon/testdata/go-1-24/keccak/go.mod | 11 - cannon/testdata/go-1-24/keccak/go.sum | 4 - cannon/testdata/go-1-24/keccak/main.go | 16 - .../go-1-24/mt-atomic/atomic_test_copy.go | 2567 ----------------- cannon/testdata/go-1-24/mt-atomic/go.mod | 9 - cannon/testdata/go-1-24/mt-atomic/main.go | 80 - cannon/testdata/go-1-24/mt-cond/go.mod | 5 - cannon/testdata/go-1-24/mt-cond/main.go | 302 -- cannon/testdata/go-1-24/mt-general/go.mod | 5 - cannon/testdata/go-1-24/mt-general/main.go | 46 - cannon/testdata/go-1-24/mt-map/go.mod | 9 - cannon/testdata/go-1-24/mt-map/main.go | 19 - .../go-1-24/mt-map/map_reference_test_copy.go | 299 -- .../testdata/go-1-24/mt-map/map_test_copy.go | 325 --- cannon/testdata/go-1-24/mt-mutex/go.mod | 9 - cannon/testdata/go-1-24/mt-mutex/main.go | 15 - .../go-1-24/mt-mutex/mutex_test_copy.go | 135 - cannon/testdata/go-1-24/mt-mutex/runtime.go | 14 - cannon/testdata/go-1-24/mt-once/go.mod | 5 - cannon/testdata/go-1-24/mt-once/main.go | 98 - cannon/testdata/go-1-24/mt-oncefunc/go.mod | 9 - cannon/testdata/go-1-24/mt-oncefunc/main.go | 22 - .../go-1-24/mt-oncefunc/oncefunc_test_copy.go | 265 -- .../go-1-24/mt-pool/export_test_copy.go | 86 - cannon/testdata/go-1-24/mt-pool/go.mod | 9 - cannon/testdata/go-1-24/mt-pool/main.go | 20 - .../go-1-24/mt-pool/pool_test_copy.go | 298 -- .../go-1-24/mt-pool/poolqueue_copy.go | 338 --- cannon/testdata/go-1-24/mt-pool/runtime.go | 11 - cannon/testdata/go-1-24/mt-rwmutex/go.mod | 5 - cannon/testdata/go-1-24/mt-rwmutex/main.go | 226 -- cannon/testdata/go-1-24/mt-value/go.mod | 9 - cannon/testdata/go-1-24/mt-value/main.go | 20 - .../go-1-24/mt-value/value_test_copy.go | 312 -- cannon/testdata/go-1-24/mt-wg/go.mod | 9 - cannon/testdata/go-1-24/mt-wg/main.go | 16 - .../go-1-24/mt-wg/waitgroup_test_copy.go | 130 - cannon/testdata/go-1-24/random/go.mod | 5 - cannon/testdata/go-1-24/random/main.go | 45 - .../testdata/go-1-24/syscall-eventfd/go.mod | 9 - .../testdata/go-1-24/syscall-eventfd/main.go | 9 - cannon/testdata/go-1-24/utilscheck/go.mod | 9 - cannon/testdata/go-1-24/utilscheck/main.go | 17 - cannon/testdata/go-1-24/utilscheck2/go.mod | 9 - cannon/testdata/go-1-24/utilscheck2/main.go | 24 - cannon/testdata/go-1-24/utilscheck3/go.mod | 9 - cannon/testdata/go-1-24/utilscheck3/main.go | 20 - cannon/testdata/go-1-24/utilscheck4/go.mod | 9 - cannon/testdata/go-1-24/utilscheck4/main.go | 17 - cannon/testdata/go-1-25/Makefile | 3 - cannon/testdata/go-1-25/alloc/go.mod | 14 - cannon/testdata/go-1-25/alloc/go.sum | 12 - cannon/testdata/go-1-25/alloc/main.go | 39 - cannon/testdata/go-1-25/claim/go.mod | 14 - cannon/testdata/go-1-25/claim/go.sum | 12 - cannon/testdata/go-1-25/claim/main.go | 55 - cannon/testdata/go-1-25/entry/go.mod | 7 - cannon/testdata/go-1-25/entry/main.go | 31 - cannon/testdata/go-1-25/hello/go.mod | 7 - cannon/testdata/go-1-25/hello/main.go | 8 - cannon/testdata/go-1-25/justfile | 31 - cannon/testdata/go-1-25/keccak/go.mod | 11 - cannon/testdata/go-1-25/keccak/go.sum | 4 - cannon/testdata/go-1-25/keccak/main.go | 17 - .../go-1-25/mt-atomic/atomic_test_copy.go | 2567 ----------------- cannon/testdata/go-1-25/mt-atomic/go.mod | 9 - cannon/testdata/go-1-25/mt-atomic/main.go | 81 - cannon/testdata/go-1-25/mt-cond/go.mod | 7 - cannon/testdata/go-1-25/mt-cond/main.go | 304 -- cannon/testdata/go-1-25/mt-general/go.mod | 7 - cannon/testdata/go-1-25/mt-general/main.go | 47 - cannon/testdata/go-1-25/mt-map/go.mod | 9 - cannon/testdata/go-1-25/mt-map/main.go | 20 - .../go-1-25/mt-map/map_reference_test_copy.go | 299 -- .../testdata/go-1-25/mt-map/map_test_copy.go | 325 --- cannon/testdata/go-1-25/mt-mutex/go.mod | 9 - cannon/testdata/go-1-25/mt-mutex/main.go | 16 - .../go-1-25/mt-mutex/mutex_test_copy.go | 135 - cannon/testdata/go-1-25/mt-mutex/runtime.go | 14 - cannon/testdata/go-1-25/mt-once/go.mod | 7 - cannon/testdata/go-1-25/mt-once/main.go | 100 - cannon/testdata/go-1-25/mt-oncefunc/go.mod | 9 - cannon/testdata/go-1-25/mt-oncefunc/main.go | 23 - .../go-1-25/mt-oncefunc/oncefunc_test_copy.go | 265 -- .../go-1-25/mt-pool/export_test_copy.go | 86 - cannon/testdata/go-1-25/mt-pool/go.mod | 9 - cannon/testdata/go-1-25/mt-pool/main.go | 21 - .../go-1-25/mt-pool/pool_test_copy.go | 298 -- .../go-1-25/mt-pool/poolqueue_copy.go | 338 --- cannon/testdata/go-1-25/mt-pool/runtime.go | 11 - cannon/testdata/go-1-25/mt-rwmutex/go.mod | 7 - cannon/testdata/go-1-25/mt-rwmutex/main.go | 228 -- cannon/testdata/go-1-25/mt-value/go.mod | 9 - cannon/testdata/go-1-25/mt-value/main.go | 21 - .../go-1-25/mt-value/value_test_copy.go | 312 -- cannon/testdata/go-1-25/mt-wg/go.mod | 9 - cannon/testdata/go-1-25/mt-wg/main.go | 17 - .../go-1-25/mt-wg/waitgroup_test_copy.go | 130 - cannon/testdata/go-1-25/random/go.mod | 7 - cannon/testdata/go-1-25/random/main.go | 46 - .../testdata/go-1-25/syscall-eventfd/go.mod | 9 - .../testdata/go-1-25/syscall-eventfd/main.go | 10 - cannon/testdata/go-1-25/utilscheck/go.mod | 9 - cannon/testdata/go-1-25/utilscheck/main.go | 18 - cannon/testdata/go-1-25/utilscheck2/go.mod | 9 - cannon/testdata/go-1-25/utilscheck2/main.go | 25 - cannon/testdata/go-1-25/utilscheck3/go.mod | 9 - cannon/testdata/go-1-25/utilscheck3/main.go | 21 - cannon/testdata/go-1-25/utilscheck4/go.mod | 9 - cannon/testdata/go-1-25/utilscheck4/main.go | 18 - cannon/testdata/justfile | 21 +- cannon/testdata/utils/go.mod | 5 - cannon/testdata/utils/testutil/testing.go | 170 -- go.mod | 4 +- justfile | 2 +- mise.toml | 4 +- op-chain-ops/justfile | 1 - op-chain-ops/script/cheatcodes_external.go | 2 +- .../game/fault/trace/cannon/provider_test.go | 4 +- op-challenger/justfile | 2 +- .../gating/mocks/BlockingConnectionGater.go | 2 +- op-node/p2p/gating/mocks/ExpiryStore.go | 2 +- op-node/p2p/gating/mocks/Scores.go | 2 +- op-node/p2p/mocks/GossipMetricer.go | 2 +- op-node/p2p/mocks/Peerstore.go | 2 +- op-node/p2p/mocks/ScoreMetrics.go | 2 +- op-node/p2p/monitor/mocks/PeerManager.go | 2 +- op-node/p2p/peer_scores_test.go | 2 +- .../rollup/derive/mocks/next_data_provider.go | 2 +- op-service/sources/mocks/BeaconClient.go | 2 +- op-service/txmgr/mocks/TxManager.go | 2 +- ops/docker/deployment-utils/Dockerfile | 2 +- ops/docker/op-stack-go/Dockerfile | 4 +- .../fpvm-prestates/cannon-repro.dockerfile | 2 +- 161 files changed, 66 insertions(+), 13503 deletions(-) create mode 100644 cannon/testdata/diff-hello/go.mod rename cannon/testdata/{go-1-24/hello => diff-hello}/main.go (100%) delete mode 100644 cannon/testdata/go-1-24/Makefile delete mode 100644 cannon/testdata/go-1-24/alloc/go.mod delete mode 100644 cannon/testdata/go-1-24/alloc/go.sum delete mode 100644 cannon/testdata/go-1-24/alloc/main.go delete mode 100644 cannon/testdata/go-1-24/claim/go.mod delete mode 100644 cannon/testdata/go-1-24/claim/go.sum delete mode 100644 cannon/testdata/go-1-24/claim/main.go delete mode 100644 cannon/testdata/go-1-24/entry/go.mod delete mode 100644 cannon/testdata/go-1-24/entry/main.go delete mode 100644 cannon/testdata/go-1-24/hello/go.mod delete mode 100644 cannon/testdata/go-1-24/justfile delete mode 100644 cannon/testdata/go-1-24/keccak/go.mod delete mode 100644 cannon/testdata/go-1-24/keccak/go.sum delete mode 100644 cannon/testdata/go-1-24/keccak/main.go delete mode 100644 cannon/testdata/go-1-24/mt-atomic/atomic_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-atomic/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-atomic/main.go delete mode 100644 cannon/testdata/go-1-24/mt-cond/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-cond/main.go delete mode 100644 cannon/testdata/go-1-24/mt-general/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-general/main.go delete mode 100644 cannon/testdata/go-1-24/mt-map/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-map/main.go delete mode 100644 cannon/testdata/go-1-24/mt-map/map_reference_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-map/map_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-mutex/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-mutex/main.go delete mode 100644 cannon/testdata/go-1-24/mt-mutex/mutex_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-mutex/runtime.go delete mode 100644 cannon/testdata/go-1-24/mt-once/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-once/main.go delete mode 100644 cannon/testdata/go-1-24/mt-oncefunc/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-oncefunc/main.go delete mode 100644 cannon/testdata/go-1-24/mt-oncefunc/oncefunc_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-pool/export_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-pool/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-pool/main.go delete mode 100644 cannon/testdata/go-1-24/mt-pool/pool_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-pool/poolqueue_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-pool/runtime.go delete mode 100644 cannon/testdata/go-1-24/mt-rwmutex/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-rwmutex/main.go delete mode 100644 cannon/testdata/go-1-24/mt-value/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-value/main.go delete mode 100644 cannon/testdata/go-1-24/mt-value/value_test_copy.go delete mode 100644 cannon/testdata/go-1-24/mt-wg/go.mod delete mode 100644 cannon/testdata/go-1-24/mt-wg/main.go delete mode 100644 cannon/testdata/go-1-24/mt-wg/waitgroup_test_copy.go delete mode 100644 cannon/testdata/go-1-24/random/go.mod delete mode 100644 cannon/testdata/go-1-24/random/main.go delete mode 100644 cannon/testdata/go-1-24/syscall-eventfd/go.mod delete mode 100644 cannon/testdata/go-1-24/syscall-eventfd/main.go delete mode 100644 cannon/testdata/go-1-24/utilscheck/go.mod delete mode 100644 cannon/testdata/go-1-24/utilscheck/main.go delete mode 100644 cannon/testdata/go-1-24/utilscheck2/go.mod delete mode 100644 cannon/testdata/go-1-24/utilscheck2/main.go delete mode 100644 cannon/testdata/go-1-24/utilscheck3/go.mod delete mode 100644 cannon/testdata/go-1-24/utilscheck3/main.go delete mode 100644 cannon/testdata/go-1-24/utilscheck4/go.mod delete mode 100644 cannon/testdata/go-1-24/utilscheck4/main.go delete mode 100644 cannon/testdata/go-1-25/Makefile delete mode 100644 cannon/testdata/go-1-25/alloc/go.mod delete mode 100644 cannon/testdata/go-1-25/alloc/go.sum delete mode 100644 cannon/testdata/go-1-25/alloc/main.go delete mode 100644 cannon/testdata/go-1-25/claim/go.mod delete mode 100644 cannon/testdata/go-1-25/claim/go.sum delete mode 100644 cannon/testdata/go-1-25/claim/main.go delete mode 100644 cannon/testdata/go-1-25/entry/go.mod delete mode 100644 cannon/testdata/go-1-25/entry/main.go delete mode 100644 cannon/testdata/go-1-25/hello/go.mod delete mode 100644 cannon/testdata/go-1-25/hello/main.go delete mode 100644 cannon/testdata/go-1-25/justfile delete mode 100644 cannon/testdata/go-1-25/keccak/go.mod delete mode 100644 cannon/testdata/go-1-25/keccak/go.sum delete mode 100644 cannon/testdata/go-1-25/keccak/main.go delete mode 100644 cannon/testdata/go-1-25/mt-atomic/atomic_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-atomic/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-atomic/main.go delete mode 100644 cannon/testdata/go-1-25/mt-cond/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-cond/main.go delete mode 100644 cannon/testdata/go-1-25/mt-general/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-general/main.go delete mode 100644 cannon/testdata/go-1-25/mt-map/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-map/main.go delete mode 100644 cannon/testdata/go-1-25/mt-map/map_reference_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-map/map_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-mutex/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-mutex/main.go delete mode 100644 cannon/testdata/go-1-25/mt-mutex/mutex_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-mutex/runtime.go delete mode 100644 cannon/testdata/go-1-25/mt-once/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-once/main.go delete mode 100644 cannon/testdata/go-1-25/mt-oncefunc/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-oncefunc/main.go delete mode 100644 cannon/testdata/go-1-25/mt-oncefunc/oncefunc_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-pool/export_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-pool/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-pool/main.go delete mode 100644 cannon/testdata/go-1-25/mt-pool/pool_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-pool/poolqueue_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-pool/runtime.go delete mode 100644 cannon/testdata/go-1-25/mt-rwmutex/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-rwmutex/main.go delete mode 100644 cannon/testdata/go-1-25/mt-value/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-value/main.go delete mode 100644 cannon/testdata/go-1-25/mt-value/value_test_copy.go delete mode 100644 cannon/testdata/go-1-25/mt-wg/go.mod delete mode 100644 cannon/testdata/go-1-25/mt-wg/main.go delete mode 100644 cannon/testdata/go-1-25/mt-wg/waitgroup_test_copy.go delete mode 100644 cannon/testdata/go-1-25/random/go.mod delete mode 100644 cannon/testdata/go-1-25/random/main.go delete mode 100644 cannon/testdata/go-1-25/syscall-eventfd/go.mod delete mode 100644 cannon/testdata/go-1-25/syscall-eventfd/main.go delete mode 100644 cannon/testdata/go-1-25/utilscheck/go.mod delete mode 100644 cannon/testdata/go-1-25/utilscheck/main.go delete mode 100644 cannon/testdata/go-1-25/utilscheck2/go.mod delete mode 100644 cannon/testdata/go-1-25/utilscheck2/main.go delete mode 100644 cannon/testdata/go-1-25/utilscheck3/go.mod delete mode 100644 cannon/testdata/go-1-25/utilscheck3/main.go delete mode 100644 cannon/testdata/go-1-25/utilscheck4/go.mod delete mode 100644 cannon/testdata/go-1-25/utilscheck4/main.go delete mode 100644 cannon/testdata/utils/go.mod delete mode 100644 cannon/testdata/utils/testutil/testing.go 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..091ecf007f0 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 diff --git a/justfile b/justfile index 347286a7c81..d91301eeb3a 100644 --- a/justfile +++ b/justfile @@ -263,7 +263,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-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 From 3f1ec18a0b0773e74c6ddecb1f17a0aad70c3e7d Mon Sep 17 00:00:00 2001 From: Philippe Camacho Date: Sat, 25 Jul 2026 12:45:29 -0400 Subject: [PATCH 2/5] deps: update golang.org/x/net to v0.53.0 (audit Issue A) Second part of the remediation for Least Authority Initial Audit Report (20 July 2026), Issue A: DoS vulnerabilities reachable through the L1 RPC requests used for Espresso batch authentication. The Go 1.26.4 toolchain bump (previous commit, cherry-picked from upstream ad29082f9488) covers the stdlib issues (GO-2026-4870 TLS KeyUpdate deadlock, GO-2026-5037 quadratic X.509 SAN verification). This commit updates golang.org/x/net to v0.53.0 to cover the HTTP/2 zero SETTINGS_MAX_FRAME_SIZE loop (GO-2026-4918), along with the sibling golang.org/x/* version bumps required by go get / go mod tidy. Co-Authored-By: Claude Fable 5 --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 091ecf007f0..5b5e06e1d1d 100644 --- a/go.mod +++ b/go.mod @@ -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= From d95c3618f7585b8b7ecd75479694eff8a5aef1a2 Mon Sep 17 00:00:00 2001 From: Javier Cortejoso Date: Mon, 27 Jul 2026 18:29:23 +0200 Subject: [PATCH 3/5] op-program: use Go 1.26.4 for reproducible prestate build The reproducible prestate Docker build was still pinned to Go 1.24, which fails 'go mod download' now that go.mod requires go >= 1.26 (GOTOOLCHAIN=local in the image prevents auto-upgrade). This left the cannon-prestate CI job green without producing op-program prestates, which in turn failed the acceptance tests with 'cannon pre-state should be built'. Also wait on the parallel prestate builds separately: 'wait pid1 pid2' only propagates the last PID's exit status, so the op-program build failure was masked by the kona build succeeding. --- justfile | 5 ++++- op-program/Dockerfile.repro | 2 +- op-program/justfile | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/justfile b/justfile index d91301eeb3a..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) 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/justfile b/op-program/justfile index dc2694e2dcb..391469cc3c6 100644 --- a/op-program/justfile +++ b/op-program/justfile @@ -51,8 +51,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: From 6fd3df077fcb5f0cafa45392eda7b48679a5730b Mon Sep 17 00:00:00 2001 From: Philippe Camacho Date: Mon, 27 Jul 2026 14:08:56 -0400 Subject: [PATCH 4/5] op-program: build client packages, not main.go, to keep decoratemappings=0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MIPS client ELFs were built with 'go build ./client/cmd/main.go', which compiles only that single file and silently drops godebug.go — the file carrying the '//go:debug decoratemappings=0' directive. With the prestate build now on Go 1.26, the runtime's default decoratemappings=1 makes the client call prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ...) — syscall 5153 on mips64 — which cannon does not implement, so every cannon trace execution panicked with 'unrecognized syscall: 5153' (memory-all-opn-op-geth: TestExecuteStep_Cannon, TestFPP, etc.). Build the package directories instead so the directive is honored (go version -m now shows DefaultGODEBUG=decoratemappings=0), and add the same godebug.go to client/interopcmd, which never had one. Co-Authored-By: Claude Fable 5 --- op-program/client/interopcmd/godebug.go | 8 ++++++++ op-program/justfile | 13 ++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 op-program/client/interopcmd/godebug.go 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 391469cc3c6..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 From 98450b7287fe1372e77675328987250ebd8d55a1 Mon Sep 17 00:00:00 2001 From: Philippe Camacho Date: Mon, 27 Jul 2026 14:21:55 -0400 Subject: [PATCH 5/5] ci: retrigger pipeline after CircleCI infrastructure failures Three jobs (semgrep-scan-local, fuzz-golang-op-node, contracts-bedrock-build-1) died with infrastructure_fail before memory-all-opn-op-geth could run; no way to rerun from failed without a CircleCI token. Co-Authored-By: Claude Fable 5