1<?php 2 3use MongoDB\Driver\Command; 4use MongoDB\Driver\Manager; 5use MongoDB\Driver\ReadPreference; 6use MongoDB\Driver\Server; 7use MongoDB\Driver\Exception\ConnectionException; 8use MongoDB\Driver\Exception\RuntimeException; 9 10require_once __DIR__ . '/basic.inc'; 11require_once __DIR__ . '/tools.php'; 12 13/** 14 * Skips the test if the topology is a sharded cluster. 15 */ 16function skip_if_mongos() 17{ 18 is_mongos(URI) and exit('skip topology is a sharded cluster'); 19} 20 21/** 22 * Skips the test if the topology contains multiple mongos nodes. 23 * 24 * This is particularly useful for tests that rely on configureFailPoint, since 25 * randomized server selection can interfere with testing. 26 */ 27function skip_if_multiple_mongos() 28{ 29 $manager = new Manager(URI); 30 31 // Ensure SDAM is initialized before calling Manager::getServers() 32 $manager->selectServer(new ReadPreference('nearest')); 33 34 $mongosNodes = array_filter($manager->getServers(), function(Server $server) { 35 return $server->getType() === Server::TYPE_MONGOS; 36 }); 37 38 if (count($mongosNodes) > 1) { 39 exit('skip topology contains multiple mongos nodes'); 40 } 41} 42 43/** 44 * Skips the test if the topology is not a shard cluster. 45 */ 46function skip_if_not_mongos() 47{ 48 is_mongos(URI) or exit('skip topology is not a sharded cluster'); 49} 50 51function skip_if_not_mongos_with_replica_set() 52{ 53 is_mongos_with_replica_set(URI) or exit('skip topology is not a sharded cluster with replica set'); 54} 55 56/** 57 * Skips the test if the topology is a replica set. 58 */ 59function skip_if_replica_set() 60{ 61 is_replica_set(URI) and exit('skip topology is a replica set'); 62} 63 64/** 65 * Skips the test if the topology is not a replica set. 66 */ 67function skip_if_not_replica_set() 68{ 69 is_replica_set(URI) or exit('skip topology is not a replica set'); 70} 71 72/** 73 * Skips the test if the topology is not a replica set or sharded cluster backed by replica sets 74 */ 75function skip_if_not_replica_set_or_mongos_with_replica_set() 76{ 77 is_replica_set(URI) or is_mongos_with_replica_set(URI) or exit('skip topology is not a replica set or sharded cluster with replica set'); 78} 79 80function skip_if_no_transactions() 81{ 82 if (is_mongos_with_replica_set(URI)) { 83 skip_if_server_version('<', '4.2'); 84 } elseif (is_replica_set(URI)) { 85 skip_if_server_version('<', '4.0'); 86 } else { 87 exit('skip topology does not support transactions'); 88 } 89} 90 91/** 92 * Skips the test if the topology has no arbiter. 93 */ 94function skip_if_no_arbiter() 95{ 96 try { 97 $primary = get_primary_server(URI); 98 } catch (ConnectionException $e) { 99 exit('skip primary server is not accessible: ' . $e->getMessage()); 100 } 101 $info = $primary->getInfo(); 102 103 if (!isset($info['arbiters']) || count($info['arbiters']) < 1) { 104 exit('skip no arbiters available'); 105 } 106} 107 108/** 109 * Skips the test if the topology has no secondary. 110 */ 111function skip_if_no_secondary() 112{ 113 try { 114 $primary = get_primary_server(URI); 115 } catch (ConnectionException $e) { 116 exit('skip primary server is not accessible: ' . $e->getMessage()); 117 } 118 $info = $primary->getInfo(); 119 120 if (!isset($info['hosts']) || count($info['hosts']) < 2) { 121 exit('skip no secondaries available'); 122 } 123} 124 125/** 126 * Skips the test if the topology does not have enough data carrying nodes 127 */ 128function skip_if_not_enough_data_nodes($requiredNodes, $maxNodeCount = null) 129{ 130 try { 131 $primary = get_primary_server(URI); 132 } catch (ConnectionException $e) { 133 exit('skip primary server is not accessible: ' . $e->getMessage()); 134 } 135 $info = $primary->getInfo(); 136 137 $dataNodeCount = isset($info['hosts']) ? count($info['hosts']) : 0; 138 139 if ($dataNodeCount < $requiredNodes) { 140 exit("skip not enough nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')'); 141 } 142 if ($maxNodeCount !== null && $dataNodeCount > $requiredNodes) { 143 exit("skip too many nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')'); 144 } 145} 146 147/** 148 * Skips the test if the topology does not have enough nodes 149 */ 150function skip_if_not_enough_nodes($requiredNodes, $maxNodeCount = null) 151{ 152 try { 153 $primary = get_primary_server(URI); 154 } catch (ConnectionException $e) { 155 exit('skip primary server is not accessible: ' . $e->getMessage()); 156 } 157 $info = $primary->getInfo(); 158 159 $nodeCount = 160 (isset($info['hosts']) ? count($info['hosts']) : 0) + 161 (isset($info['arbiters']) ? count($info['arbiters']) : 0); 162 163 if ($nodeCount < $requiredNodes) { 164 exit("skip not enough nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')'); 165 } 166 if ($maxNodeCount !== null && $nodeCount > $requiredNodes) { 167 exit("skip too many nodes available (wanted: {$requiredNodes}, available: " . count($info['hosts']) . ')'); 168 } 169} 170 171/** 172 * Skips the test if the topology is a standalone. 173 */ 174function skip_if_standalone() 175{ 176 is_standalone(URI) and exit('skip topology is a standalone'); 177} 178 179/** 180 * Skips the test if the topology is not a standalone. 181 */ 182function skip_if_not_standalone() 183{ 184 is_standalone(URI) or exit('skip topology is not a standalone'); 185} 186 187/** 188 * Skips the test if the connection string uses SSL. 189 */ 190function skip_if_ssl() 191{ 192 is_ssl(URI) and exit('skip URI is using SSL'); 193} 194 195/** 196 * Skips the test if the connection string uses SSL. 197 */ 198function skip_if_not_ssl() 199{ 200 is_ssl(URI) or exit('skip URI is not using SSL'); 201} 202 203/** 204 * Skips the test if no SSL directory has been defined. 205 */ 206function skip_if_no_ssl_dir() 207{ 208 $sslDir = getenv('SSL_DIR'); 209 $sslDir !== false or exit('skip SSL_DIR environment variable not set'); 210 211 $sslDir = realpath($sslDir); 212 ($sslDir !== false && is_dir($sslDir)) or exit('skip SSL_DIR is not a valid directory'); 213} 214 215/** 216 * Skips the test if the connection string is using auth. 217 */ 218function skip_if_auth() 219{ 220 is_auth(URI) and exit('skip URI is using auth'); 221} 222 223/** 224 * Skips the test if the connection string is not using auth. 225 */ 226function skip_if_not_auth() 227{ 228 is_auth(URI) or exit('skip URI is not using auth'); 229} 230 231/** 232 * Skips the test if the connection string is not using a particular 233 * authMechanism. 234 * 235 * @param string $authMechanism 236 */ 237function skip_if_not_auth_mechanism($authMechanism) 238{ 239 $uriAuthMechanism = get_uri_option(URI, 'authMechanism'); 240 241 if ($uriAuthMechanism === null && $authMechanism !== null) { 242 exit('skip URI is not using authMechanism'); 243 } 244 245 if ($uriAuthMechanism !== $authMechanism) { 246 exit("skip URI authMechanism is '$uriAuthMechanism' (needed: '$authMechanism')"); 247 } 248} 249 250/** 251 * Skips the test if the server is not accessible. 252 */ 253function skip_if_not_live() 254{ 255 try { 256 get_primary_server(URI); 257 } catch (ConnectionException $e) { 258 exit('skip server is not accessible: ' . $e->getMessage()); 259 } 260} 261 262/** 263 * Skips the test if the server version satisfies a comparison. 264 * 265 * @see http://php.net/version_compare 266 * @param string $operator Comparison operator 267 * @param string $version Version to compare against 268 */ 269function skip_if_server_version($operator, $version) 270{ 271 $serverVersion = get_server_version(URI); 272 273 if (version_compare($serverVersion, $version, $operator)) { 274 exit("skip Server version '$serverVersion' $operator '$version'"); 275 } 276} 277 278/** 279 * Skips the test if the PHP version satisfies a comparison. 280 * 281 * @see http://php.net/version_compare 282 * @param string $operator Comparison operator 283 * @param string $version Version to compare against 284 */ 285function skip_if_php_version($operator, $version) 286{ 287 if (version_compare(PHP_VERSION, $version, $operator)) { 288 exit("skip PHP version '" . PHP_VERSION . "' $operator '$version'"); 289 } 290} 291 292/** 293 * Skips the test if the server not using a particular storage engine. 294 * 295 * @param string $storageEngine Storage engine name 296 */ 297function skip_if_not_server_storage_engine($storageEngine) 298{ 299 $serverStorageEngine = get_server_storage_engine(URI); 300 301 if ($serverStorageEngine !== $storageEngine) { 302 exit("skip Server storage engine is '$serverStorageEngine' (needed '$storageEngine')"); 303 } 304} 305 306/** 307 * Skips the test if the server does not support the sleep command. 308 */ 309function skip_if_sleep_command_unavailable() 310{ 311 if (!command_works(URI, ['sleep' => 1, 'secs' => 1, 'w' => false])) { 312 exit('skip sleep command not available'); 313 } 314} 315 316/** 317 * Skips the test if the server does not support test commands. 318 */ 319function skip_if_test_commands_disabled() 320{ 321 if (!get_server_parameter(URI, 'enableTestCommands')) { 322 exit('skip test commands are disabled'); 323 } 324} 325 326/** 327 * Skips the test if libmongoc does not support crypto. 328 * 329 * If one or more libaries are provided, additionally check that the reported 330 * library is in that array. Possible values are "libcrypto", "Common Crypto", 331 * and "CNG". 332 * 333 * @param array $libs Optional list of crypto libraries to require 334 */ 335function skip_if_not_libmongoc_crypto(array $libs = []) 336{ 337 $lib = get_module_info('libmongoc crypto library'); 338 339 if ($lib === null) { 340 exit('skip libmongoc crypto is not enabled'); 341 } 342 343 if (!empty($libs) && !in_array($lib, $libs)) { 344 exit('skip Needs libmongoc crypto library ' . implode(', ', $libs) . ', but found ' . $lib); 345 } 346} 347 348/** 349 * Skips the test if libmongoc does not support SSL. 350 * 351 * If one or more libaries are provided, additionally check that the reported 352 * library is in that array. Possible values are "OpenSSL", "LibreSSL", 353 * "Secure Transport", and "Secure Channel". 354 * 355 * @param array $libs Optional list of SSL libraries to require 356 */ 357function skip_if_not_libmongoc_ssl(array $libs = []) 358{ 359 $lib = get_module_info('libmongoc SSL library'); 360 361 if ($lib === null) { 362 exit('skip libmongoc SSL is not enabled'); 363 } 364 365 if (!empty($libs) && !in_array($lib, $libs)) { 366 exit('skip Needs libmongoc SSL library ' . implode(', ', $libs) . ', but found ' . $lib); 367 } 368} 369 370/** 371 * Skips the test if the driver was not compiled with support for FLE 372 */ 373function skip_if_not_libmongocrypt() 374{ 375 $lib = get_module_info('libmongocrypt'); 376 377 if ($lib === 'disabled') { 378 exit('skip libmongocrypt is not enabled'); 379 } 380} 381 382/** 383 * Skips the test if the driver was compiled with support for FLE 384 */ 385function skip_if_libmongocrypt() 386{ 387 $lib = get_module_info('libmongocrypt'); 388 389 if ($lib !== 'disabled') { 390 exit('skip libmongocrypt is enabled'); 391 } 392} 393 394/** 395 * Skips the test if the collection cannot be dropped. 396 * 397 * @param string $databaseName Database name 398 * @param string $collectionName Collection name 399 */ 400function skip_if_not_clean($databaseName = DATABASE_NAME, $collectionName = COLLECTION_NAME) 401{ 402 try { 403 drop_collection(URI, $databaseName, $collectionName); 404 } catch (RuntimeException $e) { 405 exit("skip Could not drop '$databaseName.$collectionName': " . $e->getMessage()); 406 } 407} 408 409function skip_if_no_getmore_failpoint() 410{ 411 $serverVersion = get_server_version(URI); 412 413 if ( 414 version_compare($serverVersion, '3.2', '>=') && 415 version_compare($serverVersion, '4.0', '<') 416 ) { 417 exit("skip Server version '$serverVersion' does not support a getMore failpoint'"); 418 } 419} 420 421function skip_if_no_failcommand_failpoint() 422{ 423 skip_if_test_commands_disabled(); 424 425 $serverVersion = get_server_version(URI); 426 427 if (is_mongos(URI) && version_compare($serverVersion, '4.1.8', '<')) { 428 exit("skip mongos version '$serverVersion' does not support 'failCommand' failpoint'"); 429 } elseif (version_compare($serverVersion, '4.0', '<')) { 430 exit("skip mongod version '$serverVersion' does not support 'failCommand' failpoint'"); 431 } 432} 433 434function skip_if_no_mongo_orchestration() 435{ 436 $ctx = stream_context_create(['http' => ['timeout' => 0.5]]); 437 $result = @file_get_contents(MONGO_ORCHESTRATION_URI, false, $ctx); 438 439 /* Note: file_get_contents emits an E_WARNING on failure, which will be 440 * caught by the error handler in basic-skipif.inc. In that case, this may 441 * never be reached. */ 442 if ($result === false) { 443 exit("skip mongo-orchestration is not accessible: '" . MONGO_ORCHESTRATION_URI . "'"); 444 } 445} 446 447function skip_if_appveyor() 448{ 449 if (getenv('APPVEYOR')) { 450 exit('skip Test cannot be run on AppVeyor'); 451 } 452} 453