summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorAdityavardhan Agrawal <aa729@cornell.edu>2022-10-20 18:29:47 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-20 19:16:19 +0000
commitfb7df9a15a313857c87c1661cda126049fe410bf (patch)
tree7d6384032c3cd31deb39eaa637504055fbaba6e9 /jstests
parente73a86e6dd30ea480c8449f77b93973d1fc94218 (diff)
downloadmongo-fb7df9a15a313857c87c1661cda126049fe410bf.tar.gz
SERVER-70158 Specify argument evaluation order in generateTrigExpressionBinary
Diffstat (limited to 'jstests')
-rw-r--r--jstests/aggregation/expressions/expression_trigonometric.js469
1 files changed, 235 insertions, 234 deletions
diff --git a/jstests/aggregation/expressions/expression_trigonometric.js b/jstests/aggregation/expressions/expression_trigonometric.js
index 8992ab4b5cc..29da3b96315 100644
--- a/jstests/aggregation/expressions/expression_trigonometric.js
+++ b/jstests/aggregation/expressions/expression_trigonometric.js
@@ -8,285 +8,286 @@ load('jstests/libs/sbe_assert_error_override.js'); // Override error-code-check
const coll = db.expression_trigonometric;
coll.drop();
-// We need at least one document in the collection in order to test expressions, add it here.
-assert.commandWorked(coll.insert({}));
-
-// Run a pipeline with `op` and check that the result of operation against the `expResult` value. If
-// the actual or expected result is non-numeric (NaN or infinite), this function asserts that they
-// match and returns 0 if they do. If they are both numeric, this function returns the difference
-// between them as a double.
-function testOpReturningDifference(op, expResult) {
- const pipeline = [
- {$project: {_id: 0, result: op, expected: {$literal: expResult}}},
- {
- $addFields: {
- resultType: {$type: "$result"},
- expType: {$type: "$expected"},
- resultAsString: {$convert: {input: "$result", to: "string"}},
- expAsString: {$convert: {input: "$expected", to: "string"}},
- difference:
- {$abs: {$convert: {input: {$subtract: ["$result", "$expected"]}, to: "double"}}}
- }
- }
- ];
- const {result, resultType, expType, resultAsString, expAsString, difference} = function() {
- const resultArray = coll.aggregate(pipeline).toArray();
- assert.eq(resultArray.length, 1, resultArray);
- return resultArray[0];
- }();
-
- assert.eq(resultType, expType);
-
- // We don't want to do direct comparisons with non-real values, because they can have unexpected
- // semantics. String comparisons gives us the desired equality semantics for the purposes of
- // this test.
- const nonRealValues = ["NaN", "Infinity", "-Infinity"];
- if (nonRealValues.includes(expAsString) || nonRealValues.includes(resultAsString)) {
- assert.eq(expAsString, resultAsString, tojson(result));
- return 0;
- }
- return difference;
+// Constructs and inserts a document containing 'val', which are the arguments to trigonometric
+// aggregation expression 'op'. If an aggregation expression has constant arguments, it will be
+// constant folded and will not be evaluated during query execution. Embedding in a document ensures
+// we evaluate expressions during query execution. eg. {$acos: NumberInt(1)} -> {$acos: "$y"} on
+// document {"y" : NumberInt(1)}
+function convertToOpOnDocument(op, val) {
+ let nonOptimizedOp = {};
+ if (Array.isArray(val) && val.length === 2) {
+ nonOptimizedOp = {[op]: ["$y", "$x"]};
+ assert.commandWorked(coll.insert({"y": val[0], "x": val[1]}));
+ } else {
+ nonOptimizedOp = {[op]: "$y"};
+ assert.commandWorked(coll.insert({"y": val}));
+ }
+ return nonOptimizedOp;
}
-// Helper for testing that op returns expResult.
-function testOp(op, expResult) {
- const diff = testOpReturningDifference(op, expResult);
- assert.eq(0, diff);
+function testOp(op, val, expResult) {
+ const nonOptimizedOp = convertToOpOnDocument(op, val);
+ const pipeline = [{$project: {_id: 0, result: nonOptimizedOp}}];
+ assert.eq(coll.aggregate(pipeline).toArray(), [{result: expResult}]);
+ assert(coll.drop());
}
// Helper for testing that the aggregation expression 'op' returns expResult, approximately,
// since NumberDecimal has so many representations for a given number (0 versus 0e-40 for
// instance).
-function testOpApprox(op, expResult) {
- const diff = testOpReturningDifference(op, expResult);
- assert.lt(diff, 0.00000005);
+function testOpApprox(op, val, expResult) {
+ const nonOptimizedOp = convertToOpOnDocument(op, val);
+ const pipeline = [{$project: {_id: 0, result: nonOptimizedOp}}];
+ const res = coll.aggregate(pipeline).toArray();
+ const {result} = res[0];
+ const pipeline2 = {
+ $project: {
+ difference: {$abs: {$convert: {input: {$subtract: [result, expResult]}, to: "double"}}}
+ }
+ };
+ const res2 = coll.aggregate(pipeline2).toArray();
+ const {difference} = res2[0];
+ assert.lt(difference, 0.00000005);
+ assert(coll.drop());
+}
+
+function testErrorCode(op, val, expErrorCode) {
+ const nonOptimizedOp = convertToOpOnDocument(op, val);
+ const pipeline = [{$project: {_id: 0, result: nonOptimizedOp}}];
+ assertErrorCode(coll, pipeline, expErrorCode);
+ assert(coll.drop());
}
// Simple successful int input.
-testOp({$acos: NumberInt(1)}, 0);
-testOp({$acosh: NumberInt(1)}, 0);
-testOp({$asin: NumberInt(0)}, 0);
-testOp({$asinh: NumberInt(0)}, 0);
-testOp({$atan: NumberInt(0)}, 0);
-testOp({$atan2: [NumberInt(0), NumberInt(1)]}, 0);
-testOp({$atan2: [NumberInt(0), NumberInt(0)]}, 0);
-testOp({$atanh: NumberInt(0)}, 0);
-testOp({$cos: NumberInt(0)}, 1);
-testOp({$cosh: NumberInt(0)}, 1);
-testOp({$sin: NumberInt(0)}, 0);
-testOp({$sinh: NumberInt(0)}, 0);
-testOp({$tan: NumberInt(0)}, 0);
-testOp({$tanh: NumberInt(0)}, 0);
-testOp({$degreesToRadians: NumberInt(0)}, 0);
-testOp({$radiansToDegrees: NumberInt(0)}, 0);
+testOp("$acos", NumberInt(1), 0);
+testOp("$acosh", NumberInt(1), 0);
+testOp("$asin", NumberInt(0), 0);
+testOp("$asinh", NumberInt(0), 0);
+testOp("$atan", NumberInt(0), 0);
+testOp("$atan2", [NumberInt(0), NumberInt(1)], 0);
+testOp("$atan2", [NumberInt(0), NumberInt(0)], 0);
+testOp("$atanh", NumberInt(0), 0);
+testOp("$cos", NumberInt(0), 1);
+testOp("$cosh", NumberInt(0), 1);
+testOp("$sin", NumberInt(0), 0);
+testOp("$sinh", NumberInt(0), 0);
+testOp("$tan", NumberInt(0), 0);
+testOp("$tanh", NumberInt(0), 0);
+testOp("$degreesToRadians", NumberInt(0), 0);
+testOp("$radiansToDegrees", NumberInt(0), 0);
// Simple successful long input.
-testOp({$acos: NumberLong(1)}, 0);
-testOp({$acosh: NumberLong(1)}, 0);
-testOp({$asin: NumberLong(0)}, 0);
-testOp({$asinh: NumberLong(0)}, 0);
-testOp({$atan: NumberLong(0)}, 0);
-testOp({$atan2: [NumberLong(0), NumberLong(1)]}, 0);
-testOp({$atan2: [NumberLong(0), NumberLong(0)]}, 0);
-testOp({$atanh: NumberLong(0)}, 0);
-testOp({$cos: NumberLong(0)}, 1);
-testOp({$cosh: NumberLong(0)}, 1);
-testOp({$sin: NumberLong(0)}, 0);
-testOp({$sinh: NumberLong(0)}, 0);
-testOp({$tan: NumberLong(0)}, 0);
-testOp({$tanh: NumberLong(0)}, 0);
-testOp({$degreesToRadians: NumberLong(0)}, 0);
-testOp({$radiansToDegrees: NumberLong(0)}, 0);
+testOp("$acos", NumberLong(1), 0);
+testOp("$acosh", NumberLong(1), 0);
+testOp("$asin", NumberLong(0), 0);
+testOp("$asinh", NumberLong(0), 0);
+testOp("$atan", NumberLong(0), 0);
+testOp("$atan2", [NumberLong(0), NumberLong(1)], 0);
+testOp("$atan2", [NumberLong(0), NumberLong(0)], 0);
+testOp("$atanh", NumberLong(0), 0);
+testOp("$cos", NumberLong(0), 1);
+testOp("$cosh", NumberLong(0), 1);
+testOp("$sin", NumberLong(0), 0);
+testOp("$sinh", NumberLong(0), 0);
+testOp("$tan", NumberLong(0), 0);
+testOp("$tanh", NumberLong(0), 0);
+testOp("$degreesToRadians", NumberLong(0), 0);
+testOp("$radiansToDegrees", NumberLong(0), 0);
// Simple successful double input.
-testOp({$acos: 1}, 0);
-testOp({$acosh: 1}, 0);
-testOp({$asin: 0}, 0);
-testOp({$asinh: 0}, 0);
-testOp({$atan: 0}, 0);
-testOp({$atan2: [0, 1]}, 0);
-testOp({$atan2: [0, 0]}, 0);
-testOp({$atanh: 0}, 0);
-testOp({$cos: 0}, 1);
-testOp({$cosh: 0}, 1);
-testOp({$sin: 0}, 0);
-testOp({$sinh: 0}, 0);
-testOp({$tan: 0}, 0);
-testOp({$tanh: 0}, 0);
-testOp({$degreesToRadians: 0}, 0);
-testOp({$radiansToDegrees: 0}, 0);
+testOp("$acos", 1, 0);
+testOp("$acosh", 1, 0);
+testOp("$asin", 0, 0);
+testOp("$asinh", 0, 0);
+testOp("$atan", 0, 0);
+testOp("$atan2", [0, 1], 0);
+testOp("$atan2", [0, 0], 0);
+testOp("$atanh", 0, 0);
+testOp("$cos", 0, 1);
+testOp("$cosh", 0, 1);
+testOp("$sin", 0, 0);
+testOp("$sinh", 0, 0);
+testOp("$tan", 0, 0);
+testOp("$tanh", 0, 0);
+testOp("$degreesToRadians", 0, 0);
+testOp("$radiansToDegrees", 0, 0);
// Simple successful decimal input.
-testOpApprox({$acos: NumberDecimal(1)}, NumberDecimal(0));
-testOpApprox({$acosh: NumberDecimal(1)}, NumberDecimal(0));
-testOpApprox({$asin: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$asinh: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$atan: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$atan2: [NumberDecimal(0), 1]}, NumberDecimal(0));
-testOpApprox({$atan2: [NumberDecimal(0), 0]}, NumberDecimal(0));
-testOpApprox({$atanh: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$cos: NumberDecimal(0)}, NumberDecimal(1));
-testOpApprox({$cosh: NumberDecimal(0)}, NumberDecimal(1));
-testOpApprox({$sin: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$sinh: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$tan: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$tanh: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$degreesToRadians: NumberDecimal(0)}, NumberDecimal(0));
-testOpApprox({$radiansToDegrees: NumberDecimal(0)}, NumberDecimal(0));
+testOpApprox("$acos", NumberDecimal(1), NumberDecimal(0));
+testOpApprox("$acosh", NumberDecimal(1), NumberDecimal(0));
+testOpApprox("$asin", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$asinh", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$atan", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$atan2", [NumberDecimal(0), 1], NumberDecimal(0));
+testOpApprox("$atan2", [NumberDecimal(0), 0], NumberDecimal(0));
+testOpApprox("$atanh", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$cos", NumberDecimal(0), NumberDecimal(1));
+testOpApprox("$cosh", NumberDecimal(0), NumberDecimal(1));
+testOpApprox("$sin", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$sinh", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$tan", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$tanh", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$degreesToRadians", NumberDecimal(0), NumberDecimal(0));
+testOpApprox("$radiansToDegrees", NumberDecimal(0), NumberDecimal(0));
// Infinity input produces out of bounds error.
-assertErrorCode(coll, [{$project: {a: {$acos: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: NumberDecimal('-Infinity')}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: NumberDecimal('Infinity')}}}], 50989);
-
-assertErrorCode(coll, [{$project: {a: {$acosh: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acosh: NumberDecimal('-Infinity')}}}], 50989);
-
-assertErrorCode(coll, [{$project: {a: {$asin: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberDecimal('-Infinity')}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberDecimal('Infinity')}}}], 50989);
-
-assertErrorCode(coll, [{$project: {a: {$atanh: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberDecimal('-Infinity')}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberDecimal('Infinity')}}}], 50989);
-
-assertErrorCode(coll, [{$project: {a: {$cos: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$cos: NumberDecimal('-Infinity')}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$cos: Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$cos: NumberDecimal('Infinity')}}}], 50989);
-
-assertErrorCode(coll, [{$project: {a: {$sin: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$sin: NumberDecimal('-Infinity')}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$sin: Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$sin: NumberDecimal('Infinity')}}}], 50989);
-
-assertErrorCode(coll, [{$project: {a: {$tan: -Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$tan: NumberDecimal('-Infinity')}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$tan: Infinity}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$tan: NumberDecimal('Infinity')}}}], 50989);
+testErrorCode("$acos", -Infinity, 50989);
+testErrorCode("$acos", NumberDecimal('-Infinity'), 50989);
+testErrorCode("$acos", Infinity, 50989);
+testErrorCode("$acos", NumberDecimal('Infinity'), 50989);
+
+testErrorCode("$acosh", -Infinity, 50989);
+testErrorCode("$acosh", NumberDecimal('-Infinity'), 50989);
+
+testErrorCode("$asin", -Infinity, 50989);
+testErrorCode("$asin", NumberDecimal('-Infinity'), 50989);
+testErrorCode("$asin", Infinity, 50989);
+testErrorCode("$asin", NumberDecimal('Infinity'), 50989);
+
+testErrorCode("$atanh", -Infinity, 50989);
+testErrorCode("$atanh", NumberDecimal('-Infinity'), 50989);
+testErrorCode("$atanh", Infinity, 50989);
+testErrorCode("$atanh", NumberDecimal('Infinity'), 50989);
+
+testErrorCode("$cos", -Infinity, 50989);
+testErrorCode("$cos", NumberDecimal('-Infinity'), 50989);
+testErrorCode("$cos", Infinity, 50989);
+testErrorCode("$cos", NumberDecimal('Infinity'), 50989);
+
+testErrorCode("$sin", -Infinity, 50989);
+testErrorCode("$sin", NumberDecimal('-Infinity'), 50989);
+testErrorCode("$sin", Infinity, 50989);
+testErrorCode("$sin", NumberDecimal('Infinity'), 50989);
+
+testErrorCode("$tan", -Infinity, 50989);
+testErrorCode("$tan", NumberDecimal('-Infinity'), 50989);
+testErrorCode("$tan", Infinity, 50989);
+testErrorCode("$tan", NumberDecimal('Infinity'), 50989);
// Infinity input produces Infinity as output.
-testOp({$acosh: NumberDecimal('Infinity')}, NumberDecimal('Infinity'));
-testOp({$acosh: Infinity}, Infinity);
-
-testOp({$asinh: NumberDecimal('Infinity')}, NumberDecimal('Infinity'));
-testOp({$asinh: NumberDecimal('-Infinity')}, NumberDecimal('-Infinity'));
-testOp({$asinh: Infinity}, Infinity);
-testOp({$asinh: -Infinity}, -Infinity);
-testOp({$cosh: NumberDecimal('Infinity')}, NumberDecimal('Infinity'));
-testOp({$cosh: NumberDecimal('-Infinity')}, NumberDecimal('Infinity'));
-testOp({$cosh: Infinity}, Infinity);
-testOp({$cosh: -Infinity}, Infinity);
-testOp({$sinh: NumberDecimal('Infinity')}, NumberDecimal('Infinity'));
-testOp({$sinh: NumberDecimal('-Infinity')}, NumberDecimal('-Infinity'));
-testOp({$sinh: Infinity}, Infinity);
-testOp({$sinh: -Infinity}, -Infinity);
+testOp("$acosh", NumberDecimal('Infinity'), NumberDecimal('Infinity'));
+testOp("$acosh", Infinity, Infinity);
+
+testOp("$asinh", NumberDecimal('Infinity'), NumberDecimal('Infinity'));
+testOp("$asinh", NumberDecimal('-Infinity'), NumberDecimal('-Infinity'));
+testOp("$asinh", Infinity, Infinity);
+testOp("$asinh", -Infinity, -Infinity);
+testOp("$cosh", NumberDecimal('Infinity'), NumberDecimal('Infinity'));
+testOp("$cosh", NumberDecimal('-Infinity'), NumberDecimal('Infinity'));
+testOp("$cosh", Infinity, Infinity);
+testOp("$cosh", -Infinity, Infinity);
+testOp("$sinh", NumberDecimal('Infinity'), NumberDecimal('Infinity'));
+testOp("$sinh", NumberDecimal('-Infinity'), NumberDecimal('-Infinity'));
+testOp("$sinh", Infinity, Infinity);
+testOp("$sinh", -Infinity, -Infinity);
// Infinity produces finite output (due to asymptotic bounds).
-testOpApprox({$atan: NumberDecimal('Infinity')}, NumberDecimal(Math.PI / 2));
-testOpApprox({$atan: NumberDecimal('-Infinity')}, NumberDecimal(-Math.PI / 2));
-testOpApprox({$atan: Infinity}, Math.PI / 2);
-testOpApprox({$atan: -Infinity}, -Math.PI / 2);
-
-testOpApprox({$atan2: [NumberDecimal('Infinity'), 0]}, NumberDecimal(Math.PI / 2));
-testOpApprox({$atan2: [NumberDecimal('-Infinity'), 0]}, NumberDecimal(-Math.PI / 2));
-testOpApprox({$atan2: [NumberDecimal('-Infinity'), NumberDecimal("Infinity")]},
- NumberDecimal(-Math.PI / 4));
-testOpApprox({$atan2: [NumberDecimal('-Infinity'), NumberDecimal("-Infinity")]},
+testOpApprox("$atan", NumberDecimal('Infinity'), NumberDecimal(Math.PI / 2));
+testOpApprox("$atan", NumberDecimal('-Infinity'), NumberDecimal(-Math.PI / 2));
+testOpApprox("$atan", Infinity, Math.PI / 2);
+testOpApprox("$atan", -Infinity, -Math.PI / 2);
+
+testOpApprox("$atan2", [NumberDecimal('Infinity'), 0], NumberDecimal(Math.PI / 2));
+testOpApprox("$atan2", [NumberDecimal('-Infinity'), 0], NumberDecimal(-Math.PI / 2));
+testOpApprox(
+ "$atan2", [NumberDecimal('-Infinity'), NumberDecimal("Infinity")], NumberDecimal(-Math.PI / 4));
+testOpApprox("$atan2",
+ [NumberDecimal('-Infinity'), NumberDecimal("-Infinity")],
NumberDecimal(-3 * Math.PI / 4));
-testOpApprox({$atan2: [NumberDecimal('0'), NumberDecimal("-Infinity")]}, NumberDecimal(Math.PI));
-testOpApprox({$atan2: [NumberDecimal('0'), NumberDecimal("Infinity")]}, NumberDecimal(0));
+testOpApprox("$atan2", [NumberDecimal('0'), NumberDecimal("-Infinity")], NumberDecimal(Math.PI));
+testOpApprox("$atan2", [NumberDecimal('0'), NumberDecimal("Infinity")], NumberDecimal(0));
-testOp({$tanh: NumberDecimal('Infinity')}, NumberDecimal('1'));
-testOp({$tanh: NumberDecimal('-Infinity')}, NumberDecimal('-1'));
+testOp("$tanh", NumberDecimal('Infinity'), NumberDecimal('1'));
+testOp("$tanh", NumberDecimal('-Infinity'), NumberDecimal('-1'));
// Finite input produces infinite outputs.
-testOp({$atanh: NumberDecimal(1)}, NumberDecimal('Infinity'));
-testOp({$atanh: NumberDecimal(-1)}, NumberDecimal('-Infinity'));
-testOp({$atanh: 1}, Infinity);
-testOp({$atanh: -1}, -Infinity);
+testOp("$atanh", NumberDecimal(1), NumberDecimal('Infinity'));
+testOp("$atanh", NumberDecimal(-1), NumberDecimal('-Infinity'));
+testOp("$atanh", 1, Infinity);
+testOp("$atanh", -1, -Infinity);
-testOp({$tanh: Infinity}, 1);
-testOp({$tanh: -Infinity}, -1);
+testOp("$tanh", Infinity, 1);
+testOp("$tanh", -Infinity, -1);
// Int argument out of bounds.
-assertErrorCode(coll, [{$project: {a: {$acos: NumberInt(-2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: NumberInt(2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberInt(-2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberInt(2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acosh: NumberInt(0)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberInt(2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberInt(-2)}}}], 50989);
+testErrorCode("$acos", NumberInt(-2), 50989);
+testErrorCode("$acos", NumberInt(2), 50989);
+testErrorCode("$asin", NumberInt(-2), 50989);
+testErrorCode("$asin", NumberInt(2), 50989);
+testErrorCode("$acosh", NumberInt(0), 50989);
+testErrorCode("$atanh", NumberInt(2), 50989);
+testErrorCode("$atanh", NumberInt(-2), 50989);
// Long argument out of bounds.
-assertErrorCode(coll, [{$project: {a: {$acos: NumberLong(-2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: NumberLong(2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberLong(-2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberLong(2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acosh: NumberLong(0)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberLong(2)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberLong(-2)}}}], 50989);
+testErrorCode("$acos", NumberLong(-2), 50989);
+testErrorCode("$acos", NumberLong(2), 50989);
+testErrorCode("$asin", NumberLong(-2), 50989);
+testErrorCode("$asin", NumberLong(2), 50989);
+testErrorCode("$acosh", NumberLong(0), 50989);
+testErrorCode("$atanh", NumberLong(2), 50989);
+testErrorCode("$atanh", NumberLong(-2), 50989);
// Double argument out of bounds.
-assertErrorCode(coll, [{$project: {a: {$acos: -1.1}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: 1.1}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: -1.1}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: 1.1}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acosh: 0.9}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: -1.00001}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: 1.00001}}}], 50989);
+testErrorCode("$acos", -1.1, 50989);
+testErrorCode("$acos", 1.1, 50989);
+testErrorCode("$asin", -1.1, 50989);
+testErrorCode("$asin", 1.1, 50989);
+testErrorCode("$acosh", 0.9, 50989);
+testErrorCode("$atanh", -1.00001, 50989);
+testErrorCode("$atanh", 1.00001, 50989);
// Decimal argument out of bounds.
-assertErrorCode(coll, [{$project: {a: {$acos: NumberDecimal(-1.1)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acos: NumberDecimal(1.1)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberDecimal(-1.1)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$asin: NumberDecimal(1.1)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$acosh: NumberDecimal(0.9)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberDecimal(-1.00001)}}}], 50989);
-assertErrorCode(coll, [{$project: {a: {$atanh: NumberDecimal(1.000001)}}}], 50989);
+testErrorCode("$acos", NumberDecimal(-1.1), 50989);
+testErrorCode("$acos", NumberDecimal(1.1), 50989);
+testErrorCode("$asin", NumberDecimal(-1.1), 50989);
+testErrorCode("$asin", NumberDecimal(1.1), 50989);
+testErrorCode("$acosh", NumberDecimal(0.9), 50989);
+testErrorCode("$atanh", NumberDecimal(-1.00001), 50989);
+testErrorCode("$atanh", NumberDecimal(1.000001), 50989);
// Check NaN is preserved.
["$acos", "$asin", "$atan", "$cos", "$sin", "$tan"].forEach(op => {
- testOp({[op]: NaN}, NaN);
- testOp({[op]: NumberDecimal(NaN)}, NumberDecimal(NaN));
+ testOp([op], NaN, NaN);
+ testOp([op], NumberDecimal(NaN), NumberDecimal(NaN));
// Check the hyperbolic version of each function.
- testOp({[op + 'h']: NaN}, NaN);
- testOp({[op + 'h']: NumberDecimal(NaN)}, NumberDecimal(NaN));
+ testOp([op + 'h'], NaN, NaN);
+ testOp([op + 'h'], NumberDecimal(NaN), NumberDecimal(NaN));
});
["$radiansToDegrees", "$degreesToRadians"].forEach(op => {
- testOp({[op]: NaN}, NaN);
- testOp({[op]: NumberDecimal(NaN)}, NumberDecimal(NaN));
- testOp({[op]: -Infinity}, -Infinity);
- testOp({[op]: NumberDecimal(-Infinity)}, NumberDecimal(-Infinity));
- testOp({[op]: Infinity}, Infinity);
- testOp({[op]: NumberDecimal(Infinity)}, NumberDecimal(Infinity));
+ testOp([op], NaN, NaN);
+ testOp([op], NumberDecimal(NaN), NumberDecimal(NaN));
+ testOp([op], -Infinity, -Infinity);
+ testOp([op], NumberDecimal(-Infinity), NumberDecimal(-Infinity));
+ testOp([op], Infinity, Infinity);
+ testOp([op], NumberDecimal(Infinity), NumberDecimal(Infinity));
});
-testOp({$atan2: [NumberDecimal('NaN'), NumberDecimal('NaN')]}, NumberDecimal('NaN'));
-testOp({$atan2: [NumberDecimal('NaN'), NumberDecimal('0')]}, NumberDecimal('NaN'));
-testOp({$atan2: [NumberDecimal('0'), NumberDecimal('NaN')]}, NumberDecimal('NaN'));
+testOp("$atan2", [NumberDecimal('NaN'), NumberDecimal('NaN')], NumberDecimal('NaN'));
+testOp("$atan2", [NumberDecimal('NaN'), NumberDecimal('0')], NumberDecimal('NaN'));
+testOp("$atan2", [NumberDecimal('0'), NumberDecimal('NaN')], NumberDecimal('NaN'));
+
+// atan2 additional testing with unknown constants
+testOpApprox("$atan2", [NumberInt(3), NumberInt(2)], NumberDecimal(0.9827937232));
+testOpApprox("$atan2", [NumberInt(621), NumberInt(84)], NumberDecimal(1.4363466632));
// Non-numeric input.
-assertErrorCode(coll, [{$project: {a: {$acos: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$acosh: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$asin: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$asinh: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$atan: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$atan2: ["string", "string"]}}}], 51044);
-assertErrorCode(coll, [{$project: {a: {$atan2: ["string", 0.0]}}}], 51044);
-assertErrorCode(coll, [{$project: {a: {$atan2: [0.0, "string"]}}}], 51045);
-assertErrorCode(coll, [{$project: {a: {$atanh: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$cos: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$cosh: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$sin: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$sinh: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$tan: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$tanh: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$degreesToRadians: "string"}}}], 28765);
-assertErrorCode(coll, [{$project: {a: {$radiansToDegrees: "string"}}}], 28765);
+testErrorCode("$acos", "string", 28765);
+testErrorCode("$acosh", "string", 28765);
+testErrorCode("$asin", "string", 28765);
+testErrorCode("$asinh", "string", 28765);
+testErrorCode("$atan", "string", 28765);
+testErrorCode("$atan2", ["string", "string"], 51044);
+testErrorCode("$atan2", ["string", 0.0], 51044);
+testErrorCode("$atan2", [0.0, "string"], 51045);
+testErrorCode("$atanh", "string", 28765);
+testErrorCode("$cos", "string", 28765);
+testErrorCode("$cosh", "string", 28765);
+testErrorCode("$sin", "string", 28765);
+testErrorCode("$sinh", "string", 28765);
+testErrorCode("$tan", "string", 28765);
+testErrorCode("$tanh", "string", 28765);
+testErrorCode("$degreesToRadians", "string", 28765);
+testErrorCode("$radiansToDegrees", "string", 28765);
}());