mongo/jstests/aggregation/expressions/substrbytes.js

162 lines
4.8 KiB
JavaScript

// Aggregation $substrBytes tests.
import "jstests/libs/query/sbe_assert_error_override.js";
import {assertErrorCode} from "jstests/aggregation/extras/utils.js";
let t = db.jstests_aggregation_substr;
t.drop();
t.save({});
function assertSubstring(expected, str, offset, len) {
assert.eq(expected, t.aggregate({$project: {a: {$substrBytes: [str, offset, len]}}}).toArray()[0].a);
}
function assertArgsException(args) {
assert.commandFailed(t.runCommand("aggregate", {pipeline: [{$substrBytes: args}]}));
}
function assertException(str, offset, len) {
assertArgsException([str, offset, len]);
}
// Wrong number of arguments.
assertArgsException([]);
assertArgsException(["foo"]);
assertArgsException(["foo", 1]);
assertArgsException(["foo", 1, 1, 1]);
// Basic offset / length checks.
assertSubstring("abcd", "abcd", 0, 4);
assertSubstring("abcd", "abcd", 0, 5);
assertSubstring("a", "abcd", 0, 1);
assertSubstring("ab", "abcd", 0, 2);
assertSubstring("b", "abcd", 1, 1);
assertSubstring("d", "abcd", 3, 1);
assertSubstring("", "abcd", 4, 1);
assertSubstring("", "abcd", 3, 0);
assertSubstring("cd", "abcd", 2, -1);
// Passing a negative number for the start position should return an error.
assertException("abcd", -1, 4);
assertException("abcd", -1, 0);
assertException("abcd", -10, 0);
// See server6186.js for additional offset / length checks.
// Additional numeric types for offset / length.
assertSubstring("bc", "abcd", 1, 2);
assertSubstring("bc", "abcd", 1.0, 2.0);
assertSubstring("bc", "abcd", NumberInt("1"), NumberInt("2"));
assertSubstring("bc", "abcd", NumberLong("1"), NumberLong("2"));
assertSubstring("bc", "abcd", NumberInt("1"), NumberLong("2"));
assertSubstring("bc", "abcd", NumberLong("1"), NumberInt("2"));
assertSubstring("bc", "abcd", NumberDecimal("1"), NumberDecimal("2"));
// Integer component is used.
assertSubstring("bc", "abcd", 1.2, 2.2);
assertSubstring("bc", "abcd", 1.9, 2.9);
assertSubstring("cd", "abcd", 2, -1);
assertSubstring("abcd", "abcd", 0, -1);
// Any negative number for length will return the rest of the string.
assertSubstring("cd", "abcd", 2, -5);
assertSubstring("", "abcd", 4, -1);
assertSubstring("", "abcd", 10, -1);
// Non numeric types for offset / length.
assertException("abcd", false, 2);
assertException("abcd", 1, true);
assertException("abcd", "q", 2);
assertException("abcd", 1, "r");
assertException("abcd", null, 3);
assertException("abcd", 1, undefined);
// String coercion.
assertSubstring("123", 123, 0, 3);
assertSubstring("2", 123, 1, 1);
assertSubstring("1970", new Date(0), 0, 4);
assertSubstring("", null, 0, 4);
assertException(/abc/, 0, 4);
// Field path like string.
assertSubstring("$a", "a$a", 1, 2);
// Multi byte utf-8.
assertSubstring("\u0080", "\u0080", 0, 2);
assertException("\u0080", 0, 1);
assertException("\u0080", 1, 1);
assertSubstring("\u0080", "\u0080\u20ac", 0, 2);
assertSubstring("\u20ac", "\u0080\u20ac", 2, 3);
assertException("\u0080\u20ac", 1, 3);
assertException("\u0080\u20ac", 1, 4);
assertException("\u0080\u20ac", 0, 3);
assertException("\uD834\uDF06", 1, 4);
assertException("\uD834\uDF06", 0, 3);
assertSubstring("\u0044\u20ac", "\u0080\u0044\u20ac", 2, 4);
assertSubstring("\u0044", "\u0080\u0044\u20ac", 2, 1);
// The four byte utf-8 character 𝌆 (have to represent in surrogate halves).
assertSubstring("\uD834\uDF06", "\uD834\uDF06", 0, 4);
// Operands from document.
t.drop();
t.save({
w: "ó",
x: "a",
y: "abc",
z: "abcde",
a: 0,
b: 1,
c: 2,
d: 3,
e: 4,
f: 5,
g: -2,
/* Max unsigned int plus one */
k: NumberLong(4294967297),
});
assertSubstring("a", "$x", "$a", "$b");
assertSubstring("abcde", "$z", "$a", "$k");
assertSubstring("", "$x", "$k", "$f");
assertSubstring("a", "$x", "$a", "$f");
assertSubstring("b", "$y", "$b", "$b");
assertSubstring("b", "$z", "$b", "$b");
assertSubstring("bcd", "$z", "$b", "$d");
assertSubstring("cde", "$z", "$c", "$f");
assertSubstring("c", "$y", "$c", "$f");
assertException("$w", "$b", "$d");
assertException("$w", "$a", "$c");
assertException("$w", "$a", "$g");
assertException("$w", "$g", "$a");
// String coercion fails.
assertErrorCode(t, [{$project: {a: {$substrCP: [new Map(), "$a", "$b"]}}}], 16007, "string coercion failed");
// Computed operands.
assertSubstring("cde", "$z", {$add: ["$b", "$b"]}, {$add: ["$c", "$d"]});
assertSubstring("cde", "$z", {$add: ["$b", 1]}, {$add: [2, "$d"]});
// Nested.
assert.eq(
"e",
t
.aggregate({
$project: {
a: {
$substrBytes: [
{
$substrBytes: [{$substrBytes: [{$substrBytes: ["abcdefghij", 1, 6]}, 2, 5]}, 0, 3],
},
1,
1,
],
},
},
})
.toArray()[0].a,
);