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 ) {
@@ -98,7 +104,7 @@ public function __construct(?stdClass $o, EntityMap $entityMap)
98104
99105 if (isset ($ o ->errorResponse )) {
100106 assertIsObject ($ o ->errorResponse );
101- $ this ->matchesResultDocument = new Matches ($ o ->errorResponse , $ entityMap );
107+ $ this ->matchesErrorResponse = new Matches ($ o ->errorResponse , $ entityMap );
102108 }
103109
104110 if (isset ($ o ->errorLabelsContain )) {
@@ -116,6 +122,24 @@ public function __construct(?stdClass $o, EntityMap $entityMap)
116122 if (property_exists ($ o , 'expectResult ' )) {
117123 $ this ->expectedResult = new ExpectedResult ($ o , $ entityMap );
118124 }
125+
126+ if (isset ($ o ->writeErrors )) {
127+ assertIsObject ($ o ->writeErrors );
128+ assertContainsOnly ('object ' , (array ) $ o ->writeErrors );
129+
130+ foreach ($ o ->writeErrors as $ i => $ writeError ) {
131+ $ this ->writeErrors [$ i ] = new Matches ($ writeError , $ entityMap );
132+ }
133+ }
134+
135+ if (isset ($ o ->writeConcernErrors )) {
136+ assertIsArray ($ o ->writeConcernErrors );
137+ assertContainsOnly ('object ' , $ o ->writeConcernErrors );
138+
139+ foreach ($ o ->writeConcernErrors as $ i => $ writeConcernError ) {
140+ $ this ->writeConcernErrors [$ i ] = new Matches ($ writeConcernError , $ entityMap );
141+ }
142+ }
119143 }
120144
121145 /**
@@ -155,15 +179,21 @@ public function assert(?Throwable $e = null): void
155179 $ this ->assertCodeName ($ e );
156180 }
157181
158- if (isset ($ this ->matchesResultDocument )) {
159- assertThat ($ e , logicalOr (isInstanceOf (CommandException::class), isInstanceOf (BulkWriteException::class)));
182+ if (isset ($ this ->matchesErrorResponse )) {
183+ assertThat ($ e , logicalOr (
184+ isInstanceOf (CommandException::class),
185+ isInstanceOf (BulkWriteException::class),
186+ isInstanceOf (BulkWriteCommandException::class),
187+ ));
160188
161189 if ($ e instanceof CommandException) {
162- assertThat ($ e ->getResultDocument (), $ this ->matchesResultDocument , 'CommandException result document matches ' );
190+ assertThat ($ e ->getResultDocument (), $ this ->matchesErrorResponse , 'CommandException result document matches expected errorResponse ' );
191+ } elseif ($ e instanceof BulkWriteCommandException) {
192+ assertThat ($ e ->getErrorReply (), $ this ->matchesErrorResponse , 'BulkWriteCommandException error reply matches expected errorResponse ' );
163193 } elseif ($ e instanceof BulkWriteException) {
164194 $ writeErrors = $ e ->getWriteResult ()->getErrorReplies ();
165195 assertCount (1 , $ writeErrors );
166- assertThat ($ writeErrors [0 ], $ this ->matchesResultDocument , 'BulkWriteException result document matches ' );
196+ assertThat ($ writeErrors [0 ], $ this ->matchesErrorResponse , 'BulkWriteException first error reply matches expected errorResponse ' );
167197 }
168198 }
169199
@@ -180,16 +210,34 @@ public function assert(?Throwable $e = null): void
180210 }
181211
182212 if (isset ($ this ->expectedResult )) {
183- assertInstanceOf (BulkWriteException::class, $ e );
184- $ this ->expectedResult ->assert ($ e ->getWriteResult ());
213+ assertThat ($ e , logicalOr (
214+ isInstanceOf (BulkWriteException::class),
215+ isInstanceOf (BulkWriteCommandException::class),
216+ ));
217+
218+ if ($ e instanceof BulkWriteCommandException) {
219+ $ this ->expectedResult ->assert ($ e ->getPartialResult ());
220+ } elseif ($ e instanceof BulkWriteException) {
221+ $ this ->expectedResult ->assert ($ e ->getWriteResult ());
222+ }
223+ }
224+
225+ if (isset ($ this ->writeErrors )) {
226+ assertInstanceOf (BulkWriteCommandException::class, $ e );
227+ $ this ->assertWriteErrors ($ e ->getWriteErrors ());
228+ }
229+
230+ if (isset ($ this ->writeConcernErrors )) {
231+ assertInstanceOf (BulkWriteCommandException::class, $ e );
232+ $ this ->assertWriteConcernErrors ($ e ->getWriteConcernErrors ());
185233 }
186234 }
187235
188236 private function assertIsClientError (Throwable $ e ): void
189237 {
190- /* Note: BulkWriteException may proxy a previous exception. Unwrap it
191- * to check the original error. */
192- if ($ e instanceof BulkWriteException && $ e ->getPrevious () !== null ) {
238+ /* Note: BulkWriteException and BulkWriteCommandException may proxy a
239+ * previous exception. Unwrap it to check the original error. */
240+ if (( $ e instanceof BulkWriteException || $ e instanceof BulkWriteCommandException) && $ e ->getPrevious () !== null ) {
193241 $ e = $ e ->getPrevious ();
194242 }
195243
@@ -226,4 +274,47 @@ private function assertCodeName(ServerException $e): void
226274 assertObjectHasProperty ('codeName ' , $ result );
227275 assertSame ($ this ->codeName , $ result ->codeName );
228276 }
277+
278+ private function assertWriteErrors (array $ writeErrors ): void
279+ {
280+ assertCount (count ($ this ->writeErrors ), $ writeErrors );
281+
282+ foreach ($ this ->writeErrors as $ i => $ matchesWriteError ) {
283+ assertArrayHasKey ($ i , $ writeErrors );
284+ $ writeError = $ writeErrors [$ i ];
285+
286+ // Not required by the spec test, but asserts PHPC correctness
287+ assertSame ((int ) $ i , $ writeError ->getIndex ());
288+
289+ /* Convert the WriteError into a document for matching. These
290+ * field names are derived from the CRUD spec. */
291+ $ writeErrorDocument = [
292+ 'code ' => $ writeError ->getCode (),
293+ 'message ' => $ writeError ->getMessage (),
294+ 'details ' => $ writeError ->getInfo (),
295+ ];
296+
297+ assertThat ($ writeErrorDocument , $ matchesWriteError );
298+ }
299+ }
300+
301+ private function assertWriteConcernErrors (array $ writeConcernErrors ): void
302+ {
303+ assertCount (count ($ this ->writeConcernErrors ), $ writeConcernErrors );
304+
305+ foreach ($ this ->writeConcernErrors as $ i => $ matchesWriteConcernError ) {
306+ assertArrayHasKey ($ i , $ writeConcernErrors );
307+ $ writeConcernError = $ writeConcernErrors [$ i ];
308+
309+ /* Convert the WriteConcernError into a document for matching.
310+ * These field names are derived from the CRUD spec. */
311+ $ writeConcernErrorDocument = [
312+ 'code ' => $ writeConcernError ->getCode (),
313+ 'message ' => $ writeConcernError ->getMessage (),
314+ 'details ' => $ writeConcernError ->getInfo (),
315+ ];
316+
317+ assertThat ($ writeConcernErrorDocument , $ matchesWriteConcernError );
318+ }
319+ }
229320}
0 commit comments