Skip to content

test(extism): cover Eval loadInputData and ConvertToExtismFormat errors#119

Merged
robbyt merged 1 commit into
mainfrom
tests/issue-109-eval-error-paths
May 10, 2026
Merged

test(extism): cover Eval loadInputData and ConvertToExtismFormat errors#119
robbyt merged 1 commit into
mainfrom
tests/issue-109-eval-error-paths

Conversation

@robbyt
Copy link
Copy Markdown
Owner

@robbyt robbyt commented May 10, 2026

Summary

Issue #109 listed 6 hard-to-reach error branches in engines/extism/evaluator/evaluator.go. Auditing the existing test suite found that 4 of the 6 were already covered:

Issue's proposed subtest Already covered by
plugin instance error TestEvaluator_Evaluate/error_cases/error creating plugin instance (L443)
call with context cancellation TestEvaluator_Evaluate/error_cases/context cancellation (L366) + metadata_tests/exec helper/context cancellation (L553)
call with context plain error metadata_tests/exec helper/execution error (L540)
non-JSON output falls back to string success_cases/successful execution with string output (L185) — passes plain text bytes, asserts string fallback

The remaining two branches in Eval() itself were genuinely uncovered. This PR adds two subtests under TestEvaluator_Evaluate/error_cases:

1. load input data error — covers evaluator.go:172-175

Wires the existing mockErrProvider into ExecutableUnit.DataProvider. Verifies Eval returns the wrapped "failed to get input data" error and never reaches plugin.Instance.

2. convert to extism format error — covers evaluator.go:178-181

Adds a tiny mockMapProvider helper next to mockErrProvider; populates it with chan int (not JSON-marshalable). Verifies Eval returns the wrapped "failed to marshal input data" error and never reaches plugin.Instance.

Scaffolding

mockMapProvider is the only new scaffolding — MockCompiledPlugin, mockPluginInstance, mockErrProvider, and createMockExecutable() all existed.

Out of scope

The instance.Close(ctx) failure paths (L96-98 in compiler, L118-122 in evaluator) — the issue body notes these are "logged-only, doesn't propagate, so coverage value is low." Left intentionally untested.

The exit-code-vs-output design question (#94) — separate issue.

Test plan

  • go test -race -count=1 ./engines/extism/evaluator/... — green; 2 new subtests visible
  • Coverage: extism/evaluator went from ~93% to 95.5%
  • go test -race -count=1 ./... — full suite green
  • go vet ./... — clean
  • CI on the PR

Closes #109

https://claude.ai/code/session_01C61VEAmjxSnX5Xhbab8NvL


Generated by Claude Code

Closes #109

Issue #109 listed 6 hard-to-reach error branches in
`engines/extism/evaluator/evaluator.go`. Auditing the existing test
suite found that 4 of the 6 were already covered:

  - "plugin instance error"          → "error creating plugin instance" (line 443)
  - "call with context cancellation" → "context cancellation" (line 366) +
                                       execHelper "context cancellation" (line 553)
  - "call with context plain error"  → execHelper "execution error" (line 540)
  - "non-JSON output → string"       → "successful execution with string output" (line 185)

The remaining two branches in `Eval()` itself were genuinely uncovered:

  - L172-175: `loadInputData` returning an error from the data provider
  - L178-181: `internal.ConvertToExtismFormat` failing on json.Marshal

Add two new subtests under `TestEvaluator_Evaluate/error_cases`:

  - "load input data error" — wires `mockErrProvider` (already in this
    file) into `ExecutableUnit.DataProvider`; verifies Eval returns the
    wrapped "failed to get input data" error and never touches
    `plugin.Instance`.

  - "convert to extism format error" — adds a tiny `mockMapProvider`
    helper next to `mockErrProvider`; populates it with `chan int`
    (not JSON-marshalable); verifies Eval returns the wrapped
    "failed to marshal input data" error and never touches
    `plugin.Instance`.

The `mockMapProvider` is the only new scaffolding — `MockCompiledPlugin`,
`mockPluginInstance`, `mockErrProvider`, and `createMockExecutable()`
all existed.

Coverage: extism/evaluator package moved from ~93% to 95.5%. The two
remaining uncovered branches are `instance.Close(ctx)` failure paths
(L96-98 in compiler, L118-122 in evaluator) which the issue notes are
"logged-only, doesn't propagate, so coverage value is low" — left
intentionally untested.
Copilot AI review requested due to automatic review settings May 10, 2026 16:03
@github-actions
Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves unit-test coverage for the Extism evaluator by exercising two previously uncovered error branches in Evaluator.Eval() related to input data loading and input marshaling.

Changes:

  • Add mockMapProvider test helper to return controlled map[string]any input without errors.
  • Add subtest covering loadInputData failure (failed to get input data) and asserting plugin.Instance is not reached.
  • Add subtest covering internal.ConvertToExtismFormat marshaling failure (failed to marshal input data) and asserting plugin.Instance is not reached.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@robbyt robbyt merged commit 926aea9 into main May 10, 2026
7 checks passed
@robbyt robbyt deleted the tests/issue-109-eval-error-paths branch May 10, 2026 16:08
@robbyt robbyt mentioned this pull request May 10, 2026
3 tasks
robbyt added a commit that referenced this pull request May 10, 2026
* docs: add CHANGELOG.md (Keep a Changelog 1.1.0)

Closes #102

Repo had no CHANGELOG.md; users had to read GitHub release notes to
find what changed between versions. With v1 ahead and a queue of
breaking changes (#86, #87, #88, #89, #90, #91, #104), having a
CHANGELOG before landing those gives downstream code reviewers and
IDEs visibility into what's coming.

Format follows Keep a Changelog 1.1.0 with the standard six headings
(Added / Changed / Deprecated / Removed / Fixed / Security).

[Unreleased] section captures the run of merged-but-not-released PRs
since v0.7.0:

  - #103  polyscript.New[E] generic constructor (deprecates 12 FromXxx)
  - #105  slog.Handler optional in engine subpackages
  - #106  RequestToMap mutation fix
  - #107  HTTP loader MaxBodySize cap
  - #110  unify nil-handler on slog.Default(); drop stdout fallbacks
  - #113  WithLogHandler(nil)/WithLogger(nil) → no-op
  - #114  drop redundant nil-guards; tighten WithLogHandler doc
  - #115  docs/LOGGING.md
  - #117  fix bare top-level json.Number leak
  - #118  WithGlobals additive; drop dead URL check
  - #119  extism Eval test coverage

Backfilled the three releases the issue called out (v0.5.0, v0.6.0,
v0.7.0) from existing GitHub release notes, sorted into Keep a
Changelog categories.

Earlier releases (v0.0.x through v0.4.0) intentionally not backfilled
per the issue scope; can be added in a follow-up if desired.

Out of scope: the optional CI gate that fails PRs not touching
CHANGELOG.md. Adds noise to small bug PRs and wants opt-out-label
infrastructure to support it; better as a separate issue.

* docs(CHANGELOG): clarify deprecated FromXxx still take positional handler

Copilot review noted that "no constructor demands a handler" is
misleading because the deprecated FromXxx constructors still take a
positional `logHandler slog.Handler` argument (even though nil is
accepted). Reword to distinguish the new generic constructor (no
handler arg) from the deprecated ones (still take it, but nil is OK).

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

[tests] extism Eval() error paths need expanded mocking for plugin/instance failures

3 participants