summaryrefslogtreecommitdiff
path: root/jstests/core/projection_expr_mod.js
blob: 859e99edf1bdf8fdcd3086c262de803fcb9f7873 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Confirm correctness of $mod evaluation in find projection.

(function() {
"use strict";

load("jstests/aggregation/extras/utils.js");  // For assertArrayEq.
load("jstests/libs/sbe_util.js");             // For checkSBEEnabled.

const isSBEEnabled = checkSBEEnabled(db);
if (isSBEEnabled) {
    // Override error-code-checking APIs. We only load this when SBE is explicitly enabled, because
    // it causes failures in the parallel suites.
    load("jstests/libs/sbe_assert_error_override.js");
}

const coll = db.projection_expr_mod;
coll.drop();

assert.commandWorked(coll.insertMany([
    {n: "double % double", v: 138.5, m: 3.0},
    {n: "double % long", v: 138.5, m: NumberLong(3)},
    {n: "double % int", v: 138.5, m: NumberInt(3)},
    {n: "int % double", v: NumberInt(8), m: 3.25},
    {n: "int % double int", v: NumberInt(8), m: 3.0},
    {n: "int % int", v: NumberInt(8), m: NumberInt(3)},
    {n: "int % long", v: NumberInt(8), m: NumberLong(3)},
    {n: "long % double", v: NumberLong(8), m: 3.25},
    {n: "long % double int", v: NumberLong(8), m: 3.0},
    {n: "long % double long", v: NumberLong(500000000000), m: 450000000000.0},
    {n: "long % int", v: NumberLong(8), m: NumberInt(3)},
    {n: "long % long", v: NumberLong(8), m: NumberLong(3)},
    {n: "very long % very long", v: NumberLong(800000000000), m: NumberLong(300000000000)}
]));

const result = coll.find({}, {f: {$mod: ["$v", "$m"]}, _id: 0, n: 1}).toArray();
const expectedResult = [
    {n: "double % double", f: 0.5},
    {n: "double % long", f: 0.5},
    {n: "double % int", f: 0.5},
    {n: "int % double", f: 1.5},
    {n: "int % double int", f: 2},
    {n: "int % int", f: 2},
    {n: "int % long", f: NumberLong(2)},
    {n: "long % double", f: 1.5},
    {n: "long % double int", f: NumberLong(2)},
    {n: "long % double long", f: 50000000000},
    {n: "long % int", f: NumberLong(2)},
    {n: "long % long", f: NumberLong(2)},
    {n: "very long % very long", f: NumberLong(200000000000)}
];
assertArrayEq({actual: result, expected: expectedResult});

//
// Confirm error cases.
//

// Confirm mod by 0 fails in an expected manner.
assert(coll.drop());
assert.commandWorked(coll.insert({a: 10}));
let error = assert.throws(() => coll.find({}, {f: {$mod: ["$a", 0]}, _id: 0, n: 1}).toArray());
assert.commandFailedWithCode(error, 16610);

assert(coll.drop());
assert.commandWorked(coll.insert({a: NumberInt(10)}));
error =
    assert.throws(() => coll.find({}, {f: {$mod: ["$a", NumberInt(0)]}, _id: 0, n: 1}).toArray());
assert.commandFailedWithCode(error, 16610);

assert(coll.drop());
assert.commandWorked(coll.insert({a: NumberLong(10)}));
error =
    assert.throws(() => coll.find({}, {f: {$mod: ["$a", NumberLong(0)]}, _id: 0, n: 1}).toArray());
assert.commandFailedWithCode(error, 16610);

// Clear collection again and reset.
assert(coll.drop());
assert.commandWorked(coll.insert({a: 10}));

// Confirm expected behavior for NaN and Infinity values.
assert.eq(coll.findOne({}, {f: {$mod: ["$a", NaN]}, _id: 0}), {f: NaN});
assert.eq(coll.findOne({}, {f: {$mod: ["$a", Infinity]}, _id: 0}), {f: 10});
assert.eq(coll.findOne({}, {f: {$mod: ["$a", -Infinity]}, _id: 0}), {f: 10});
assert.eq(coll.findOne({}, {f: {$mod: [Infinity, "$a"]}, _id: 0}), {f: NaN});
assert.eq(coll.findOne({}, {f: {$mod: [-Infinity, "$a"]}, _id: 0}), {f: NaN});
assert.eq(coll.findOne({}, {f: {$mod: [NaN, "$a"]}, _id: 0}), {f: NaN});
})();