summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorDianna <dianna.hohensee@10gen.com>2019-04-10 13:09:52 -0400
committerDianna <dianna.hohensee@10gen.com>2019-04-17 16:25:03 -0400
commitc539768709f9dbf1cdc59e7dc156c8eab7dad828 (patch)
treee14f7fd04007bf43f3f0ccd3ba3f82bb3bfada57 /jstests
parente0cafae280e508ef887bd08978dcbc5630c08a34 (diff)
downloadmongo-c539768709f9dbf1cdc59e7dc156c8eab7dad828.tar.gz
SERVER-40321 Transaction CRUD ops on a shard against a capped collection fail
Diffstat (limited to 'jstests')
-rw-r--r--jstests/core/txns/ban_tailable_cursor.js7
-rw-r--r--jstests/core/txns/multi_statement_transaction_write_error.js18
-rw-r--r--jstests/core/txns/prepare_transaction_fails_on_temp_collections.js2
-rw-r--r--jstests/core/txns/transaction_ops_succeed_against_capped_collection.js45
-rw-r--r--jstests/sharding/transaction_ops_fail_against_capped_collection_on_shards.js55
5 files changed, 116 insertions, 11 deletions
diff --git a/jstests/core/txns/ban_tailable_cursor.js b/jstests/core/txns/ban_tailable_cursor.js
index e228c1b4c60..6751496ac36 100644
--- a/jstests/core/txns/ban_tailable_cursor.js
+++ b/jstests/core/txns/ban_tailable_cursor.js
@@ -1,5 +1,10 @@
// Check that opening a tailable cursor within a transaction is not allowed.
-// @tags: [uses_transactions]
+//
+// This test cannot run on shards because transactions are not allowed to operate on a capped
+// collection on a shard.
+//
+// @tags: [requires_capped, uses_transactions]
+
(function() {
const dbName = 'test';
const collName = 'tailable-cursor-ban';
diff --git a/jstests/core/txns/multi_statement_transaction_write_error.js b/jstests/core/txns/multi_statement_transaction_write_error.js
index d01e8afa351..293d28d93e5 100644
--- a/jstests/core/txns/multi_statement_transaction_write_error.js
+++ b/jstests/core/txns/multi_statement_transaction_write_error.js
@@ -1,7 +1,7 @@
/**
* Test that write errors in transactions are reported in the writeErrors array, except for
* TransientTransactionErrors.
- * @tags: [uses_transactions]
+ * @tags: [requires_capped, uses_transactions]
*/
(function() {
"use strict";
@@ -19,9 +19,6 @@
assert.commandWorked(testDB.createCollection(testColl.getName()));
assert.commandWorked(testDB.createCollection(cappedCollName, {capped: true, size: 1000}));
- assert.commandWorked(testColl.insertOne({_id: 0, x: "string"}));
- assert.commandWorked(cappedColl.insertOne({_id: 0, x: "string"}));
-
// Assert that "cmd" fails with error "code" after "nExpected" operations, or fail with "msg"
function runInTxn({cmd, msg, code, nExpected, expectedErrorIndex}) {
const session = db.getMongo().startSession();
@@ -151,17 +148,20 @@
}
}
+ // Set up a document so we can get a DuplicateKey error trying to insert it again.
+ assert.commandWorked(testColl.insert({_id: 5}));
exerciseWriteInTxn({
- collNames: [testCollName, cappedCollName],
+ collNames: [testCollName],
cmdName: "insert",
goodOp: {},
- badOp: {_id: 0},
+ badOp: {_id: 5},
code: ErrorCodes.DuplicateKey
});
- // The good op updates "string" to "STRING", preserving doc size, required in capped collection
+ // Set up a document with a string field so we can update it but fail to increment it.
+ assert.commandWorked(testColl.insertOne({_id: 0, x: "string"}));
exerciseWriteInTxn({
- collNames: [testCollName, cappedCollName],
+ collNames: [testCollName],
cmdName: "update",
goodOp: {q: {_id: 0}, u: {$set: {x: "STRING"}}},
badOp: {q: {_id: 0}, u: {$inc: {x: 1}}},
@@ -169,7 +169,7 @@
});
// Give the good delete operation some documents to delete
- testColl.insertMany([{}, {}, {}, {}]);
+ assert.commandWorked(testColl.insertMany([{}, {}, {}, {}]));
exerciseWriteInTxn({
collNames: [testCollName],
cmdName: "delete",
diff --git a/jstests/core/txns/prepare_transaction_fails_on_temp_collections.js b/jstests/core/txns/prepare_transaction_fails_on_temp_collections.js
index 3b23266daf9..091665d2509 100644
--- a/jstests/core/txns/prepare_transaction_fails_on_temp_collections.js
+++ b/jstests/core/txns/prepare_transaction_fails_on_temp_collections.js
@@ -4,7 +4,7 @@
* Transactions should not operate on temporary collections because they are for internal use only
* and are deleted on both repl stepup and server startup.
*
- * @tags: [uses_transactions, uses_prepare_transaction, requires_replication]
+ * @tags: [uses_transactions, uses_prepare_transaction]
*/
(function() {
diff --git a/jstests/core/txns/transaction_ops_succeed_against_capped_collection.js b/jstests/core/txns/transaction_ops_succeed_against_capped_collection.js
new file mode 100644
index 00000000000..6f98daabcab
--- /dev/null
+++ b/jstests/core/txns/transaction_ops_succeed_against_capped_collection.js
@@ -0,0 +1,45 @@
+/**
+ * Tests that transaction CRUD operations on a capped collection against a non-shard replica set is
+ * allowed and succeeds.
+ *
+ * 'requires_capped' tagged tests are excluded from sharding txn passthrough suites.
+ * @tags: [requires_capped, uses_transactions]
+ */
+(function() {
+ "use strict";
+
+ const dbName = "test";
+ const cappedCollName = "transaction_ops_succeed_against_capped_collection";
+ const testDB = db.getSiblingDB(dbName);
+ const cappedTestColl = testDB.getCollection(cappedCollName);
+ const testDocument = {"a": "docToTryToUpdateThenDelete"};
+
+ cappedTestColl.drop({writeConcern: {w: "majority"}});
+
+ jsTest.log("Creating a capped collection '" + dbName + "." + cappedCollName + "'.");
+ assert.commandWorked(testDB.createCollection(cappedCollName, {capped: true, size: 500}));
+
+ jsTest.log("Adding a document to the capped collection so that the update op can be tested " +
+ "in the subsequent transaction attempts");
+ assert.commandWorked(cappedTestColl.insert(testDocument));
+
+ jsTest.log("Setting up a transaction in which to execute transaction ops.");
+ const session = db.getMongo().startSession();
+ const sessionDB = session.getDatabase(dbName);
+ const sessionCappedColl = sessionDB.getCollection(cappedCollName);
+ session.startTransaction();
+
+ jsTest.log("Running an insert op in the transaction against a capped collection that should " +
+ "succeed");
+ assert.commandWorked(sessionCappedColl.insert({x: 55}));
+
+ jsTest.log("Running an update op in the transaction against a capped collection that should " +
+ "succeed");
+ assert.commandWorked(
+ sessionCappedColl.update(testDocument, {"a": "docIsGettingUpdatedAndSize"}));
+
+ // Deletes do not work against capped collections so we will not test it in a transaction.
+
+ assert.commandWorked(session.commitTransaction_forTesting());
+ session.endSession();
+})();
diff --git a/jstests/sharding/transaction_ops_fail_against_capped_collection_on_shards.js b/jstests/sharding/transaction_ops_fail_against_capped_collection_on_shards.js
new file mode 100644
index 00000000000..614b7cb7aae
--- /dev/null
+++ b/jstests/sharding/transaction_ops_fail_against_capped_collection_on_shards.js
@@ -0,0 +1,55 @@
+/**
+ * Tests that transaction CRUD operations against a shard on a capped collection fail.
+ *
+ * Capped collection writes take collection X locks and cannot guarantee successful application
+ * across all replica set members (a write could succeed on a primary and fail on one of the
+ * secondaries), so they are not allowed in prepared transactions or transactions on shards more
+ * generally.
+ *
+ * @tags: [uses_transactions, uses_prepare_transaction]
+ */
+(function() {
+ "use strict";
+
+ const st = new ShardingTest({shards: 1});
+
+ const dbName = "test_db";
+ const cappedCollName = "test_capped_coll";
+ const testDB = st.shard0.getDB('test_db');
+
+ jsTest.log("Creating a capped collection '" + dbName + "." + cappedCollName + "'.");
+ assert.commandWorked(testDB.createCollection(cappedCollName, {capped: true, size: 500}));
+
+ jsTest.log("Adding data to the capped collection so that the update op can be tested in " +
+ "the subsequent transaction attempts");
+ const testCappedColl = testDB.getCollection(cappedCollName);
+ const testDocument = {"a": "docToTryToUpdateThenDelete"};
+ assert.writeOK(testCappedColl.insert(testDocument));
+
+ jsTest.log("Setting up a session in which to execute transaction ops.");
+ const session = testDB.getMongo().startSession();
+ const sessionDB = session.getDatabase(dbName);
+ const sessionCappedColl = sessionDB.getCollection(cappedCollName);
+
+ jsTest.log("Starting a transaction for an insert op against a capped collection that should " +
+ "fail");
+ session.startTransaction();
+ assert.commandFailedWithCode(sessionCappedColl.insert({"x": 55}),
+ ErrorCodes.OperationNotSupportedInTransaction);
+ assert.commandFailedWithCode(session.abortTransaction_forTesting(),
+ ErrorCodes.NoSuchTransaction);
+
+ jsTest.log("Starting a transaction for an update op against a capped collection that should " +
+ "fail");
+ session.startTransaction();
+ assert.commandFailedWithCode(sessionCappedColl.update(testDocument, {"a": 1000}),
+ ErrorCodes.OperationNotSupportedInTransaction);
+ assert.commandFailedWithCode(session.abortTransaction_forTesting(),
+ ErrorCodes.NoSuchTransaction);
+
+ // Deletes do not work against capped collections so we will not test it in a transaction.
+
+ session.endSession();
+
+ st.stop();
+})();