// In SERVER-22580 and SERVER-51557, the $substrCP expression was introduced. In this file, we test // the error cases and the intended behavior of this expression. import "jstests/libs/query/sbe_assert_error_override.js"; import {assertErrorCode} from "jstests/aggregation/extras/utils.js"; let coll = db.substrCP; coll.drop(); // Need an empty document for pipeline. assert.commandWorked(coll.insertOne({"a": "abc"})); function assertArgsException(errorCode, args) { assertErrorCode(coll, [{$project: {a: {$substrCP: args}}}], errorCode, "error thrown, check parameters"); } function assertSubstring(expected, str, offset, len) { assert.eq(expected, coll.aggregate({$project: {a: {$substrCP: [str, offset, len]}}}).toArray()[0].a); } function assertSubstringBytes(expected, str, offset, len) { assert.eq(expected, coll.aggregate({$project: {a: {$substrBytes: [str, offset, len]}}}).toArray()[0].a); } assertArgsException(34452, ["$a", 0, "a"]); assertArgsException(34453, ["$a", 0, NaN]); assertArgsException(34450, ["$a", "abc", 3]); assertArgsException(34451, ["$a", 2.2, 3]); assertArgsException(34455, ["$a", -1, 3]); assertArgsException(34454, ["$a", 1, -3]); assert(coll.drop()); coll.insertOne({ t: "寿司sushi", u: "éclair", v: "Å", w: "◢◢◢", x: "a", y: "abc", z: "abcde", a: 0, b: 1, c: 2, d: 3, e: 4, f: 5, neg: -4, invalidStr: new Map(), /* Max unsigned int plus one */ bigNum: NumberLong(4294967297), }); // Wrong number of args. assertArgsException(16020, []); assertArgsException(16020, ["$x"]); assertArgsException(16020, ["$x", 1, 2, 3]); // Tests that $substrCP performs as expected. assertSubstring("", "$x", 999, 0); assertSubstring("", "$x", 999, 1); assertSubstring("Å", "$v", "$a", "$b"); assertSubstring("a", "$x", "$a", "$b"); assertSubstring("◢◢", "$w", "$b", "$c"); assertSubstring("cde", "$z", "$c", "$d"); // Covers additional errors and ensures errors are thrown following document retrival. assertArgsException(5155700, ["a", "$invalidStr", 7]); assertArgsException(5155700, ["a", "$bigNum", 7]); assertArgsException(5155702, ["a", 0, "$t"]); assertArgsException(5155701, ["a", "$neg", 2]); assertArgsException(5155703, ["a", 0, "$neg"]); // String coercion fails as expected. assertArgsException(16007, ["$invalidStr", "$a", "$b"]); // Computed operands. assertSubstring("cde", "$z", {$add: ["$b", "$b"]}, {$add: ["$c", "$d"]}); assertSubstring("cde", "$z", {$add: ["$b", 1]}, {$add: [2, "$d"]}); // Nested. assert.eq( "e", coll .aggregate({ $project: { a: { $substrCP: [ { $substrCP: [{$substrCP: [{$substrCP: ["abcdefghij", "$b", 6]}, "$c", 5]}, 0, 3], }, 1, 1, ], }, }, }) .toArray()[0].a, ); // $substrBytes and $substrCP returns different results when encountering multi-byte // utf-chars. assertSubstring("écla", "$u", "$a", "$e"); assertSubstringBytes("écl", "$u", "$a", "$e"); assertSubstring("寿司sush", "$t", "$a", 6); assertSubstringBytes("寿司", "$t", "$a", 6);