Skip to content

Commit 4f34c29

Browse files
committed
wip
1 parent fc78ab1 commit 4f34c29

8 files changed

+1445
-0
lines changed

tests/UnifiedSpecTests/DocumentsMatchConstraint.php

Lines changed: 458 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\SpecTests;
4+
5+
use MongoDB\BSON\Binary;
6+
use MongoDB\BSON\Decimal128;
7+
use MongoDB\BSON\Javascript;
8+
use MongoDB\BSON\MaxKey;
9+
use MongoDB\BSON\MinKey;
10+
use MongoDB\BSON\ObjectId;
11+
use MongoDB\BSON\Regex;
12+
use MongoDB\BSON\Timestamp;
13+
use MongoDB\BSON\UTCDateTime;
14+
use MongoDB\Model\BSONArray;
15+
use MongoDB\Model\BSONDocument;
16+
use MongoDB\Tests\TestCase;
17+
use PHPUnit\Framework\ExpectationFailedException;
18+
use function MongoDB\BSON\fromJSON;
19+
use function MongoDB\BSON\toPHP;
20+
use function unserialize;
21+
use const PHP_INT_SIZE;
22+
23+
class DocumentsMatchConstraintTest extends TestCase
24+
{
25+
public function testIgnoreExtraKeysInRoot()
26+
{
27+
$c = new DocumentsMatchConstraint(['x' => 1, 'y' => ['a' => 1, 'b' => 2]], true, false);
28+
29+
$this->assertResult(false, $c, ['x' => 1, 'y' => 2], 'Incorrect value');
30+
$this->assertResult(true, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 2]], 'Exact match');
31+
$this->assertResult(true, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 2], 'z' => 3], 'Extra keys in root are permitted');
32+
$this->assertResult(false, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 2, 'c' => 3]], 'Extra keys in embedded are not permitted');
33+
$this->assertResult(true, $c, ['y' => ['b' => 2, 'a' => 1], 'x' => 1], 'Root and embedded key order is not significant');
34+
35+
// Arrays are always interpreted as root documents
36+
$c = new DocumentsMatchConstraint([1, ['a' => 1]], true, false);
37+
38+
$this->assertResult(false, $c, [1, 2], 'Incorrect value');
39+
$this->assertResult(true, $c, [1, ['a' => 1]], 'Exact match');
40+
$this->assertResult(true, $c, [1, ['a' => 1], 3], 'Extra keys in root are permitted');
41+
$this->assertResult(false, $c, [1, ['a' => 1, 'b' => 2]], 'Extra keys in embedded are not permitted');
42+
}
43+
44+
public function testIgnoreExtraKeysInEmbedded()
45+
{
46+
$c = new DocumentsMatchConstraint(['x' => 1, 'y' => ['a' => 1, 'b' => 2]], false, true);
47+
48+
$this->assertResult(false, $c, ['x' => 1, 'y' => 2], 'Incorrect value');
49+
$this->assertResult(false, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 3]], 'Incorrect value');
50+
$this->assertResult(true, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 2]], 'Exact match');
51+
$this->assertResult(false, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 2], 'z' => 3], 'Extra keys in root are not permitted');
52+
$this->assertResult(true, $c, ['x' => 1, 'y' => ['a' => 1, 'b' => 2, 'c' => 3]], 'Extra keys in embedded are permitted');
53+
$this->assertResult(true, $c, ['y' => ['b' => 2, 'a' => 1], 'x' => 1], 'Root and embedded Key order is not significant');
54+
55+
// Arrays are always interpreted as root documents
56+
$c = new DocumentsMatchConstraint([1, ['a' => 1]], false, true);
57+
58+
$this->assertResult(false, $c, [1, 2], 'Incorrect value');
59+
$this->assertResult(true, $c, [1, ['a' => 1]], 'Exact match');
60+
$this->assertResult(false, $c, [1, ['a' => 1], 3], 'Extra keys in root are not permitted');
61+
$this->assertResult(true, $c, [1, ['a' => 1, 'b' => 2]], 'Extra keys in embedded are permitted');
62+
$this->assertResult(false, $c, [1, ['a' => 2]], 'Keys must have the correct value');
63+
}
64+
65+
public function testPlaceholders()
66+
{
67+
$c = new DocumentsMatchConstraint(['x' => '42', 'y' => 42, 'z' => ['a' => 24]], false, false, [24, 42]);
68+
69+
$this->assertResult(true, $c, ['x' => '42', 'y' => 'foo', 'z' => ['a' => 1]], 'Placeholders accept any value');
70+
$this->assertResult(false, $c, ['x' => 42, 'y' => 'foo', 'z' => ['a' => 1]], 'Placeholder type must match');
71+
$this->assertResult(true, $c, ['x' => '42', 'y' => 42, 'z' => ['a' => 24]], 'Exact match');
72+
}
73+
74+
/**
75+
* @dataProvider provideBSONTypes
76+
*/
77+
public function testBSONTypeAssertions($type, $value)
78+
{
79+
$constraint = new DocumentsMatchConstraint(['x' => ['$$type' => $type]]);
80+
81+
$this->assertResult(true, $constraint, ['x' => $value], 'Type matches');
82+
}
83+
84+
public function provideBSONTypes()
85+
{
86+
$undefined = toPHP(fromJSON('{ "undefined": {"$undefined": true} }'));
87+
$symbol = toPHP(fromJSON('{ "symbol": {"$symbol": "test"} }'));
88+
$dbPointer = toPHP(fromJSON('{ "dbPointer": {"$dbPointer": {"$ref": "phongo.test", "$id" : { "$oid" : "5a2e78accd485d55b405ac12" } }} }'));
89+
90+
return [
91+
'double' => ['double', 1.4],
92+
'string' => ['string', 'foo'],
93+
'object' => ['object', new BSONDocument()],
94+
'array' => ['array', ['foo']],
95+
'binData' => ['binData', new Binary('', 0)],
96+
'undefined' => ['undefined', $undefined->undefined],
97+
'objectId' => ['objectId', new ObjectId()],
98+
'boolean' => ['boolean', true],
99+
'date' => ['date', new UTCDateTime()],
100+
'null' => ['null', null],
101+
'regex' => ['regex', new Regex('.*')],
102+
'dbPointer' => ['dbPointer', $dbPointer->dbPointer],
103+
'javascript' => ['javascript', new Javascript('foo = 1;')],
104+
'symbol' => ['symbol', $symbol->symbol],
105+
'int' => ['int', 1],
106+
'timestamp' => ['timestamp', new Timestamp(0, 0)],
107+
'long' => ['long', PHP_INT_SIZE == 4 ? unserialize('C:18:"MongoDB\BSON\Int64":38:{a:1:{s:7:"integer";s:10:"4294967296";}}') : 4294967296],
108+
'decimal' => ['decimal', new Decimal128('18446744073709551616')],
109+
'minKey' => ['minKey', new MinKey()],
110+
'maxKey' => ['maxKey', new MaxKey()],
111+
];
112+
}
113+
114+
/**
115+
* @dataProvider errorMessageProvider
116+
*/
117+
public function testErrorMessages($expectedMessagePart, DocumentsMatchConstraint $constraint, $actualValue)
118+
{
119+
try {
120+
$constraint->evaluate($actualValue);
121+
$this->fail('Expected a comparison failure');
122+
} catch (ExpectationFailedException $failure) {
123+
$this->assertStringContainsString('Failed asserting that two BSON objects are equal.', $failure->getMessage());
124+
$this->assertStringContainsString($expectedMessagePart, $failure->getMessage());
125+
}
126+
}
127+
128+
public function errorMessageProvider()
129+
{
130+
return [
131+
'Root type mismatch' => [
132+
'MongoDB\Model\BSONArray Object (...) is not instance of expected class "MongoDB\Model\BSONDocument"',
133+
new DocumentsMatchConstraint(['foo' => 'bar']),
134+
new BSONArray(['foo' => 'bar']),
135+
],
136+
'Missing key' => [
137+
'$actual is missing key: "foo.bar"',
138+
new DocumentsMatchConstraint(['foo' => ['bar' => 'baz']]),
139+
['foo' => ['foo' => 'bar']],
140+
],
141+
'Extra key' => [
142+
'$actual has extra key: "foo.foo"',
143+
new DocumentsMatchConstraint(['foo' => ['bar' => 'baz']]),
144+
['foo' => ['foo' => 'bar', 'bar' => 'baz']],
145+
],
146+
'Scalar value not equal' => [
147+
'Field path "foo": Failed asserting that two values are equal.',
148+
new DocumentsMatchConstraint(['foo' => 'bar']),
149+
['foo' => 'baz'],
150+
],
151+
'Scalar type mismatch' => [
152+
'Field path "foo": Failed asserting that two values are equal.',
153+
new DocumentsMatchConstraint(['foo' => 42]),
154+
['foo' => '42'],
155+
],
156+
'Type mismatch' => [
157+
'Field path "foo": MongoDB\Model\BSONDocument Object (...) is not instance of expected type "MongoDB\Model\BSONArray".',
158+
new DocumentsMatchConstraint(['foo' => ['bar']]),
159+
['foo' => (object) ['bar']],
160+
],
161+
];
162+
}
163+
164+
private function assertResult($expectedResult, DocumentsMatchConstraint $constraint, $value, $message)
165+
{
166+
$this->assertSame($expectedResult, $constraint->evaluate($value, '', true), $message);
167+
}
168+
}

tests/UnifiedSpecTests/EntityMap.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\UnifiedSpecTests;
4+
5+
use ArrayAccess;
6+
use BadMethodCallException;
7+
use InvalidArgumentException;
8+
use OutOfBoundsException;
9+
use function is_string;
10+
use function sprintf;
11+
12+
class EntityMap implements ArrayAccess
13+
{
14+
private $container = [];
15+
16+
/**
17+
* Check whether an entity exists in the map.
18+
*
19+
* @see http://php.net/arrayaccess.offsetexists
20+
* @param mixed $key
21+
* @return boolean
22+
* @throws InvalidArgumentException if the key is not a string
23+
*/
24+
public function offsetExists($key)
25+
{
26+
if (! is_string($key)) {
27+
throw new InvalidArgumentException('Key is not a string');
28+
}
29+
30+
return array_key_exists($key, $this->container);
31+
}
32+
33+
/**
34+
* Return an entity from the map.
35+
*
36+
* @see http://php.net/arrayaccess.offsetget
37+
* @param mixed $key
38+
* @return mixed
39+
* @throws InvalidArgumentException if the key is not a string
40+
* @throws OutOfBoundsException if the entity is not defined
41+
*/
42+
public function offsetGet($key)
43+
{
44+
if (! is_string($key)) {
45+
throw new InvalidArgumentException('Key is not a string');
46+
}
47+
48+
if (! $this->offsetExists($key)) {
49+
throw new OutOfBoundsException(sprintf('No entity is defined for "%s"', $key));
50+
}
51+
52+
return $this->container[$key];
53+
}
54+
55+
/**
56+
* Assigns an entity to the map.
57+
*
58+
* @see http://php.net/arrayaccess.offsetset
59+
* @param mixed $key
60+
* @param mixed $value
61+
* @throws InvalidArgumentException if the key is not a string
62+
* @throws OutOfBoundsException if the entity is already defined
63+
*/
64+
public function offsetSet($key, $value)
65+
{
66+
if (! is_string($key)) {
67+
throw new InvalidArgumentException('Key is not a string');
68+
}
69+
70+
if ($this->offsetExists($key)) {
71+
throw new OutOfBoundsException('Entity already exists for key "%s" and cannot be replaced');
72+
}
73+
74+
$this->container[$key] = $value;
75+
}
76+
77+
/**
78+
* Not supported.
79+
*
80+
* @see http://php.net/arrayaccess.offsetunset
81+
* @param mixed $key
82+
* @throws BadMethodCallException
83+
*/
84+
public function offsetUnset($key)
85+
{
86+
throw new BadMethodCallException('Entities cannot be removed from the map');
87+
}
88+
}

0 commit comments

Comments
 (0)