summaryrefslogtreecommitdiff
path: root/jstests/replsets/rollback_collMod_PowerOf2Sizes.js
blob: 24177ebe6b7d236ecb69d4523704021efeb3bc30 (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
// Test that a rollback of collModding usePowerOf2Sizes and validator can be rolled back.
//
// If all data-bearing nodes in a replica set are using an ephemeral storage engine, the set will
// not be able to survive a scenario where all data-bearing nodes are down simultaneously. In such a
// scenario, none of the members will have any data, and upon restart will each look for a member to
// inital sync from, so no primary will be elected. This test induces such a scenario, so cannot be
// run on ephemeral storage engines.
// @tags: [requires_persistence]
(function() {
    "use strict";

    function getOptions(conn) {
        return conn.getDB(name).foo.exists().options;
    }

    // Set up a set and grab things for later.
    var name = "rollback_collMod_PowerOf2Sizes";
    var replTest = new ReplSetTest({name: name, nodes: 3});
    var nodes = replTest.nodeList();
    var conns = replTest.startSet();
    replTest.initiate({
        "_id": name,
        "members": [
            {"_id": 0, "host": nodes[0]},
            {"_id": 1, "host": nodes[1]},
            {"_id": 2, "host": nodes[2], arbiterOnly: true}
        ]
    });
    // Get master and do an initial write.
    var master = replTest.getPrimary();
    var a_conn = master;
    var slaves = replTest.liveNodes.slaves;
    var b_conn = slaves[0];
    var AID = replTest.getNodeId(a_conn);
    var BID = replTest.getNodeId(b_conn);

    // Create collection with custom options.
    var originalCollectionOptions = {
        flags: 0,
        validator: {x: {$exists: 1}},
        validationLevel: "moderate",
        validationAction: "warn"
    };
    assert.commandWorked(a_conn.getDB(name).createCollection('foo', originalCollectionOptions));

    var options = {writeConcern: {w: 2, wtimeout: 60000}, upsert: true};
    assert.writeOK(a_conn.getDB(name).foo.insert({x: 1}, options));

    assert.eq(getOptions(a_conn), originalCollectionOptions);
    assert.eq(getOptions(b_conn), originalCollectionOptions);

    // Stop the slave so it never sees the collMod.
    replTest.stop(BID);

    // Run the collMod only on A.
    assert.commandWorked(a_conn.getDB(name).runCommand({
        collMod: "foo",
        usePowerOf2Sizes: false,
        noPadding: true,
        validator: {a: 1},
        validationLevel: "moderate",
        validationAction: "warn"
    }));
    assert.eq(getOptions(a_conn),
              {flags: 2, validator: {a: 1}, validationLevel: "moderate", validationAction: "warn"});

    // Shut down A and fail over to B.
    replTest.stop(AID);
    replTest.restart(BID);
    master = replTest.getPrimary();
    assert.eq(b_conn.host, master.host, "b_conn assumed to be master");
    b_conn = master;

    // Do a write on B so that A will have to roll back.
    options = {writeConcern: {w: 1, wtimeout: 60000}, upsert: true};
    assert.writeOK(b_conn.getDB(name).foo.insert({x: 2}, options));

    // Restart A, which should rollback the collMod before becoming primary.
    replTest.restart(AID);
    try {
        b_conn.adminCommand({replSetStepDown: 60, secondaryCatchUpPeriodSecs: 60});
    } catch (e) {
        // Ignore network disconnect.
    }
    replTest.waitForState(a_conn, ReplSetTest.State.PRIMARY);
    assert.eq(getOptions(a_conn), originalCollectionOptions);
}());