tests/spec: record the expression evaluator's spec from mongod

27 cases, recorded before a line of the evaluator is written, which is the
whole point of having built the recorder first: the expectations come from
mongod 8.3.7 rather than from what the implementation is about to do.

The corpus reads 1 pass / 26 fail, and the one pass is the unknown-operator
refusal M2 already answers correctly. Expressions are exercised through
`$group` because `_id` and the accumulator arguments are the only expression
positions that exist until `$addFields` and `$project`'s computed fields land;
testing them anywhere else would be testing a stage that is not there.

Ten things the recording settled that guessing would have got wrong:

    $add over a missing field or null   null -- not an error, and not 0
    $add over a string                  error 7157723
    $divide by zero                     error 4848401
    $mod of -5 by 4                     -1, the dividend's sign
    $lt of a number and a string        true, canonical type order
    $and over -5                        truthy
    $not of a missing field             true
    $switch, no branch and no default   error 40069
    two operators in one expression     error 15983, *not* $group's 40238
    $subtract with one operand          error 16020

The six error codes are in `ErrorCode` already, so the evaluator's refusals and
its runtime failures have somewhere measured to land. The evaluator itself is
the next commit and is not started.

191/191 unit tests, crud corpus unchanged at 201/90/196.
This commit is contained in:
A.Shakhmatov
2026-08-09 22:12:48 +03:00
parent 76afa75efe
commit 1c72aa8938
3 changed files with 1814 additions and 5 deletions

View File

@@ -63,10 +63,31 @@ accumulators in:
```
group-accumulators.json 18 pass 1 fail 0 skip
expressions.json 1 pass 26 fail 0 skip
```
The one that remains is the compound `_id`, which needs the expression
evaluator and is the next tier. The corpus found its first real disagreement on
the way there: `$avg` over a group with no numeric value is `null`, not `0`,
and a divisor that counted documents rather than numbers would have passed
every test anybody would think to write by hand.
`group-accumulators` found its first real disagreement on the way to 18:
`$avg` over a group with no numeric value is `null`, not `0`, and a divisor
that counted documents rather than numbers would have passed every test
anybody would think to write by hand.
`expressions.json` is the next tier's spec, recorded and not yet implemented --
its one pass is the unknown-operator refusal M2 already answers correctly.
Expressions are exercised through `$group`, because `_id` and the accumulator
arguments are the only expression positions that exist until `$addFields` and
`$project`'s computed fields land.
What recording it settled, none of which is guessable:
| | mongod |
|---|---|
| `$add` over a missing field or null | `null`, not an error and not `0` |
| `$add` over a string | error 7157723 |
| `$divide` by zero | error 4848401 |
| `$mod` of -5 by 4 | `-1` — the dividend's sign |
| `$lt` of a number and a string | `true` — canonical type order |
| `$and` over `-5` | truthy |
| `$not` of a missing field | `true` |
| `$switch` with no branch and no default | error 40069 |
| two operators in one expression document | error 15983, *not* `$group`'s 40238 |
| `$subtract` with one operand | error 16020 |