Skip to content

Commit

Permalink
PHPLIB-1144: Add unit tests on Explainable::getCommandDocument() (#…
Browse files Browse the repository at this point in the history
…1105)

* PHPLIB-1144: Add unit tests on Explainable::getCommandDocument

* Add tests on FindOneAnd*::getCommandDocument

* Refactor Find::getCommandDocument

Remove private function createCommandDocument introduced by c7b2b03 and used only for the explain command.

* Add let and comment to explain delete

Separate Intentionally omitted option

* Aggregate option explain is incompatible with the explain command

The 'explain' option is illegal when a explain verbosity is also provided

* Let the server throw errors
  • Loading branch information
GromNaN authored Jun 19, 2023
1 parent 4e849c8 commit 53052b6
Show file tree
Hide file tree
Showing 13 changed files with 382 additions and 17 deletions.
2 changes: 1 addition & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@
<code>$this-&gt;options['writeConcern']</code>
</MixedArgument>
<MixedAssignment occurrences="5">
<code>$cmd['writeConcern']</code>
<code>$cmd['comment']</code>
<code>$deleteOptions['hint']</code>
<code>$options['comment']</code>
<code>$options['session']</code>
Expand Down
12 changes: 11 additions & 1 deletion src/Operation/Delete.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,17 @@ public function execute(Server $server)
*/
public function getCommandDocument()
{
return ['delete' => $this->collectionName, 'deletes' => [['q' => $this->filter] + $this->createDeleteOptions()]];
$cmd = ['delete' => $this->collectionName, 'deletes' => [['q' => $this->filter] + $this->createDeleteOptions()]];

if (isset($this->options['comment'])) {
$cmd['comment'] = $this->options['comment'];
}

if (isset($this->options['let'])) {
$cmd['let'] = (object) $this->options['let'];
}

return $cmd;
}

/**
Expand Down
15 changes: 0 additions & 15 deletions src/Operation/Find.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,21 +329,6 @@ public function execute(Server $server)
* @return array
*/
public function getCommandDocument()
{
$cmd = $this->createCommandDocument();

// Read concern can change the query plan
if (isset($this->options['readConcern'])) {
$cmd['readConcern'] = $this->options['readConcern'];
}

return $cmd;
}

/**
* Construct a command document for Find
*/
private function createCommandDocument(): array
{
$cmd = ['find' => $this->collectionName, 'filter' => (object) $this->filter];

Expand Down
40 changes: 40 additions & 0 deletions tests/Operation/AggregateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\Aggregate;

Expand Down Expand Up @@ -104,4 +107,41 @@ private function getInvalidHintValues()
{
return [123, 3.14, true];
}

public function testExplainableCommandDocument(): void
{
$options = [
'allowDiskUse' => true,
'batchSize' => 100,
'bypassDocumentValidation' => true,
'collation' => ['locale' => 'fr'],
'comment' => 'explain me',
'hint' => '_id_',
'let' => ['a' => 1],
'maxTimeMS' => 100,
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
'useCursor' => true,
// Intentionally omitted options
// The "explain" option is illegal
'readPreference' => new ReadPreference(ReadPreference::SECONDARY_PREFERRED),
'typeMap' => ['root' => 'array', 'document' => 'array'],
'writeConcern' => new WriteConcern(0),
];
$operation = new Aggregate($this->getDatabaseName(), $this->getCollectionName(), [['$project' => ['_id' => 0]]], $options);

$expected = [
'aggregate' => $this->getCollectionName(),
'pipeline' => [['$project' => ['_id' => 0]]],
'allowDiskUse' => true,
'bypassDocumentValidation' => true,
'collation' => (object) ['locale' => 'fr'],
'comment' => 'explain me',
'hint' => '_id_',
'maxTimeMS' => 100,
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
'let' => (object) ['a' => 1],
'cursor' => ['batchSize' => 100],
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
28 changes: 28 additions & 0 deletions tests/Operation/CountTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\ReadConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\Count;

Expand Down Expand Up @@ -64,4 +65,31 @@ private function getInvalidHintValues()
{
return [123, 3.14, true];
}

public function testExplainableCommandDocument(): void
{
$options = [
'hint' => '_id_',
'limit' => 10,
'skip' => 20,
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
'collation' => ['locale' => 'fr'],
'comment' => 'explain me',
'maxTimeMS' => 100,
];
$operation = new Count($this->getDatabaseName(), $this->getCollectionName(), ['x' => 1], $options);

$expected = [
'count' => $this->getCollectionName(),
'query' => (object) ['x' => 1],
'collation' => (object) ['locale' => 'fr'],
'hint' => '_id_',
'comment' => 'explain me',
'limit' => 10,
'skip' => 20,
'maxTimeMS' => 100,
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
29 changes: 29 additions & 0 deletions tests/Operation/DeleteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\Delete;
use TypeError;
Expand Down Expand Up @@ -65,4 +66,32 @@ public function provideInvalidConstructorOptions()

return $options;
}

public function testExplainableCommandDocument(): void
{
$options = [
'collation' => ['locale' => 'fr'],
'hint' => '_id_',
'let' => ['a' => 1],
'comment' => 'explain me',
// Intentionally omitted options
'writeConcern' => new WriteConcern(0),
];
$operation = new Delete($this->getDatabaseName(), $this->getCollectionName(), ['x' => 1], 0, $options);

$expected = [
'delete' => $this->getCollectionName(),
'deletes' => [
[
'q' => ['x' => 1],
'limit' => 0,
'collation' => (object) ['locale' => 'fr'],
'hint' => '_id_',
],
],
'comment' => 'explain me',
'let' => (object) ['a' => 1],
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
27 changes: 27 additions & 0 deletions tests/Operation/DistinctTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\ReadPreference;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\Distinct;

Expand Down Expand Up @@ -51,4 +53,29 @@ public function provideInvalidConstructorOptions()

return $options;
}

public function testExplainableCommandDocument(): void
{
$options = [
'collation' => ['locale' => 'fr'],
'maxTimeMS' => 100,
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
'comment' => 'explain me',
// Intentionally omitted options
'readPreference' => new ReadPreference(ReadPreference::SECONDARY_PREFERRED),
'typeMap' => ['root' => 'array'],
];
$operation = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'f', ['x' => 1], $options);

$expected = [
'distinct' => $this->getCollectionName(),
'key' => 'f',
'query' => (object) ['x' => 1],
'collation' => (object) ['locale' => 'fr'],
'comment' => 'explain me',
'maxTimeMS' => 100,
'readConcern' => new ReadConcern(ReadConcern::LOCAL),
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
43 changes: 43 additions & 0 deletions tests/Operation/FindAndModifyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\FindAndModify;

Expand Down Expand Up @@ -83,4 +84,46 @@ public function testConstructorUpdateAndRemoveOptionsAreMutuallyExclusive(): voi
$this->expectExceptionMessage('The "remove" option must be true or an "update" document must be specified, but not both');
new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), ['remove' => true, 'update' => []]);
}

public function testExplainableCommandDocument(): void
{
$options = [
'arrayFilters' => [['x' => 1]],
'bypassDocumentValidation' => true,
'collation' => ['locale' => 'fr'],
'comment' => 'explain me',
'fields' => ['_id' => 0],
'hint' => '_id_',
'maxTimeMS' => 100,
'new' => true,
'query' => ['y' => 2],
'sort' => ['x' => 1],
'update' => ['$set' => ['x' => 2]],
'upsert' => true,
'let' => ['a' => 3],
// Intentionally omitted options
'remove' => false, // When "update" is set
'typeMap' => ['root' => 'array'],
'writeConcern' => new WriteConcern(0),
];
$operation = new FindAndModify($this->getDatabaseName(), $this->getCollectionName(), $options);

$expected = [
'findAndModify' => $this->getCollectionName(),
'new' => true,
'upsert' => true,
'collation' => (object) ['locale' => 'fr'],
'fields' => (object) ['_id' => 0],
'let' => (object) ['a' => 3],
'query' => (object) ['y' => 2],
'sort' => (object) ['x' => 1],
'update' => (object) ['$set' => ['x' => 2]],
'arrayFilters' => [['x' => 1]],
'bypassDocumentValidation' => true,
'comment' => 'explain me',
'hint' => '_id_',
'maxTimeMS' => 100,
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
32 changes: 32 additions & 0 deletions tests/Operation/FindOneAndDeleteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\FindOneAndDelete;

Expand Down Expand Up @@ -31,4 +32,35 @@ public function provideInvalidConstructorOptions()

return $options;
}

public function testExplainableCommandDocument(): void
{
$options = [
'collation' => ['locale' => 'fr'],
'comment' => 'explain me',
'hint' => '_id_',
'maxTimeMS' => 100,
'sort' => ['x' => 1],
'let' => ['a' => 3],
// Intentionally omitted options
'projection' => ['_id' => 0],
'typeMap' => ['root' => 'array'],
'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
];
$operation = new FindOneAndDelete($this->getDatabaseName(), $this->getCollectionName(), ['y' => 2], $options);

$expected = [
'findAndModify' => $this->getCollectionName(),
'collation' => (object) ['locale' => 'fr'],
'fields' => (object) ['_id' => 0],
'let' => (object) ['a' => 3],
'query' => (object) ['y' => 2],
'sort' => (object) ['x' => 1],
'comment' => 'explain me',
'hint' => '_id_',
'maxTimeMS' => 100,
'remove' => true,
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
37 changes: 37 additions & 0 deletions tests/Operation/FindOneAndReplaceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace MongoDB\Tests\Operation;

use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Operation\FindOneAndReplace;

Expand Down Expand Up @@ -82,4 +83,40 @@ public function provideInvalidConstructorReturnDocumentOptions()
{
return $this->wrapValuesForDataProvider([-1, 0, 3]);
}

public function testExplainableCommandDocument(): void
{
$options = [
'bypassDocumentValidation' => true,
'collation' => ['locale' => 'fr'],
'comment' => 'explain me',
'fields' => ['_id' => 0],
'hint' => '_id_',
'maxTimeMS' => 100,
'projection' => ['_id' => 0],
'sort' => ['x' => 1],
'let' => ['a' => 3],
// Intentionally omitted options
'returnDocument' => FindOneAndReplace::RETURN_DOCUMENT_AFTER,
'typeMap' => ['root' => 'array'],
'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
];
$operation = new FindOneAndReplace($this->getDatabaseName(), $this->getCollectionName(), ['y' => 2], ['y' => 3], $options);

$expected = [
'findAndModify' => $this->getCollectionName(),
'new' => true,
'collation' => (object) ['locale' => 'fr'],
'fields' => (object) ['_id' => 0],
'let' => (object) ['a' => 3],
'query' => (object) ['y' => 2],
'sort' => (object) ['x' => 1],
'update' => (object) ['y' => 3],
'bypassDocumentValidation' => true,
'comment' => 'explain me',
'hint' => '_id_',
'maxTimeMS' => 100,
];
$this->assertEquals($expected, $operation->getCommandDocument());
}
}
Loading

0 comments on commit 53052b6

Please sign in to comment.