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
|
// Test basic inserts and updates with document validation.
(function() {
"use strict";
function assertFailsValidation(res) {
var DocumentValidationFailure = 121;
assert.writeError(res);
assert.eq(res.getWriteError().code, DocumentValidationFailure);
}
var array = [];
for (var i = 0; i < 2048; i++) {
array.push({arbitrary: i});
}
var collName = "doc_validation";
var coll = db[collName];
coll.drop();
// Create collection with document validator.
assert.commandWorked(db.createCollection(collName, {validator: {a: {$exists: true}}}));
// Insert and upsert documents that will pass validation.
assert.writeOK(coll.insert({_id: 'valid1', a: 1}));
assert.writeOK(coll.update({_id: 'valid2'}, {_id: 'valid2', a: 2}, {upsert: true}));
// Insert and upsert documents that will not pass validation.
assertFailsValidation(coll.insert({_id: 'invalid3', b: 1}));
assertFailsValidation(coll.update({_id: 'invalid4'}, {_id: 'invalid4', b: 2}, {upsert: true}));
// Remove document that passed validation.
assert.writeOK(coll.remove({_id: 'valid1'}));
// Drop will assert on failure.
coll.drop();
// Check that we can only update documents that pass validation.
// Set up valid and invalid docs then set validator.
assert.writeOK(coll.insert({_id: 'valid1', a: 1}));
assert.writeOK(coll.insert({_id: 'invalid2', b: 1}));
assert.commandWorked(db.runCommand({"collMod": collName, "validator": {a: {$exists: true}}}));
// Updates affecting fields not included in validator document
// on a conforming document.
// Add new field.
assert.writeOK(coll.update({_id: 'valid1'}, {$set: {z: 1}}));
// In place update.
assert.writeOK(coll.update({_id: 'valid1'}, {$inc: {z: 1}}));
// Out of place update.
assert.writeOK(coll.update({_id: 'valid1'}, {$set: {z: array}}));
// No-op update.
assert.writeOK(coll.update({_id: 'valid1'}, {a: 1}));
// Verify those updates will fail on non-conforming document.
assertFailsValidation(coll.update({_id: 'invalid2'}, {$set: {z: 1}}));
assertFailsValidation(coll.update({_id: 'invalid2'}, {$inc: {z: 1}}));
assertFailsValidation(coll.update({_id: 'invalid2'}, {$set: {z: array}}));
// A no-op update of an invalid doc will succeed.
assert.writeOK(coll.update({_id: 'invalid2'}, {$set: {b: 1}}));
// Verify that the validator respects the collection's default collation. We do this by setting
// a case-insensitive (strength 2) US English collation, and ensuring that the validation is
// case-insensitive.
coll.drop();
assert.commandWorked(db.createCollection(
collName, {validator: {a: "xyz"}, collation: {locale: "en_US", strength: 2}}));
assert.writeOK(coll.insert({a: "XYZ"}));
assert.writeOK(coll.insert({a: "XyZ", b: "foo"}));
assert.writeOK(coll.update({b: "foo"}, {a: "xyZ", b: "foo"}));
assert.writeOK(coll.update({b: "foo"}, {$set: {a: "Xyz"}}));
assertFailsValidation(coll.insert({a: "not xyz"}));
assertFailsValidation(coll.update({b: "foo"}, {$set: {a: "xyzz"}}));
// Verify can't make a conforming doc fail validation,
// but can update non-conforming doc to pass validation.
coll.drop();
assert.writeOK(coll.insert({_id: 'valid1', a: 1}));
assert.writeOK(coll.insert({_id: 'invalid2', b: 1}));
assert.commandWorked(db.runCommand({"collMod": collName, "validator": {a: {$exists: true}}}));
assertFailsValidation(coll.update({_id: 'valid1'}, {$unset: {a: 1}}));
assert.writeOK(coll.update({_id: 'invalid2'}, {$set: {a: 1}}));
// Modify collection to remove validator statement
assert.commandWorked(db.runCommand({"collMod": collName, "validator": {}}));
// Verify no validation applied to updates.
assert.writeOK(coll.update({_id: 'valid1'}, {$set: {z: 1}}));
assert.writeOK(coll.update({_id: 'invalid2'}, {$set: {z: 1}}));
assert.writeOK(coll.update({_id: 'valid1'}, {$unset: {a: 1}}));
assert.writeOK(coll.update({_id: 'invalid2'}, {$set: {a: 1}}));
coll.drop();
})();
|