Skip to content

PHPLIB-683 Test against Proxy as a Mongos #854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,38 @@ functions:
script: |
DRIVERS_TOOLS="${DRIVERS_TOOLS}" sh ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/run-mongohouse-local.sh

"create serverless instance":
- command: shell.exec
params:
working_dir: "src"
shell: bash
script: |-
${PREPARE_SHELL}
export PROJECT=${PROJECT}
export SERVERLESS_DRIVERS_GROUP=${SERVERLESS_DRIVERS_GROUP}
export SERVERLESS_API_PUBLIC_KEY=${SERVERLESS_API_PUBLIC_KEY}
export SERVERLESS_API_PRIVATE_KEY=${SERVERLESS_API_PRIVATE_KEY}
export SERVERLESS_ATLAS_USER=${SERVERLESS_ATLAS_USER}
export SERVERLESS_ATLAS_PASSWORD=${SERVERLESS_ATLAS_PASSWORD}
sh ${PROJECT_DIRECTORY}/.evergreen/serverless/create-instance.sh
- command: expansions.update
params:
file: src/serverless-expansion.yml

"delete serverless instance":
- command: shell.exec
params:
shell: bash
script: |-
set -o errexit
export SERVERLESS_DRIVERS_GROUP=${SERVERLESS_DRIVERS_GROUP}
export SERVERLESS_API_PUBLIC_KEY=${SERVERLESS_API_PUBLIC_KEY}
export SERVERLESS_API_PRIVATE_KEY=${SERVERLESS_API_PRIVATE_KEY}
export SERVERLESS_ATLAS_USER=${SERVERLESS_ATLAS_USER}
export SERVERLESS_ATLAS_PASSWORD=${SERVERLESS_ATLAS_PASSWORD}
export SERVERLESS_INSTANCE_NAME=${SERVERLESS_INSTANCE_NAME}
sh ${PROJECT_DIRECTORY}/.evergreen/serverless/delete-instance.sh

"run tests":
- command: shell.exec
type: test
Expand Down Expand Up @@ -226,6 +258,20 @@ functions:
export PATH="${PHP_PATH}/bin:$PATH"
PHP_VERSION=${PHP_VERSION} TESTS="atlas-data-lake" AUTH=${AUTH} SSL=${SSL} MONGODB_URI="${MONGODB_URI}" sh ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh

"run serverless tests":
- command: shell.exec
type: test
params:
working_dir: "src"
shell: bash
script: |-
${PREPARE_SHELL}
export MONGODB_IS_SERVERLESS=on
export MONGODB_USERNAME=${SERVERLESS_ATLAS_USER}
export MONGODB_PASSWORD=${SERVERLESS_ATLAS_PASSWORD}
export PATH="${PHP_PATH}/bin:$PATH"
PHP_VERSION=${PHP_VERSION} TESTS="serverless" MONGODB_URI="${MONGODB_URI}" sh ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh

"cleanup":
- command: shell.exec
params:
Expand Down Expand Up @@ -377,6 +423,15 @@ tasks:
- func: "run tests"
vars:
TESTS: "versioned-api"

- name: "test-serverless"
tags: ["serverless"]
commands:
- func: "create serverless instance"
vars:
PROJECT: "mongo-php-library"
- func: "run serverless tests"
- func: "delete serverless instance"
# }}}


Expand Down Expand Up @@ -631,3 +686,10 @@ buildvariants:
run_on: rhel70
tasks:
- .versioned-api

- matrix_name: "serverless"
matrix_spec: { "php-edge-versions": "latest-stable", "driver-versions": "latest-dev" }
display_name: "Serverless"
run_on: rhel70
tasks:
- .serverless
4 changes: 4 additions & 0 deletions .evergreen/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ case "$TESTS" in
php vendor/bin/simple-phpunit --configuration phpunit.evergreen.xml --group versioned-api $PHPUNIT_OPTS
;;

serverless)
php vendor/bin/simple-phpunit --configuration phpunit.evergreen.xml --group serverless $PHPUNIT_OPTS
;;

*)
php vendor/bin/simple-phpunit --configuration phpunit.evergreen.xml $PHPUNIT_OPTS
;;
Expand Down
87 changes: 87 additions & 0 deletions .evergreen/serverless/create-instance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/bash

set -o errexit
set +o xtrace # disable xtrace to ensure credentials aren't leaked

if [ -z "$PROJECT" ]; then
echo "Project name must be provided via PROJECT environment variable"
exit 1
fi
INSTANCE_NAME="$RANDOM-$PROJECT"

if [ -z "$SERVERLESS_DRIVERS_GROUP" ]; then
echo "Drivers Atlas group must be provided via SERVERLESS_DRIVERS_GROUP environment variable"
exit 1
fi

if [ -z "$SERVERLESS_API_PRIVATE_KEY" ]; then
echo "Atlas API private key must be provided via SERVERLESS_API_PRIVATE_KEY environment variable"
exit 1
fi

if [ -z "$SERVERLESS_API_PUBLIC_KEY" ]; then
echo "Atlas API public key must be provided via SERVERLESS_API_PUBLIC_KEY environment variable"
exit 1
fi

echo "creating new serverless instance \"${INSTANCE_NAME}\"..."

DIR=$(dirname $0)
API_BASE_URL="https://account-dev.mongodb.com/api/atlas/v1.0/groups/$SERVERLESS_DRIVERS_GROUP"

curl \
-u "$SERVERLESS_API_PUBLIC_KEY:$SERVERLESS_API_PRIVATE_KEY" \
--silent \
--show-error \
-X POST \
--digest \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
"$API_BASE_URL/serverless?pretty=true" \
--data "
{
\"name\" : \"${INSTANCE_NAME}\",
\"providerSettings\" : {
\"providerName\": \"SERVERLESS\",
\"backingProviderName\": \"GCP\",
\"instanceSizeName\" : \"SERVERLESS_V2\",
\"regionName\" : \"CENTRAL_US\"
}
}"

echo ""

if [ "Windows_NT" = "$OS" ]; then
PYTHON_BINARY=C:/python/Python38/python.exe
else
PYTHON_BINARY=python
fi

SECONDS=0
while [ true ]; do
API_RESPONSE=`SERVERLESS_INSTANCE_NAME=$INSTANCE_NAME bash $DIR/get-instance.sh`
STATE_NAME=`echo $API_RESPONSE | $PYTHON_BINARY -c "import sys, json; print(json.load(sys.stdin)['stateName'])" | tr -d '\r\n'`

if [ "$STATE_NAME" = "IDLE" ]; then
duration="$SECONDS"
echo "setup done! ($(($duration / 60))m $(($duration % 60))s elapsed)"
echo "SERVERLESS_INSTANCE_NAME=\"$INSTANCE_NAME\""
SRV_ADDRESS=$(echo $API_RESPONSE | $PYTHON_BINARY -c "import sys, json; print(json.load(sys.stdin)['connectionStrings']['standardSrv'])" | tr -d '\r\n')
echo "MONGODB_SRV_URI=\"$SRV_ADDRESS\""
STANDARD_ADDRESS=$(echo $API_RESPONSE | $PYTHON_BINARY -c "import sys, json; print(json.load(sys.stdin)['connectionStrings']['standard'].replace('&authSource=admin', ''))" | tr -d '\r\n')
echo "MONGODB_URI=\"$STANDARD_ADDRESS\""
cat <<EOF > serverless-expansion.yml
MONGODB_URI: "$STANDARD_ADDRESS"
MONGODB_SRV_URI: "$SRV_ADDRESS"
SERVERLESS_INSTANCE_NAME: "$INSTANCE_NAME"
SSL: ssl
AUTH: auth
TOPOLOGY: sharded_cluster
SERVERLESS: serverless
EOF
exit 0
else
echo "setup still in progress, status=$STATE_NAME, sleeping for 1 minute..."
sleep 60
fi
done
40 changes: 40 additions & 0 deletions .evergreen/serverless/delete-instance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

set -o errexit
set +o xtrace

if [ -z "$SERVERLESS_INSTANCE_NAME" ]; then
echo "Instance name must be provided via SERVERLESS_INSTANCE_NAME environment variable"
exit 1
fi

if [ -z "$SERVERLESS_DRIVERS_GROUP" ]; then
echo "Drivers Atlas group must be provided via SERVERLESS_DRIVERS_GROUP environment variable"
exit 1
fi

if [ -z "$SERVERLESS_API_PRIVATE_KEY" ]; then
echo "Atlas API private key must be provided via SERVERLESS_API_PRIVATE_KEY environment variable"
exit 1
fi

if [ -z "$SERVERLESS_API_PUBLIC_KEY" ]; then
echo "Atlas API public key must be provided via SERVERLESS_API_PUBLIC_KEY environment variable"
exit 1
fi

echo "deleting serverless instance \"${SERVERLESS_INSTANCE_NAME}\"..."

API_BASE_URL="https://account-dev.mongodb.com/api/atlas/v1.0/groups/$SERVERLESS_DRIVERS_GROUP"

curl \
--silent \
--show-error \
-u "$SERVERLESS_API_PUBLIC_KEY:$SERVERLESS_API_PRIVATE_KEY" \
-X DELETE \
--digest \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
"${API_BASE_URL}/serverless/${SERVERLESS_INSTANCE_NAME}?pretty=true"

echo ""
37 changes: 37 additions & 0 deletions .evergreen/serverless/get-instance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

set -o errexit
set +o xtrace

if [ -z "$SERVERLESS_INSTANCE_NAME" ]; then
echo "Instance name must be provided via SERVERLESS_INSTANCE_NAME environment variable"
exit 1
fi

if [ -z "$SERVERLESS_DRIVERS_GROUP" ]; then
echo "Drivers Atlas group must be provided via SERVERLESS_DRIVERS_GROUP environment variable"
exit 1
fi

if [ -z "$SERVERLESS_API_PRIVATE_KEY" ]; then
echo "Atlas API private key must be provided via SERVERLESS_API_PRIVATE_KEY environment variable"
exit 1
fi

if [ -z "$SERVERLESS_API_PUBLIC_KEY" ]; then
echo "Atlas API public key must be provided via SERVERLESS_API_PUBLIC_KEY environment variable"
exit 1
fi

API_BASE_URL="https://account-dev.mongodb.com/api/private/nds/serverless/groups/$SERVERLESS_DRIVERS_GROUP"

curl \
--silent \
--show-error \
-u "$SERVERLESS_API_PUBLIC_KEY:$SERVERLESS_API_PRIVATE_KEY" \
-X GET \
--digest \
--header "Accept: application/json" \
"${API_BASE_URL}/instances/${SERVERLESS_INSTANCE_NAME}?pretty=true" \

echo ""
9 changes: 8 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ The `phpunit.xml.dist` file is used as the default configuration file for the
test suite. In addition to various PHPUnit options, it defines required
`MONGODB_URI` and `MONGODB_DATABASE` environment variables. You may customize
this configuration by creating your own `phpunit.xml` file based on the
`phpunit.xml.dist` file we provide.
`phpunit.xml.dist` file we provide. To run the tests in serverless mode, set the
`MONGODB_IS_SERVERLESS` environment variable to `on`.

To run tests against a cluster that requires authentication, either include the
credentials in the connection string given in the `MONGODB_URI` environment
variable, or set the `MONGODB_USERNAME` and `MONGODB_PASSWORD` environment
variables accordingly. Note that values defined through the environment override
credentials present in the URI.

By default, the `simple-phpunit` binary chooses the correct PHPUnit version for
the PHP version you are running. To run tests against a specific PHPUnit version,
Expand Down
46 changes: 41 additions & 5 deletions tests/Collection/CrudSpecFunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@
*
* @see https://github.com/mongodb/specifications/tree/master/source/crud/tests
*
* @group serverless
* @group matrix-testing-exclude-server-5.0-driver-4.0
*/
class CrudSpecFunctionalTest extends FunctionalTestCase
{
public const SERVERLESS_ALLOW = 'allow';
public const SERVERLESS_FORBID = 'forbid';
public const SERVERLESS_REQUIRE = 'require';

/** @var Collection */
private $expectedCollection;

Expand All @@ -50,12 +55,14 @@ public function setUp(): void
/**
* @dataProvider provideSpecificationTests
*/
public function testSpecification(array $initialData, array $test, $minServerVersion, $maxServerVersion): void
public function testSpecification(array $initialData, array $test, $minServerVersion, $maxServerVersion, $serverless): void
{
if (isset($minServerVersion) || isset($maxServerVersion)) {
$this->checkServerVersion($minServerVersion, $maxServerVersion);
}

$this->checkServerlessRequirement($serverless);

$expectedData = $test['outcome']['collection']['data'] ?? null;
$this->initializeData($initialData, $expectedData);

Expand Down Expand Up @@ -83,12 +90,15 @@ public function provideSpecificationTests()
foreach (glob(__DIR__ . '/spec-tests/*/*.json') as $filename) {
$json = json_decode(file_get_contents($filename), true);

$minServerVersion = $json['minServerVersion'] ?? null;
$maxServerVersion = $json['maxServerVersion'] ?? null;

foreach ($json['tests'] as $test) {
$name = str_replace(' ', '_', $test['description']);
$testArgs[$name] = [$json['data'], $test, $minServerVersion, $maxServerVersion];
$testArgs[$name] = [
$json['data'],
$test,
$json['minServerVersion'] ?? null,
$json['maxServerVersion'] ?? null,
$json['serverless'] ?? null,
];
}
}

Expand All @@ -113,6 +123,32 @@ private function assertEquivalentCollections(Collection $expectedCollection, Col
}
}

private function checkServerlessRequirement(?string $serverless): void
{
switch ($serverless) {
case null:
case self::SERVERLESS_ALLOW:
return;

case self::SERVERLESS_FORBID:
if ($this->isServerless()) {
$this->markTestSkipped('Test does not apply on serverless');
}

return;

case self::SERVERLESS_REQUIRE:
if (! $this->isServerless()) {
$this->markTestSkipped('Test requires serverless');
}

return;

default:
$this->fail(sprintf('Unknown serverless requirement "%s".', $serverless));
}
}

/**
* Checks that the server version is within the allowed bounds (if any).
*
Expand Down
1 change: 1 addition & 0 deletions tests/Collection/spec-tests/read/aggregate-collation.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
}
],
"minServerVersion": "3.4",
"serverless": "forbid",
"tests": [
{
"description": "Aggregate with collation",
Expand Down
Loading