@@ -272,39 +272,59 @@ func testHasherCorrectness(h bmt.Hasher, data []byte, n, count int) (err error)
272272}
273273
274274// TestGoroutineSIMDParity verifies that the goroutine and SIMD pools produce
275- // identical root hashes for the same input, across a spread of write lengths.
276- // The SIMD sub-test is a no-op on platforms where the dispatcher falls back to
277- // the goroutine pool (non-linux/amd64 or CPU without AVX2).
275+ // identical root hashes for the same input across every segment count in
276+ // testSegmentCounts and a spread of write lengths. Iterating over the full
277+ // segment-count table exercises the degenerate 1-level and shallow-tree branches
278+ // of simdHasher.Hash that a fixed 128-segment test would miss.
279+ //
280+ // On platforms where the dispatcher falls back to the goroutine pool
281+ // (non-linux/amd64 or CPU without AVX2/AVX-512), both pools end up as goroutine
282+ // pools and the test degrades to a goroutine-vs-goroutine comparison.
283+ //
284+ // Sub-tests are intentionally not run in parallel: the SIMDOptIn flip is global
285+ // state and concurrent NewPool calls would see flapping values.
278286func TestGoroutineSIMDParity (t * testing.T ) {
279287 testData := testutil .RandBytesWithSeed (t , 4096 , seed )
280- lengths := []int {1 , 31 , 32 , 33 , 64 , 128 , 500 , 1024 , 2048 , 4095 , 4096 }
281288
282- prev := bmt .SIMDOptIn
283- defer func () { bmt .SIMDOptIn = prev }( )
289+ prev := bmt .SIMDOptIn ()
290+ defer bmt .SetSIMDOptIn ( prev )
284291
285- bmt . SIMDOptIn = false
286- gPool := bmt . NewPool ( bmt . NewConf ( testSegmentCount , 1 ))
287- bmt . SIMDOptIn = true
288- sPool := bmt . NewPool ( bmt . NewConf ( testSegmentCount , 1 ))
292+ // Representative write lengths; clamped per segment count below. 0 covers the
293+ // empty-input path, and the neighbourhood of section boundaries (31/32/33,
294+ // 63/64/65) tickles the padding/fall-through in Hash.
295+ lengths := [] int { 0 , 1 , 31 , 32 , 33 , 63 , 64 , 65 , 128 , 500 , 1024 , 2048 , 4095 , 4096 }
289296
290- for _ , n := range lengths {
291- t .Run (fmt .Sprintf ("len_%d" , n ), func (t * testing.T ) {
292- gh := gPool .Get ()
293- gHash , err := syncHash (gh , testData [:n ])
294- gPool .Put (gh )
295- if err != nil {
296- t .Fatal (err )
297- }
297+ for _ , count := range testSegmentCounts {
298+ t .Run (fmt .Sprintf ("segments_%d" , count ), func (t * testing.T ) {
299+ bmt .SetSIMDOptIn (false )
300+ gPool := bmt .NewPool (bmt .NewConf (count , 1 ))
301+ bmt .SetSIMDOptIn (true )
302+ sPool := bmt .NewPool (bmt .NewConf (count , 1 ))
303+
304+ maxLen := count * hashSize
305+ for _ , n := range lengths {
306+ if n > maxLen {
307+ continue
308+ }
309+ t .Run (fmt .Sprintf ("len_%d" , n ), func (t * testing.T ) {
310+ gh := gPool .Get ()
311+ gHash , err := syncHash (gh , testData [:n ])
312+ gPool .Put (gh )
313+ if err != nil {
314+ t .Fatal (err )
315+ }
298316
299- sh := sPool .Get ()
300- sHash , err := syncHash (sh , testData [:n ])
301- sPool .Put (sh )
302- if err != nil {
303- t .Fatal (err )
304- }
317+ sh := sPool .Get ()
318+ sHash , err := syncHash (sh , testData [:n ])
319+ sPool .Put (sh )
320+ if err != nil {
321+ t .Fatal (err )
322+ }
305323
306- if ! bytes .Equal (gHash , sHash ) {
307- t .Fatalf ("goroutine/simd mismatch at len=%d\n goroutine: %x\n simd: %x" , n , gHash , sHash )
324+ if ! bytes .Equal (gHash , sHash ) {
325+ t .Fatalf ("goroutine/simd mismatch at count=%d len=%d\n goroutine: %x\n simd: %x" , count , n , gHash , sHash )
326+ }
327+ })
308328 }
309329 })
310330 }
0 commit comments