Skip to content

Commit 4064b74

Browse files
committed
wip client bulkWrite spec tests
1 parent 34b88a1 commit 4064b74

File tree

5 files changed

+155
-4
lines changed

5 files changed

+155
-4
lines changed

Diff for: tests/UnifiedSpecTests/ExpectedError.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace MongoDB\Tests\UnifiedSpecTests;
44

5+
use MongoDB\Driver\Exception\BulkWriteCommandException;
56
use MongoDB\Driver\Exception\BulkWriteException;
67
use MongoDB\Driver\Exception\CommandException;
78
use MongoDB\Driver\Exception\ExecutionTimeoutException;
@@ -180,8 +181,13 @@ public function assert(?Throwable $e = null): void
180181
}
181182

182183
if (isset($this->expectedResult)) {
183-
assertInstanceOf(BulkWriteException::class, $e);
184-
$this->expectedResult->assert($e->getWriteResult());
184+
assertThat($e, logicalOr(isInstanceOf(BulkWriteCommandException::class), isInstanceOf(BulkWriteException::class)));
185+
186+
if ($e instanceof BulkWriteCommandException) {
187+
$this->expectedResult->assert($e->getBulkWriteCommandResult());
188+
} elseif ($e instanceof BulkWriteException) {
189+
$this->expectedResult->assert($e->getWriteResult());
190+
}
185191
}
186192
}
187193

Diff for: tests/UnifiedSpecTests/ExpectedResult.php

+31-1
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
use MongoDB\BulkWriteResult;
66
use MongoDB\DeleteResult;
7+
use MongoDB\Driver\BulkWriteCommandResult;
78
use MongoDB\Driver\WriteResult;
89
use MongoDB\InsertManyResult;
910
use MongoDB\InsertOneResult;
1011
use MongoDB\Tests\UnifiedSpecTests\Constraint\Matches;
1112
use MongoDB\UpdateResult;
1213
use stdClass;
1314

15+
use function array_filter;
1416
use function is_object;
1517
use function PHPUnit\Framework\assertThat;
1618
use function property_exists;
@@ -57,6 +59,10 @@ private static function prepare($value)
5759
return $value;
5860
}
5961

62+
if ($value instanceof BulkWriteCommandResult) {
63+
return self::prepareBulkWriteCommandResult($value);
64+
}
65+
6066
if (
6167
$value instanceof BulkWriteResult ||
6268
$value instanceof WriteResult ||
@@ -71,7 +77,31 @@ private static function prepare($value)
7177
return $value;
7278
}
7379

74-
private static function prepareWriteResult($value)
80+
private static function prepareBulkWriteCommandResult(BulkWriteCommandResult $result): array
81+
{
82+
$retval = [
83+
'deletedCount' => $result->getDeletedCount(),
84+
'insertedCount' => $result->getInsertedCount(),
85+
'matchedCount' => $result->getMatchedCount(),
86+
'modifiedCount' => $result->getModifiedCount(),
87+
'upsertedCount' => $result->getUpsertedCount(),
88+
];
89+
90+
/* Tests use $$unsetOrMatches to expect either no key or an empty
91+
* document when verboseResults=false, so filter out null values. */
92+
$retval += array_filter(
93+
[
94+
'deleteResults' => $result->getDeleteResults()?->toPHP(),
95+
'insertResults' => $result->getInsertResults()?->toPHP(),
96+
'updateResults' => $result->getUpdateResults()?->toPHP(),
97+
],
98+
fn ($value) => $value !== null,
99+
);
100+
101+
return $retval;
102+
}
103+
104+
private static function prepareWriteResult($value): array
75105
{
76106
$result = ['acknowledged' => $value->isAcknowledged()];
77107

Diff for: tests/UnifiedSpecTests/Operation.php

+90-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use MongoDB\Client;
88
use MongoDB\Collection;
99
use MongoDB\Database;
10+
use MongoDB\Driver\BulkWriteCommand;
1011
use MongoDB\Driver\ClientEncryption;
1112
use MongoDB\Driver\Cursor;
1213
use MongoDB\Driver\Server;
@@ -88,7 +89,6 @@ final class Operation
8889
'createEntities' => 'createEntities is not implemented (PHPC-1760)',
8990
],
9091
Client::class => [
91-
'clientBulkWrite' => 'clientBulkWrite is not implemented (PHPLIB-847)',
9292
'listDatabaseObjects' => 'listDatabaseObjects is not implemented',
9393
],
9494
Cursor::class => ['iterateOnce' => 'iterateOnce is not implemented (PHPC-1760)'],
@@ -257,6 +257,18 @@ private function executeForClient(Client $client)
257257
Util::assertArgumentsBySchema(Client::class, $this->name, $args);
258258

259259
switch ($this->name) {
260+
case 'clientBulkWrite':
261+
assertArrayHasKey('models', $args);
262+
assertIsArray($args['models']);
263+
264+
// Options for BulkWriteCommand and Server::executeBulkWriteCommand() will be mixed
265+
$options = array_diff_key($args, ['models' => 1]);
266+
267+
return $client->bulkWrite(
268+
self::prepareBulkWriteCommand($args['models'], $options),
269+
$options,
270+
);
271+
260272
case 'createChangeStream':
261273
assertArrayHasKey('pipeline', $args);
262274
assertIsArray($args['pipeline']);
@@ -1001,6 +1013,82 @@ private function skipIfOperationIsNotSupported(string $executingObjectName): voi
10011013
Assert::markTestSkipped($skipReason);
10021014
}
10031015

1016+
private static function prepareBulkWriteCommand(array $models, array $options): BulkWriteCommand
1017+
{
1018+
$bulk = new BulkWriteCommand($options);
1019+
1020+
foreach ($models as $model) {
1021+
$model = (array) $model;
1022+
assertCount(1, $model);
1023+
1024+
$type = key($model);
1025+
$args = current($model);
1026+
assertIsObject($args);
1027+
$args = (array) $args;
1028+
1029+
assertArrayHasKey('namespace', $args);
1030+
assertIsString($args['namespace']);
1031+
1032+
switch ($type) {
1033+
case 'deleteMany':
1034+
case 'deleteOne':
1035+
assertArrayHasKey('filter', $args);
1036+
assertInstanceOf(stdClass::class, $args['filter']);
1037+
1038+
$bulk->{$type}(
1039+
$args['namespace'],
1040+
$args['filter'],
1041+
array_diff_key($args, ['namespace' => 1, 'filter' => 1]),
1042+
);
1043+
break;
1044+
1045+
case 'insertOne':
1046+
assertArrayHasKey('document', $args);
1047+
assertInstanceOf(stdClass::class, $args['document']);
1048+
1049+
$bulk->insertOne(
1050+
$args['namespace'],
1051+
$args['document'],
1052+
);
1053+
break;
1054+
1055+
case 'replaceOne':
1056+
assertArrayHasKey('filter', $args);
1057+
assertArrayHasKey('replacement', $args);
1058+
assertInstanceOf(stdClass::class, $args['filter']);
1059+
assertInstanceOf(stdClass::class, $args['replacement']);
1060+
1061+
$bulk->replaceOne(
1062+
$args['namespace'],
1063+
$args['filter'],
1064+
$args['replacement'],
1065+
array_diff_key($args, ['namespace' => 1, 'filter' => 1, 'replacement' => 1]),
1066+
);
1067+
break;
1068+
1069+
case 'updateMany':
1070+
case 'updateOne':
1071+
assertArrayHasKey('filter', $args);
1072+
assertArrayHasKey('update', $args);
1073+
assertInstanceOf(stdClass::class, $args['filter']);
1074+
assertThat($args['update'], logicalOr(new IsType('array'), new IsType('object')));
1075+
1076+
$bulk->{$type}(
1077+
$args['namespace'],
1078+
$args['filter'],
1079+
$args['update'],
1080+
array_diff_key($args, ['namespace' => 1, 'filter' => 1, 'update' => 1]),
1081+
);
1082+
break;
1083+
1084+
default:
1085+
Assert::fail('Unsupported bulk write model: ' . $type);
1086+
}
1087+
}
1088+
1089+
return $bulk;
1090+
}
1091+
10041092
private static function prepareBulkWriteRequest(stdClass $request): array
10051093
{
10061094
$request = (array) $request;
@@ -1026,6 +1114,7 @@ private static function prepareBulkWriteRequest(stdClass $request): array
10261114

10271115
case 'insertOne':
10281116
assertArrayHasKey('document', $args);
1117+
assertInstanceOf(stdClass::class, $args['document']);
10291118

10301119
return ['insertOne' => [$args['document']]];
10311120

Diff for: tests/UnifiedSpecTests/UnifiedSpecTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -396,4 +396,29 @@ private static function provideTests(string $directory, string $testGroup): Gene
396396
}
397397
}
398398
}
399+
400+
#[DataProvider('provideClientBulkWriteTests')]
401+
public function testClientBulkWrite(UnifiedTestCase $test): void
402+
{
403+
self::$runner->run($test);
404+
}
405+
406+
public static function provideClientBulkWriteTests(): Generator
407+
{
408+
$pattern = self::$testDir . '/crud/tests/unified/client-bulkWrite-*.json';
409+
410+
$duplicateTests = array_flip(self::$duplicateTests);
411+
412+
foreach (glob($pattern) as $filename) {
413+
foreach (UnifiedTestCase::fromFile($filename) as $name => $test) {
414+
$testKey = 'crud/' . $name;
415+
416+
if (isset($duplicateTests[$testKey])) {
417+
continue;
418+
}
419+
420+
yield $testKey => [$test];
421+
}
422+
}
423+
}
399424
}

Diff for: tests/UnifiedSpecTests/Util.php

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ final class Util
5858
'loop' => ['operations', 'storeErrorsAsEntity', 'storeFailuresAsEntity', 'storeSuccessesAsEntity', 'storeIterationsAsEntity'],
5959
],
6060
Client::class => [
61+
'clientBulkWrite' => ['models', 'bypassDocumentValidation', 'comment', 'let', 'ordered', 'session', 'verboseResults', 'writeConcern'],
6162
'createChangeStream' => ['pipeline', 'session', 'fullDocument', 'resumeAfter', 'startAfter', 'startAtOperationTime', 'batchSize', 'collation', 'maxAwaitTimeMS', 'showExpandedEvents'],
6263
'listDatabaseNames' => ['authorizedDatabases', 'filter', 'maxTimeMS', 'session'],
6364
'listDatabases' => ['authorizedDatabases', 'filter', 'maxTimeMS', 'session'],

0 commit comments

Comments
 (0)