summaryrefslogtreecommitdiff
path: root/jstests/core/bypass_doc_validation.js
blob: d9bca81ab6d93ca806b53881b6870b4aeae055db (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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Test the bypassDocumentValidation flag with some database commands. The test uses relevant shell
// helpers when they're available for the respective server commands.

(function() {
    'use strict';

    var dbName = 'bypass_document_validation';
    var collName = 'bypass_document_validation';
    var myDb = db.getSiblingDB(dbName);
    var coll = myDb[collName];
    var docValidationErrorCode = ErrorCodes.DocumentValidationFailure;
    coll.drop();

    // Add a validator to an existing collection.
    assert.writeOK(coll.insert({_id: 1}));
    assert.writeOK(coll.insert({_id: 2}));
    assert.commandWorked(myDb.runCommand({collMod: collName, validator: {a: {$exists: true}}}));

    // Test applyOps with a simple insert if not on mongos.
    if (!db.runCommand({isdbgrid: 1}).isdbgrid) {
        var op = [{ts: Timestamp(0, 0), h: 1, v: 2, op: 'i', ns: coll.getFullName(), o: {_id: 9}}];
        assert.commandFailedWithCode(
            myDb.runCommand({applyOps: op, bypassDocumentValidation: false}),
            ErrorCodes.DocumentValidationFailure);
        assert.eq(0, coll.count({_id: 9}));
        assert.commandWorked(myDb.runCommand({applyOps: op, bypassDocumentValidation: true}));
        assert.eq(1, coll.count({_id: 9}));
    }

    // Test aggregation with $out collection.
    var outputCollName = 'bypass_output_coll';
    var outputColl = myDb[outputCollName];
    outputColl.drop();
    assert.commandWorked(myDb.createCollection(outputCollName, {validator: {a: {$exists: true}}}));

    // Test the aggregate shell helper.
    var pipeline =
        [{$match: {_id: 1}}, {$project: {aggregation: {$add: [1]}}}, {$out: outputCollName}];
    assert.throws(function() {
        coll.aggregate(pipeline, {bypassDocumentValidation: false});
    });
    assert.eq(0, outputColl.count({aggregation: 1}));
    coll.aggregate(pipeline, {bypassDocumentValidation: true});
    assert.eq(1, outputColl.count({aggregation: 1}));

    // Test the copyDb command.
    var copyDbName = dbName + '_copy';
    myDb.getSiblingDB(copyDbName).dropDatabase();
    assert.commandFailedWithCode(
        db.adminCommand(
            {copydb: 1, fromdb: dbName, todb: copyDbName, bypassDocumentValidation: false}),
        docValidationErrorCode);
    assert.eq(0, db.getSiblingDB(copyDbName)[collName].count());
    myDb.getSiblingDB(copyDbName).dropDatabase();
    assert.commandWorked(db.adminCommand(
        {copydb: 1, fromdb: dbName, todb: copyDbName, bypassDocumentValidation: true}));
    assert.eq(coll.count(), db.getSiblingDB(copyDbName)[collName].count());

    // Test the findAndModify shell helper.
    assert.throws(function() {
        coll.findAndModify({update: {$set: {findAndModify: 1}}, bypassDocumentValidation: false});
    });
    assert.eq(0, coll.count({findAndModify: 1}));
    coll.findAndModify({update: {$set: {findAndModify: 1}}, bypassDocumentValidation: true});
    assert.eq(1, coll.count({findAndModify: 1}));

    // Test the map/reduce command.
    var map = function() {
        emit(1, 1);
    };
    var reduce = function(k, vs) {
        return 'mapReduce';
    };
    assert.commandFailedWithCode(coll.runCommand({
        mapReduce: collName,
        map: map,
        reduce: reduce,
        out: {replace: outputCollName},
        bypassDocumentValidation: false
    }),
                                 docValidationErrorCode);
    assert.eq(0, outputColl.count({value: 'mapReduce'}));
    var res = coll.runCommand({
        mapReduce: collName,
        map: map,
        reduce: reduce,
        out: {replace: outputCollName},
        bypassDocumentValidation: true
    });
    assert.commandWorked(res);
    assert.eq(1, outputColl.count({value: 'mapReduce'}));

    // Test the insert command.  Includes a test for a doc with no _id (SERVER-20859).
    res = myDb.runCommand({insert: collName, documents: [{}], bypassDocumentValidation: false});
    assert.eq(res.writeErrors[0].code, docValidationErrorCode, tojson(res));
    res = myDb.runCommand(
        {insert: collName, documents: [{}, {_id: 6}], bypassDocumentValidation: false});
    assert.eq(0, coll.count({_id: 6}));
    assert.eq(res.writeErrors[0].code, docValidationErrorCode, tojson(res));
    res = myDb.runCommand(
        {insert: collName, documents: [{}, {_id: 6}], bypassDocumentValidation: true});
    assert.commandWorked(res);
    assert.eq(null, res.writeErrors);
    assert.eq(1, coll.count({_id: 6}));

    // Test the update command.
    res = myDb.runCommand({
        update: collName,
        updates: [{q: {}, u: {$set: {update: 1}}}],
        bypassDocumentValidation: false
    });
    assert.eq(res.writeErrors[0].code, docValidationErrorCode, tojson(res));
    assert.eq(0, coll.count({update: 1}));
    res = myDb.runCommand({
        update: collName,
        updates: [{q: {}, u: {$set: {update: 1}}}],
        bypassDocumentValidation: true
    });
    assert.commandWorked(res);
    assert.eq(null, res.writeErrors);
    assert.eq(1, coll.count({update: 1}));
})();