diff options
author | Dianna <dianna.hohensee@10gen.com> | 2019-04-10 13:09:52 -0400 |
---|---|---|
committer | Dianna <dianna.hohensee@10gen.com> | 2019-04-17 16:25:03 -0400 |
commit | c539768709f9dbf1cdc59e7dc156c8eab7dad828 (patch) | |
tree | e14f7fd04007bf43f3f0ccd3ba3f82bb3bfada57 /jstests | |
parent | e0cafae280e508ef887bd08978dcbc5630c08a34 (diff) | |
download | mongo-c539768709f9dbf1cdc59e7dc156c8eab7dad828.tar.gz |
SERVER-40321 Transaction CRUD ops on a shard against a capped collection fail
Diffstat (limited to 'jstests')
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(); +})(); |