|
| 1 | +.. role:: javascript(code) |
| 2 | + :language: javascript |
| 3 | + |
| 4 | +======================================== |
| 5 | +Connection Monitoring and Pooling (CMAP) |
| 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 Connection Monitoring and Pooling (CMAP) 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 | +Common Test Format |
| 22 | +================== |
| 23 | + |
| 24 | +Each YAML file has the following keys: |
| 25 | + |
| 26 | +- ``version``: A version number indicating the expected format of the spec tests (current version = 1) |
| 27 | +- ``style``: A string indicating what style of tests this file contains. Currently ``unit`` is the only valid value |
| 28 | +- ``description``: A text description of what the test is meant to assert |
| 29 | + |
| 30 | +Unit Test Format: |
| 31 | +================= |
| 32 | + |
| 33 | +All Unit Tests have some of the following fields: |
| 34 | + |
| 35 | +- ``poolOptions``: if present, connection pool options to use when creating a pool |
| 36 | +- ``operations``: A list of operations to perform. All operations support the following fields: |
| 37 | + |
| 38 | + - ``name``: A string describing which operation to issue. |
| 39 | + - ``thread``: The name of the thread in which to run this operation. If not specified, runs in the default thread |
| 40 | + |
| 41 | +- ``error``: Indicates that the main thread is expected to error during this test. An error may include of the following fields: |
| 42 | + |
| 43 | + - ``type``: the type of error emitted |
| 44 | + - ``message``: the message associated with that error |
| 45 | + - ``address``: Address of pool emitting error |
| 46 | + |
| 47 | +- ``events``: An array of all connection monitoring events expected to occur while running ``operations``. An event may contain any of the following fields |
| 48 | + |
| 49 | + - ``type``: The type of event emitted |
| 50 | + - ``address``: The address of the pool emitting the event |
| 51 | + - ``connectionId``: The id of a connection associated with the event |
| 52 | + - ``options``: Options used to create the pool |
| 53 | + - ``reason``: A reason giving mroe information on why the event was emitted |
| 54 | + |
| 55 | +- ``ignore``: An array of event names to ignore |
| 56 | + |
| 57 | +Valid Unit Test Operations are the following: |
| 58 | + |
| 59 | +- ``start(target)``: Starts a new thread named ``target`` |
| 60 | + |
| 61 | + - ``target``: The name of the new thread to start |
| 62 | + |
| 63 | +- ``wait(ms)``: Sleep the current thread for ``ms`` milliseconds |
| 64 | + |
| 65 | + - ``ms``: The number of milliseconds to sleep the current thread for |
| 66 | + |
| 67 | +- ``waitForThread(target)``: wait for thread ``target`` to finish executing. Propagate any errors to the main thread. |
| 68 | + |
| 69 | + - ``target``: The name of the thread to wait for. |
| 70 | + |
| 71 | +- ``waitForEvent(event, count)``: block the current thread until ``event`` has occurred ``count`` times |
| 72 | + |
| 73 | + - ``event``: The name of the event |
| 74 | + - ``count``: The number of times the event must occur (counting from the start of the test) |
| 75 | + |
| 76 | +- ``label = pool.checkOut()``: call ``checkOut`` on pool, returning the checked out connection |
| 77 | + |
| 78 | + - ``label``: If specified, associate this label with the returned connection, so that it may be referenced in later operations |
| 79 | + |
| 80 | +- ``pool.checkIn(connection)``: call ``checkIn`` on pool |
| 81 | + |
| 82 | + - ``connection``: A string label identifying which connection to check in. Should be a label that was previously set with ``checkOut`` |
| 83 | + |
| 84 | +- ``pool.clear()``: call ``clear`` on Pool |
| 85 | +- ``pool.close()``: call ``close`` on Pool |
| 86 | + |
| 87 | +Spec Test Match Function |
| 88 | +======================== |
| 89 | + |
| 90 | +The definition of MATCH or MATCHES in the Spec Test Runner is as follows: |
| 91 | + |
| 92 | +- MATCH takes two values, ``expected`` and ``actual`` |
| 93 | +- Notation is "Assert [actual] MATCHES [expected] |
| 94 | +- Assertion passes if ``expected`` is a subset of ``actual``, with the values ``42`` and ``"42"`` acting as placeholders for "any value" |
| 95 | + |
| 96 | +Pseudocode implementation of ``actual`` MATCHES ``expected``: |
| 97 | + |
| 98 | +:: |
| 99 | + |
| 100 | + If expected is "42" or 42: |
| 101 | + Assert that actual exists (is not null or undefined) |
| 102 | + Else: |
| 103 | + Assert that actual is of the same JSON type as expected |
| 104 | + If expected is a JSON array: |
| 105 | + For every idx/value in expected: |
| 106 | + Assert that actual[idx] MATCHES value |
| 107 | + Else if expected is a JSON object: |
| 108 | + For every key/value in expected |
| 109 | + Assert that actual[key] MATCHES value |
| 110 | + Else: |
| 111 | + Assert that expected equals actual |
| 112 | + |
| 113 | +Unit Test Runner: |
| 114 | +================= |
| 115 | + |
| 116 | +For the unit tests, the behavior of a Connection is irrelevant beyond the need to asserting ``connection.id``. Drivers MAY use a mock connection class for testing the pool behavior in unit tests |
| 117 | + |
| 118 | +For each YAML file with ``style: unit``: |
| 119 | + |
| 120 | +- Create a Pool ``pool``, subscribe and capture any Connection Monitoring events emitted in order. |
| 121 | + |
| 122 | + - If ``poolOptions`` is specified, use those options to initialize both pools |
| 123 | + - The returned pool must have an ``address`` set as a string value. |
| 124 | + |
| 125 | +- Execute each ``operation`` in ``operations`` |
| 126 | + |
| 127 | + - If a ``thread`` is specified, execute in that corresponding thread. Otherwise, execute in the main thread. |
| 128 | + |
| 129 | +- Wait for the main thread to finish executing all of its operations |
| 130 | +- If ``error`` is presented |
| 131 | + |
| 132 | + - Assert that an actual error ``actualError`` was thrown by the main thread |
| 133 | + - Assert that ``actualError`` MATCHES ``error`` |
| 134 | + |
| 135 | +- Else: |
| 136 | + |
| 137 | + - Assert that no errors were thrown by the main thread |
| 138 | + |
| 139 | +- calculate ``actualEvents`` as every Connection Event emitted whose ``type`` is not in ``ignore`` |
| 140 | +- if ``events`` is not empty, then for every ``idx``/``expectedEvent`` in ``events`` |
| 141 | + |
| 142 | + - Assert that ``actualEvents[idx]`` exists |
| 143 | + - Assert that ``actualEvents[idx]`` MATCHES ``expectedEvent`` |
| 144 | + |
| 145 | + |
| 146 | +It is important to note that the ``ignore`` list is used for calculating ``actualEvents``, but is NOT used for the ``waitForEvent`` command |
| 147 | + |
| 148 | +Prose Tests |
| 149 | +=========== |
| 150 | + |
| 151 | +The following tests have not yet been automated, but MUST still be tested |
| 152 | + |
| 153 | +#. All ConnectionPoolOptions MUST be specified at the MongoClient level |
| 154 | +#. All ConnectionPoolOptions MUST be the same for all pools created by a MongoClient |
| 155 | +#. A user MUST be able to specify all ConnectionPoolOptions via a URI string |
| 156 | +#. A user MUST be able to subscribe to Connection Monitoring Events in a manner idiomatic to their language and driver |
| 157 | +#. When a check out attempt fails because connection set up throws an error, |
| 158 | + assert that a ConnectionCheckOutFailedEvent with reason="connectionError" is emitted. |
0 commit comments