Skip to content

verify: align recorded(RequestMatch) XPath element value with rift 0.23 (rift#1495) - #335

Merged
EtaCassiopeia merged 1 commit into
masterfrom
fix/rift-330-xpath-first-child
Oct 17, 2026
Merged

EtaCassiopeia merged 1 commit into
masterfrom
fix/rift-330-xpath-first-child

Conversation

@EtaCassiopeia

Copy link
Copy Markdown
Collaborator

Summary

rift 0.23.0 (rift#1495, PR achird-labs/rift#1529) reads an XPath-selected element as Mountebank's nodeValue does: as its first child node's text, or "undefined" when it has no children or starts with a child element. So //a on <a>x<b/>y</a> is x, not xy.

PredicateEvaluator backs Imposter.recorded(RequestMatch), but it still read getTextContent(), the element's whole text. On the 0.23.0 pin, recorded(match) could therefore disagree with what the engine's xpath stub matched and with what verify counted.

  • Elements: an element reads as its first child's value, or undefined. Text and attribute nodes read their own value.
  • Parsing: the parser coalesces, so text, references and CDATA form one node, as the engine sees them.
  • String-valued selectors: a selector that yields a string, number or boolean, such as string(//a) (the engine's documented way to read an element's whole text) or count(//a), is evaluated to that one value. It used to be refused as an invalid selector. A malformed selector still throws InvalidDefinition.

Tests

  • PredicateEvaluatorTest:

    • <a>x<b/>y</a> reads x (and not xy);
    • <a><b/>z</a> and <a/> read undefined;
    • text, references and CDATA form one node;
    • text(), @id and string(//a) read their own values.

    Both new tests were red before the fix. The existing XXE and malformed-selector tests still pass.

  • XPathRecordedMatchIT (conformance, spawn and embedded lanes, live rift 0.23.0): two XML bodies go through an imposter whose stub matches body == "x" at //a. The engine matches only the first, and recorded(match) agrees, for both x and undefined.

Verification

The core and conformance unit tests pass against the 0.23.0 corpus, and the IT passes on both lanes against the rift 0.23.0 binary and dylib.

rift-scala: no change. It inherits the evaluator through rift-java.

Closes #330

🤖 Generated with Claude Code

…ift 0.23.0

rift 0.23.0 reads a selected element as Mountebank's nodeValue, its first
child node's text, or "undefined" when it has none or starts with an element
(rift#1495). The client-side evaluator behind recorded(RequestMatch) still read
the element's whole text, so on 0.23 it could disagree with what the engine
matched and verify counted. It now reads the first child, parses text,
references and CDATA as one node, and evaluates a string-valued selector such
as string(//a), the engine's way to read the whole text, instead of refusing it.

Closes #330
@EtaCassiopeia
EtaCassiopeia merged commit 7c6ab16 into master Oct 17, 2026
16 checks passed
@EtaCassiopeia
EtaCassiopeia deleted the fix/rift-330-xpath-first-child branch October 17, 2026 03:44
EtaCassiopeia added a commit that referenced this pull request Oct 28, 2026
…rules apply (#350)

recorded(match) filtered the journal with a JVM copy of Mountebank's
predicate rules. That copy drifted from the engine three times (#330,
#335, and rift 0.24.0's repeated-key and JSON-body array rules), so a
filter could disagree with what the engine matched. It now asks the
engine's verify with includeRequests, as verify itself does since #127:
one call, the engine's answer, and inject predicates work too.

PredicateEvaluator is no longer called and is deprecated for removal.

Closes #337
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.

verify: align recorded(RequestMatch) XPath element value with rift 0.23 (rift#1495)

1 participant