|
2 | 2 |
|
3 | 3 | namespace MongoDB\Tests\SpecTests\ClientSideEncryption;
|
4 | 4 |
|
| 5 | +use ArrayIterator; |
5 | 6 | use Generator;
|
| 7 | +use Iterator; |
6 | 8 | use MongoDB\BSON\Binary;
|
7 | 9 | use MongoDB\BSON\Decimal128;
|
8 | 10 | use MongoDB\BSON\Document;
|
9 | 11 | use MongoDB\BSON\UTCDateTime;
|
10 | 12 | use MongoDB\Driver\ClientEncryption;
|
| 13 | +use MultipleIterator; |
11 | 14 |
|
12 | 15 | use function base64_decode;
|
13 | 16 | use function file_get_contents;
|
@@ -207,6 +210,59 @@ public function testCase1_CanDecryptAPayload(string $type, array $rangeOpts): vo
|
207 | 210 | $this->assertEquals($originalValue, $decryptedValue);
|
208 | 211 | }
|
209 | 212 |
|
| 213 | + /** |
| 214 | + * @see https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#case-2-can-find-encrypted-range-and-return-the-maximum |
| 215 | + * @dataProvider provideTypeAndRangeOpts |
| 216 | + */ |
| 217 | + public function testCase2_CanFindEncryptedRangeAndReturnTheMaximum(string $type, array $rangeOpts): void |
| 218 | + { |
| 219 | + $this->setUpWithTypeAndRangeOpts($type, $rangeOpts); |
| 220 | + |
| 221 | + $encryptOpts = [ |
| 222 | + 'keyId' => $this->key1Id, |
| 223 | + 'algorithm' => ClientEncryption::ALGORITHM_RANGE_PREVIEW, |
| 224 | + 'queryType' => ClientEncryption::QUERY_TYPE_RANGE_PREVIEW, |
| 225 | + 'contentionFactor' => 0, |
| 226 | + 'rangeOpts' => $rangeOpts, |
| 227 | + ]; |
| 228 | + |
| 229 | + $cast = self::getCastCallableForType($type); |
| 230 | + $fieldName = 'encrypted' . $type; |
| 231 | + |
| 232 | + $expr = [ |
| 233 | + '$and' => [ |
| 234 | + [$fieldName => ['$gte' => $cast(6)]], |
| 235 | + [$fieldName => ['$lte' => $cast(200)]], |
| 236 | + ], |
| 237 | + ]; |
| 238 | + |
| 239 | + $encryptedExpr = $this->clientEncryption->encryptExpression($expr, $encryptOpts); |
| 240 | + $cursor = $this->collection->find($encryptedExpr, ['sort' => ['_id' => 1]]); |
| 241 | + |
| 242 | + $expectedDocuments = [ |
| 243 | + ['_id' => 1, $fieldName => $cast(6)], |
| 244 | + ['_id' => 2, $fieldName => $cast(30)], |
| 245 | + ['_id' => 3, $fieldName => $cast(200)], |
| 246 | + ]; |
| 247 | + |
| 248 | + $this->assertMultipleDocumentsMatch($expectedDocuments, $cursor); |
| 249 | + } |
| 250 | + |
| 251 | + private function assertMultipleDocumentsMatch(array $expectedDocuments, Iterator $actualDocuments): void |
| 252 | + { |
| 253 | + $mi = new MultipleIterator(MultipleIterator::MIT_NEED_ANY); |
| 254 | + $mi->attachIterator(new ArrayIterator($expectedDocuments)); |
| 255 | + $mi->attachIterator($actualDocuments); |
| 256 | + |
| 257 | + foreach ($mi as $documents) { |
| 258 | + [$expectedDocument, $actualDocument] = $documents; |
| 259 | + $this->assertNotNull($expectedDocument); |
| 260 | + $this->assertNotNull($actualDocument); |
| 261 | + |
| 262 | + $this->assertDocumentsMatch($expectedDocument, $actualDocument); |
| 263 | + } |
| 264 | + } |
| 265 | + |
210 | 266 | private static function getCastCallableForType(string $type): callable
|
211 | 267 | {
|
212 | 268 | switch ($type) {
|
|
0 commit comments