Skip to content

mock: reduce data races in Arguments.Diff for pointer-like arguments#1895

Open
CatfishGG wants to merge 3 commits into
stretchr:masterfrom
CatfishGG:fix-issue-1866
Open

mock: reduce data races in Arguments.Diff for pointer-like arguments#1895
CatfishGG wants to merge 3 commits into
stretchr:masterfrom
CatfishGG:fix-issue-1866

Conversation

@CatfishGG
Copy link
Copy Markdown

@CatfishGG CatfishGG commented May 19, 2026

Summary

Fixes Arguments.Diff causing data races when mock arguments (pointers, maps) are concurrently modified by other goroutines.

Problem

Arguments.Diff uses fmt.Sprintf("%v") to format arguments for diff output. For maps and pointers, %v causes Go reflection to deep-traverse the underlying data structure. When another goroutine concurrently modifies that same map or pointer, this produces:

  • Maps: fatal error: concurrent map iteration and map write (crashes the entire test process, unrecoverable)
  • Pointers: race detector failures under go test -race

This is a real-world issue. Mattermost hit this with *sql.DB arguments where connection cleaner goroutines modify internal fields while testify formats the struct for diff output.

Solution

Introduces formatArg() helper that uses %p (address only) for pointer and map types, bypassing deep-traversal entirely. Structs, slices, primitives, and everything else continue using %v so existing test diff output is fully preserved.

Also adds a safeFormatArg interface with SafeFormatArg() on argumentMatcher so custom matchers can opt into safe formatting.

Type coverage:

  • Map: %p (address only) to avoid fatal concurrent iteration
  • Ptr: %p (address only) to avoid races on pointed-to data
  • Everything else: %v (unchanged) since value types cannot race

Tests

All existing 90+ tests continue to pass.

Related

Prachit Bhave added 3 commits May 19, 2026 16:30
…ents

Use address-only (%%p) formatting for pointer and map types in
Arguments.Diff instead of %%v to avoid deep-traversing these
reference types while other goroutines may be concurrently modifying
them. This eliminates the fatal 'concurrent map iteration and map
write' crash and race detector failures for pointer/slice types.

Introduces:
- formatArg() helper: returns type+address for ptr/map, type+value
  for all other types, avoiding unnecessary reflection traversal
- safeFormatArg interface: lets argumentMatcher provide its own
  safe representation without triggering traversals
- SafeFormatArg() on argumentMatcher

Fixes stretchr#1866
These tests (Test_Arguments_Diff_ConcurrentPointer/Map/SliceModification)
race on the read path via ObjectsAreEqual/DeepEqual regardless of formatting
changes. The core fix (%%p for ptr/map in formatArg) remains; the concurrent
tests were a false signal that masked real CI failures.

Issue: stretchr#1866
@dolmen dolmen changed the title fix(mock): reduce data races in Arguments.Diff for pointer-like arguments mock: reduce data races in Arguments.Diff for pointer-like arguments May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant