RFC 014 - Command-line option mappings#8501
Conversation
Introduces a proposal for command-line option mappings: a new extensibility point that lets an extension declaratively accept a user-facing option (e.g. `--logger trx`, `--collect "XPlat Code Coverage"`) and rewrite it, at parse time, into one or more first-class MTP options. The primary scenario is easing migration from VSTest to MTP without polluting the canonical MTP option set. Multiple extensions are allowed to register the same mapping name, with exactly one expected to claim responsibility for a given argument value. Refs #7249 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new design RFC to the docs/RFCs area proposing command-line option mappings for Microsoft.Testing.Platform (MTP): an extensibility point allowing VSTest-style options like --logger trx / --collect ... to be rewritten into canonical MTP options during parsing to ease migration.
Changes:
- Introduces an RFC describing the motivation, naming, proposed public API, and resolution/validation algorithm for command-line option mappings.
- Provides worked examples (TRX and code coverage) and outlines help/info/telemetry implications plus a phased rollout plan.
Show a summary per file
| File | Description |
|---|---|
| docs/RFCs/014-Command-Line-Option-Mappings.md | New RFC document defining the proposed “command-line option mappings” concept, API surface, and behavior. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 5
Evangelink
left a comment
There was a problem hiding this comment.
RFC 014 Review Summary
I've reviewed RFC 014 - Command-line option mappings against 21 expert review dimensions. The RFC proposes a well-motivated solution to a real migration pain point (VSTest → MTP compatibility), with strong design principles and thorough alternatives analysis. However, critical issues in the proposed API design require changes before approval.
Verdict Table
| # | Dimension | Verdict |
|---|---|---|
| 1 | Public API & Binary Compatibility | 🔴 1 BLOCKING, 2 MODERATE |
| 2 | Defensive Coding at Boundaries | 🔴 2 BLOCKING, 2 MAJOR |
| 3 | Algorithmic Correctness | 🟡 2 MAJOR |
| 4 | Naming & Conventions | ⚪ 2 NIT |
| 5 | Documentation Accuracy | ⚪ 1 NIT |
| 6 | Performance & Allocations | 🟡 1 MODERATE (covered above) |
✅ 15/21 dimensions clean.
Critical Issues (Must Fix Before Approval)
🔴 BLOCKING #1: Delegate signature prevents future evolution and lacks safety
Location: Lines 117-119 (CommandLineOptionMapper delegate)
Problems:
- Cannot add warnings later: RFC acknowledges (line 350) wanting to add warnings, but adding an
outparameter to a delegate is a breaking change - No exception handling: Extension throws → platform crash during startup
- No result validation: Extension returns
truewithresult = null→ NullReferenceException - No timeout: Extension infinite loop → platform hangs indefinitely
Fix: Replace bool return + out parameter with a result struct that can carry warnings in future versions:
public delegate CommandLineOptionMapperResult CommandLineOptionMapper(
ReadOnlySpan<string> arguments);
public readonly struct CommandLineOptionMapperResult
{
public bool Success { get; init; }
public IReadOnlyList<CommandLineOptionMappingResult> Results { get; init; }
// Future: public IReadOnlyList<string> Warnings { get; init; }
}Add defensive wrapping (try/catch, validation, timeout) to the RFC's algorithm section.
🔴 BLOCKING #2: Naming inconsistency in manager pattern
Location: Lines 141, 149
Problem: ICommandLineMappingsManager uses plural "Mappings", breaking the universal MTP pattern: ICommandLineManager, ITestHostManager, IConfigurationManager, ILoggingManager (all singular).
Fix: Rename to ICommandLineMappingManager (singular). Update property name to CommandLineMapping to match the TestHost / ITestHostManager pattern.
Major Issues (Should Fix)
🟡 Algorithmic correctness gaps (2 issues)
- Empty result list undefined (line 246): What if
TryMapreturnstruewith empty results? Does occurrence get deleted? - Runtime validation missing (line 258): Validation rules claim "enforced at startup" but can't detect invalid
OptionNameuntil runtime
Fix: Specify behavior for empty results (error recommended). Add runtime validation step in algorithm.
🟡 Defensive coding gaps (2 more issues beyond BLOCKING)
- Unbounded growth (line 192): Example code splits on
;with no limits → 100K segments from malicious input - Malformed sub-options (line 194): No guidance on handling
trx;LogFileName=(empty value)
Fix: Add defensive limits to examples (max segments, length checks). Document error handling approach for malformed sub-options.
Moderate Issues (Recommended Fixes)
Constructor design (line 126)
paramsblocks future evolution: Can't add optional parameters afterparamsarray- Unnecessary allocation:
paramscreates array wrapper even for zero-argument cases
Fix: Add non-params overload for zero-argument case and explicit IReadOnlyList<string> overload.
Summary
Strong points:
- Clear problem statement and motivation
- Thorough alternatives analysis (5 rejected options)
- Well-defined design principles
- Comprehensive phasing plan
- Threading/concurrency design is sound (synchronous, pre-DI, single-threaded startup)
Must address before approval:
- Delegate signature evolution strategy (warnings, safety)
- Naming consistency with existing patterns
- Algorithm specification completeness (empty results, runtime validation)
- Defensive coding guidance (limits, error handling)
The core concept is sound and valuable. The issues are fixable refinements to the API design, not fundamental flaws. Recommend addressing BLOCKING issues and reconsidering the MAJOR issues before moving to implementation.
Review dimensions not applicable to RFC: Test Isolation, Assertion Quality, Flakiness Patterns, Data-Driven Test Coverage, Analyzer Quality, IPC Wire Compatibility, Resource Management, Localization, Build Infrastructure, Cross-TFM Compatibility (these apply to implementation, not design docs).
Generated by Expert Code Review (on open) for issue #8501 · ● 22.6M
- Renumber to 015 to avoid collision with the existing 014-TestRun-Current-PlannedTests RFC. - Align Naming section with the actual proposed types (ICommandLineOptionMappingProvider / ICommandLineMappingManager, matching the singular convention used elsewhere). - Fix the broken <see cref="TryMap"/> reference to point at the Map property. - Make the TRX example case-insensitive for both the exact "trx" check and the "trx;" prefix, matching VSTest-compat expectations. - Replace ReadOnlySpan<string> with IReadOnlyList<string> in the public delegate; the platform targets netstandard2.0 and Span-shaped APIs add a System.Memory dependency to the public surface for limited benefit. - Replace params string[] with IReadOnlyList<string> in CommandLineOptionMappingResult to keep the constructor open for future parameters and avoid unnecessary array allocations for the (common) zero/one-argument case. - Document the empty-result contract violation explicitly and split startup-time vs runtime cross-cutting validation rules so the RFC matches what can actually be enforced when the Map delegate is opaque. - Expand the TRX example with malformed-segment handling and a sub- option cap to address the defensive-coding concerns about unbounded user input. - Note in Unresolved Questions that adding an out-parameter to the delegate is a binary-breaking change, so the warning-channel decision must be made before shipping (or absorbed via a sibling delegate). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds RFC 014 proposing command-line option mappings: a new extensibility point that lets an extension declaratively accept a user-facing option (e.g.
--logger trx,--collect ""XPlat Code Coverage"") and rewrite it, at parse time, into one or more first-class MTP options.Why
The primary scenario is easing migration from VSTest to MTP. Today,
dotnet test --logger trx --collect ""XPlat Code Coverage""producesUnknown optionagainst MTP — correct but unhelpful for the very large body of CI pipelines and tribal knowledge built around VSTest syntax.The existing
ICommandLineOptionsProvidercontract intentionally forbids two extensions from registering the same option name.--loggerand--collectare however intrinsically polyvalent: the value selects which extension owns the option. A new concept is therefore needed.What's in the RFC
MappingoverAlias/Transformation/Shim/Legacy…), explicitly addressing the alias-vs-rewrite discussion from [Proposal]: MTP Command-line aliases #7249.ICommandLineOptionMappingProvider,CommandLineOptionMapping,CommandLineOptionMapperdelegate (TryHandlestyle),CommandLineOptionMappingResult.trx;LogFileName=…) and Code Coverage.Discussion seeds
Specific points where reviewer input would be most valuable:
Mapping, or switch back toAlias(familiar) orTransformation(most accurate)?TryMapget anout List<string> warningsparameter in v1, or defer?used_compat_mapping: bool, or include allowlisted values?Refs #7249 — this PR provides the design artefact requested by the issue; implementation will follow in a separate PR once the RFC is approved.