|
| 1 | +--TEST-- |
| 2 | +PHPC-1529: Resetting a client should also reset the keyVaultClient |
| 3 | +--SKIPIF-- |
| 4 | +<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?> |
| 5 | +<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?> |
| 6 | +<?php skip_if_not_live(); ?> |
| 7 | +<?php skip_if_not_clean(); ?> |
| 8 | +<?php skip_if_server_version('<', '4.2'); ?> |
| 9 | +<?php skip_if_not_libmongocrypt(); ?> |
| 10 | +--FILE-- |
| 11 | +<?php |
| 12 | +require_once __DIR__ . "/../utils/basic.inc"; |
| 13 | + |
| 14 | +class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber |
| 15 | +{ |
| 16 | + private $pid; |
| 17 | + |
| 18 | + public function __construct() |
| 19 | + { |
| 20 | + $this->pid = getmypid(); |
| 21 | + } |
| 22 | + |
| 23 | + public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event) |
| 24 | + { |
| 25 | + $command = $event->getCommand(); |
| 26 | + $commandName = $event->getCommandName(); |
| 27 | + $process = $this->pid === getmypid() ? 'Parent' : 'Child'; |
| 28 | + |
| 29 | + if ($commandName === 'find' || $commandName === 'getMore') { |
| 30 | + printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize); |
| 31 | + return; |
| 32 | + } |
| 33 | + |
| 34 | + printf("%s executes %s\n", $process, $commandName); |
| 35 | + } |
| 36 | + |
| 37 | + public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event) |
| 38 | + { |
| 39 | + } |
| 40 | + |
| 41 | + public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event) |
| 42 | + { |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +$keyVaultClient = new MongoDB\Driver\Manager(URI, [], ['disableClientPersistence' => true]); |
| 47 | +$autoEncryptionOpts = [ |
| 48 | + 'keyVaultClient' => $keyVaultClient, |
| 49 | + 'keyVaultNamespace' => 'default.keys', |
| 50 | + 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary(str_repeat('0', 96), 0)]], |
| 51 | +]; |
| 52 | + |
| 53 | +$manager = new MongoDB\Driver\Manager(URI, [], ['autoEncryption' => $autoEncryptionOpts, 'disableClientPersistence' => true]); |
| 54 | + |
| 55 | +$bulk = new MongoDB\Driver\BulkWrite(); |
| 56 | +$bulk->insert(['x' => 1]); |
| 57 | +$bulk->insert(['x' => 2]); |
| 58 | +$bulk->insert(['x' => 3]); |
| 59 | +$keyVaultClient->executeBulkWrite(NS, $bulk); |
| 60 | + |
| 61 | +MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger); |
| 62 | + |
| 63 | +$query = new MongoDB\Driver\Query([], ['batchSize' => 2]); |
| 64 | +$cursor = $keyVaultClient->executeQuery(NS, $query); |
| 65 | + |
| 66 | +$childPid = pcntl_fork(); |
| 67 | + |
| 68 | +if ($childPid === 0) { |
| 69 | + /* Executing any operation with the parent's client resets this client as well as |
| 70 | + * the keyVaultClient. Continuing iteration of the cursor opened on the |
| 71 | + * keyVaultClient before resetting it should then result in an error due to |
| 72 | + * the client having been reset. */ |
| 73 | + $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1])); |
| 74 | + |
| 75 | + echo throws( |
| 76 | + function () use ($cursor) { iterator_count($cursor); }, |
| 77 | + MongoDB\Driver\Exception\RuntimeException::class |
| 78 | + ), "\n"; |
| 79 | + |
| 80 | + echo "Child exits\n"; |
| 81 | + exit; |
| 82 | +} |
| 83 | + |
| 84 | +if ($childPid > 0) { |
| 85 | + $waitPid = pcntl_waitpid($childPid, $status); |
| 86 | + |
| 87 | + if ($waitPid === $childPid) { |
| 88 | + echo "Parent waited for child to exit\n"; |
| 89 | + } |
| 90 | + |
| 91 | + unset($cursor); |
| 92 | +} |
| 93 | + |
| 94 | +?> |
| 95 | +===DONE=== |
| 96 | +<?php exit(0); ?> |
| 97 | +--EXPECT-- |
| 98 | +Parent executes find with batchSize: 2 |
| 99 | +Child executes ping |
| 100 | +OK: Got MongoDB\Driver\Exception\RuntimeException |
| 101 | +Cannot advance cursor after client reset |
| 102 | +Child exits |
| 103 | +Parent waited for child to exit |
| 104 | +Parent executes killCursors |
| 105 | +===DONE=== |
0 commit comments