Skip to content

Commit 6e633c2

Browse files
committed
PHPLIB-496: Test collection and index creation in multi-doc transactions
1 parent 10434c6 commit 6e633c2

File tree

4 files changed

+526
-1
lines changed

4 files changed

+526
-1
lines changed

tests/SpecTests/CommandExpectations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public static function fromTransactions(array $expectedEvents)
130130
* configureFailPoint needs to be ignored as the targetedFailPoint
131131
* operation will be caught by command monitoring and is also not
132132
* present in the expected commands in spec tests. */
133-
$o->ignoredCommandNames = ['buildInfo', 'getParameter', 'configureFailPoint'];
133+
$o->ignoredCommandNames = ['buildInfo', 'getParameter', 'configureFailPoint', 'listCollections', 'listIndexes'];
134134

135135
return $o;
136136
}

tests/SpecTests/Operation.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
use MongoDB\Driver\Session;
1414
use MongoDB\Driver\WriteConcern;
1515
use MongoDB\GridFS\Bucket;
16+
use MongoDB\Model\CollectionInfo;
17+
use MongoDB\Model\IndexInfo;
1618
use MongoDB\Operation\FindOneAndReplace;
1719
use MongoDB\Operation\FindOneAndUpdate;
1820
use stdClass;
1921
use function array_diff_key;
2022
use function array_map;
2123
use function fclose;
2224
use function fopen;
25+
use function iterator_to_array;
2326
use function MongoDB\is_last_pipeline_operator_write;
2427
use function MongoDB\with_transaction;
2528
use function stream_get_contents;
@@ -359,6 +362,11 @@ private function executeForCollection(Collection $collection, Context $context)
359362
array_map([$this, 'prepareBulkWriteRequest'], $args['requests']),
360363
$options
361364
);
365+
case 'createIndex':
366+
return $collection->createIndex(
367+
$args['keys'],
368+
array_diff_key($args, ['keys' => 1])
369+
);
362370
case 'count':
363371
case 'countDocuments':
364372
case 'find':
@@ -466,6 +474,16 @@ private function executeForDatabase(Database $database, Context $context)
466474
$args['pipeline'],
467475
array_diff_key($args, ['pipeline' => 1])
468476
);
477+
case 'createCollection':
478+
return $database->createCollection(
479+
$args['collection'],
480+
array_diff_key($args, ['collection' => 1])
481+
);
482+
case 'dropCollection':
483+
return $database->dropCollection(
484+
$args['collection'],
485+
array_diff_key($args, ['collection' => 1])
486+
);
469487
case 'listCollections':
470488
return $database->listCollections($args);
471489
case 'runCommand':
@@ -570,6 +588,36 @@ private function executeForTestRunner(FunctionalTestCase $test, Context $context
570588
$context->replaceArgumentSessionPlaceholder($args);
571589

572590
switch ($this->name) {
591+
case 'assertCollectionExists':
592+
$databaseName = $args['database'];
593+
$collectionName = $args['collection'];
594+
595+
$test->assertContains($collectionName, $this->getCollectionNames($context, $databaseName));
596+
597+
return null;
598+
case 'assertCollectionNotExists':
599+
$databaseName = $args['database'];
600+
$collectionName = $args['collection'];
601+
602+
$test->assertNotContains($collectionName, $this->getCollectionNames($context, $databaseName));
603+
604+
return null;
605+
case 'assertIndexExists':
606+
$databaseName = $args['database'];
607+
$collectionName = $args['collection'];
608+
$indexName = $args['index'];
609+
610+
$test->assertContains($indexName, $this->getIndexNames($context, $databaseName, $collectionName));
611+
612+
return null;
613+
case 'assertIndexNotExists':
614+
$databaseName = $args['database'];
615+
$collectionName = $args['collection'];
616+
$indexName = $args['index'];
617+
618+
$test->assertNotContains($indexName, $this->getIndexNames($context, $databaseName, $collectionName));
619+
620+
return null;
573621
case 'assertSessionPinned':
574622
$test->assertInstanceOf(Session::class, $args['session']);
575623
$test->assertInstanceOf(Server::class, $args['session']->getServer());
@@ -599,6 +647,37 @@ private function executeForTestRunner(FunctionalTestCase $test, Context $context
599647
}
600648
}
601649

650+
/**
651+
* @param string $databaseName
652+
*
653+
* @return array
654+
*/
655+
private function getCollectionNames(Context $context, $databaseName)
656+
{
657+
return array_map(
658+
function (CollectionInfo $collectionInfo) {
659+
return $collectionInfo->getName();
660+
},
661+
iterator_to_array($context->selectDatabase($databaseName)->listCollections())
662+
);
663+
}
664+
665+
/**
666+
* @param string $databaseName
667+
* @param string $collectionName
668+
*
669+
* @return array
670+
*/
671+
private function getIndexNames(Context $context, $databaseName, $collectionName)
672+
{
673+
return array_map(
674+
function (IndexInfo $indexInfo) {
675+
return $indexInfo->getName();
676+
},
677+
iterator_to_array($context->selectCollection($databaseName, $collectionName)->listIndexes())
678+
);
679+
}
680+
602681
/**
603682
* @throws LogicException if the operation object is unsupported
604683
*/
@@ -657,6 +736,9 @@ private function getResultAssertionTypeForCollection()
657736
return ResultExpectation::ASSERT_BULKWRITE;
658737
case 'count':
659738
case 'countDocuments':
739+
return ResultExpectation::ASSERT_SAME;
740+
case 'createIndex':
741+
return ResultExpectation::ASSERT_MATCHES_DOCUMENT;
660742
case 'distinct':
661743
case 'estimatedDocumentCount':
662744
return ResultExpectation::ASSERT_SAME;
@@ -700,6 +782,8 @@ private function getResultAssertionTypeForDatabase()
700782
case 'aggregate':
701783
case 'listCollections':
702784
return ResultExpectation::ASSERT_SAME_DOCUMENTS;
785+
case 'createCollection':
786+
case 'dropCollection':
703787
case 'runCommand':
704788
return ResultExpectation::ASSERT_MATCHES_DOCUMENT;
705789
case 'watch':
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
{
2+
"runOn": [
3+
{
4+
"minServerVersion": "4.3.4",
5+
"topology": [
6+
"replicaset",
7+
"sharded"
8+
]
9+
}
10+
],
11+
"database_name": "transaction-tests",
12+
"collection_name": "test",
13+
"data": [],
14+
"tests": [
15+
{
16+
"description": "explicitly create collection using create command",
17+
"operations": [
18+
{
19+
"name": "dropCollection",
20+
"object": "database",
21+
"arguments": {
22+
"collection": "test"
23+
}
24+
},
25+
{
26+
"name": "startTransaction",
27+
"object": "session0"
28+
},
29+
{
30+
"name": "createCollection",
31+
"object": "database",
32+
"arguments": {
33+
"session": "session0",
34+
"collection": "test"
35+
}
36+
},
37+
{
38+
"name": "assertCollectionNotExists",
39+
"object": "testRunner",
40+
"arguments": {
41+
"database": "transaction-tests",
42+
"collection": "test"
43+
}
44+
},
45+
{
46+
"name": "commitTransaction",
47+
"object": "session0"
48+
},
49+
{
50+
"name": "assertCollectionExists",
51+
"object": "testRunner",
52+
"arguments": {
53+
"database": "transaction-tests",
54+
"collection": "test"
55+
}
56+
}
57+
],
58+
"expectations": [
59+
{
60+
"command_started_event": {
61+
"command": {
62+
"drop": "test",
63+
"writeConcern": null
64+
},
65+
"command_name": "drop",
66+
"database_name": "transaction-tests"
67+
}
68+
},
69+
{
70+
"command_started_event": {
71+
"command": {
72+
"create": "test",
73+
"lsid": "session0",
74+
"txnNumber": {
75+
"$numberLong": "1"
76+
},
77+
"startTransaction": true,
78+
"autocommit": false,
79+
"writeConcern": null
80+
},
81+
"command_name": "create",
82+
"database_name": "transaction-tests"
83+
}
84+
},
85+
{
86+
"command_started_event": {
87+
"command": {
88+
"commitTransaction": 1,
89+
"lsid": "session0",
90+
"txnNumber": {
91+
"$numberLong": "1"
92+
},
93+
"startTransaction": null,
94+
"autocommit": false,
95+
"writeConcern": null
96+
},
97+
"command_name": "commitTransaction",
98+
"database_name": "admin"
99+
}
100+
}
101+
]
102+
},
103+
{
104+
"description": "implicitly create collection using insert",
105+
"operations": [
106+
{
107+
"name": "dropCollection",
108+
"object": "database",
109+
"arguments": {
110+
"collection": "test"
111+
}
112+
},
113+
{
114+
"name": "startTransaction",
115+
"object": "session0"
116+
},
117+
{
118+
"name": "insertOne",
119+
"object": "collection",
120+
"arguments": {
121+
"session": "session0",
122+
"document": {
123+
"_id": 1
124+
}
125+
},
126+
"result": {
127+
"insertedId": 1
128+
}
129+
},
130+
{
131+
"name": "assertCollectionNotExists",
132+
"object": "testRunner",
133+
"arguments": {
134+
"database": "transaction-tests",
135+
"collection": "test"
136+
}
137+
},
138+
{
139+
"name": "commitTransaction",
140+
"object": "session0"
141+
},
142+
{
143+
"name": "assertCollectionExists",
144+
"object": "testRunner",
145+
"arguments": {
146+
"database": "transaction-tests",
147+
"collection": "test"
148+
}
149+
}
150+
],
151+
"expectations": [
152+
{
153+
"command_started_event": {
154+
"command": {
155+
"drop": "test",
156+
"writeConcern": null
157+
},
158+
"command_name": "drop",
159+
"database_name": "transaction-tests"
160+
}
161+
},
162+
{
163+
"command_started_event": {
164+
"command": {
165+
"insert": "test",
166+
"documents": [
167+
{
168+
"_id": 1
169+
}
170+
],
171+
"ordered": true,
172+
"readConcern": null,
173+
"lsid": "session0",
174+
"txnNumber": {
175+
"$numberLong": "1"
176+
},
177+
"startTransaction": true,
178+
"autocommit": false,
179+
"writeConcern": null
180+
},
181+
"command_name": "insert",
182+
"database_name": "transaction-tests"
183+
}
184+
},
185+
{
186+
"command_started_event": {
187+
"command": {
188+
"commitTransaction": 1,
189+
"lsid": "session0",
190+
"txnNumber": {
191+
"$numberLong": "1"
192+
},
193+
"startTransaction": null,
194+
"autocommit": false,
195+
"writeConcern": null
196+
},
197+
"command_name": "commitTransaction",
198+
"database_name": "admin"
199+
}
200+
}
201+
]
202+
}
203+
]
204+
}

0 commit comments

Comments
 (0)