Skip to content

fix: HavePatternsMatcher reports actual content instead of Go type for io.Reader inputs#1

Closed
Blankf wants to merge 1 commit intomasterfrom
fix/have-patterns-reader-bug
Closed

fix: HavePatternsMatcher reports actual content instead of Go type for io.Reader inputs#1
Blankf wants to merge 1 commit intomasterfrom
fix/have-patterns-reader-bug

Conversation

@Blankf
Copy link
Copy Markdown
Owner

@Blankf Blankf commented Apr 20, 2026

Summary

HavePatternsMatcher.FailureResult() and NegatedFailureResult() render io.Reader inputs as their Go type string (e.g. "object: *bytes.Reader", "object: *os.File") instead of the actual content read from the reader.

This affects every Command stdout and File contents check that uses pattern matching -- when a pattern fails, the output is useless for debugging because it shows the type instead of what was actually read.

Root Cause

The default branch in the type switch used:

a = fmt.Sprintf("object: %T", actual)

for any type that isn't string or []string. Since Command and File resources pass their output as io.Reader, the actual content was never displayed.

Fix

Cache the lines read during Match() and use the cached content in failure result output. This ensures:

  • Failed pattern matches show the actual command/file output
  • No other matchers are affected -- only HavePatternsMatcher had this issue
  • All non-Reader paths (string, []string) remain untouched
  • The existing basic_reader test case now expects actual content instead of "object: *strings.Reader"

Evidence

Tested against CIS benchmark gossfiles on both Linux and Windows:

Platform Binary object: *bytes.Reader occurrences
Windows Upstream 153
Windows Patched 0
Linux Upstream 150
Linux Patched 0

The upstream binary also returned significantly fewer results on Windows (155 vs 881) suggesting the broken output may cause downstream parsing failures.

Test Fixtures Updated

The basic_reader test fixtures previously expected "object: *strings.Reader" -- confirming this was a known-but-unaddressed bug. Updated to expect the actual content ("foo bar\nmoo cow").

…r io.Reader inputs

When a Command stdout or File contents check failed pattern matching, the
FailureResult and NegatedFailureResult methods rendered the actual value as
"object: *bytes.Reader" (or *os.File, *strings.Reader) instead of showing
the actual content that was read from the io.Reader.

This happened because the default branch in the type switch used
fmt.Sprintf("object: %T", actual) for any non-string/non-[]string type,
which includes all io.Reader inputs (the primary path for Command and File
resource outputs).

The fix caches the lines read during Match() and uses the cached content
in the failure result output. This ensures that:
- Failed pattern matches show the actual command/file output
- Operators can see what content was tested against their patterns
- No other matchers are affected (only HavePatternsMatcher had this issue)
- All non-Reader paths (string, []string) remain untouched

The existing test suite explicitly tests io.Reader inputs (basic_reader test
case). The test fixtures previously expected "object: *strings.Reader" as
the output, confirming this was a known-but-unaddressed bug. The fixtures
now expect the actual content.
@Blankf
Copy link
Copy Markdown
Owner Author

Blankf commented Apr 20, 2026

Closing -- duplicate of goss-org#1055 which takes a cleaner approach by fixing at the validate.go level.

@Blankf Blankf closed this Apr 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