PLAN §3 lists eight 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 identical
update against mongod 8.3.7 and this server found all eight answering
`bad update`, code 2, one message for every question.
It also found the thing this directory exists for: `$push`'s `$slice`,
`$position` and `$sort` are **silently ignored**. `{$each: [3, 4], $slice: -3}`
appends both values, slices nothing, and answers ok: 1 with modifiedCount: 1.
A missing operator is an error the client can see; a modifier that is parsed,
accepted and then dropped is the same class of wrong answer the positional
operators were.
103 cases in six files, 18 pass / 84 fail -- red by construction, like
`tests/spec/aggregate/expressions.json` at 1/26 and the positional corpus at
15/36. Inputs authored in `sources/`, every expectation measured.
Two things here cannot be recorded as values, and both become a `$$type`
assertion rather than being left out: a `$currentDate` field is whatever the
clock said (named per case in `volatile`, so a real stored date can still be
pinned one day), and an upsert that inserts gets a generated ObjectId (that
one automatic -- no source authors an ObjectId). Everything else is compared
exactly. Files are canonical extended JSON, which the runner already parses
that way: `$mul` overflowing an int32 produces an int64, and writing
`4000000000` as a bare number would not have said so.
What recording it settled, none of it guessable:
- `$mul` of a missing field writes **0**, not the operand; of a non-numeric
field, or by one, TypeMismatch (14).
- `$min`/`$max` are not numeric operators. They compare in BSON canonical
order, so `$min: {s: 5}` on `s: "b"` writes 5, and a missing field is
always written.
- two operators writing one field is **ConflictingUpdateOperators (40)** --
`$min`+`$max`, `$set`+`$inc`, `$setOnInsert`+`$set`. A whole error class
this server does not have.
- `$addToSet` compares documents whole, **field order included**:
`{a:1,b:2}` and `{b:2,a:1}` are two values. But `2` and `2.0` are one.
- `$push` modifiers are only modifiers when `$each` is there: `{$slice: 1}`
alone is a value to push. With it, the order is position, then sort the
whole array, then slice.
- `$currentDate` with `false` still writes a date.
- `$setOnInsert` may write `_id` on an insert, where `$set` may not.
- an unknown modifier is FailedToParse (9), not BadValue.
One case was authored and then removed: `{b: 1, $set: {c: 1}}` never reaches a
server -- the driver rejects it -- so there was no answer to record and the
case would have asserted nothing.
2 lines
11 KiB
JSON
2 lines
11 KiB
JSON
{"description":"numeric","schemaVersion":"1.4","createEntities":[{"client":{"id":"client0"}},{"database":{"id":"database0","client":"client0","databaseName":"operator-corpus"}},{"collection":{"id":"collection0","database":"database0","collectionName":"coll"}}],"initialData":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}],"tests":[{"description":"$mul multiplies an int by an int","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"a":{"$numberInt":"2"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"10"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$mul of a missing field","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"gone":{"$numberInt":"5"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"},"gone":{"$numberInt":"0"}}]}]},{"description":"$mul mixes int and double","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"d":{"$numberInt":"2"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberInt":"5"}}]}]},{"description":"$mul by zero","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"a":{"$numberInt":"0"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"0"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$mul overflowing an int32","operations":[{"object":"collection0","name":"deleteMany","arguments":{"filter":{}}},{"object":"collection0","name":"insertMany","arguments":{"documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"2000000000"}}]}},{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"a":{"$numberInt":"2"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberLong":"4000000000"}}]}]},{"description":"$mul of a non-numeric field","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"s":{"$numberInt":"2"}}}},"expectError":{"isError":true,"errorCode":{"$numberInt":"14"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$mul by a non-numeric operand","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"a":"x"}}},"expectError":{"isError":true,"errorCode":{"$numberInt":"14"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$mul down a dotted path","operations":[{"object":"collection0","name":"deleteMany","arguments":{"filter":{}}},{"object":"collection0","name":"insertMany","arguments":{"documents":[{"_id":{"$numberInt":"1"},"n":{"a":{"$numberInt":"3"}}}]}},{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"n.a":{"$numberInt":"4"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"n":{"a":{"$numberInt":"12"}}}]}]},{"description":"$min writes when the operand is lower","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"a":{"$numberInt":"3"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"3"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$min leaves the field when the operand is higher","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"a":{"$numberInt":"7"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"0"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$min of a missing field always writes","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"gone":{"$numberInt":"7"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"},"gone":{"$numberInt":"7"}}]}]},{"description":"$min against a field of another type","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"s":{"$numberInt":"5"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":{"$numberInt":"5"},"d":{"$numberDouble":"2.5"}}]}]},{"description":"$min compares an int and an equal double","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"a":{"$numberInt":"5"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"0"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$max writes when the operand is higher","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$max":{"a":{"$numberInt":"7"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"7"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$max leaves the field when the operand is lower","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$max":{"a":{"$numberInt":"3"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"0"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$max of a missing field always writes","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$max":{"gone":{"$numberInt":"7"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"},"gone":{"$numberInt":"7"}}]}]},{"description":"$max against a field of another type","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$max":{"s":{"$numberInt":"5"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"0"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$max against a null field","operations":[{"object":"collection0","name":"deleteMany","arguments":{"filter":{}}},{"object":"collection0","name":"insertMany","arguments":{"documents":[{"_id":{"$numberInt":"1"},"a":null}]}},{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$max":{"a":{"$numberInt":"1"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"1"}}]}]},{"description":"$min and $max on the same field in one update","operations":[{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"a":{"$numberInt":"3"}},"$max":{"a":{"$numberInt":"9"}}}},"expectError":{"isError":true,"errorCode":{"$numberInt":"40"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"a":{"$numberInt":"5"},"s":"b","d":{"$numberDouble":"2.5"}}]}]},{"description":"$min through an array index","operations":[{"object":"collection0","name":"deleteMany","arguments":{"filter":{}}},{"object":"collection0","name":"insertMany","arguments":{"documents":[{"_id":{"$numberInt":"1"},"t":[{"$numberInt":"5"},{"$numberInt":"5"}]}]}},{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$min":{"t.0":{"$numberInt":"1"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"t":[{"$numberInt":"1"},{"$numberInt":"5"}]}]}]},{"description":"$mul through a positional segment","operations":[{"object":"collection0","name":"deleteMany","arguments":{"filter":{}}},{"object":"collection0","name":"insertMany","arguments":{"documents":[{"_id":{"$numberInt":"1"},"t":[{"a":{"$numberInt":"2"}},{"a":{"$numberInt":"3"}}]}]}},{"object":"collection0","name":"updateOne","arguments":{"filter":{},"update":{"$mul":{"t.$[].a":{"$numberInt":"10"}}}},"expectResult":{"matchedCount":{"$numberInt":"1"},"modifiedCount":{"$numberInt":"1"},"upsertedCount":{"$numberInt":"0"}}}],"outcome":[{"collectionName":"coll","databaseName":"operator-corpus","documents":[{"_id":{"$numberInt":"1"},"t":[{"a":{"$numberInt":"20"}},{"a":{"$numberInt":"30"}}]}]}]}]}
|