Skip to content

Fix run_tests array params double-encoding when client sends JSON-str…#695

Closed
voonfoo wants to merge 2 commits intoCoplayDev:betafrom
voonfoo:fix/run-tests-array-double-encoding
Closed

Fix run_tests array params double-encoding when client sends JSON-str…#695
voonfoo wants to merge 2 commits intoCoplayDev:betafrom
voonfoo:fix/run-tests-array-double-encoding

Conversation

@voonfoo
Copy link
Contributor

@voonfoo voonfoo commented Feb 7, 2026

Description

Fix run_tests array parameter filtering (test_names, group_names, category_names, assembly_names) returning zero matching tests due to double-encoding.

Type of Change

Save your change type

  • Bug fix (non-breaking change that fixes an issue)

Changes Made

  • Updated _coerce_string_list in Server/src/services/tools/run_tests.py to detect and parse JSON-stringified arrays before forwarding to Unity
  • When FastMCP/Pydantic coerces a list[str] | str union parameter to str, it produces '["test1"]' instead of a native list. The helper now parses these back to a proper list[str]

Testing/Screenshots/Recordings

Debug logs on the C# side confirmed the double-encoding:

Before (broken):
{"testNames":["[\"Namespace.Test1\"]"]}
Unity receives the literal string ["Namespace.Test1"] as the test name — matches nothing, returns 0 tests.

After (fixed):
{"testNames":["Namespace.Test1"]}
Unity correctly matches and runs targeted tests correctly.

Summary by Sourcery

Bug Fixes:

  • Ensure JSON-stringified arrays passed as string values to run_tests are parsed into proper string lists before being forwarded to Unity.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced input validation to robustly handle various string formats, including whitespace trimming and array parsing, improving test configuration reliability.

…ingified lists

When MCP clients send array parameters like test_names as JSON arrays,
FastMCP/Pydantic can coerce list[str] | str union types to the str
variant, producing a JSON-stringified array (e.g. '["test1"]') instead
of a native list. _coerce_string_list then wraps this string as
['["test1"]'], causing Unity's test filter to receive the literal string
'["test1"]' instead of 'test1' — matching zero tests.

The fix detects JSON-stringified arrays in the str branch and parses
them back to a proper list before forwarding to Unity.
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 7, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts run_tests string list coercion to correctly handle JSON-stringified arrays, preventing double-encoded test filters from resulting in zero matches.

File-Level Changes

Change Details Files
Improve string-to-list coercion for run_tests filter parameters to handle JSON-stringified arrays and ignore empty values.
  • Return None for empty or whitespace-only string inputs instead of a single empty string element.
  • Detect inputs that look like JSON arrays (starting with '[') and attempt to json.loads them.
  • If JSON parsing succeeds and yields a list, normalize each element to a stripped string and drop falsy/blank entries, returning None if the resulting list is empty.
  • Gracefully fall back to treating the original value as a single string element if JSON parsing fails or does not yield a list.
  • Preserve existing behavior for list inputs by normalizing elements to stripped strings and dropping falsy/blank entries.
Server/src/services/tools/run_tests.py

Possibly linked issues

  • #run_tests test filtering broken: snake_case params ignored + double-serialized arrays: Link: PR fixes the described double-serialized array bug causing run_tests filters to match zero tests.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

The _coerce_string_list function in run_tests.py was made more robust: it returns None for whitespace-only strings, attempts to parse JSON array strings into trimmed non-empty lists, falls back to single-element trimmed lists for plain strings, and preserves existing list handling.

Changes

Cohort / File(s) Summary
String Parsing Enhancement
Server/src/services/tools/run_tests.py
Refined _coerce_string_list: treat whitespace-only input as None; parse JSON array strings into trimmed lists (log on JSON errors); convert non-JSON trimmed strings into single-item lists; filter falsy/empty items from lists.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

I’m a rabbit tidying strings with glee,
Trimming, parsing arrays, setting empties free,
A JSON hop, a whitespace skip,
One-item lists from a single blip,
Hooray for clean inputs — hop, hop, whee! 🐰✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing double-encoding of array parameters in run_tests when clients send JSON-stringified data.
Description check ✅ Passed The description covers the required sections: description of the bug, type of change (bug fix), specific changes made, testing/verification with before/after logs, and additional context. All essential information is present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Consider moving the json import to the module level instead of importing inside _coerce_string_list to avoid repeated imports on hot paths.
  • The JSON detection currently only checks stripped.startswith("["); you might also guard with stripped.endswith("]") or a more explicit heuristic to avoid accidentally treating non-JSON strings that start with [ as lists.
  • When JSON parsing fails you silently fall back to treating the value as a scalar string; if this is unexpected input, you may want to at least log at debug level to make future mis-encodings easier to diagnose.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider moving the `json` import to the module level instead of importing inside `_coerce_string_list` to avoid repeated imports on hot paths.
- The JSON detection currently only checks `stripped.startswith("[")`; you might also guard with `stripped.endswith("]")` or a more explicit heuristic to avoid accidentally treating non-JSON strings that start with `[` as lists.
- When JSON parsing fails you silently fall back to treating the value as a scalar string; if this is unexpected input, you may want to at least log at debug level to make future mis-encodings easier to diagnose.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

…ug logging

- Move json import to module level to avoid repeated imports
- Guard JSON detection with both startswith("[") and endswith("]")
- Log at debug level when JSON parsing fails for easier diagnostics
@voonfoo
Copy link
Contributor Author

voonfoo commented Feb 7, 2026

duplicated PR #690, will close this

@voonfoo voonfoo closed this Feb 7, 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