BulkWriteTest.php 17.4 KB
Newer Older
1 2 3 4
<?php

namespace MongoDB\Tests\Operation;

5
use MongoDB\Exception\InvalidArgumentException;
6 7 8 9 10 11
use MongoDB\Operation\BulkWrite;

class BulkWriteTest extends TestCase
{
    public function testOperationsMustNotBeEmpty()
    {
12 13
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('$operations is empty');
Jeremy Mikola's avatar
Jeremy Mikola committed
14
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), []);
15 16 17 18
    }

    public function testOperationsMustBeAList()
    {
19 20
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('$operations is not a list (unexpected index: "1")');
Jeremy Mikola's avatar
Jeremy Mikola committed
21 22 23
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            1 => [BulkWrite::INSERT_ONE => [['x' => 1]]],
        ]);
24 25 26 27
    }

    public function testMultipleOperationsInOneElement()
    {
28 29
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Expected one element in $operation[0], actually: 2');
Jeremy Mikola's avatar
Jeremy Mikola committed
30 31 32 33 34 35
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [
                BulkWrite::INSERT_ONE => [['x' => 1]],
                BulkWrite::DELETE_ONE => [['x' => 1]],
            ],
        ]);
36 37 38 39
    }

    public function testUnknownOperation()
    {
40 41
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Unknown operation type "foo" in $operations[0]');
Jeremy Mikola's avatar
Jeremy Mikola committed
42 43 44
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            ['foo' => [['_id' => 1]]],
        ]);
45 46 47 48
    }

    public function testInsertOneDocumentArgumentMissing()
    {
49 50
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing first argument for $operations[0]["insertOne"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
51 52 53
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::INSERT_ONE => []],
        ]);
54 55 56
    }

    /**
57
     * @dataProvider provideInvalidDocumentValues
58
     */
59
    public function testInsertOneDocumentArgumentTypeCheck($document)
60
    {
61 62
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["insertOne"\]\[0\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
63 64 65
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::INSERT_ONE => [$document]],
        ]);
66 67 68 69
    }

    public function testDeleteManyFilterArgumentMissing()
    {
70 71
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing first argument for $operations[0]["deleteMany"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
72 73 74
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::DELETE_MANY => []],
        ]);
75 76 77
    }

    /**
78
     * @dataProvider provideInvalidDocumentValues
79
     */
80
    public function testDeleteManyFilterArgumentTypeCheck($document)
81
    {
82 83
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["deleteMany"\]\[0\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
84 85 86
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::DELETE_MANY => [$document]],
        ]);
87 88
    }

89 90 91 92 93
    /**
     * @dataProvider provideInvalidDocumentValues
     */
    public function testDeleteManyCollationOptionTypeCheck($collation)
    {
94 95
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["deleteMany"\]\[1\]\["collation"\] to have type "array or object" but found "[\w ]+"/');
96 97 98 99 100 101 102 103 104 105
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::DELETE_MANY => [['x' => 1], ['collation' => $collation]]],
        ]);
    }

    public function provideInvalidDocumentValues()
    {
        return $this->wrapValuesForDataProvider($this->getInvalidDocumentValues());
    }

106 107
    public function testDeleteOneFilterArgumentMissing()
    {
108 109
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing first argument for $operations[0]["deleteOne"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
110 111 112
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::DELETE_ONE => []],
        ]);
113 114 115
    }

    /**
116
     * @dataProvider provideInvalidDocumentValues
117
     */
118
    public function testDeleteOneFilterArgumentTypeCheck($document)
119
    {
120 121
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["deleteOne"\]\[0\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
122 123 124
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::DELETE_ONE => [$document]],
        ]);
125 126
    }

127 128 129 130 131
    /**
     * @dataProvider provideInvalidDocumentValues
     */
    public function testDeleteOneCollationOptionTypeCheck($collation)
    {
132 133
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["deleteOne"\]\[1\]\["collation"\] to have type "array or object" but found "[\w ]+"/');
134 135 136 137 138
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::DELETE_ONE => [['x' => 1], ['collation' => $collation]]],
        ]);
    }

139 140
    public function testReplaceOneFilterArgumentMissing()
    {
141 142
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing first argument for $operations[0]["replaceOne"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
143 144 145
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => []],
        ]);
146 147 148
    }

    /**
149
     * @dataProvider provideInvalidDocumentValues
150
     */
151
    public function testReplaceOneFilterArgumentTypeCheck($filter)
152
    {
153 154
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["replaceOne"\]\[0\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
155 156 157
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => [$filter, ['y' => 1]]],
        ]);
158 159 160 161
    }

    public function testReplaceOneReplacementArgumentMissing()
    {
162 163
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing second argument for $operations[0]["replaceOne"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
164 165 166
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => [['x' => 1]]],
        ]);
167 168 169
    }

    /**
170
     * @dataProvider provideInvalidDocumentValues
171
     */
172
    public function testReplaceOneReplacementArgumentTypeCheck($replacement)
173
    {
174 175
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["replaceOne"\]\[1\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
176 177 178
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => [['x' => 1], $replacement]],
        ]);
179 180 181 182
    }

    public function testReplaceOneReplacementArgumentRequiresNoOperators()
    {
183 184
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('First key in $operations[0]["replaceOne"][1] is an update operator');
Jeremy Mikola's avatar
Jeremy Mikola committed
185 186 187
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => [['_id' => 1], ['$inc' => ['x' => 1]]]],
        ]);
188 189
    }

190 191 192 193 194
    /**
     * @dataProvider provideInvalidDocumentValues
     */
    public function testReplaceOneCollationOptionTypeCheck($collation)
    {
195 196
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["replaceOne"\]\[2\]\["collation"\] to have type "array or object" but found "[\w ]+"/');
197 198 199 200 201
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => [['x' => 1], ['y' => 1], ['collation' => $collation]]],
        ]);
    }

202
    /**
203
     * @dataProvider provideInvalidBooleanValues
204
     */
205
    public function testReplaceOneUpsertOptionTypeCheck($upsert)
206
    {
207 208
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["replaceOne"\]\[2\]\["upsert"\] to have type "boolean" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
209 210 211
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::REPLACE_ONE => [['x' => 1], ['y' => 1], ['upsert' => $upsert]]],
        ]);
212 213
    }

214 215 216 217 218
    public function provideInvalidBooleanValues()
    {
        return $this->wrapValuesForDataProvider($this->getInvalidBooleanValues());
    }

219 220
    public function testUpdateManyFilterArgumentMissing()
    {
221 222
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing first argument for $operations[0]["updateMany"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
223 224 225
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => []],
        ]);
226 227 228
    }

    /**
229
     * @dataProvider provideInvalidDocumentValues
230
     */
231
    public function testUpdateManyFilterArgumentTypeCheck($filter)
232
    {
233 234
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateMany"\]\[0\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
235 236 237
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [$filter, ['$set' => ['x' => 1]]]],
        ]);
238 239 240 241
    }

    public function testUpdateManyUpdateArgumentMissing()
    {
242 243
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing second argument for $operations[0]["updateMany"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
244 245 246
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [['x' => 1]]],
        ]);
247 248 249
    }

    /**
250
     * @dataProvider provideInvalidDocumentValues
251
     */
252
    public function testUpdateManyUpdateArgumentTypeCheck($update)
253
    {
254 255
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateMany"\]\[1\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
256 257 258
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [['x' => 1], $update]],
        ]);
259 260
    }

261
    public function testUpdateManyUpdateArgumentRequiresOperatorsOrPipeline()
262
    {
263
        $this->expectException(InvalidArgumentException::class);
264
        $this->expectExceptionMessage('First key in $operations[0]["updateMany"][1] is neither an update operator nor a pipeline');
Jeremy Mikola's avatar
Jeremy Mikola committed
265 266 267
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [['_id' => ['$gt' => 1]], ['x' => 1]]],
        ]);
268 269
    }

270 271 272 273 274
    /**
     * @dataProvider provideInvalidArrayValues
     */
    public function testUpdateManyArrayFiltersOptionTypeCheck($arrayFilters)
    {
275 276
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateMany"\]\[2\]\["arrayFilters"\] to have type "array" but found "[\w ]+"/');
277 278 279 280 281
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [['x' => 1], ['$set' => ['x' => 1]], ['arrayFilters' => $arrayFilters]]],
        ]);
    }

282 283 284 285 286
    /**
     * @dataProvider provideInvalidDocumentValues
     */
    public function testUpdateManyCollationOptionTypeCheck($collation)
    {
287 288
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateMany"\]\[2\]\["collation"\] to have type "array or object" but found "[\w ]+"/');
289 290 291 292 293
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [['x' => 1], ['$set' => ['x' => 1]], ['collation' => $collation]]],
        ]);
    }

294
    /**
295
     * @dataProvider provideInvalidBooleanValues
296
     */
297
    public function testUpdateManyUpsertOptionTypeCheck($upsert)
298
    {
299 300
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateMany"\]\[2\]\["upsert"\] to have type "boolean" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
301 302 303
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_MANY => [['x' => 1], ['$set' => ['x' => 1]], ['upsert' => $upsert]]],
        ]);
304 305 306 307
    }

    public function testUpdateOneFilterArgumentMissing()
    {
308 309
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing first argument for $operations[0]["updateOne"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
310 311 312
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => []],
        ]);
313 314 315
    }

    /**
316
     * @dataProvider provideInvalidDocumentValues
317
     */
318
    public function testUpdateOneFilterArgumentTypeCheck($filter)
319
    {
320 321
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateOne"\]\[0\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
322 323 324
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [$filter, ['$set' => ['x' => 1]]]],
        ]);
325 326 327 328
    }

    public function testUpdateOneUpdateArgumentMissing()
    {
329 330
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Missing second argument for $operations[0]["updateOne"]');
Jeremy Mikola's avatar
Jeremy Mikola committed
331 332 333
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [['x' => 1]]],
        ]);
334 335 336
    }

    /**
337
     * @dataProvider provideInvalidDocumentValues
338
     */
339
    public function testUpdateOneUpdateArgumentTypeCheck($update)
340
    {
341 342
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateOne"\]\[1\] to have type "array or object" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
343 344 345
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [['x' => 1], $update]],
        ]);
346 347
    }

348
    public function testUpdateOneUpdateArgumentRequiresOperatorsOrPipeline()
349
    {
350
        $this->expectException(InvalidArgumentException::class);
351
        $this->expectExceptionMessage('First key in $operations[0]["updateOne"][1] is neither an update operator nor a pipeline');
Jeremy Mikola's avatar
Jeremy Mikola committed
352 353 354
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [['_id' => 1], ['x' => 1]]],
        ]);
355 356 357 358 359 360 361
    }

    /**
     * @dataProvider provideInvalidArrayValues
     */
    public function testUpdateOneArrayFiltersOptionTypeCheck($arrayFilters)
    {
362 363
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateOne"\]\[2\]\["arrayFilters"\] to have type "array" but found "[\w ]+"/');
364 365 366
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [['x' => 1], ['$set' => ['x' => 1]], ['arrayFilters' => $arrayFilters]]],
        ]);
367 368
    }

369 370 371 372 373
    /**
     * @dataProvider provideInvalidDocumentValues
     */
    public function testUpdateOneCollationOptionTypeCheck($collation)
    {
374 375
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateOne"\]\[2\]\["collation"\] to have type "array or object" but found "[\w ]+"/');
376 377 378 379 380
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [['x' => 1], ['$set' => ['x' => 1]], ['collation' => $collation]]],
        ]);
    }

381
    /**
382
     * @dataProvider provideInvalidBooleanValues
383
     */
384
    public function testUpdateOneUpsertOptionTypeCheck($upsert)
385
    {
386 387
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessageRegExp('/Expected \$operations\[0\]\["updateOne"\]\[2\]\["upsert"\] to have type "boolean" but found "[\w ]+"/');
Jeremy Mikola's avatar
Jeremy Mikola committed
388 389 390
        new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [
            [BulkWrite::UPDATE_ONE => [['x' => 1], ['$set' => ['x' => 1]], ['upsert' => $upsert]]],
        ]);
391
    }
392 393 394 395 396 397

    /**
     * @dataProvider provideInvalidConstructorOptions
     */
    public function testConstructorOptionTypeChecks(array $options)
    {
398
        $this->expectException(InvalidArgumentException::class);
399 400 401
        new BulkWrite(
            $this->getDatabaseName(),
            $this->getCollectionName(),
Jeremy Mikola's avatar
Jeremy Mikola committed
402
            [[BulkWrite::INSERT_ONE => [['x' => 1]]]],
403 404 405 406 407 408
            $options
        );
    }

    public function provideInvalidConstructorOptions()
    {
Jeremy Mikola's avatar
Jeremy Mikola committed
409
        $options = [];
410

411 412 413 414
        foreach ($this->getInvalidBooleanValues() as $value) {
            $options[][] = ['bypassDocumentValidation' => $value];
        }

415
        foreach ($this->getInvalidBooleanValues(true) as $value) {
Jeremy Mikola's avatar
Jeremy Mikola committed
416
            $options[][] = ['ordered' => $value];
417 418
        }

419 420 421 422
        foreach ($this->getInvalidSessionValues() as $value) {
            $options[][] = ['session' => $value];
        }

423
        foreach ($this->getInvalidWriteConcernValues() as $value) {
Jeremy Mikola's avatar
Jeremy Mikola committed
424
            $options[][] = ['writeConcern' => $value];
425 426 427 428
        }

        return $options;
    }
429
}