summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorYuhong Zhang <yuhong.zhang@mongodb.com>2022-06-28 02:46:39 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-06-28 03:16:45 +0000
commit6f4ad824d65ab928f04356e6e1a2fefc15499884 (patch)
tree8dde7a5fa06fc621aa53e272d4441637af673701 /jstests
parenta5382fb01bb2d023c80c2eb1af807eca1f145c43 (diff)
downloadmongo-6f4ad824d65ab928f04356e6e1a2fefc15499884.tar.gz
SERVER-67045 Create a testing interface to insert non-conformant BSON documents
Diffstat (limited to 'jstests')
-rw-r--r--jstests/disk/libs/wt_file_helper.js49
-rw-r--r--jstests/disk/validate_bson_inconsistency.js39
2 files changed, 88 insertions, 0 deletions
diff --git a/jstests/disk/libs/wt_file_helper.js b/jstests/disk/libs/wt_file_helper.js
index 862d189c85d..b94420434f7 100644
--- a/jstests/disk/libs/wt_file_helper.js
+++ b/jstests/disk/libs/wt_file_helper.js
@@ -234,3 +234,52 @@ let truncateUriAndRestartMongod = function(uri, conn, mongodOptions) {
runWiredTigerTool("-h", conn.dbpath, "truncate", uri);
return startMongodOnExistingPath(conn.dbpath, mongodOptions);
};
+
+/**
+ * Stops the given mongod, dumps the table with the uri, modifies the content, and loads it back to
+ * the table.
+ */
+let rewriteTable = function(uri, conn, modifyData) {
+ MongoRunner.stopMongod(conn, null, {skipValidation: true});
+ const tempDumpFile = conn.dbpath + "/temp_dump";
+ const newTableFile = conn.dbpath + "/new_table_file";
+ runWiredTigerTool("-h",
+ conn.dbpath,
+ "-r",
+ "-C",
+ "log=(compressor=snappy,path=journal)",
+ "dump",
+ "-x",
+ "-f",
+ tempDumpFile,
+ "table:" + uri);
+ let dumpLines = cat(tempDumpFile).split("\n");
+ modifyData(dumpLines);
+ writeFile(newTableFile, dumpLines.join("\n"));
+ runWiredTigerTool("-h", conn.dbpath, "load", "-f", newTableFile, "-r", uri);
+};
+
+// In WiredTiger table dumps, the first seven lines are the header and key that we don't want to
+// modify. We will skip them and start from the line containing the first value.
+const wtHeaderLines = 7;
+
+/**
+ * Inserts the documents with duplicate field names into the MongoDB server.
+ */
+let insertDocDuplicateFieldName = function(coll, uri, conn, numDocs) {
+ for (let i = 0; i < numDocs; ++i) {
+ coll.insert({a: "aaaaaaa", b: "bbbbbbb"});
+ }
+ // The format of the BSON documents will be {_id: ObjectId(), a: "aaaaaaa", a: "bbbbbbb"}.
+ let makeDuplicateFieldNames = function(lines) {
+ // The offset of the document's field name 'b' in the hex string dumped by wt tool.
+ const offsetToFieldB = 75;
+ // Each record takes two lines with a key and a value. We will only modify the values.
+ for (let i = wtHeaderLines; i < lines.length; i += 2) {
+ // Switch the field name 'b' to 'a' to create a duplicate field name.
+ lines[i] = lines[i].substring(0, offsetToFieldB) + "1" +
+ lines[i].substring(offsetToFieldB + 1);
+ }
+ };
+ rewriteTable(uri, conn, makeDuplicateFieldNames);
+}; \ No newline at end of file
diff --git a/jstests/disk/validate_bson_inconsistency.js b/jstests/disk/validate_bson_inconsistency.js
new file mode 100644
index 00000000000..a91eb8d7695
--- /dev/null
+++ b/jstests/disk/validate_bson_inconsistency.js
@@ -0,0 +1,39 @@
+/**
+ * Tests that the validate command detects various types of BSON inconsistencies.
+ */
+
+(function() {
+
+load('jstests/disk/libs/wt_file_helper.js');
+
+const baseName = "validate_bson_inconsistency";
+const collNamePrefix = "test_";
+let count = 0;
+const dbpath = MongoRunner.dataPath + baseName + "/";
+
+resetDbpath(dbpath);
+
+(function validateDocumentsDuplicateFieldNames() {
+ jsTestLog("Validate documents with duplicate field names");
+
+ let mongod = startMongodOnExistingPath(dbpath);
+ let db = mongod.getDB(baseName);
+ const collName = collNamePrefix + count++;
+ db.createCollection(collName);
+ let testColl = db[collName];
+
+ let uri = getUriForColl(testColl);
+ const numDocs = 10;
+ insertDocDuplicateFieldName(testColl, uri, mongod, numDocs);
+
+ mongod = startMongodOnExistingPath(dbpath);
+ db = mongod.getDB(baseName);
+ testColl = db[collName];
+
+ let res = assert.commandWorked(testColl.validate());
+ assert(res.valid, tojson(res));
+ // TODO: Check the warnings that the documents with duplicate field names are detected.
+
+ MongoRunner.stopMongod(mongod, null, {skipValidation: true});
+})();
+})();