From 3f1317e3e52e63c8aaaf251ae77efc0e4dfe0f6e Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Mon, 30 Aug 2021 10:47:21 -0700 Subject: [PATCH] util/deephash: fix TestArrayAllocs Unfortunately this test fails on certain architectures. The problem comes down to inconsistencies in the Go escape analysis where specific variables are marked as escaping on certain architectures. The variables escaping to the heap are unfortunately in crypto/sha256, which makes it impossible to fixthis locally in deephash. For now, fix the test by compensating for the allocations that occur from calling sha256.digest.Sum. See golang/go#48055 Fixes #2727 Signed-off-by: Joe Tsai --- util/deephash/deephash_test.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/util/deephash/deephash_test.go b/util/deephash/deephash_test.go index 3d2efd443..74321bf58 100644 --- a/util/deephash/deephash_test.go +++ b/util/deephash/deephash_test.go @@ -8,9 +8,11 @@ import ( "archive/tar" "bufio" "bytes" + "crypto/sha256" "fmt" "math" "reflect" + "runtime" "testing" "inet.af/netaddr" @@ -332,15 +334,32 @@ func TestArrayAllocs(t *testing.T) { if version.IsRace() { t.Skip("skipping test under race detector") } + + // In theory, there should be no allocations. However, escape analysis on + // certain architectures fails to detect that certain cases do not escape. + // This discrepency currently affects sha256.digest.Sum. + // Measure the number of allocations in sha256 to ensure that Hash does + // not allocate on top of its usage of sha256. + // See https://golang.org/issue/48055. + var b []byte + h := sha256.New() + want := int(testing.AllocsPerRun(1000, func() { + b = h.Sum(b[:0]) + })) + switch runtime.GOARCH { + case "amd64", "arm64": + want = 0 // ensure no allocations on popular architectures + } + type T struct { X [32]byte } x := &T{X: [32]byte{1: 1, 2: 2, 3: 3, 4: 4}} - n := int(testing.AllocsPerRun(1000, func() { + got := int(testing.AllocsPerRun(1000, func() { sink = Hash(x) })) - if n > 0 { - t.Errorf("allocs = %v; want 0", n) + if got > want { + t.Errorf("allocs = %v; want %v", got, want) } }