summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/user_write_blocking_ttl_index.js
blob: 5fcc7750aeedac3d0757ea2b46e19fc8b688cceb (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
// Validate that write blocking mode prevents reaping of user, but not system, TTL indexes
// @tags: [
//   creates_and_authenticates_user,
//   requires_auth,
//   requires_fcv_60,
//   requires_non_retryable_commands,
//   requires_replication,
// ]

(function() {
"use strict";

load("jstests/libs/fail_point_util.js");

// Test on replset primary
const rst = new ReplSetTest({
    nodes: 1,
    nodeOptions: {
        setParameter: {
            "ttlMonitorSleepSecs": 1,
        }
    }
});
rst.startSet();
rst.initiate();
const primary = rst.getPrimary();

function runTest(conn, testCase) {
    const admin = conn.getDB("admin");

    // Make sure the TTLMonitor is disabled, while not holding any global locks
    const pauseTtl = configureFailPoint(primary, 'hangTTLMonitorBetweenPasses');
    pauseTtl.wait();

    function runTTLMonitor() {
        const ttlPass = admin.serverStatus().metrics.ttl.passes;
        assert.commandWorked(
            admin.runCommand({configureFailPoint: "hangTTLMonitorBetweenPasses", mode: {skip: 1}}));
        assert.soon(() => admin.serverStatus().metrics.ttl.passes >= ttlPass + 1,
                    "TTL monitor didn't run before timing out.");
    }

    // Set up data and TTL indexes
    for (const target of testCase) {
        target.db = conn.getDB(target.dbname);
        target.col = target.db.getCollection(target.colName);

        target.col.insertOne({"createdAt": new Date(), "logEvent": 2, "logMessage": "Success!"});

        assert.commandWorked(target.col.createIndex({"createdAt": 1}, {expireAfterSeconds: 0}));
    }

    // Enable global write block mode
    assert.commandWorked(admin.runCommand({setUserWriteBlockMode: 1, global: true}));
    for (const target of testCase) {
        assert.eq(1, target.col.count());
    }

    // Run the TTLMonitor, and expect user collections to remain unreaped
    runTTLMonitor();
    for (const target of testCase) {
        if (target.expectReap) {
            assert.eq(0, target.col.count());
        } else {
            assert.eq(1, target.col.count());
            checkLog.containsJson(conn, 5400703, {
                "error": {
                    "code": ErrorCodes.UserWritesBlocked,
                    "codeName": "UserWritesBlocked",
                    "errmsg": "User writes blocked"
                }
            });
        }
    }

    // Disable write blocking, then run the TTLMonitor, expecting it to reap all collections
    assert.commandWorked(admin.runCommand({setUserWriteBlockMode: 1, global: false}));
    runTTLMonitor();

    for (const target of testCase) {
        // All documents should be reaped now
        assert.soon(() => target.col.count() == 0);

        // Finally, cleanup the collection
        if (target.colName != "system.js") {
            assert(target.col.drop());
        }
    }
}

runTest(primary, [
    // Collections in a regular database should not be reaped
    {dbname: "db", colName: "user_write_blocking_ttl_index", expectReap: false},
    // Not even system collections in a regular database should be reaped
    {dbname: "db2", colName: "system.js", expectReap: false},
    // Collections in system databases should be reaped
    {dbname: "admin", colName: "user_write_blocking_ttl_index", expectReap: true},
    {dbname: "config", colName: "user_write_blocking_ttl_index", expectReap: true},
    {dbname: "local", colName: "user_write_blocking_ttl_index", expectReap: true}
]);
rst.stopSet();
})();