Files
MultiforaDB/tests/spec/aggregate/expressions.json
A.Shakhmatov 1c72aa8938 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.
2026-08-09 22:12:48 +03:00

1140 lines
24 KiB
JSON

{
"description": "expressions",
"schemaVersion": "1.4",
"createEntities": [
{
"client": {
"id": "client0"
}
},
{
"database": {
"id": "database0",
"client": "client0",
"databaseName": "aggregate-corpus"
}
},
{
"collection": {
"id": "collection0",
"database": "database0",
"collectionName": "coll"
}
}
],
"initialData": [
{
"collectionName": "coll",
"databaseName": "aggregate-corpus",
"documents": [
{
"_id": 1,
"a": 10,
"b": 3,
"s": "x",
"n": null,
"f": false
},
{
"_id": 2,
"a": 20,
"b": 0,
"s": "y",
"f": true
},
{
"_id": 3,
"a": -5,
"b": 4,
"s": "x",
"n": 7,
"f": false
}
]
}
],
"tests": [
{
"description": "a compound _id groups on every field",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"s": "$s",
"f": "$f"
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id.s": 1,
"_id.f": 1
}
}
]
},
"expectResult": [
{
"_id": {
"s": "x",
"f": false
},
"n": 2
},
{
"_id": {
"s": "y",
"f": true
},
"n": 1
}
]
}
]
},
{
"description": "a nested compound _id",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"outer": {
"inner": "$s"
}
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id.outer.inner": 1
}
}
]
},
"expectResult": [
{
"_id": {
"outer": {
"inner": "x"
}
},
"n": 2
},
{
"_id": {
"outer": {
"inner": "y"
}
},
"n": 1
}
]
}
]
},
{
"description": "$literal keeps a $-string from being a path",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$literal": "$s"
},
"n": {
"$sum": 1
}
}
}
]
},
"expectResult": [
{
"_id": "$s",
"n": 3
}
]
}
]
},
{
"description": "$literal of a document",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$literal": {
"$sum": 1
}
},
"n": {
"$sum": 1
}
}
}
]
},
"expectResult": [
{
"_id": {
"$sum": 1
},
"n": 3
}
]
}
]
},
{
"description": "$add of a path and a constant",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$add": [
"$a",
1
]
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": -4,
"n": 1
},
{
"_id": 11,
"n": 1
},
{
"_id": 21,
"n": 1
}
]
}
]
},
{
"description": "$subtract and $multiply",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": "$s",
"d": {
"$sum": {
"$subtract": [
"$a",
"$b"
]
}
},
"m": {
"$sum": {
"$multiply": [
"$a",
2
]
}
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "x",
"d": -2,
"m": 10
},
{
"_id": "y",
"d": 20,
"m": 40
}
]
}
]
},
{
"description": "$divide by zero is an error",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": null,
"v": {
"$sum": {
"$divide": [
"$a",
"$b"
]
}
}
}
}
]
},
"expectError": {
"isError": true,
"errorCode": 4848401
}
}
]
},
{
"description": "$divide and $mod",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$match": {
"b": {
"$gt": 0
}
}
},
{
"$group": {
"_id": "$s",
"d": {
"$push": {
"$divide": [
"$a",
"$b"
]
}
},
"m": {
"$push": {
"$mod": [
"$a",
"$b"
]
}
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "x",
"d": [
3.3333333333333335,
-1.25
],
"m": [
1,
-1
]
}
]
}
]
},
{
"description": "arithmetic over a missing field",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$add": [
"$missing",
1
]
},
"n": {
"$sum": 1
}
}
}
]
},
"expectResult": [
{
"_id": null,
"n": 3
}
]
}
]
},
{
"description": "arithmetic over null",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": "$s",
"v": {
"$push": {
"$add": [
"$n",
1
]
}
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "x",
"v": [
null,
8
]
},
{
"_id": "y",
"v": [
null
]
}
]
}
]
},
{
"description": "$eq and $ne",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$eq": [
"$s",
"x"
]
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": false,
"n": 1
},
{
"_id": true,
"n": 2
}
]
}
]
},
{
"description": "comparison across types follows canonical order",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$lt": [
"$a",
"$s"
]
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": true,
"n": 3
}
]
}
]
},
{
"description": "$cmp returns the ordering",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": "$s",
"v": {
"$push": {
"$cmp": [
"$a",
"$b"
]
}
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "x",
"v": [
1,
-1
]
},
{
"_id": "y",
"v": [
1
]
}
]
}
]
},
{
"description": "$and and $or are truthy over non-booleans",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$and": [
"$a",
"$f"
]
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": false,
"n": 2
},
{
"_id": true,
"n": 1
}
]
}
]
},
{
"description": "$not of a missing field",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$not": [
"$missing"
]
},
"n": {
"$sum": 1
}
}
}
]
},
"expectResult": [
{
"_id": true,
"n": 3
}
]
}
]
},
{
"description": "$cond in its array form",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$cond": [
{
"$gt": [
"$a",
0
]
},
"positive",
"negative"
]
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "negative",
"n": 1
},
{
"_id": "positive",
"n": 2
}
]
}
]
},
{
"description": "$cond in its document form",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$cond": {
"if": "$f",
"then": "yes",
"else": "no"
}
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "no",
"n": 2
},
{
"_id": "yes",
"n": 1
}
]
}
]
},
{
"description": "$ifNull falls through on missing and on null",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$ifNull": [
"$n",
"fallback"
]
},
"count": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": 7,
"count": 1
},
{
"_id": "fallback",
"count": 2
}
]
}
]
},
{
"description": "$switch picks the first matching branch",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$switch": {
"branches": [
{
"case": {
"$lt": [
"$a",
0
]
},
"then": "neg"
},
{
"case": {
"$lt": [
"$a",
15
]
},
"then": "small"
}
],
"default": "big"
}
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": "big",
"n": 1
},
{
"_id": "neg",
"n": 1
},
{
"_id": "small",
"n": 1
}
]
}
]
},
{
"description": "$switch with no branch matching and no default is an error",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$switch": {
"branches": [
{
"case": false,
"then": "never"
}
]
}
},
"n": {
"$sum": 1
}
}
}
]
},
"expectError": {
"isError": true,
"errorCode": 40069
}
}
]
},
{
"description": "an unknown expression operator is refused",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$bogusExpr": "$a"
},
"n": {
"$sum": 1
}
}
}
]
},
"expectError": {
"isError": true,
"errorCode": 168
}
}
]
},
{
"description": "two operators in one expression document are refused",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$add": [
"$a",
1
],
"$literal": 2
},
"n": {
"$sum": 1
}
}
}
]
},
"expectError": {
"isError": true,
"errorCode": 15983
}
}
]
},
{
"description": "a nested expression inside an accumulator argument",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": null,
"v": {
"$max": {
"$add": [
{
"$multiply": [
"$a",
2
]
},
"$b"
]
}
}
}
}
]
},
"expectResult": [
{
"_id": null,
"v": 40
}
]
}
]
},
{
"description": "arithmetic over a non-numeric value is an error",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$add": [
"$s",
1
]
},
"n": {
"$sum": 1
}
}
}
]
},
"expectError": {
"isError": true,
"errorCode": 7157723
}
}
]
},
{
"description": "$not takes a bare argument as well as an array",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$not": "$f"
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": false,
"n": 1
},
{
"_id": true,
"n": 2
}
]
}
]
},
{
"description": "$add of several operands",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$add": [
"$a",
"$b",
100
]
},
"n": {
"$sum": 1
}
}
},
{
"$sort": {
"_id": 1
}
}
]
},
"expectResult": [
{
"_id": 99,
"n": 1
},
{
"_id": 113,
"n": 1
},
{
"_id": 120,
"n": 1
}
]
}
]
},
{
"description": "$subtract needs exactly two operands",
"operations": [
{
"object": "collection0",
"name": "aggregate",
"arguments": {
"pipeline": [
{
"$group": {
"_id": {
"$subtract": [
"$a"
]
},
"n": {
"$sum": 1
}
}
}
]
},
"expectError": {
"isError": true,
"errorCode": 16020
}
}
]
}
]
}