summaryrefslogtreecommitdiff
path: root/jstests/core/hello_response_validation.js
blob: d335d9d50002b733bc34d6f080a5b6e4cce1c34c (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
//
// This test ensures that the hello command and its aliases, ismaster and isMaster,
// are all accepted.
//
// @tags: [
//    # Assert on the isWritablePrimary field of a hello response. If a primary steps down after
//    # accepting a hello command and returns before its connection is closed, the response can
//    # contain isWritablePrimary: false.
//    does_not_support_stepdowns,
// ]

(function() {
"use strict";

function checkResponseFields(command, commandType) {
    var res = db.runCommand(command);
    // check that the fields that should be there are there and have proper values
    assert(res.maxBsonObjectSize && isNumber(res.maxBsonObjectSize) && res.maxBsonObjectSize > 0,
           "maxBsonObjectSize possibly missing:" + tojson(res));
    assert(
        res.maxMessageSizeBytes && isNumber(res.maxMessageSizeBytes) && res.maxBsonObjectSize > 0,
        "maxMessageSizeBytes possibly missing:" + tojson(res));
    assert(res.maxWriteBatchSize && isNumber(res.maxWriteBatchSize) && res.maxWriteBatchSize > 0,
           "maxWriteBatchSize possibly missing:" + tojson(res));

    if (commandType === "hello") {
        assert.eq("boolean",
                  typeof res.isWritablePrimary,
                  "isWritablePrimary field is not a boolean" + tojson(res));
        assert(res.isWritablePrimary === true, "isWritablePrimary field is false" + tojson(res));
    } else {
        assert.eq("boolean", typeof res.ismaster, "ismaster field is not a boolean" + tojson(res));
        assert(res.ismaster === true, "ismaster field is false" + tojson(res));
    }
    assert(res.localTime, "localTime possibly missing:" + tojson(res));
    assert(res.connectionId, "connectionId missing or false" + tojson(res));

    if (!testingReplication) {
        var badFields = [];
        var unwantedReplSetFields = [
            "setName",
            "setVersion",
            "secondary",
            "hosts",
            "passives",
            "arbiters",
            "primary",
            "arbiterOnly",
            "passive",
            "slaveDelay",
            "secondaryDelaySecs",
            "hidden",
            "tags",
            "buildIndexes",
            "me"
        ];
        var field;
        // check that the fields that shouldn't be there are not there
        for (field in res) {
            if (!res.hasOwnProperty(field)) {
                continue;
            }
            if (Array.contains(unwantedReplSetFields, field)) {
                badFields.push(field);
            }
        }
        assert(
            badFields.length === 0,
            "\nthe result:\n" + tojson(res) + "\ncontained fields it shouldn't have: " + badFields);
    }
}

checkResponseFields("hello", "hello");
checkResponseFields("ismaster", "ismaster");
checkResponseFields("isMaster", "isMaster");
checkResponseFields({hello: 1, unknownField: 1}, "hello");
checkResponseFields({ismaster: 1, unknownField: 1}, "ismaster");
checkResponseFields({isMaster: 1, unknownField: 1}, "isMaster");

// As operations happen concurrently, the response objects may have different timestamps. To compare
// response objects returned from calling commands directly and shell helpers below, we must remove
// the timestamps.
function removeTimestamps(cmdResponse) {
    delete cmdResponse.localTime;
    delete cmdResponse.operationTime;
    delete cmdResponse.$clusterTime;
    if (cmdResponse.lastWrite) {
        delete cmdResponse.lastWrite.opTime;
        delete cmdResponse.lastWrite.majorityOpTime;
    }
}

// We also test the db.hello() and db.isMaster() helpers to ensure that they return
// the same response objects as from running the commands directly.
let cmdResponse1 = removeTimestamps(db.runCommand("hello"));
let cmdResponse2 = removeTimestamps(db.hello());
assert.eq(cmdResponse1, cmdResponse2);

cmdResponse1 = removeTimestamps(db.runCommand("isMaster"));
cmdResponse2 = removeTimestamps(db.isMaster());
assert.eq(cmdResponse1, cmdResponse2);
})();