summaryrefslogtreecommitdiff
path: root/jstests/replsets/initial_sync_fcv.js
blob: 01d2e8d95369a5f683027f7c362a064f0427fc55 (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
/**
 * Tests that setting the feature compatibility version during initial sync leads to initial sync
 * restarting. This test also ensures that even if initial sync takes two attempts to complete,
 * that the fCV is reset between attempts.
 */

(function() {
    'use strict';

    load("jstests/libs/feature_compatibility_version.js");
    load('jstests/libs/check_log.js');

    const rst = new ReplSetTest({nodes: 2});
    rst.startSet();

    // We disallow the secondary node from voting so that the primary's featureCompatibilityVersion
    // can be modified while the secondary node is still waiting to complete its initial sync.
    const replSetConfig = rst.getReplSetConfig();
    replSetConfig.members[1].priority = 0;
    replSetConfig.members[1].votes = 0;
    rst.initiate(replSetConfig);

    const primary = rst.getPrimary();
    const dbName = 'foo';
    const collName = 'bar';

    assert.writeOK(primary.getDB(dbName).getCollection(collName).insert({a: 1}));

    function runInitialSync(cmd, initialFCV) {
        assert.commandWorked(primary.adminCommand({setFeatureCompatibilityVersion: initialFCV}));

        jsTestLog('Testing setting fCV with ' + tojson(cmd));

        const failPointOptions = tojson({mode: 'alwaysOn', data: {database: dbName}});
        rst.restart(1, {
            startClean: true,
            setParameter: {
                'failpoint.initialSyncHangBeforeListCollections': failPointOptions,
                numInitialSyncAttempts: 2
            }
        });
        const secondary = rst.nodes[1];

        // Initial sync clones the 'admin' database first, which will set the fCV on the
        // secondary to initialFCV. We then block the secondary before issuing 'listCollections' on
        // the test database.
        checkLog.contains(secondary,
                          'initial sync - initialSyncHangBeforeListCollections fail point enabled');

        // Initial sync is stopped right before 'listCollections' on the test database. We now run
        // the test command to modify the fCV.
        assert.commandWorked(primary.adminCommand(cmd));

        // Let initial sync finish, making sure that it fails due to the feature compatibility
        // version change.
        assert.commandWorked(secondary.adminCommand(
            {configureFailPoint: 'initialSyncHangBeforeListCollections', mode: 'off'}));
        checkLog.contains(secondary,
                          'Applying operation on feature compatibility version document');

        jsTestLog('Wait for both nodes to be up-to-date');
        rst.awaitSecondaryNodes();
        rst.awaitReplication();

        let res =
            assert.commandWorked(secondary.adminCommand({replSetGetStatus: 1, initialSync: 1}));
        assert.eq(res.initialSyncStatus.failedInitialSyncAttempts, 1);

        // We check oplogs and data hashes before we restart the second node.
        rst.checkOplogs();
        rst.checkReplicatedDataHashes();
    }

    // Ensure that attempting to downgrade the featureCompatibilityVersion during initial sync
    // fails.
    runInitialSync({setFeatureCompatibilityVersion: lastStableFCV}, /*initialFCV*/ latestFCV);

    // Ensure that attempting to upgrade the featureCompatibilityVersion during initial sync fails.
    runInitialSync({setFeatureCompatibilityVersion: latestFCV}, /*initialFCV*/ lastStableFCV);

    // Modifications to the featureCompatibilityVersion document during initial sync should be
    // caught and cause initial sync to fail.
    runInitialSync({
        update: 'system.version',
        updates: [{q: {_id: 'featureCompatibilityVersion'}, u: {'version': lastStableFCV}}]
    },
                   /*initialFCV*/ latestFCV);

    rst.stopSet();
})();