summaryrefslogtreecommitdiff
path: root/jstests/multiVersion/targetedTestsLastLtsFeatures/accumulator_fix_last_lts.js
blob: 8e8d6573796abd8358cfed8fdc3e72a44825fe6f (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
161
162
163
/**
 * Tests whether $sum accumulator incorrect result bug is fixed when upgrading from the last-lts to
 * the latest.
 *
 * @tags: [
 *  requires_sharding,
 * ]
 */
(function() {
'use strict';

load('jstests/multiVersion/libs/multi_cluster.js');  // For upgradeCluster()

// TODO SERVER-64227 Remove this test case since this test case is unnecessary after we branch
// for 6.1.
(function testUpgradeFromLastLtsToLatest() {
    const st = new ShardingTest({
        shards: 2,
        rs: {nodes: 2, binVersion: "last-lts"},
        other: {mongosOptions: {binVersion: "last-lts"}}
    });

    let db = st.getDB(jsTestName());

    // Makes sure that the test db is sharded.
    assert.commandWorked(st.s0.adminCommand({enableSharding: db.getName()}));

    let verifyShardedAccumulatorResultsOnBothEngine =
        (isGreaterLastContinous, coll, pipeline, verifyThis) => {
            const dbs = [
                st.rs0.getPrimary().getDB(jsTestName()),
                st.rs0.getSecondary().getDB(jsTestName()),
                st.rs1.getPrimary().getDB(jsTestName()),
                st.rs1.getSecondary().getDB(jsTestName())
            ];

            // In the last-lts, we don't have the 'internalQueryEnableSlotBasedExecutionEngine'
            // query knob.
            if (isGreaterLastContinous) {
                // Turns to the classic engine at the shards.
                dbs.forEach(
                    (db) => assert.commandWorked(
                        db.adminCommand(
                            {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: false}),
                        `at node ${db.getMongo().host}`));
            }

            // Verifies that the classic engine's results are same as the expected results.
            const classicRes = coll.aggregate(pipeline).toArray();
            verifyThis(classicRes);

            // In the last-lts, we have neither the 'internalQueryEnableSlotBasedExecutionEngine'
            // query knob nor the SBE $group pushdown feature.
            if (isGreaterLastContinous) {
                // Turns to the SBE engine at the shards.
                dbs.forEach(
                    (db) => assert.commandWorked(
                        db.adminCommand(
                            {setParameter: 1, internalQueryEnableSlotBasedExecutionEngine: true}),
                        `at node ${db.getMongo().host}`));

                // Verifies that the SBE engine's results are same as the expected results.
                const sbeRes = coll.aggregate(pipeline).toArray();
                verifyThis(sbeRes);
            }
        };

    let shardCollectionByHashing = coll => {
        coll.drop();

        // Makes sure that the collection is sharded.
        assert.commandWorked(
            st.s0.adminCommand({shardCollection: coll.getFullName(), key: {_id: "hashed"}}));

        return coll;
    };

    let hashShardedColl = shardCollectionByHashing(db.partial_sum);

    for (let i = 0; i < 10; ++i) {
        const docs = [
            {k: i, n: 1e+34},
            {k: i, n: NumberDecimal("0.1")},
            {k: i, n: NumberDecimal("0.01")},
            {k: i, n: -1e+34}
        ];
        assert.commandWorked(hashShardedColl.insert(docs));
    }

    const pipelineWithSum = [{$group: {_id: "$k", s: {$sum: "$n"}}}, {$group: {_id: "$s"}}];
    const pipelineWithAvg = [{$group: {_id: "$k", s: {$avg: "$n"}}}, {$group: {_id: "$s"}}];

    // The results on an unsharded collection is the expected results.
    const expectedResSum = [{"_id": NumberDecimal("0.11")}];
    verifyShardedAccumulatorResultsOnBothEngine(
        false /* isGreaterLastContinous */,
        hashShardedColl,
        pipelineWithSum,
        (actualRes) => assert.neq(
            actualRes,
            expectedResSum,
            `Sharded sum for mixed data by which only decimal sum survive on ${version}: \n` +
                `${tojson(actualRes)} == ${tojson(expectedResSum)}`));

    const expectedResAvg = [{"_id": NumberDecimal("0.0275")}];
    verifyShardedAccumulatorResultsOnBothEngine(
        false /* isGreaterLastContinous */,
        hashShardedColl,
        pipelineWithAvg,
        (actualRes) => assert.neq(
            actualRes,
            expectedResAvg,
            `Sharded avg for mixed data by which only decimal sum survive on ${version}: \n` +
                `${tojson(actualRes)} == ${tojson(expectedResAvg)}`));

    // Upgrade the cluster to the latest.
    st.upgradeCluster(
        "latest",
        {upgradeShards: true, upgradeConfigs: true, upgradeMongos: true, waitUntilStable: true});

    db = st.getDB(jsTestName());
    checkFCV(st.rs0.getPrimary().getDB("admin"), lastLTSFCV);

    hashShardedColl = db.partial_sum;

    // $sum fix is FCV-gated. So, it's not applied after binary upgrade.
    verifyShardedAccumulatorResultsOnBothEngine(
        true /* isGreaterLastContinuous */,
        hashShardedColl,
        pipelineWithSum,
        (actualRes) => assert.neq(
            actualRes,
            expectedResSum,
            "Sharded sum for mixed data by which only decimal sum survive on latest after binary upgrade: \n" +
                `${tojson(actualRes)} == ${tojson(expectedResSum)}`));

    // On the other hand, $avg fix is not FCV-gated. So, it's applied after binary upgrade.
    verifyShardedAccumulatorResultsOnBothEngine(
        true /* isGreaterLastContinuous */,
        hashShardedColl,
        pipelineWithAvg,
        (actualRes) => assert.eq(
            actualRes,
            expectedResAvg,
            "Sharded avg for mixed data by which only decimal sum survive on latest after binary upgrade: \n" +
                `${tojson(actualRes)} != ${tojson(expectedResAvg)}`));

    assert.commandWorked(st.s.adminCommand({setFeatureCompatibilityVersion: latestFCV}));

    // The FCV is upgraded to the 'latestFCV' and $sum fix must be applied now.
    verifyShardedAccumulatorResultsOnBothEngine(
        true /* isGreaterLastContinuous */,
        hashShardedColl,
        pipelineWithSum,
        (actualRes) => assert.eq(
            actualRes,
            expectedResSum,
            "Sharded sum for mixed data by which only decimal sum survive on latest after FCV upgrade: \n" +
                `${tojson(actualRes)} != ${tojson(expectedResSum)}`));

    st.stop();
}());
}());