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
|
/**
* Randomized testing to confirm the correctness of left-to-right associativity for arithmetic
* operations that take multiple arguments.
*/
// Randomized property testing.
(function() {
"use strict";
load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers
load("jstests/aggregation/extras/utils.js"); // For assertErrorCode() and assertArrayEq().
var conn = MongoRunner.runMongod();
const dbName = jsTestName();
const testDB = conn.getDB(dbName);
const coll = testDB.getCollection('coll');
coll.drop();
function assertPipelineCorrect(pipeline, v) {
coll.drop();
coll.insert({v});
testDB.adminCommand({
configureFailPoint: 'disablePipelineOptimization',
mode: 'off',
});
let optimizedResults = coll.aggregate(pipeline).toArray();
testDB.adminCommand({
configureFailPoint: 'disablePipelineOptimization',
mode: 'alwaysOn',
});
let unoptimizedResults = coll.aggregate(pipeline).toArray();
testDB.adminCommand({
configureFailPoint: 'disablePipelineOptimization',
mode: 'off',
});
assert.eq(unoptimizedResults.length, 1);
assert.eq(optimizedResults.length, 1);
assert.eq(unoptimizedResults[0]._id, optimizedResults[0]._id, tojson(pipeline));
}
/**
* Randomized, property-based test of the left-to-right constant folding optimization. The purpose
* of folding left-to-right is to preserve the same order-of-operations during ahead-of-time
* constant folding that occurs during runtime execution.
*
* Given:
* - A random list of numbers of any type
* - A fieldpath reference placed at a random location in the list of numbers
* - A pipeline that performs an arithmetic operation over the list of arguments (fieldpath +
* numbers)
* Show:
* - The arithmetic operation produces the exact same result with and without optimizations.
* @param {options} options
*/
function runRandomizedPropertyTest({op, min, max}) {
// Function to generate random numbers of float, long, double, and NumberDecimal (with different
// probabilities).
const generateNumber = () => {
const r = Math.random() * (max - min) + min;
const t = Math.random();
if (t < 0.7) {
return r;
}
if (t < 0.85) {
return NumberInt(Math.round(r));
}
if (t < 0.99) {
return NumberLong(Math.round(r));
}
return NumberDecimal(String(r));
};
const generateNumberList = (length) => Array.from({length}, () => generateNumber(min, max));
const numbers = generateNumberList(10);
// Place a fieldpath reference randomly within the list of numbers to produce an argument list.
const pos = Math.floor(numbers.length * Math.random());
const args = [].concat(numbers.slice(0, pos), ["$v"], numbers.slice(pos));
const pipeline = [{
$group: {
_id: {[op]: args},
sum: {$sum: 1},
},
}];
coll.drop();
const v = generateNumber();
assertPipelineCorrect(pipeline, v);
}
// TODO: SERVER-67282 Randomized property testing should work after SBE is updated to match classic
// engine, so remove this setParameter. When this knob is removed from this test, move this test
// into jstests/aggregation/expressions/arithmetic_constant_folding.js.
testDB.adminCommand({setParameter: 1, internalQueryFrameworkControl: "forceClassicEngine"});
for (let i = 0; i < 5; i++) {
runRandomizedPropertyTest({op: "$add", min: -314159255, max: 314159255});
runRandomizedPropertyTest({op: "$multiply", min: -31415, max: 31415});
}
// TODO: SERVER-67282 Randomized property testing should work after SBE is updated to match classic
// engine, so remove this setParameter.
testDB.adminCommand({setParameter: 1, internalQueryFrameworkControl: "tryBonsai"});
MongoRunner.stopMongod(conn);
})();
|