Skip to content

Commit

Permalink
PHPLIB-683 Test against Proxy as a Mongos (#854)
Browse files Browse the repository at this point in the history
* Split transactions tests for more targeted execution

The tests for transactions are the same for the classic and convenient APIs. Since the serverless spec excludes the convenient API from testing, we need to split this so we can only target the classic API for testing.

* PHPLIB-684 Add test group annotations for serverless spec tests

* PHPLIB-685 Sync tests for serverless testing

* PHPLIB-688 Report serverless mode in unified test runner

* Support passing authentication options to test framework

* Don't run killAllSessions on serverless

* PHPLIB-688 Check serverless requirement in legacy spec test runner

* PHPLIB-702 Skip crud-v1 tests that use disabled serverless features

* PHPLIB-686 Run serverless tests on evergreen

* Package serverless for better local debugging

* Add note about environment variables overriding URI credentials

* PHPLIB-715 Skip failing mapReduce test

* Fix wrong driver identifier for serverless tests
  • Loading branch information
alcaeus committed Sep 2, 2021
1 parent e787475 commit ce61fc8
Show file tree
Hide file tree
Showing 94 changed files with 572 additions and 128 deletions.
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

0 comments on commit ce61fc8

Please sign in to comment.