20
20
use function fclose ;
21
21
use function fopen ;
22
22
use function MongoDB \is_last_pipeline_operator_write ;
23
+ use function MongoDB \with_transaction ;
23
24
use function stream_get_contents ;
24
25
use function strtolower ;
25
26
@@ -127,6 +128,29 @@ public static function fromCommandMonitoring(stdClass $operation)
127
128
return $ o ;
128
129
}
129
130
131
+ /**
132
+ * This method is exclusively used to prepare nested operations for the
133
+ * withTransaction session operation
134
+ *
135
+ * @return Operation
136
+ */
137
+ private static function fromConvenientTransactions (stdClass $ operation )
138
+ {
139
+ $ o = new self ($ operation );
140
+
141
+ if (isset ($ operation ->error )) {
142
+ $ o ->errorExpectation = ErrorExpectation::fromTransactions ($ operation );
143
+ }
144
+
145
+ $ o ->resultExpectation = ResultExpectation::fromTransactions ($ operation , $ o ->getResultAssertionType ());
146
+
147
+ if (isset ($ operation ->collectionOptions )) {
148
+ $ o ->collectionOptions = (array ) $ operation ->collectionOptions ;
149
+ }
150
+
151
+ return $ o ;
152
+ }
153
+
130
154
public static function fromCrud (stdClass $ operation )
131
155
{
132
156
$ o = new self ($ operation );
@@ -177,16 +201,17 @@ public static function fromTransactions(stdClass $operation)
177
201
/**
178
202
* Execute the operation and assert its outcome.
179
203
*
180
- * @param FunctionalTestCase $test Test instance
181
- * @param Context $context Execution context
204
+ * @param FunctionalTestCase $test Test instance
205
+ * @param Context $context Execution context
206
+ * @param bool $bubbleExceptions If true, any exception that was caught is rethrown
182
207
*/
183
- public function assert (FunctionalTestCase $ test , Context $ context )
208
+ public function assert (FunctionalTestCase $ test , Context $ context, $ bubbleExceptions = false )
184
209
{
185
210
$ result = null ;
186
211
$ exception = null ;
187
212
188
213
try {
189
- $ result = $ this ->execute ($ context );
214
+ $ result = $ this ->execute ($ test , $ context );
190
215
191
216
/* Eagerly iterate the results of a cursor. This both allows an
192
217
* exception to be thrown sooner and ensures that any expected
@@ -211,6 +236,10 @@ public function assert(FunctionalTestCase $test, Context $context)
211
236
if (isset ($ this ->resultExpectation )) {
212
237
$ this ->resultExpectation ->assert ($ test , $ result );
213
238
}
239
+
240
+ if ($ exception && $ bubbleExceptions ) {
241
+ throw $ exception ;
242
+ }
214
243
}
215
244
216
245
/**
@@ -220,7 +249,7 @@ public function assert(FunctionalTestCase $test, Context $context)
220
249
* @return mixed
221
250
* @throws LogicException if the operation is unsupported
222
251
*/
223
- private function execute (Context $ context )
252
+ private function execute (FunctionalTestCase $ test , Context $ context )
224
253
{
225
254
switch ($ this ->object ) {
226
255
case self ::OBJECT_CLIENT :
@@ -248,9 +277,9 @@ private function execute(Context $context)
248
277
249
278
return $ this ->executeForDatabase ($ database , $ context );
250
279
case self ::OBJECT_SESSION0 :
251
- return $ this ->executeForSession ($ context ->session0 , $ context );
280
+ return $ this ->executeForSession ($ context ->session0 , $ test , $ context );
252
281
case self ::OBJECT_SESSION1 :
253
- return $ this ->executeForSession ($ context ->session1 , $ context );
282
+ return $ this ->executeForSession ($ context ->session1 , $ test , $ context );
254
283
default :
255
284
throw new LogicException ('Unsupported object: ' . $ this ->object );
256
285
}
@@ -479,12 +508,13 @@ private function executeForGridFSBucket(Bucket $bucket, Context $context)
479
508
/**
480
509
* Executes the session operation and return its result.
481
510
*
482
- * @param Session $session
483
- * @param Context $context Execution context
511
+ * @param Session $session
512
+ * @param FunctionalTestCase $test
513
+ * @param Context $context Execution context
484
514
* @return mixed
485
515
* @throws LogicException if the session operation is unsupported
486
516
*/
487
- private function executeForSession (Session $ session , Context $ context )
517
+ private function executeForSession (Session $ session , FunctionalTestCase $ test , Context $ context )
488
518
{
489
519
switch ($ this ->name ) {
490
520
case 'abortTransaction ' :
@@ -495,6 +525,21 @@ private function executeForSession(Session $session, Context $context)
495
525
$ options = isset ($ this ->arguments ['options ' ]) ? (array ) $ this ->arguments ['options ' ] : [];
496
526
497
527
return $ session ->startTransaction ($ context ->prepareOptions ($ options ));
528
+ case 'withTransaction ' :
529
+ /** @var self[] $callbackOperations */
530
+ $ callbackOperations = array_map (function ($ operation ) {
531
+ return self ::fromConvenientTransactions ($ operation );
532
+ }, $ this ->arguments ['callback ' ]->operations );
533
+
534
+ $ callback = function () use ($ callbackOperations , $ test , $ context ) {
535
+ foreach ($ callbackOperations as $ operation ) {
536
+ $ operation ->assert ($ test , $ context , true );
537
+ }
538
+ };
539
+
540
+ $ options = isset ($ this ->arguments ['options ' ]) ? (array ) $ this ->arguments ['options ' ] : [];
541
+
542
+ return with_transaction ($ session , $ callback , $ context ->prepareOptions ($ options ));
498
543
default :
499
544
throw new LogicException ('Unsupported session operation: ' . $ this ->name );
500
545
}
0 commit comments