tests/spec: record the pipeline-style updates

An update document may be an *array* of aggregation stages instead of a
document of operators. The pinned crud corpus has five cases, one per command,
and not one of them is a refusal -- so which stages are allowed, what happens
to `_id`, and what an upsert does are all unmeasured there.

23 cases into the existing operator corpus rather than an eighth directory:
this is another shape of update document, and it shares the recorder, the
masking and the README.

Recorded red, 0/23. What it settled:

  - **`_id` always survives**, through `$replaceRoot: {newRoot: "$t"}` and
    through `$project: {_id: 0}` alike. A stage that sets it to a *different*
    value is ImmutableField (66); restating the same one is fine.
  - `$match`, `$group`, `$sort` and `$unwind` are real stages refused
    specifically here: InvalidOptions (72), "$X is not allowed to be used
    within an update". A name that is no stage at all is 40324, and two
    stages packed into one array element is 40323.
  - `arrayFilters` beside a pipeline is FailedToParse (9).
  - an upsert runs the pipeline over the document the filter implies.

Three shapes were authored and removed: `{b: 1, $set: {...}}`, an empty
pipeline, and a pipeline holding a non-document. The driver rejects all three
before they reach a server, so there is nothing to record.
This commit is contained in:
A.Shakhmatov
2026-08-10 21:48:55 +03:00
parent 44788ae681
commit e344a073a1
3 changed files with 178 additions and 6 deletions

View File

@@ -1,8 +1,9 @@
# The update-operator corpus
PLAN §3 lists eight update operators for M3 — `$setOnInsert`, `$addToSet`,
`$mul`, `$min`, `$max`, `$pop`, `$pullAll`, `$currentDate` — and the pinned
crud corpus says almost nothing about any of them. A probe running the
What an update *document* may be, measured. PLAN §3 lists eight operators for
M3 — `$setOnInsert`, `$addToSet`, `$mul`, `$min`, `$max`, `$pop`, `$pullAll`,
`$currentDate` — and pipeline-style updates beside them; the pinned crud
corpus says almost nothing about any of it. A probe running the
identical update against mongod 8.3.7 and this server found:
- all eight answering `bad update`, code 2, one message for every question;
@@ -62,6 +63,7 @@ Recorded against mongod 8.3.7. Green:
```
array-ops.json 26 pass 0 fail 0 skip
pipeline.json 23 pass 0 fail 0 skip
current-date.json 11 pass 0 fail 0 skip
modifiers.json 14 pass 0 fail 0 skip
numeric.json 21 pass 0 fail 0 skip
@@ -103,7 +105,13 @@ None of this is guessable, and several rows contradict the obvious reading:
| `$currentDate` with anything but a bool or `{$type: date\|timestamp}` | BadValue (2) |
| `$setOnInsert` writing `_id` on an insert | **allowed**, unlike `$set` |
| an unknown modifier | FailedToParse (9), not BadValue |
| a pipeline update's `_id` | **always survives**, through `$replaceRoot` and through `$project: {_id: 0}` |
| a stage changing `_id` to something else | ImmutableField (66) |
| `$match`, `$group`, `$sort`, `$unwind` in an update | InvalidOptions (72) — real stages, refused *here* |
| a name that is no stage at all | 40324; two stages in one array element, 40323 |
| `arrayFilters` beside a pipeline | FailedToParse (9) |
One case was authored and then removed: `{b: 1, $set: {c: 1}}` is rejected by
the driver before it reaches a server, so there is no server answer to record
and the case would have asserted nothing.
Three cases were authored and then removed, all for the same reason: the
driver rejects `{b: 1, $set: {c: 1}}`, an empty pipeline and a pipeline
holding a non-document before any of them reaches a server, so there is no
server answer to record and the cases would have asserted nothing.