summaryrefslogtreecommitdiff
path: root/jstests/libs/all_commands_test.js
blob: c3d02fbd54858c6953ef1a9ca4f59f8ebababbac (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
/**
 * A library for testing behaviors over the set of all available commands.
 * Users of this library must declare the expected results for all commands and pass
 * them into a cmdMap object.
 *
 * Each entry in the map should have at least the following fields:
 *      {
 *          command: {<command object, e.g. 'find: test, filter: {a: 1}'>}
 *          skip: <reason string> // optional field
 *      }
 *
 * All the logic about how exactly a test should run is defined by the user.
 * See the 'testAllCommands' function.
 */
const AllCommandsTest = (function() {
    "use strict";
    /**
     * Verifies that the command map contains an entry for every command that exists on the server.
     * This is already called in 'testAllCommands', so there is no need to call this directly.
     *
     * @param {Object} conn The shell connection to run the suite over.
     * @param {map} cmdMap A map of all commands, with their invocations and expected behavior.
     */
    function checkCommandCoverage(conn, cmdMap) {
        const res = assert.commandWorked(conn.adminCommand({listCommands: 1}));
        const commandsInListCommands = Object.keys(res.commands);
        let missingCommands = [];

        // Make sure that all valid commands are covered in the cmdMap.
        for (const command of commandsInListCommands) {
            if (!cmdMap[command]) {
                missingCommands.push(command);
            }
        }
        if (missingCommands.length !== 0) {
            throw new Error("Command map is missing entries for " + missingCommands);
        }

        return commandsInListCommands;
    }

    /**
     * The runner function for this library.
     * Use the 'skip' option for tests that should not run.
     *
     * @param {Object} conn The shell connection to run the suite over.
     * @param {map} cmdMap A map of all commands, with their invocations and expected behavior.
     * @param {function} testFn A user-defined function to execute on every command.
     */
    function testAllCommands(conn, cmdMap, testFn) {
        // First check that the map contains all available commands.
        const commands = checkCommandCoverage(conn, cmdMap);

        for (const command of commands) {
            const test = cmdMap[command];

            // Coverage already guaranteed above, but check again just in case.
            assert(test, "Coverage failure: must explicitly define a test for " + command);

            if (test.skip !== undefined) {
                jsTestLog("Skipping " + command + ": " + test.skip);
                continue;
            }

            // Run logic specified by caller.
            jsTestName("Testing " + command);
            testFn(test);
        }
    }

    return {testAllCommands: testAllCommands};
})();