overlay/checksum: test each arch implementation directly

The correctness sweeps only exercised the public Checksum dispatcher, so
wherever it resolved to the gvisor fallback (non-AVX2 amd64, fallback
architectures) the suite compared gvisor against itself and the AVX2
assembly went untested -- silently green. Per-arch export_test.go files
now enumerate the hand-written implementations and every sweep runs
against the dispatcher plus each of them, skipping with an explicit
message when the running CPU can't execute one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
JackDoan
2026-07-27 15:55:28 -05:00
parent 8cebecc087
commit 865dc9725c
4 changed files with 132 additions and 64 deletions
+47 -5
View File
@@ -8,10 +8,40 @@ import (
gvisorchecksum "gvisor.dev/gvisor/pkg/tcpip/checksum" gvisorchecksum "gvisor.dev/gvisor/pkg/tcpip/checksum"
) )
// archImpl names one checksum function under test. The per-arch
// export_*_test.go files enumerate the hand-written implementations so the
// suite compares each one against gvisor directly, regardless of which one
// the public Checksum dispatches to on the running CPU. Testing only the
// dispatcher was tautological wherever it resolved to the gvisor fallback
// (non-AVX2 amd64, fallback architectures) — gvisor compared with itself,
// assembly untested, suite green.
type archImpl struct {
name string
fn func([]byte, uint16) uint16
available bool
}
// implsUnderTest is the public dispatcher plus every arch implementation.
func implsUnderTest() []archImpl {
return append([]archImpl{{name: "dispatch", fn: Checksum, available: true}}, archImpls...)
}
// requireAvailable skips loudly when the running CPU can't execute an
// implementation — visible in test output, unlike the old silent tautology.
func requireAvailable(t *testing.T, impl archImpl) {
t.Helper()
if !impl.available {
t.Skipf("%s not supported on this CPU; its assembly is NOT tested in this run", impl.name)
}
}
// TestChecksumMatchesGvisor walks lengths from 0 to 4096, with several initial // TestChecksumMatchesGvisor walks lengths from 0 to 4096, with several initial
// seeds and a handful of starting alignments, asserting that our local // seeds and a handful of starting alignments, asserting that each local
// Checksum matches gvisor's reference bit-for-bit. // implementation matches gvisor's reference bit-for-bit.
func TestChecksumMatchesGvisor(t *testing.T) { func TestChecksumMatchesGvisor(t *testing.T) {
for _, impl := range implsUnderTest() {
t.Run(impl.name, func(t *testing.T) {
requireAvailable(t, impl)
rng := rand.New(rand.NewPCG(1, 2)) rng := rand.New(rand.NewPCG(1, 2))
const padFront = 16 const padFront = 16
@@ -32,7 +62,7 @@ func TestChecksumMatchesGvisor(t *testing.T) {
} }
buf := pool[off : off+length] buf := pool[off : off+length]
want := gvisorchecksum.Checksum(buf, seed) want := gvisorchecksum.Checksum(buf, seed)
got := Checksum(buf, seed) got := impl.fn(buf, seed)
if got != want { if got != want {
t.Fatalf("len=%d off=%d seed=%#x: got %#04x want %#04x", t.Fatalf("len=%d off=%d seed=%#x: got %#04x want %#04x",
length, off, seed, got, want) length, off, seed, got, want)
@@ -40,12 +70,17 @@ func TestChecksumMatchesGvisor(t *testing.T) {
} }
} }
} }
})
}
} }
// TestChecksumPatternedBuffers exercises specific byte patterns that have // TestChecksumPatternedBuffers exercises specific byte patterns that have
// historically tripped up checksum implementations: all-zero, all-0xff, // historically tripped up checksum implementations: all-zero, all-0xff,
// alternating, and ascending sequences. // alternating, and ascending sequences.
func TestChecksumPatternedBuffers(t *testing.T) { func TestChecksumPatternedBuffers(t *testing.T) {
for _, impl := range implsUnderTest() {
t.Run(impl.name, func(t *testing.T) {
requireAvailable(t, impl)
for length := 0; length <= 256; length++ { for length := 0; length <= 256; length++ {
patterns := map[string][]byte{ patterns := map[string][]byte{
"zeros": make([]byte, length), "zeros": make([]byte, length),
@@ -56,7 +91,7 @@ func TestChecksumPatternedBuffers(t *testing.T) {
for name, buf := range patterns { for name, buf := range patterns {
for _, seed := range []uint16{0, 0xffff, 0x8000} { for _, seed := range []uint16{0, 0xffff, 0x8000} {
want := gvisorchecksum.Checksum(buf, seed) want := gvisorchecksum.Checksum(buf, seed)
got := Checksum(buf, seed) got := impl.fn(buf, seed)
if got != want { if got != want {
t.Fatalf("%s len=%d seed=%#x: got %#04x want %#04x", t.Fatalf("%s len=%d seed=%#x: got %#04x want %#04x",
name, length, seed, got, want) name, length, seed, got, want)
@@ -64,6 +99,8 @@ func TestChecksumPatternedBuffers(t *testing.T) {
} }
} }
} }
})
}
} }
func bytes(n int, v byte) []byte { func bytes(n int, v byte) []byte {
@@ -98,6 +135,9 @@ func ascending(n int) []byte {
// and k=1 (one main loop iter, then tail). It's explicit coverage for // and k=1 (one main loop iter, then tail). It's explicit coverage for
// payload sizes that are odd, not divisible by 4, by 8, or by 32. // payload sizes that are odd, not divisible by 4, by 8, or by 32.
func TestChecksumTailPaths(t *testing.T) { func TestChecksumTailPaths(t *testing.T) {
for _, impl := range implsUnderTest() {
t.Run(impl.name, func(t *testing.T) {
requireAvailable(t, impl)
rng := rand.New(rand.NewPCG(42, 17)) rng := rand.New(rand.NewPCG(42, 17))
const padFront = 16 const padFront = 16
const maxK = 8 const maxK = 8
@@ -120,7 +160,7 @@ func TestChecksumTailPaths(t *testing.T) {
} }
buf := pool[off : off+length] buf := pool[off : off+length]
want := gvisorchecksum.Checksum(buf, seed) want := gvisorchecksum.Checksum(buf, seed)
got := Checksum(buf, seed) got := impl.fn(buf, seed)
if got != want { if got != want {
t.Fatalf("k=%d tail=%d (len=%d) off=%d seed=%#x: got %#04x want %#04x", t.Fatalf("k=%d tail=%d (len=%d) off=%d seed=%#x: got %#04x want %#04x",
k, tail, length, off, seed, got, want) k, tail, length, off, seed, got, want)
@@ -129,6 +169,8 @@ func TestChecksumTailPaths(t *testing.T) {
} }
} }
} }
})
}
} }
// BenchmarkChecksumTailSizes covers payload sizes that aren't clean multiples // BenchmarkChecksumTailSizes covers payload sizes that aren't clean multiples
+11
View File
@@ -0,0 +1,11 @@
package checksum
// archImpls exposes every hand-written implementation on this architecture
// so the tests exercise them directly, independent of what the public
// Checksum dispatches to on the running CPU. Without this, running the
// suite on a non-AVX2 machine compared gvisor against itself and left the
// assembly untested — silently. available=false makes the test skip loudly
// instead.
var archImpls = []archImpl{
{name: "avx2", fn: checksumAVX2, available: hasAVX2},
}
+8
View File
@@ -0,0 +1,8 @@
package checksum
// archImpls exposes every hand-written implementation on this architecture
// for direct testing; see export_amd64_test.go for the rationale. NEON is
// mandatory in armv8, so it is always available.
var archImpls = []archImpl{
{name: "neon", fn: checksumNEON, available: true},
}
+7
View File
@@ -0,0 +1,7 @@
//go:build !amd64 && !arm64
package checksum
// No hand-written implementations on this architecture; the dispatcher is
// pure gvisor and there is nothing separate to test.
var archImpls []archImpl