|
| 1 | +================== |
| 2 | +Transactions Tests |
| 3 | +================== |
| 4 | + |
| 5 | +.. contents:: |
| 6 | + |
| 7 | +---- |
| 8 | + |
| 9 | +Introduction |
| 10 | +============ |
| 11 | + |
| 12 | +The YAML and JSON files in this directory are platform-independent tests that |
| 13 | +drivers can use to prove their conformance to the Transactions Spec. They are |
| 14 | +designed with the intention of sharing some test-runner code with the CRUD Spec |
| 15 | +tests and the Command Monitoring Spec tests. |
| 16 | + |
| 17 | +Several prose tests, which are not easily expressed in YAML, are also presented |
| 18 | +in this file. Those tests will need to be manually implemented by each driver. |
| 19 | + |
| 20 | +Server Fail Point |
| 21 | +================= |
| 22 | + |
| 23 | +Some tests depend on a server fail point, expressed in the ``failPoint`` field. |
| 24 | +For example the ``failCommand`` fail point allows the client to force the |
| 25 | +server to return an error. Keep in mind that the fail point only triggers for |
| 26 | +commands listed in the "failCommands" field. See `SERVER-35004`_ and |
| 27 | +`SERVER-35083`_ for more information. |
| 28 | + |
| 29 | +.. _SERVER-35004: https://jira.mongodb.org/browse/SERVER-35004 |
| 30 | +.. _SERVER-35083: https://jira.mongodb.org/browse/SERVER-35083 |
| 31 | + |
| 32 | +The ``failCommand`` fail point may be configured like so:: |
| 33 | + |
| 34 | + db.adminCommand({ |
| 35 | + configureFailPoint: "failCommand", |
| 36 | + mode: <string|document>, |
| 37 | + data: { |
| 38 | + failCommands: ["commandName", "commandName2"], |
| 39 | + closeConnection: <true|false>, |
| 40 | + errorCode: <Number>, |
| 41 | + writeConcernError: <document> |
| 42 | + } |
| 43 | + }); |
| 44 | + |
| 45 | +``mode`` is a generic fail point option and may be assigned a string or document |
| 46 | +value. The string values ``"alwaysOn"`` and ``"off"`` may be used to enable or |
| 47 | +disable the fail point, respectively. A document may be used to specify either |
| 48 | +``times`` or ``skip``, which are mutually exclusive: |
| 49 | + |
| 50 | +- ``{ times: <integer> }`` may be used to limit the number of times the fail |
| 51 | + point may trigger before transitioning to ``"off"``. |
| 52 | +- ``{ skip: <integer> }`` may be used to defer the first trigger of a fail |
| 53 | + point, after which it will transition to ``"alwaysOn"``. |
| 54 | + |
| 55 | +The ``data`` option is a document that may be used to specify options that |
| 56 | +control the fail point's behavior. ``failCommand`` supports the following |
| 57 | +``data`` options, which may be combined if desired: |
| 58 | + |
| 59 | +- ``failCommands``: Required, the list of command names to fail. |
| 60 | +- ``closeConnection``: Boolean option, which defaults to ``false``. If |
| 61 | + ``true``, the connection on which the command is executed will be closed |
| 62 | + and the client will see a network error. |
| 63 | +- ``errorCode``: Integer option, which is unset by default. If set, the |
| 64 | + specified command error code will be returned as a command error. |
| 65 | +- ``writeConcernError``: A document, which is unset by default. If set, the |
| 66 | + server will return this document in the "writeConcernError" field. This |
| 67 | + failure response only applies to commands that support write concern and |
| 68 | + happens *after* the command finishes (regardless of success or failure). |
| 69 | + |
| 70 | +Test Format |
| 71 | +=========== |
| 72 | + |
| 73 | +Each YAML file has the following keys: |
| 74 | + |
| 75 | +- ``database_name`` and ``collection_name``: The database and collection to use |
| 76 | + for testing. |
| 77 | + |
| 78 | +- ``data``: The data that should exist in the collection under test before each |
| 79 | + test run. |
| 80 | + |
| 81 | +- ``tests``: An array of tests that are to be run independently of each other. |
| 82 | + Each test will have some or all of the following fields: |
| 83 | + |
| 84 | + - ``description``: The name of the test. |
| 85 | + |
| 86 | + - ``clientOptions``: Optional, parameters to pass to MongoClient(). |
| 87 | + |
| 88 | + - ``failPoint``: Optional, a server failpoint to enable expressed as the |
| 89 | + configureFailPoint command to run on the admin database. |
| 90 | + |
| 91 | + - ``sessionOptions``: Optional, parameters to pass to |
| 92 | + MongoClient.startSession(). |
| 93 | + |
| 94 | + - ``operations``: Array of documents, each describing an operation to be |
| 95 | + executed. Each document has the following fields: |
| 96 | + |
| 97 | + - ``name``: The name of the operation on ``object``. |
| 98 | + |
| 99 | + - ``object``: The name of the object to perform the operation on. Can be |
| 100 | + "database", "collection", "session0", or "session1". |
| 101 | + |
| 102 | + - ``collectionOptions``: Optional, parameters to pass to the Collection() |
| 103 | + used for this operation. |
| 104 | + |
| 105 | + - ``command_name``: Present only when ``name`` is "runCommand". The name |
| 106 | + of the command to run. Required for languages that are unable preserve |
| 107 | + the order keys in the "command" argument when parsing JSON/YAML. |
| 108 | + |
| 109 | + - ``arguments``: Optional, the names and values of arguments. |
| 110 | + |
| 111 | + - ``result``: The return value from the operation, if any. This field may |
| 112 | + be a single document or an array of documents in the case of a |
| 113 | + multi-document read. If the operation is expected to return an error, the |
| 114 | + ``result`` is a single document that has one or more of the following |
| 115 | + fields: |
| 116 | + |
| 117 | + - ``errorContains``: A substring of the expected error message. |
| 118 | + |
| 119 | + - ``errorCodeName``: The expected "codeName" field in the server |
| 120 | + error response. |
| 121 | + |
| 122 | + - ``errorLabelsContain``: A list of error label strings that the |
| 123 | + error is expected to have. |
| 124 | + |
| 125 | + - ``errorLabelsOmit``: A list of error label strings that the |
| 126 | + error is expected not to have. |
| 127 | + |
| 128 | + - ``expectations``: Optional list of command-started events. |
| 129 | + |
| 130 | + - ``outcome``: Document describing the return value and/or expected state of |
| 131 | + the collection after the operation is executed. Contains the following |
| 132 | + fields: |
| 133 | + |
| 134 | + - ``collection``: |
| 135 | + |
| 136 | + - ``data``: The data that should exist in the collection after the |
| 137 | + operations have run. |
| 138 | + |
| 139 | +Use as integration tests |
| 140 | +======================== |
| 141 | + |
| 142 | +Run a MongoDB replica set with a primary, a secondary, and an arbiter, |
| 143 | +**server version 4.0.0-rc4 or later**. (Including a secondary ensures that |
| 144 | +server selection in a transaction works properly. Including an arbiter helps |
| 145 | +ensure that no new bugs have been introduced related to arbiters.) |
| 146 | + |
| 147 | +Load each YAML (or JSON) file using a Canonical Extended JSON parser. |
| 148 | + |
| 149 | +Then for each element in ``tests``: |
| 150 | + |
| 151 | +#. Create a MongoClient and call |
| 152 | + ``client.admin.runCommand({killAllSessions: []})`` to clean up any open |
| 153 | + transactions from previous test failures. The command will fail with message |
| 154 | + "operation was interrupted", because it kills its own implicit session. Catch |
| 155 | + the exception and continue. |
| 156 | +#. Create a collection object from the MongoClient, using the ``database_name`` |
| 157 | + and ``collection_name`` fields of the YAML file. |
| 158 | +#. Drop the test collection, using writeConcern "majority". |
| 159 | +#. Execute the "create" command to recreate the collection, using writeConcern |
| 160 | + "majority". (Creating the collection inside a transaction is prohibited, so |
| 161 | + create it explicitly.) |
| 162 | +#. If the YAML file contains a ``data`` array, insert the documents in ``data`` |
| 163 | + into the test collection, using writeConcern "majority". |
| 164 | +#. If ``failPoint`` is specified, its value is a configureFailPoint command. |
| 165 | + Run the command on the admin database to enable the fail point. |
| 166 | +#. Create a **new** MongoClient ``client``, with Command Monitoring listeners |
| 167 | + enabled. (Using a new MongoClient for each test ensures a fresh session pool |
| 168 | + that hasn't executed any transactions previously, so the tests can assert |
| 169 | + actual txnNumbers, starting from 1.) Pass this test's ``clientOptions`` if |
| 170 | + present. |
| 171 | +#. Call ``client.startSession`` twice to create ClientSession objects |
| 172 | + ``session0`` and ``session1``, using the test's "sessionOptions" if they |
| 173 | + are present. Save their lsids so they are available after calling |
| 174 | + ``endSession``, see `Logical Session Id`. |
| 175 | +#. For each element in ``operations``: |
| 176 | + |
| 177 | + - Enter a "try" block or your programming language's closest equivalent. |
| 178 | + - Create a Database object from the MongoClient, using the ``database_name`` |
| 179 | + field at the top level of the test file. |
| 180 | + - Create a Collection object from the Database, using the |
| 181 | + ``collection_name`` field at the top level of the test file. |
| 182 | + If ``collectionOptions`` is present create the Collection object with the |
| 183 | + provided options. Otherwise create the object with the default options. |
| 184 | + - Execute the named method on the provided ``object``, passing the |
| 185 | + arguments listed. Pass ``session0`` or ``session1`` to the method, |
| 186 | + depending on which session's name is in the arguments list. |
| 187 | + If ``arguments`` contains no "session", pass no explicit session to the |
| 188 | + method. |
| 189 | + - If the driver throws an exception / returns an error while executing this |
| 190 | + series of operations, store the error message and server error code. |
| 191 | + - If the result document has an "errorContains" field, verify that the |
| 192 | + method threw an exception or returned an error, and that the value of the |
| 193 | + "errorContains" field matches the error string. "errorContains" is a |
| 194 | + substring (case-insensitive) of the actual error message. |
| 195 | + |
| 196 | + If the result document has an "errorCodeName" field, verify that the |
| 197 | + method threw a command failed exception or returned an error, and that |
| 198 | + the value of the "errorCodeName" field matches the "codeName" in the |
| 199 | + server error response. |
| 200 | + |
| 201 | + If the result document has an "errorLabelsContain" field, verify that the |
| 202 | + method threw an exception or returned an error. Verify that all of the |
| 203 | + error labels in "errorLabelsContain" are present in the error or exception |
| 204 | + using the ``hasErrorLabel`` method. |
| 205 | + |
| 206 | + If the result document has an "errorLabelsOmit" field, verify that the |
| 207 | + method threw an exception or returned an error. Verify that none of the |
| 208 | + error labels in "errorLabelsOmit" are present in the error or exception |
| 209 | + using the ``hasErrorLabel`` method. |
| 210 | + - If the operation returns a raw command response, eg from ``runCommand``, |
| 211 | + then compare only the fields present in the expected result document. |
| 212 | + Otherwise, compare the method's return value to ``result`` using the same |
| 213 | + logic as the CRUD Spec Tests runner. |
| 214 | + |
| 215 | +#. Call ``session0.endSession()`` and ``session1.endSession``. |
| 216 | +#. If the test includes a list of command-started events in ``expectations``, |
| 217 | + compare them to the actual command-started events using the |
| 218 | + same logic as the Command Monitoring Spec Tests runner, plus the rules in |
| 219 | + the Command-Started Events instructions below. |
| 220 | +#. If ``failPoint`` is specified, disable the fail point to avoid spurious |
| 221 | + failures in subsequent tests. The fail point may be disabled like so:: |
| 222 | + |
| 223 | + db.adminCommand({ |
| 224 | + configureFailPoint: <fail point name>, |
| 225 | + mode: "off" |
| 226 | + }); |
| 227 | + |
| 228 | +#. For each element in ``outcome``: |
| 229 | + |
| 230 | + - If ``name`` is "collection", verify that the test collection contains |
| 231 | + exactly the documents in the ``data`` array. Ensure this find uses |
| 232 | + Primary read preference even when the MongoClient is configured with |
| 233 | + another read preference. |
| 234 | + |
| 235 | +Command-Started Events |
| 236 | +`````````````````````` |
| 237 | + |
| 238 | +The event listener used for these tests MUST ignore the security commands |
| 239 | +listed in the Command Monitoring Spec. |
| 240 | + |
| 241 | +Logical Session Id |
| 242 | +~~~~~~~~~~~~~~~~~~ |
| 243 | + |
| 244 | +Each command-started event in ``expectations`` includes an ``lsid`` with the |
| 245 | +value "session0" or "session1". Tests MUST assert that the command's actual |
| 246 | +``lsid`` matches the id of the correct ClientSession named ``session0`` or |
| 247 | +``session1``. |
| 248 | + |
| 249 | +Null Values |
| 250 | +~~~~~~~~~~~ |
| 251 | + |
| 252 | +Some command-started events in ``expectations`` include ``null`` values for |
| 253 | +fields such as ``txnNumber``, ``autocommit``, and ``writeConcern``. |
| 254 | +Tests MUST assert that the actual command **omits** any field that has a |
| 255 | +``null`` value in the expected command. |
| 256 | + |
| 257 | +Cursor Id |
| 258 | +^^^^^^^^^ |
| 259 | + |
| 260 | +A ``getMore`` value of ``"42"`` in a command-started event is a fake cursorId |
| 261 | +that MUST be ignored. (In the Command Monitoring Spec tests, fake cursorIds are |
| 262 | +correlated with real ones, but that is not necessary for Transactions Spec |
| 263 | +tests.) |
| 264 | + |
| 265 | +afterClusterTime |
| 266 | +^^^^^^^^^^^^^^^^ |
| 267 | + |
| 268 | +A ``readConcern.afterClusterTime`` value of ``42`` in a command-started event |
| 269 | +is a fake cluster time. Drivers MUST assert that the actual command includes an |
| 270 | +afterClusterTime. |
0 commit comments