summaryrefslogtreecommitdiff
path: root/jstests/aggregation/expressions/multiply.js
blob: 2859046bc732820afdf9364fa7170ff518f6ea4b (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Tests for $multiply aggregation expression.
(function() {
"use strict";

load("jstests/aggregation/extras/utils.js");        // For assertErrorCode().
load("jstests/libs/sbe_assert_error_override.js");  // Override error-code-checking APIs.

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

const binaryTestCases = [
    // Test various argument types pairs.
    {document: {left: NumberInt(10), right: NumberInt(2)}, expected: NumberInt(20)},
    {document: {left: NumberInt(10), right: 2.55}, expected: 25.5},
    {document: {left: NumberInt(10), right: NumberLong("2")}, expected: NumberLong("20")},
    {
        document: {left: NumberInt(10), right: NumberDecimal("2.55")},
        expected: NumberDecimal("25.50")
    },
    {document: {left: NumberInt(10), right: null}, expected: null},

    {document: {left: 12.5, right: NumberInt(10)}, expected: 125},
    {document: {left: 12.5, right: 2.5}, expected: 31.25},
    {document: {left: 12.5, right: NumberLong("5")}, expected: 62.5},
    {
        document: {left: 12.5, right: NumberDecimal("2.5")},
        expected: NumberDecimal("31.25000000000000")
    },
    {document: {left: 12.5, right: null}, expected: null},

    {document: {left: NumberLong("10"), right: NumberInt(2)}, expected: NumberLong("20")},
    {document: {left: NumberLong("10"), right: 2.55}, expected: 25.5},
    {document: {left: NumberLong("10"), right: NumberLong("2")}, expected: NumberLong("20")},
    {
        document: {left: NumberLong("10"), right: NumberDecimal("2.55")},
        expected: NumberDecimal("25.50")
    },
    {document: {left: NumberLong("10"), right: null}, expected: null},

    {
        document: {left: NumberDecimal("12.5"), right: NumberInt(10)},
        expected: NumberDecimal("125.0")
    },
    {
        document: {left: NumberDecimal("12.5"), right: 2.5},
        expected: NumberDecimal("31.250000000000000")
    },
    {
        document: {left: NumberDecimal("12.5"), right: NumberLong("5")},
        expected: NumberDecimal("62.5")
    },
    {
        document: {left: NumberDecimal("12.5"), right: NumberDecimal("2.5")},
        expected: NumberDecimal("31.25")
    },
    {document: {left: NumberDecimal("12.5"), right: null}, expected: null},

    {document: {left: null, right: NumberInt(2)}, expected: null},
    {document: {left: null, right: 2.55}, expected: null},
    {document: {left: null, right: NumberLong("2")}, expected: null},
    {document: {left: null, right: NumberDecimal("2.55")}, expected: null},
    {document: {left: null, right: null}, expected: null}
];

binaryTestCases.forEach(function(testCase) {
    assert.commandWorked(coll.insert(testCase.document));

    const result =
        coll.aggregate({$project: {computed: {$multiply: ["$left", "$right"]}}}).toArray();

    assert.eq(result.length, 1);
    assert.eq(result[0].computed, testCase.expected);

    assert(coll.drop());
});

const nAryTestCases = [
    {
        values: [
            NumberInt(1),
            NumberInt(2),
            NumberInt(3),
            NumberInt(4),
            NumberInt(5),
            NumberInt(6),
            NumberInt(7),
            NumberInt(8),
            NumberInt(9),
            NumberInt(10)
        ],
        expected: NumberInt(3628800)
    },
    {values: [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5], expected: 13427061.1083984375},
    {
        values: [
            NumberLong(1),
            NumberLong(2),
            NumberLong(3),
            NumberLong(4),
            NumberLong(5),
            NumberLong(6),
            NumberLong(7),
            NumberLong(8),
            NumberLong(9),
            NumberLong(10)
        ],
        expected: NumberLong(3628800)
    },
    {
        values: [
            NumberDecimal("1.5"),
            NumberDecimal("2.5"),
            NumberDecimal("3.5"),
            NumberDecimal("4.5"),
            NumberDecimal("5.5"),
            NumberDecimal("6.5"),
            NumberDecimal("7.5"),
            NumberDecimal("8.5"),
            NumberDecimal("9.5"),
            NumberDecimal("10.5")
        ],
        expected: NumberDecimal("13427061.1083984375")
    },
    {values: [null, 2, 3, 4, 5, 6, 7, 8, 9, 10], expected: null},
    {values: [1, 2, 3, 4, 5, null, 7, 8, 9, 10], expected: null},
    {values: [1, 2, 3, 4, 5, 6, 7, 8, 9, null], expected: null},
];

nAryTestCases.forEach(function(testCase) {
    const document = testCase.values.reduce((doc, val, idx) => {
        doc["a" + idx] = val;
        return doc;
    }, {});
    const multiplyArguments = Array.from({length: testCase.values.length}, (_, idx) => "$a" + idx);

    assert.commandWorked(coll.insert(document));

    const result = coll.aggregate({$project: {computed: {$multiply: multiplyArguments}}}).toArray();

    assert.eq(result.length, 1);
    assert.eq(result[0].computed, testCase.expected);

    assert(coll.drop());
});

// Test error codes on incorrect use of $multiply.
const errorTestCases = [
    {document: {left: 1, right: "not a number"}, errorCode: 16555},
    {document: {left: "not a number", right: 1}, errorCode: 16555},
];

errorTestCases.forEach(function(testCase) {
    assert.commandWorked(coll.insert(testCase.document));

    assertErrorCode(
        coll, {$project: {computed: {$multiply: ["$left", "$right"]}}}, testCase.errorCode);

    assert(coll.drop());
});
}());