From 4c622ffd4730828379efca3b7803d22ff5ff05f3 Mon Sep 17 00:00:00 2001 From: Neil Shweky Date: Thu, 28 Jul 2022 15:35:20 -0400 Subject: [PATCH] RUBY-3063 sync transactions spec tests --- .../do-not-retry-read-in-transaction.yml | 64 ++++++++++ .../retryable-abort-handshake.yml | 118 ++++++++++++++++++ .../retryable-commit-handshake.yml | 118 ++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 spec/spec_tests/data/transactions_unified/do-not-retry-read-in-transaction.yml create mode 100644 spec/spec_tests/data/transactions_unified/retryable-abort-handshake.yml create mode 100644 spec/spec_tests/data/transactions_unified/retryable-commit-handshake.yml diff --git a/spec/spec_tests/data/transactions_unified/do-not-retry-read-in-transaction.yml b/spec/spec_tests/data/transactions_unified/do-not-retry-read-in-transaction.yml new file mode 100644 index 0000000000..e30df0b290 --- /dev/null +++ b/spec/spec_tests/data/transactions_unified/do-not-retry-read-in-transaction.yml @@ -0,0 +1,64 @@ +description: "do not retry read in a transaction" + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "4.0.0" + topologies: [ replicaset ] + - minServerVersion: "4.2.0" + topologies: [ sharded, load-balanced ] + +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: [commandStartedEvent] + uriOptions: { retryReads: true } + - database: + id: &database0 database0 + client: *client0 + databaseName: &databaseName retryable-read-in-transaction-test + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collectionName coll + - session: + id: &session0 session0 + client: *client0 + +tests: + - description: "find does not retry in a transaction" + operations: + + - name: startTransaction + object: *session0 + + - name: failPoint # fail the following find command + object: testRunner + arguments: + client: *client0 + failPoint: + configureFailPoint: failCommand + mode: { times: 1 } + data: + failCommands: [find] + closeConnection: true + + - name: find + object: *collection0 + arguments: + filter: {} + session: *session0 + expectError: + isError: true + errorLabelsContain: ["TransientTransactionError"] + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + find: *collectionName + filter: {} + startTransaction: true + commandName: find + databaseName: *databaseName diff --git a/spec/spec_tests/data/transactions_unified/retryable-abort-handshake.yml b/spec/spec_tests/data/transactions_unified/retryable-abort-handshake.yml new file mode 100644 index 0000000000..d0e9ec86b4 --- /dev/null +++ b/spec/spec_tests/data/transactions_unified/retryable-abort-handshake.yml @@ -0,0 +1,118 @@ +description: "retryable abortTransaction on handshake errors" + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "4.2" + topologies: [replicaset, sharded, load-balanced] + serverless: "forbid" + auth: true + +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: [commandStartedEvent, connectionCheckOutStartedEvent] + - database: + id: &database0 database0 + client: *client0 + databaseName: &databaseName retryable-handshake-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collectionName coll + - session: + # This session will be used to execute the transaction + id: &session0 session0 + client: *client0 + - session: + # This session will be used to create the failPoint, and empty the pool + id: &session1 session1 + client: *client0 + +initialData: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + +tests: + - description: "AbortTransaction succeeds after handshake network error" + skipReason: "DRIVERS-2032: Pinned servers need to be checked if they are still selectable" + operations: + + - name: startTransaction + object: *session0 + + - name: insertOne + object: *collection0 + arguments: + session: *session0 + document: { _id: 2, x: 22 } + + # The following failPoint and ping utilize session1 so that + # the transaction won't be failed by the intentional erroring of ping + # and it will have an empty pool when it goes to run abortTransaction + - name: failPoint # fail the next connection establishment + object: testRunner + arguments: + client: *client0 + session: *session1 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + # use saslContinue here to avoid SDAM errors + # this failPoint itself will create a usable connection in the connection pool + # so we run a ping (with closeConnection: true) in order to discard the connection + # before testing that abortTransaction will fail a handshake but will get retried + failCommands: [saslContinue, ping] + closeConnection: true + + - name: runCommand + object: *database0 + arguments: + commandName: ping + command: { ping: 1 } + session: *session1 + expectError: + isError: true + + - name: abortTransaction + object: *session0 + + expectEvents: + - client: *client0 + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } # startTransaction + - { connectionCheckOutStartedEvent: {} } # insertOne + - { connectionCheckOutStartedEvent: {} } # failPoint + - { connectionCheckOutStartedEvent: {} } # abortTransaction + - { connectionCheckOutStartedEvent: {} } # abortTransaction retry + - client: *client0 + events: + - commandStartedEvent: + command: + insert: *collectionName + documents: [{ _id: 2, x: 22 }] + startTransaction: true + commandName: insert + databaseName: *databaseName + - commandStartedEvent: + command: + ping: 1 + databaseName: *databaseName + - commandStartedEvent: + command: + abortTransaction: 1 + lsid: + $$sessionLsid: *session0 + commandName: abortTransaction + databaseName: admin + + outcome: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } diff --git a/spec/spec_tests/data/transactions_unified/retryable-commit-handshake.yml b/spec/spec_tests/data/transactions_unified/retryable-commit-handshake.yml new file mode 100644 index 0000000000..e9904fdf51 --- /dev/null +++ b/spec/spec_tests/data/transactions_unified/retryable-commit-handshake.yml @@ -0,0 +1,118 @@ +description: "retryable commitTransaction on handshake errors" + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "4.2" + topologies: [replicaset, sharded, load-balanced] + serverless: "forbid" + auth: true + +createEntities: + - client: + id: &client0 client0 + useMultipleMongoses: false + observeEvents: [commandStartedEvent, connectionCheckOutStartedEvent] + uriOptions: { retryWrites: false } # commitTransaction is retryable regardless of this option being set + - database: + id: &database0 database0 + client: *client0 + databaseName: &databaseName retryable-handshake-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collectionName coll + - session: + id: &session0 session0 + client: *client0 + - session: + id: &session1 session1 + client: *client0 + +initialData: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + +tests: + - description: "CommitTransaction succeeds after handshake network error" + skipReason: "DRIVERS-2032: Pinned servers need to be checked if they are still selectable" + operations: + + - name: startTransaction + object: *session0 + + - name: insertOne + object: *collection0 + arguments: + session: *session0 + document: { _id: 2, x: 22 } + + # The following failPoint and ping utilize session1 so that + # the transaction won't be failed by the intentional erroring of ping + # and it will have an empty pool when it goes to run commitTransaction + - name: failPoint # fail the next connection establishment + object: testRunner + arguments: + client: *client0 + session: *session1 + failPoint: + configureFailPoint: failCommand + mode: { times: 2 } + data: + # use saslContinue here to avoid SDAM errors + # this failPoint itself will create a usable connection in the connection pool + # so we run a ping (that also fails) in order to discard the connection + # before testing that commitTransaction gets retried + failCommands: [saslContinue, ping] + closeConnection: true + + - name: runCommand + object: *database0 + arguments: + commandName: ping + command: { ping: 1 } + session: *session1 + expectError: + isError: true + + - name: commitTransaction + object: *session0 + + expectEvents: + - client: *client0 + eventType: cmap + events: + - { connectionCheckOutStartedEvent: {} } # startTransaction + - { connectionCheckOutStartedEvent: {} } # insertOne + - { connectionCheckOutStartedEvent: {} } # failPoint + - { connectionCheckOutStartedEvent: {} } # commitTransaction + - { connectionCheckOutStartedEvent: {} } # commitTransaction retry + - client: *client0 + events: + - commandStartedEvent: + command: + insert: *collectionName + documents: [{ _id: 2, x: 22 }] + startTransaction: true + commandName: insert + databaseName: *databaseName + - commandStartedEvent: + command: + ping: 1 + databaseName: *databaseName + - commandStartedEvent: + command: + commitTransaction: 1 + lsid: + $$sessionLsid: *session0 + commandName: commitTransaction + databaseName: admin + + outcome: + - collectionName: *collectionName + databaseName: *databaseName + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } # The write was still applied