22
33namespace MongoDB \Tests \UnifiedSpecTests ;
44
5+ use MongoDB \Driver \Exception \BulkWriteCommandException ;
56use MongoDB \Driver \Exception \BulkWriteException ;
67use MongoDB \Driver \Exception \CommandException ;
78use MongoDB \Driver \Exception \ExecutionTimeoutException ;
1213use stdClass ;
1314use Throwable ;
1415
16+ use function count ;
1517use function PHPUnit \Framework \assertArrayHasKey ;
1618use function PHPUnit \Framework \assertContainsOnly ;
1719use function PHPUnit \Framework \assertCount ;
@@ -56,14 +58,18 @@ final class ExpectedError
5658
5759 private ?string $ codeName = null ;
5860
59- private ?Matches $ matchesResultDocument = null ;
61+ private ?Matches $ matchesErrorResponse = null ;
6062
6163 private array $ includedLabels = [];
6264
6365 private array $ excludedLabels = [];
6466
6567 private ?ExpectedResult $ expectedResult = null ;
6668
69+ private ?array $ writeErrors = null ;
70+
71+ private ?array $ writeConcernErrors = null ;
72+
6773 public function __construct (?stdClass $ o , EntityMap $ entityMap )
6874 {
6975 if ($ o === null ) {
@@ -102,7 +108,7 @@ public function __construct(?stdClass $o, EntityMap $entityMap)
102108
103109 if (isset ($ o ->errorResponse )) {
104110 assertIsObject ($ o ->errorResponse );
105- $ this ->matchesResultDocument = new Matches ($ o ->errorResponse , $ entityMap );
111+ $ this ->matchesErrorResponse = new Matches ($ o ->errorResponse , $ entityMap );
106112 }
107113
108114 if (isset ($ o ->errorLabelsContain )) {
@@ -120,6 +126,24 @@ public function __construct(?stdClass $o, EntityMap $entityMap)
120126 if (property_exists ($ o , 'expectResult ' )) {
121127 $ this ->expectedResult = new ExpectedResult ($ o , $ entityMap );
122128 }
129+
130+ if (isset ($ o ->writeErrors )) {
131+ assertIsObject ($ o ->writeErrors );
132+ assertContainsOnly ('object ' , (array ) $ o ->writeErrors );
133+
134+ foreach ($ o ->writeErrors as $ i => $ writeError ) {
135+ $ this ->writeErrors [$ i ] = new Matches ($ writeError , $ entityMap );
136+ }
137+ }
138+
139+ if (isset ($ o ->writeConcernErrors )) {
140+ assertIsArray ($ o ->writeConcernErrors );
141+ assertContainsOnly ('object ' , $ o ->writeConcernErrors );
142+
143+ foreach ($ o ->writeConcernErrors as $ i => $ writeConcernError ) {
144+ $ this ->writeConcernErrors [$ i ] = new Matches ($ writeConcernError , $ entityMap );
145+ }
146+ }
123147 }
124148
125149 /**
@@ -159,15 +183,21 @@ public function assert(?Throwable $e = null): void
159183 $ this ->assertCodeName ($ e );
160184 }
161185
162- if (isset ($ this ->matchesResultDocument )) {
163- assertThat ($ e , logicalOr (isInstanceOf (CommandException::class), isInstanceOf (BulkWriteException::class)));
186+ if (isset ($ this ->matchesErrorResponse )) {
187+ assertThat ($ e , logicalOr (
188+ isInstanceOf (CommandException::class),
189+ isInstanceOf (BulkWriteException::class),
190+ isInstanceOf (BulkWriteCommandException::class),
191+ ));
164192
165193 if ($ e instanceof CommandException) {
166- assertThat ($ e ->getResultDocument (), $ this ->matchesResultDocument , 'CommandException result document matches ' );
194+ assertThat ($ e ->getResultDocument (), $ this ->matchesErrorResponse , 'CommandException result document matches expected errorResponse ' );
195+ } elseif ($ e instanceof BulkWriteCommandException) {
196+ assertThat ($ e ->getErrorReply (), $ this ->matchesErrorResponse , 'BulkWriteCommandException error reply matches expected errorResponse ' );
167197 } elseif ($ e instanceof BulkWriteException) {
168198 $ writeErrors = $ e ->getWriteResult ()->getErrorReplies ();
169199 assertCount (1 , $ writeErrors );
170- assertThat ($ writeErrors [0 ], $ this ->matchesResultDocument , 'BulkWriteException result document matches ' );
200+ assertThat ($ writeErrors [0 ], $ this ->matchesErrorResponse , 'BulkWriteException first error reply matches expected errorResponse ' );
171201 }
172202 }
173203
@@ -184,16 +214,34 @@ public function assert(?Throwable $e = null): void
184214 }
185215
186216 if (isset ($ this ->expectedResult )) {
187- assertInstanceOf (BulkWriteException::class, $ e );
188- $ this ->expectedResult ->assert ($ e ->getWriteResult ());
217+ assertThat ($ e , logicalOr (
218+ isInstanceOf (BulkWriteException::class),
219+ isInstanceOf (BulkWriteCommandException::class),
220+ ));
221+
222+ if ($ e instanceof BulkWriteCommandException) {
223+ $ this ->expectedResult ->assert ($ e ->getPartialResult ());
224+ } elseif ($ e instanceof BulkWriteException) {
225+ $ this ->expectedResult ->assert ($ e ->getWriteResult ());
226+ }
227+ }
228+
229+ if (isset ($ this ->writeErrors )) {
230+ assertInstanceOf (BulkWriteCommandException::class, $ e );
231+ $ this ->assertWriteErrors ($ e ->getWriteErrors ());
232+ }
233+
234+ if (isset ($ this ->writeConcernErrors )) {
235+ assertInstanceOf (BulkWriteCommandException::class, $ e );
236+ $ this ->assertWriteConcernErrors ($ e ->getWriteConcernErrors ());
189237 }
190238 }
191239
192240 private function assertIsClientError (Throwable $ e ): void
193241 {
194- /* Note: BulkWriteException may proxy a previous exception. Unwrap it
195- * to check the original error. */
196- if ($ e instanceof BulkWriteException && $ e ->getPrevious () !== null ) {
242+ /* Note: BulkWriteException and BulkWriteCommandException may proxy a
243+ * previous exception. Unwrap it to check the original error. */
244+ if (( $ e instanceof BulkWriteException || $ e instanceof BulkWriteCommandException) && $ e ->getPrevious () !== null ) {
197245 $ e = $ e ->getPrevious ();
198246 }
199247
@@ -230,4 +278,47 @@ private function assertCodeName(ServerException $e): void
230278 assertObjectHasProperty ('codeName ' , $ result );
231279 assertSame ($ this ->codeName , $ result ->codeName );
232280 }
281+
282+ private function assertWriteErrors (array $ writeErrors ): void
283+ {
284+ assertCount (count ($ this ->writeErrors ), $ writeErrors );
285+
286+ foreach ($ this ->writeErrors as $ i => $ matchesWriteError ) {
287+ assertArrayHasKey ($ i , $ writeErrors );
288+ $ writeError = $ writeErrors [$ i ];
289+
290+ // Not required by the spec test, but asserts PHPC correctness
291+ assertSame ((int ) $ i , $ writeError ->getIndex ());
292+
293+ /* Convert the WriteError into a document for matching. These
294+ * field names are derived from the CRUD spec. */
295+ $ writeErrorDocument = [
296+ 'code ' => $ writeError ->getCode (),
297+ 'message ' => $ writeError ->getMessage (),
298+ 'details ' => $ writeError ->getInfo (),
299+ ];
300+
301+ assertThat ($ writeErrorDocument , $ matchesWriteError );
302+ }
303+ }
304+
305+ private function assertWriteConcernErrors (array $ writeConcernErrors ): void
306+ {
307+ assertCount (count ($ this ->writeConcernErrors ), $ writeConcernErrors );
308+
309+ foreach ($ this ->writeConcernErrors as $ i => $ matchesWriteConcernError ) {
310+ assertArrayHasKey ($ i , $ writeConcernErrors );
311+ $ writeConcernError = $ writeConcernErrors [$ i ];
312+
313+ /* Convert the WriteConcernError into a document for matching.
314+ * These field names are derived from the CRUD spec. */
315+ $ writeConcernErrorDocument = [
316+ 'code ' => $ writeConcernError ->getCode (),
317+ 'message ' => $ writeConcernError ->getMessage (),
318+ 'details ' => $ writeConcernError ->getInfo (),
319+ ];
320+
321+ assertThat ($ writeConcernErrorDocument , $ matchesWriteConcernError );
322+ }
323+ }
233324}
0 commit comments