Skip to content

Commit 69ed0a8

Browse files
committed
PHPLIB-1148: Add comparator for Int64 objects
1 parent 1dd5484 commit 69ed0a8

File tree

7 files changed

+219
-23
lines changed

7 files changed

+219
-23
lines changed

phpunit.evergreen.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
beStrictAboutOutputDuringTests="true"
77
beStrictAboutChangesToGlobalState="true"
88
colors="true"
9-
bootstrap="vendor/autoload.php"
9+
bootstrap="tests/bootstrap.php"
1010
defaultTestSuite="Default Test Suite"
1111
>
1212

phpunit.xml.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
beStrictAboutOutputDuringTests="true"
77
beStrictAboutChangesToGlobalState="true"
88
colors="true"
9-
bootstrap="vendor/autoload.php"
9+
bootstrap="tests/bootstrap.php"
1010
defaultTestSuite="Default Test Suite"
1111
>
1212

tests/Comparator/Int64Comparator.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Comparator;
4+
5+
use MongoDB\BSON\Int64;
6+
use SebastianBergmann\Comparator\Comparator;
7+
use SebastianBergmann\Comparator\ComparisonFailure;
8+
9+
use function is_int;
10+
use function is_numeric;
11+
use function is_string;
12+
use function sprintf;
13+
14+
use const PHP_INT_SIZE;
15+
16+
class Int64Comparator extends Comparator
17+
{
18+
public function accepts($expected, $actual)
19+
{
20+
// Only compare if either value is an Int64
21+
return ($expected instanceof Int64 && $this->isComparable($actual))
22+
|| ($actual instanceof Int64 && $this->isComparable($expected));
23+
}
24+
25+
public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false): void
26+
{
27+
if (PHP_INT_SIZE == 8) {
28+
// On 64-bit systems, compare integers directly
29+
$expectedValue = (int) $expected;
30+
$actualValue = (int) $actual;
31+
} else {
32+
// On 32-bit systems, compare integers as strings
33+
$expectedValue = (string) $expected;
34+
$actualValue = (string) $actual;
35+
}
36+
37+
if ($expectedValue === $actualValue) {
38+
return;
39+
}
40+
41+
throw new ComparisonFailure(
42+
$expected,
43+
$actual,
44+
'',
45+
'',
46+
false,
47+
sprintf(
48+
'Failed asserting that %s matches expected %s.',
49+
$this->exporter->export($actual),
50+
$this->exporter->export($expected)
51+
)
52+
);
53+
}
54+
55+
private function isComparable($value): bool
56+
{
57+
return $value instanceof Int64 // Int64 instances
58+
|| is_int($value) // Integer values
59+
|| (is_string($value) && is_numeric($value)); // Numeric strings (is_numeric accepts floats)
60+
}
61+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Comparator;
4+
5+
use Generator;
6+
use MongoDB\BSON\Int64;
7+
use PHPUnit\Framework\TestCase;
8+
use SebastianBergmann\Comparator\ComparisonFailure;
9+
10+
class Int64ComparatorTest extends TestCase
11+
{
12+
/** @dataProvider provideAcceptsValues */
13+
public function testAccepts(bool $expectedResult, $expectedValue, $actualValue): void
14+
{
15+
$this->assertSame($expectedResult, (new Int64Comparator())->accepts($expectedValue, $actualValue));
16+
}
17+
18+
public static function provideAcceptsValues(): Generator
19+
{
20+
yield 'Expects Int64, Actual Int64' => [
21+
'expectedResult' => true,
22+
'expectedValue' => new Int64(123),
23+
'actualValue' => new Int64(123),
24+
];
25+
26+
yield 'Expects Int64, Actual int' => [
27+
'expectedResult' => true,
28+
'expectedValue' => new Int64(123),
29+
'actualValue' => 123,
30+
];
31+
32+
yield 'Expects Int64, Actual string' => [
33+
'expectedResult' => true,
34+
'expectedValue' => new Int64(123),
35+
'actualValue' => '123',
36+
];
37+
38+
yield 'Expects Int64, Actual float' => [
39+
'expectedResult' => false,
40+
'expectedValue' => new Int64(123),
41+
'actualValue' => 123.0,
42+
];
43+
44+
yield 'Expects int, Actual Int64' => [
45+
'expectedResult' => true,
46+
'expectedValue' => 123,
47+
'actualValue' => new Int64(123),
48+
];
49+
50+
yield 'Expects string, Actual Int64' => [
51+
'expectedResult' => true,
52+
'expectedValue' => '123',
53+
'actualValue' => new Int64(123),
54+
];
55+
56+
yield 'Expects float, Actual Int64' => [
57+
'expectedResult' => false,
58+
'expectedValue' => 123.0,
59+
'actualValue' => new Int64(123),
60+
];
61+
62+
yield 'Expects float, Actual Float' => [
63+
'expectedResult' => false,
64+
'expectedValue' => 123.0,
65+
'actualValue' => 123.0,
66+
];
67+
68+
yield 'Expects string, Actual string' => [
69+
'expectedResult' => false,
70+
'expectedValue' => '123',
71+
'actualValue' => '123',
72+
];
73+
}
74+
75+
/**
76+
* @dataProvider provideMatchingAssertions
77+
* @doesNotPerformAssertions
78+
*/
79+
public function testMatchingAssertions($expected, $actual): void
80+
{
81+
(new Int64Comparator())->assertEquals($expected, $actual);
82+
}
83+
84+
public static function provideMatchingAssertions(): Generator
85+
{
86+
yield 'Expected Int64, Actual Int64' => [
87+
'expected' => new Int64(123),
88+
'actual' => new Int64(123),
89+
];
90+
91+
yield 'Expected Int64, Actual int' => [
92+
'expected' => new Int64(123),
93+
'actual' => 123,
94+
];
95+
96+
yield 'Expected Int64, Actual string' => [
97+
'expected' => new Int64(123),
98+
'actual' => '123',
99+
];
100+
101+
yield 'Expected int, Actual Int64' => [
102+
'expected' => 123,
103+
'actual' => new Int64(123),
104+
];
105+
106+
yield 'Expected string, Actual Int64' => [
107+
'expected' => '123',
108+
'actual' => new Int64(123),
109+
];
110+
}
111+
112+
/** @dataProvider provideFailingValues */
113+
public function testFailingAssertions($expected, $actual): void
114+
{
115+
$this->expectException(ComparisonFailure::class);
116+
117+
(new Int64Comparator())->assertEquals($expected, $actual);
118+
}
119+
120+
public static function provideFailingValues(): Generator
121+
{
122+
yield 'Expected Int64, Actual Int64' => [
123+
'expected' => new Int64(123),
124+
'actual' => new Int64(456),
125+
];
126+
127+
yield 'Expected Int64, Actual int' => [
128+
'expected' => new Int64(123),
129+
'actual' => 456,
130+
];
131+
132+
yield 'Expected Int64, Actual string' => [
133+
'expected' => new Int64(123),
134+
'actual' => '456',
135+
];
136+
137+
yield 'Expected int, Actual Int64' => [
138+
'expected' => 123,
139+
'actual' => new Int64(456),
140+
];
141+
142+
yield 'Expected string, Actual Int64' => [
143+
'expected' => '123',
144+
'actual' => new Int64(456),
145+
];
146+
}
147+
}

tests/SpecTests/DocumentsMatchConstraint.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
use function PHPUnit\Framework\logicalOr;
3131
use function sprintf;
3232

33-
use const PHP_INT_SIZE;
34-
3533
/**
3634
* Constraint that checks if one document matches another.
3735
*
@@ -308,12 +306,6 @@ private function prepareBSON($bson, bool $isRoot, bool $sortKeys = false)
308306
$bson[$key] = $this->prepareBSON($value, false, $sortKeys);
309307
continue;
310308
}
311-
312-
/* Convert Int64 objects to integers on 64-bit platforms for
313-
* compatibility reasons. */
314-
if ($value instanceof Int64 && PHP_INT_SIZE != 4) {
315-
$bson[$key] = (int) ((string) $value);
316-
}
317309
}
318310

319311
return $bson;

tests/UnifiedSpecTests/Constraint/Matches.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
use function strpos;
4141
use function strrchr;
4242

43-
use const PHP_INT_SIZE;
44-
4543
/**
4644
* Constraint that checks if one value matches another.
4745
*
@@ -425,17 +423,6 @@ private static function prepare($bson)
425423
return $bson;
426424
}
427425

428-
/* Convert Int64 objects to integers on 64-bit platforms for
429-
* compatibility reasons. */
430-
if ($bson instanceof Int64 && PHP_INT_SIZE != 4) {
431-
return (int) ((string) $bson);
432-
}
433-
434-
/* TODO: Convert Int64 objects to integers on 32-bit platforms if they
435-
* can be expressed as such. This is necessary to handle flexible
436-
* numeric comparisons if the server returns 32-bit value as a 64-bit
437-
* integer (e.g. cursor ID). */
438-
439426
// Serializable can produce an array or object, so recurse on its output
440427
if ($bson instanceof Serializable) {
441428
return self::prepare($bson->bsonSerialize());

tests/bootstrap.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
use MongoDB\Tests\Comparator\Int64Comparator;
4+
use SebastianBergmann\Comparator\Factory as ComparatorFactory;
5+
6+
require __DIR__ . '/../vendor/autoload.php';
7+
8+
// Register custom comparators
9+
ComparatorFactory::getInstance()->register(new Int64Comparator());

0 commit comments

Comments
 (0)