Skip to content

test: negative FromXml rejection tests + command-not-found e2e#38

Merged
irvingouj@Devolutions (irvingoujAtDevolution) merged 4 commits into
masterfrom
stack/xml-fromxml-tests
Jun 25, 2026
Merged

test: negative FromXml rejection tests + command-not-found e2e#38
irvingouj@Devolutions (irvingoujAtDevolution) merged 4 commits into
masterfrom
stack/xml-fromxml-tests

Conversation

@irvingoujAtDevolution

Copy link
Copy Markdown
Collaborator

Part 6/6. Base: stack/xml-fromxml-harden.

Pins the rejection behavior from #5 with negative unit tests (mixed-content leaf, Empty non-empty, single-child descend zero/multiple/wrong-name, duplicate Command/CommandState/derived ExitCode, duplicate selector/option keys) and adds a command-not-found case to the real-server command matrix e2e (asserts the error record prints to stdout and the process still exits 0).

FromXml stack (review/merge bottom-up):

  1. core + winrm migration (feat(xml): namespace-correct FromXml core + winrm migration #33)
  2. nested-tag descend fix (fix(winrm): descend into child for a tag whose value is a tag #34)
  3. delete dead AnyTag/TagList + markers (refactor(winrm): delete dead AnyTag/TagList and stale tag markers #35)
  4. tag! macro + aliases (refactor(winrm): alias-based tags via tag! macro #36)
  5. harden / reject malformed XML
  6. tests

Review-loop findings (Claude subagents + Codex, converged). The visitor→FromXml
migration had relaxed several validations the old visitors enforced; this
restores strict rejection of malformed/untrusted input across the parse layer:

- `leaf_text()` helper: text-valued leaves (Text/WsUuid/Time/numerics) reject any
  non-text child (mixed content, comments, PIs) instead of silently truncating
  via `node.text()`. `Empty` rejects any non-whitespace content.
- `Tag::from_xml` wrapper-descend (`Tag<Tag<..>,_>`): requires exactly one child
  element which must be `N` — rejects extra siblings, wrong child, duplicates.
- `#[derive(FromXml)]`: `if … else if …` matcher chain; rejects a duplicate
  element for a singleton field; reports shape errors via `syn::Error` not
  `panic!`; doc no longer references the deleted `SimpleXmlDeserialize`.
- Hand-written impls made consistent: commandline (leaf_text; empty `<Command/>`
  → None via a seen flag; duplicate `<Command>` rejected), receive (duplicate
  `<CommandState>` rejected), SelectorSet/OptionSet (leaf_text; duplicate Name
  rejected).
- Comments: flagged the deliberate `Send` alias / `std::marker::Send` shadow and
  the `Locale`/`DataLocale` empty-vs-text deserialize-collapse invariant.

Trimming in `leaf_text` is intentional and kept (original leaf behavior; strips
pretty-printed-XML indentation; WinRM values carry no significant edge
whitespace) — a Codex suggestion to drop it was declined as a regression.

Verified: fmt + clippy (-D warnings) clean, workspace tests pass, real-server
matrix 10/10.
Pin the rejection behavior the hardening round added: mixed-content leaf
rejection, Empty non-empty rejection, single-child descend (zero/multiple/
wrong-name), duplicate singleton (Command/CommandState/derived ExitCode),
and duplicate selector/option keys.
A non-existent command surfaces as an error record (non-fatal), printed via
render_concise to stdout while the process still exits 0. Asserts both, across
all auth methods.
Polish from the independent review pass (no behavior change except a clearer
error message): remove dead commented-out visitor block in ws_addressing;
correct the tag! marker-visibility doc; drop two what/how comments; loosen the
paste version pin; clearer 'found none' diagnostic for an empty tag wrapper;
restore optional-permutation derive tests and add mixed-content rejection tests
for numeric/uuid leaves.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant