Skip to content

Commit f45a522

Browse files
author
iwysiu
committed
Resync ChangeStream spec tests
GODRIVER-512 GODRIVER-745 Change-Id: Ib66d424c3ff1ce62597a10b3c28e6b955ff53ffb
1 parent a3b6cf4 commit f45a522

File tree

7 files changed

+1233
-14
lines changed

7 files changed

+1233
-14
lines changed

data/change-streams/README.rst

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
.. role:: javascript(code)
2+
:language: javascript
3+
4+
==============
5+
Change Streams
6+
==============
7+
8+
.. contents::
9+
10+
--------
11+
12+
Introduction
13+
============
14+
15+
The YAML and JSON files in this directory are platform-independent tests that
16+
drivers can use to prove their conformance to the Change Streams Spec.
17+
18+
Several prose tests, which are not easily expressed in YAML, are also presented
19+
in this file. Those tests will need to be manually implemented by each driver.
20+
21+
Spec Test Format
22+
================
23+
24+
Each YAML file has the following keys:
25+
26+
- ``database_name``: The default database
27+
- ``collection_name``: The default collection
28+
- ``database2_name``: Another database
29+
- ``collection2_name``: Another collection
30+
- ``tests``: An array of tests that are to be run independently of each other.
31+
Each test will have some of the following fields:
32+
33+
- ``description``: The name of the test.
34+
- ``minServerVersion``: The minimum server version to run this test against. If not present, assume there is no minimum server version.
35+
- ``maxServerVersion``: Reserved for later use
36+
- ``failPoint``(optional): The configureFailPoint command document to run to configure a fail point on the primary server.
37+
- ``target``: The entity on which to run the change stream. Valid values are:
38+
39+
- ``collection``: Watch changes on collection ``database_name.collection_name``
40+
- ``database``: Watch changes on database ``database_name``
41+
- ``client``: Watch changes on entire clusters
42+
- ``topology``: An array of server topologies against which to run the test.
43+
Valid topologies are ``single``, ``replicaset``, and ``sharded``.
44+
- ``changeStreamPipeline``: An array of additional aggregation pipeline stages to add to the change stream
45+
- ``changeStreamOptions``: Additional options to add to the changeStream
46+
- ``operations``: Array of documents, each describing an operation. Each document has the following fields:
47+
48+
- ``database``: Database against which to run the operation
49+
- ``collection``: Collection against which to run the operation
50+
- ``name``: Name of the command to run
51+
- ``arguments`` (optional): Object of arguments for the command (ex: document to insert)
52+
53+
- ``expectations``: Optional list of command-started events in Extended JSON format
54+
- ``result``: Document with ONE of the following fields:
55+
56+
- ``error``: Describes an error received during the test
57+
- ``success``: An Extended JSON array of documents expected to be received from the changeStream
58+
59+
Spec Test Match Function
60+
========================
61+
62+
The definition of MATCH or MATCHES in the Spec Test Runner is as follows:
63+
64+
- MATCH takes two values, ``expected`` and ``actual``
65+
- Notation is "Assert [actual] MATCHES [expected]
66+
- Assertion passes if ``expected`` is a subset of ``actual``, with the values ``42`` and ``"42"`` acting as placeholders for "any value"
67+
68+
Pseudocode implementation of ``actual`` MATCHES ``expected``:
69+
70+
::
71+
72+
If expected is "42" or 42:
73+
Assert that actual exists (is not null or undefined)
74+
Else:
75+
Assert that actual is of the same JSON type as expected
76+
If expected is a JSON array:
77+
For every idx/value in expected:
78+
Assert that actual[idx] MATCHES value
79+
Else if expected is a JSON object:
80+
For every key/value in expected
81+
Assert that actual[key] MATCHES value
82+
Else:
83+
Assert that expected equals actual
84+
85+
The expected values for ``result.success`` and ``expectations`` are written in Extended JSON. Drivers may adopt any of the following approaches to comparisons, as long as they are consistent:
86+
87+
- Convert ``actual`` to Extended JSON and compare to ``expected``
88+
- Convert ``expected`` and ``actual`` to BSON, and compare them
89+
- Convert ``expected`` and ``actual`` to native equivalents of JSON, and compare them
90+
91+
Spec Test Runner
92+
================
93+
94+
Before running the tests
95+
96+
- Create a MongoClient ``globalClient``, and connect to the server
97+
98+
For each YAML file, for each element in ``tests``:
99+
100+
- If ``topology`` does not include the topology of the server instance(s), skip this test.
101+
- Use ``globalClient`` to
102+
103+
- Drop the database ``database_name``
104+
- Drop the database ``database2_name``
105+
- Create the database ``database_name`` and the collection ``database_name.collection_name``
106+
- Create the database ``database2_name`` and the collection ``database2_name.collection2_name``
107+
- If the the ``failPoint`` field is present, configure the fail point on the primary server. See
108+
`Server Fail Point <../../transactions/tests#server-fail-point>`_ in the
109+
Transactions spec test documentation for more information.
110+
111+
- Create a new MongoClient ``client``
112+
- Begin monitoring all APM events for ``client``. (If the driver uses global listeners, filter out all events that do not originate with ``client``). Filter out any "internal" commands (e.g. ``isMaster``)
113+
- Using ``client``, create a changeStream ``changeStream`` against the specified ``target``. Use ``changeStreamPipeline`` and ``changeStreamOptions`` if they are non-empty
114+
- Using ``globalClient``, run every operation in ``operations`` in serial against the server
115+
- Wait until either:
116+
117+
- An error occurs
118+
- All operations have been successful AND the changeStream has received as many changes as there are in ``result.success``
119+
120+
- Close ``changeStream``
121+
- If there was an error:
122+
123+
- Assert that an error was expected for the test.
124+
- Assert that the error MATCHES ``result.error``
125+
126+
- Else:
127+
128+
- Assert that no error was expected for the test
129+
- Assert that the changes received from ``changeStream`` MATCH the results in ``result.success``
130+
131+
- If there are any ``expectations``
132+
133+
- For each (``expected``, ``idx``) in ``expectations``
134+
135+
- Assert that ``actual[idx]`` MATCHES ``expected``
136+
137+
- Close the MongoClient ``client``
138+
139+
After running all tests
140+
141+
- Close the MongoClient ``globalClient``
142+
- Drop database ``database_name``
143+
- Drop database ``database2_name``
144+
145+
146+
Prose Tests
147+
===========
148+
149+
The following tests have not yet been automated, but MUST still be tested
150+
151+
#. ``ChangeStream`` must continuously track the last seen ``resumeToken``
152+
#. ``ChangeStream`` will throw an exception if the server response is missing the resume token (if wire version is < 8, this is a driver-side error; for 8+, this is a server-side error)
153+
#. ``ChangeStream`` will automatically resume one time on a resumable error (including `not master`) with the initial pipeline and options, except for the addition/update of a ``resumeToken``.
154+
#. ``ChangeStream`` will not attempt to resume on any error encountered while executing an ``aggregate`` command.
155+
#. ``ChangeStream`` will not attempt to resume after encountering error code 11601 (Interrupted), 136 (CappedPositionLost), or 237 (CursorKilled) while executing a ``getMore`` command.
156+
#. ``ChangeStream`` will perform server selection before attempting to resume, using initial ``readPreference``
157+
#. Ensure that a cursor returned from an aggregate command with a cursor id and an initial empty batch is not closed on the driver side.
158+
#. The ``killCursors`` command sent during the "Resume Process" must not be allowed to throw an exception.
159+
#. ``$changeStream`` stage for ``ChangeStream`` against a server ``>=4.0`` and ``<4.0.7`` that has not received any results yet MUST include a ``startAtOperationTime`` option when resuming a changestream.
160+
#. ``ChangeStream`` will resume after a ``killCursors`` command is issued for its child cursor.
161+
#. - For a ``ChangeStream`` under these conditions:
162+
- Running against a server ``>=4.0.7``.
163+
- The batch is empty or has been iterated to the last document.
164+
- Expected result:
165+
- ``getResumeToken`` must return the ``postBatchResumeToken`` from the current command response.
166+
#. - For a ``ChangeStream`` under these conditions:
167+
- Running against a server ``<4.0.7``.
168+
- The batch is empty or has been iterated to the last document.
169+
- Expected result:
170+
- ``getResumeToken`` must return the ``_id`` of the last document returned if one exists.
171+
- ``getResumeToken`` must return ``startAfter`` from the initial aggregate if the option was specified.
172+
- ``getResumeToken`` must return ``resumeAfter`` from the initial aggregate if the option was specified.
173+
- If neither the ``startAfter`` nor ``resumeAfter`` options were specified, the ``getResumeToken`` result must be empty.
174+
#. - For a ``ChangeStream`` under these conditions:
175+
- The batch is not empty.
176+
- The batch has been iterated up to but not including the last element.
177+
- Expected result:
178+
- ``getResumeToken`` must return the ``_id`` of the previous document returned.
179+
#. - For a ``ChangeStream`` under these conditions:
180+
- The batch is not empty.
181+
- The batch hasn’t been iterated at all.
182+
- Only the initial ``aggregate`` command has been executed.
183+
- Expected result:
184+
- ``getResumeToken`` must return ``startAfter`` from the initial aggregate if the option was specified.
185+
- ``getResumeToken`` must return ``resumeAfter`` from the initial aggregate if the option was specified.
186+
- If neither the ``startAfter`` nor ``resumeAfter`` options were specified, the ``getResumeToken`` result must be empty.
187+
#. - For a ``ChangeStream`` under these conditions:
188+
- Running against a server ``>=4.0.7``.
189+
- The batch is not empty.
190+
- The batch hasn’t been iterated at all.
191+
- The stream has iterated beyond a previous batch and a ``getMore`` command has just been executed.
192+
- Expected result:
193+
- ``getResumeToken`` must return the ``postBatchResumeToken`` from the previous command response.
194+
#. - For a ``ChangeStream`` under these conditions:
195+
- Running against a server ``<4.0.7``.
196+
- The batch is not empty.
197+
- The batch hasn’t been iterated at all.
198+
- The stream has iterated beyond a previous batch and a ``getMore`` command has just been executed.
199+
- Expected result:
200+
- ``getResumeToken`` must return the ``_id`` of the previous document returned if one exists.
201+
- ``getResumeToken`` must return ``startAfter`` from the initial aggregate if the option was specified.
202+
- ``getResumeToken`` must return ``resumeAfter`` from the initial aggregate if the option was specified.
203+
- If neither the ``startAfter`` nor ``resumeAfter`` options were specified, the ``getResumeToken`` result must be empty.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
collection_name: &collection_name "test"
2+
database_name: &database_name "change-stream-tests"
3+
collection2_name: &collection2_name "test2"
4+
database2_name: &database2_name "change-stream-tests-2"
5+
tests:
6+
-
7+
description: The watch helper must not throw a custom exception when executed against a single server topology, but instead depend on a server error
8+
minServerVersion: "3.6.0"
9+
target: collection
10+
topology:
11+
- single
12+
changeStreamPipeline: []
13+
changeStreamOptions: {}
14+
operations: []
15+
expectations: []
16+
result:
17+
error:
18+
code: 40573
19+
-
20+
description: Change Stream should error when an invalid aggregation stage is passed in
21+
minServerVersion: "3.6.0"
22+
target: collection
23+
topology:
24+
- replicaset
25+
changeStreamPipeline:
26+
-
27+
$unsupported: foo
28+
changeStreamOptions: {}
29+
operations:
30+
-
31+
database: *database_name
32+
collection: *collection_name
33+
name: insertOne
34+
arguments:
35+
document:
36+
z: 3
37+
expectations:
38+
-
39+
command_started_event:
40+
command:
41+
aggregate: *collection_name
42+
cursor: {}
43+
pipeline:
44+
-
45+
$changeStream:
46+
fullDocument: default
47+
-
48+
$unsupported: foo
49+
command_name: aggregate
50+
database_name: *database_name
51+
result:
52+
error:
53+
code: 40324
54+
-
55+
description: Change Stream should error when _id is projected out
56+
minServerVersion: "4.1.11"
57+
target: collection
58+
topology:
59+
- replicaset
60+
- sharded
61+
changeStreamPipeline:
62+
-
63+
$project: { _id: 0 }
64+
changeStreamOptions: {}
65+
operations:
66+
-
67+
database: *database_name
68+
collection: *collection_name
69+
name: insertOne
70+
arguments:
71+
document:
72+
z: 3
73+
result:
74+
error:
75+
code: 280
76+
errorLabels: [ "NonResumableChangeStreamError" ]

0 commit comments

Comments
 (0)