diff --git a/tests/UnifiedSpecTests/Operation.php b/tests/UnifiedSpecTests/Operation.php index 0419acdb3..57af7e252 100644 --- a/tests/UnifiedSpecTests/Operation.php +++ b/tests/UnifiedSpecTests/Operation.php @@ -83,6 +83,19 @@ final class Operation private ?string $saveResultAsEntity = null; + private static array $unsupportedOperations = [ + Client::class => [ + 'clientBulkWrite' => 'clientBulkWrite is not implemented (PHPLIB-847)', + 'listDatabaseObjects' => 'listDatabaseObjects is not implemented', + ], + Database::class => [ + 'createCommandCursor' => 'commandCursor API is not yet implemented (PHPLIB-1077)', + 'listCollectionObjects' => 'listCollectionObjects is not implemented', + 'runCursorCommand' => 'commandCursor API is not yet implemented (PHPLIB-1077)', + ], + Collection::class => ['listIndexNames' => 'listIndexNames is not implemented'], + ]; + public function __construct(stdClass $o, private Context $context) { $this->entityMap = $context->getEntityMap(); @@ -166,6 +179,7 @@ private function execute() $object = $this->entityMap[$this->object]; assertIsObject($object); + $this->skipIfOperationIsNotSupported($object::class); $this->context->setActiveClient($this->entityMap->getRootClientIdOf($this->object)); switch ($object::class) { @@ -235,10 +249,6 @@ private function executeForChangeStream(ChangeStream $changeStream) private function executeForClient(Client $client) { - if ($this->name === 'clientBulkWrite') { - Assert::markTestSkipped('clientBulkWrite operation is not implemented'); - } - $args = $this->prepareArguments(); Util::assertArgumentsBySchema(Client::class, $this->name, $args); @@ -811,6 +821,8 @@ private function executeForBucket(Bucket $bucket) private function executeForTestRunner() { + $this->skipIfOperationIsNotSupported(self::OBJECT_TEST_RUNNER); + $args = $this->prepareArguments(); Util::assertArgumentsBySchema(self::OBJECT_TEST_RUNNER, $this->name, $args); @@ -963,6 +975,16 @@ private function prepareArguments(): array return Util::prepareCommonOptions($args); } + private function skipIfOperationIsNotSupported(string $executingObjectName): void + { + $skipReason = self::$unsupportedOperations[$executingObjectName][$this->name] ?? null; + if (! $skipReason) { + return; + } + + Assert::markTestSkipped($skipReason); + } + private static function prepareBulkWriteRequest(stdClass $request): array { $request = (array) $request; diff --git a/tests/UnifiedSpecTests/UnifiedSpecTest.php b/tests/UnifiedSpecTests/UnifiedSpecTest.php index 13b7dbc0e..1216744d6 100644 --- a/tests/UnifiedSpecTests/UnifiedSpecTest.php +++ b/tests/UnifiedSpecTests/UnifiedSpecTest.php @@ -56,60 +56,6 @@ class UnifiedSpecTest extends FunctionalTestCase 'load-balancers/transactions are correctly pinned to connections for load-balanced clusters: a connection can be shared by a transaction and a cursor' => 'PHPC does not implement CMAP', 'load-balancers/wait queue timeout errors include details about checked out connections: wait queue timeout errors include cursor statistics' => 'PHPC does not implement CMAP', 'load-balancers/wait queue timeout errors include details about checked out connections: wait queue timeout errors include transaction statistics' => 'PHPC does not implement CMAP', - // listDatabaseObjects is not implemented - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after InterruptedAtShutdown' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after InterruptedDueToReplStateChange' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after NotWritablePrimary' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after NotPrimaryNoSecondaryOk' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after NotPrimaryOrSecondary' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after PrimarySteppedDown' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after ShutdownInProgress' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after HostNotFound' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after HostUnreachable' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after NetworkTimeout' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects succeeds after SocketException' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects fails after two NotWritablePrimary errors' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects-serverErrors: ListDatabaseObjects fails after NotWritablePrimary when retryReads is false' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects: ListDatabaseObjects succeeds on first attempt' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects: ListDatabaseObjects succeeds on second attempt' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects: ListDatabaseObjects fails on first attempt' => 'listDatabaseObjects is not implemented', - 'retryable-reads/listDatabaseObjects: ListDatabaseObjects fails on second attempt' => 'listDatabaseObjects is not implemented', - // listCollectionObjects is not implemented - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after InterruptedAtShutdown' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after InterruptedDueToReplStateChange' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after NotWritablePrimary' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after NotPrimaryNoSecondaryOk' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after NotPrimaryOrSecondary' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after PrimarySteppedDown' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after ShutdownInProgress' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after HostNotFound' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after HostUnreachable' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after NetworkTimeout' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects succeeds after SocketException' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects fails after two NotWritablePrimary errors' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects-serverErrors: ListCollectionObjects fails after NotWritablePrimary when retryReads is false' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects: ListCollectionObjects succeeds on first attempt' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects: ListCollectionObjects succeeds on second attempt' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects: ListCollectionObjects fails on first attempt' => 'listCollectionObjects is not implemented', - 'retryable-reads/listCollectionObjects: ListCollectionObjects fails on second attempt' => 'listCollectionObjects is not implemented', - // listIndexNames is not implemented - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after InterruptedAtShutdown' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after InterruptedDueToReplStateChange' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after NotWritablePrimary' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after NotPrimaryNoSecondaryOk' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after NotPrimaryOrSecondary' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after PrimarySteppedDown' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after ShutdownInProgress' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after HostNotFound' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after HostUnreachable' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after NetworkTimeout' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames succeeds after SocketException' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames fails after two NotWritablePrimary errors' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames-serverErrors: ListIndexNames fails after NotWritablePrimary when retryReads is false' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames: ListIndexNames succeeds on first attempt' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames: ListIndexNames succeeds on second attempt' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames: ListIndexNames fails on first attempt' => 'listIndexNames is not implemented', - 'retryable-reads/listIndexNames: ListIndexNames fails on second attempt' => 'listIndexNames is not implemented', // mongoc_cluster_stream_for_server does not retry handshakes (CDRIVER-4532, PHPLIB-1033, PHPLIB-1042) 'retryable-reads/retryable reads handshake failures: client.listDatabases succeeds after retryable handshake network error' => 'Handshakes are not retried (CDRIVER-4532)', 'retryable-reads/retryable reads handshake failures: client.listDatabases succeeds after retryable handshake server error (ShutdownInProgress)' => 'Handshakes are not retried (CDRIVER-4532)', @@ -175,24 +121,11 @@ class UnifiedSpecTest extends FunctionalTestCase 'valid-pass/createEntities-operation: createEntities operation' => 'CSOT is not yet implemented (PHPC-1760)', 'valid-pass/entity-cursor-iterateOnce: iterateOnce' => 'CSOT is not yet implemented (PHPC-1760)', 'valid-pass/matches-lte-operator: special lte matching operator' => 'CSOT is not yet implemented (PHPC-1760)', - // commandCursor API is not yet implemented (PHPLIB-1077) - 'valid-pass/entity-commandCursor: runCursorCommand creates and exhausts cursor by running getMores' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'valid-pass/entity-commandCursor: createCommandCursor creates a cursor and stores it as an entity that can be iterated one document at a time' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'valid-pass/entity-commandCursor: createCommandCursor\'s cursor can be closed and will perform a killCursors operation' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: successfully executes checkMetadataConsistency cursor creating command' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: errors if the command response is not a cursor' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: creates an implicit session that is reused across getMores' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: accepts an explicit session that is reused across getMores' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: returns pinned connections to the pool when the cursor is exhausted' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: returns pinned connections to the pool when the cursor is closed' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: supports configuring getMore batchSize' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: supports configuring getMore maxTimeMS' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: supports configuring getMore comment' => 'commandCursor API is not yet implemented (PHPLIB-1077)', - 'run-command/runCursorCommand: does not close the cursor when receiving an empty batch' => 'commandCursor API is not yet implemented (PHPLIB-1077)', // libmongoc always adds readConcern to aggregate command 'index-management/search index operations ignore read and write concern: listSearchIndexes ignores read and write concern' => 'libmongoc appends readConcern to aggregate command', ]; + // This test uses a duplicate name private static array $duplicateTests = ['crud/client bulkWrite partial results: partialResult is set when first operation fails during an unordered bulk write (summary)']; /**