1==================
2Transactions Tests
3==================
4
5.. contents::
6
7----
8
9Introduction
10============
11
12The YAML and JSON files in this directory are platform-independent tests that
13drivers can use to prove their conformance to the Transactions Spec. They are
14designed with the intention of sharing some test-runner code with the CRUD Spec
15tests and the Command Monitoring Spec tests.
16
17Several prose tests, which are not easily expressed in YAML, are also presented
18in this file. Those tests will need to be manually implemented by each driver.
19
20Server Fail Point
21=================
22
23Some tests depend on a server fail point, expressed in the ``failPoint`` field.
24For example the ``failCommand`` fail point allows the client to force the
25server to return an error. Keep in mind that the fail point only triggers for
26commands 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
32The ``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
46value. The string values ``"alwaysOn"`` and ``"off"`` may be used to enable or
47disable 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
55The ``data`` option is a document that may be used to specify options that
56control 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
70Test Format
71===========
72
73Each 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
139Use as integration tests
140========================
141
142Run 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
144server selection in a transaction works properly. Including an arbiter helps
145ensure that no new bugs have been introduced related to arbiters.)
146
147Load each YAML (or JSON) file using a Canonical Extended JSON parser.
148
149Then 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
235Command-Started Events
236``````````````````````
237
238The event listener used for these tests MUST ignore the security commands
239listed in the Command Monitoring Spec.
240
241Logical Session Id
242~~~~~~~~~~~~~~~~~~
243
244Each command-started event in ``expectations`` includes an ``lsid`` with the
245value "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
249Null Values
250~~~~~~~~~~~
251
252Some command-started events in ``expectations`` include ``null`` values for
253fields such as ``txnNumber``, ``autocommit``, and ``writeConcern``.
254Tests MUST assert that the actual command **omits** any field that has a
255``null`` value in the expected command.
256
257Cursor Id
258^^^^^^^^^
259
260A ``getMore`` value of ``"42"`` in a command-started event is a fake cursorId
261that MUST be ignored. (In the Command Monitoring Spec tests, fake cursorIds are
262correlated with real ones, but that is not necessary for Transactions Spec
263tests.)
264
265afterClusterTime
266^^^^^^^^^^^^^^^^
267
268A ``readConcern.afterClusterTime`` value of ``42`` in a command-started event
269is a fake cluster time. Drivers MUST assert that the actual command includes an
270afterClusterTime.
271