mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-20 23:17:30 +03:00
Remove the server upgrade/downgrade tests.
These tests are intended to catch issues in upgrading HGE. However: * the tests are very convoluted and hard to understand, * we can only run a small subset of Python tests that don't mutate any data or metadata, and * I have never seen them fail for a legitimate reason, but I've seen a lot of flakes. While we do believe it's important to test that upgrades don't break the stored introspection, these tests don't seem to be doing that any more. I humbly request that we delete them now and either (a) figure out how to test this properly, or (b) just wait for v3, which does away with reintrospecting on server startup entirely. [NDAT-259]: https://hasurahq.atlassian.net/browse/NDAT-259?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8844 GitOrigin-RevId: 528bc632fce377b7eff2026b832bd58586ac5a0b
This commit is contained in:
parent
44d9987e92
commit
6ed9f36125
@ -1,7 +0,0 @@
|
||||
_output
|
||||
node_modules
|
||||
yarn.lock
|
||||
.venv
|
||||
graphql-engine-latest
|
||||
graphql-engine-latest.etag
|
||||
server-output
|
@ -1,84 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
# This is the non-circleci version of run.sh
|
||||
#
|
||||
# This script will start postgres in a docker container,
|
||||
# sets a python virtual environment,
|
||||
# and sets some of the required variables that run.sh needs,
|
||||
# before executing run.sh
|
||||
set -euo pipefail
|
||||
cd "${BASH_SOURCE[0]%/*}"
|
||||
ROOT="${PWD}"
|
||||
cd - > /dev/null
|
||||
|
||||
SERVER_DIR="$ROOT/../../server"
|
||||
|
||||
cd $SERVER_DIR
|
||||
set -x
|
||||
cabal new-build \
|
||||
--project-file=cabal/dev-sh.project \
|
||||
exe:graphql-engine
|
||||
export SERVER_BINARY="$(cabal new-exec --verbose=0 which graphql-engine)"
|
||||
echo "server binary: $SERVER_BINARY"
|
||||
cd -
|
||||
set +x
|
||||
|
||||
export SERVER_OUTPUT_DIR="$ROOT/server-output"
|
||||
export LATEST_SERVER_BINARY="$ROOT/graphql-engine-latest"
|
||||
|
||||
# Create Python virtualenv
|
||||
if ! [ -f ".venv/bin/activate" ] ; then
|
||||
virtualenv .venv
|
||||
fi
|
||||
|
||||
. .venv/bin/activate
|
||||
|
||||
PG_PORT=25432
|
||||
PG_CONTAINER_NAME="hasura-dev-postgres-$PG_PORT"
|
||||
export PGPASSWORD=postgres
|
||||
CONF=$(cat <<-EOF
|
||||
log_statement=all
|
||||
log_connections=on
|
||||
log_disconnections=on
|
||||
log_hostname=off
|
||||
log_duration=on
|
||||
port=$PG_PORT
|
||||
EOF
|
||||
)
|
||||
# Pytest is giving out deprecated warnings when postgres:// is used
|
||||
export HASURA_GRAPHQL_DATABASE_URL="postgresql://postgres:$PGPASSWORD@127.0.0.1:$PG_PORT/postgres"
|
||||
|
||||
DOCKER_PSQL="docker exec -u postgres -it $PG_CONTAINER_NAME psql -p $PG_PORT"
|
||||
|
||||
function wait_docker_postgres {
|
||||
echo -n "Waiting for postgres to come up"
|
||||
until $DOCKER_PSQL postgres -c '\l' &>/dev/null; do
|
||||
echo -n '.' && sleep 0.2
|
||||
done
|
||||
echo " Ok"
|
||||
}
|
||||
|
||||
function launch_postgres_container(){
|
||||
CONF_FLAGS=$(echo "$CONF" | sed -e 's/^/-c /' | tr '\n' ' ')
|
||||
echo "Launching postgres container: $PG_CONTAINER_NAME"
|
||||
set -x
|
||||
docker run --name "$PG_CONTAINER_NAME" -p 127.0.0.1:"$PG_PORT":$PG_PORT --expose="$PG_PORT" \
|
||||
-e POSTGRES_PASSWORD="$PGPASSWORD" -d circleci/postgres:11.5-alpine-postgis $CONF_FLAGS
|
||||
set +x
|
||||
}
|
||||
|
||||
function stop_postgres_container(){
|
||||
docker stop "$PG_CONTAINER_NAME"
|
||||
docker rm -v "$PG_CONTAINER_NAME"
|
||||
}
|
||||
|
||||
launch_postgres_container
|
||||
|
||||
wait_docker_postgres
|
||||
|
||||
trap stop_postgres_container ERR
|
||||
|
||||
set -x
|
||||
"$ROOT"/run.sh "$@"
|
||||
set +x
|
||||
|
||||
stop_postgres_container
|
@ -1,389 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
# This script tests the migration path both *from* the latest release *to* the
|
||||
# version in this PR, and the downgrade path *back* to that release. It makes
|
||||
# use of the functionality already excercised in our integration tests, and
|
||||
# does something like:
|
||||
#
|
||||
# for a subset of tests in tests that are okay to run here:
|
||||
# run setup and test using OLD_VERSION, don't run teardown
|
||||
# start THIS_VERSION, running migration code on anything set up above
|
||||
# run the same pytests, don't run setup or teardown
|
||||
# start OLD_VERSION again, running down migrations
|
||||
# run the same pytests, don't run setup
|
||||
#
|
||||
# This makes use of BUILDKITE_PARALLEL_JOB_COUNT and BUILDKITE_PARALLEL_JOB if
|
||||
# present to determine which subset of tests to run as part of a parallelized
|
||||
# test.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# # keep track of the last executed command
|
||||
# trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
||||
# # echo an error message before exiting
|
||||
# trap 'echo "\"${last_command}\" command filed with exit code $?."' EXIT
|
||||
|
||||
cd "${BASH_SOURCE[0]%/*}"
|
||||
ROOT="${PWD}"
|
||||
cd - >/dev/null
|
||||
|
||||
download_with_etag_check() {
|
||||
URL="$1"
|
||||
FILE="$2"
|
||||
ETAG="$(curl -I $URL | grep etag: | awk '{print $2}' | sed 's/\r$//')"
|
||||
set -x
|
||||
if ! ([ -f "$FILE" ] && [ "$(cat "$FILE.etag" 2>/dev/null)" == "$ETAG" ]); then
|
||||
curl -Lo "$FILE" "$URL"
|
||||
chmod +x "$FILE"
|
||||
echo -e -n "$ETAG" >"$FILE.etag"
|
||||
fi
|
||||
set +x
|
||||
}
|
||||
|
||||
fail_if_port_busy() {
|
||||
local PORT=$1
|
||||
if nc -z localhost $PORT; then
|
||||
echo "Port $PORT is busy. Exiting"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# wait_for_port PORT [PID] [LOG_FILE]
|
||||
wait_for_port() {
|
||||
local PORT=$1
|
||||
local PIDMSG=""
|
||||
local PID=${2:-}
|
||||
if [ -n "$PID" ]; then
|
||||
PIDMSG=", PID ($PID)"
|
||||
fi
|
||||
echo "waiting for ${PORT}${PIDMSG}"
|
||||
for _i in $(seq 1 60); do
|
||||
nc -z localhost $PORT && echo "port $PORT is ready" && return
|
||||
echo -n .
|
||||
sleep 1
|
||||
if [ -n "$PID" ] && ! ps $PID >/dev/null; then
|
||||
echo "Process $PID has exited"
|
||||
if [ -n "${3:-}" ]; then
|
||||
cat $3
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Failed waiting for $PORT" && exit 1
|
||||
}
|
||||
|
||||
wait_for_postgres() {
|
||||
for _i in $(seq 1 60); do
|
||||
psql "$1" -c '' >/dev/null 2>&1 && \
|
||||
echo "postgres is ready at $1" && \
|
||||
return
|
||||
echo -n .
|
||||
sleep 1
|
||||
done
|
||||
echo "failed waiting for postgres at $1" && return 1
|
||||
}
|
||||
|
||||
log() { echo $'\e[1;33m'"--> $*"$'\e[0m'; }
|
||||
|
||||
: ${HASURA_GRAPHQL_SERVER_PORT:=8080}
|
||||
: ${API_SERVER_PORT:=3000}
|
||||
: ${HASURA_PROJECT_DIR:=$ROOT/hasura}
|
||||
: ${API_SERVER_DIR:=$ROOT/api-server}
|
||||
: ${SERVER_OUTPUT_DIR:=/build/_server_output}
|
||||
: ${SERVER_TEST_OUTPUT_DIR:=/build/_server_test_output}
|
||||
: ${SERVER_BINARY:=/build/_server_output/graphql-engine}
|
||||
: ${LATEST_SERVER_BINARY:=/bin/graphql-engine-latest}
|
||||
: ${HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES:=true}
|
||||
|
||||
LATEST_SERVER_LOG=$SERVER_TEST_OUTPUT_DIR/upgrade-test-latest-release-server.log
|
||||
CURRENT_SERVER_LOG=$SERVER_TEST_OUTPUT_DIR/upgrade-test-current-server.log
|
||||
|
||||
# export them so that GraphQL Engine can use it
|
||||
export HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES="$HASURA_GRAPHQL_STRINGIFY_NUMERIC_TYPES"
|
||||
# Required for testing caching
|
||||
export GHCRTS='-N1'
|
||||
# Required for event trigger tests
|
||||
export EVENT_WEBHOOK_HANDLER="http://127.0.0.1:5592"
|
||||
export EVENT_WEBHOOK_HEADER="MyEnvValue"
|
||||
export REMOTE_SCHEMAS_WEBHOOK_DOMAIN="http://127.0.0.1:5000"
|
||||
|
||||
# graphql-engine will be run on this port
|
||||
fail_if_port_busy ${HASURA_GRAPHQL_SERVER_PORT}
|
||||
|
||||
# Remote graphql server of pytests run on this port
|
||||
fail_if_port_busy 5000
|
||||
|
||||
log "setting up directories"
|
||||
mkdir -p $SERVER_OUTPUT_DIR
|
||||
mkdir -p $SERVER_TEST_OUTPUT_DIR
|
||||
touch $LATEST_SERVER_LOG
|
||||
touch $CURRENT_SERVER_LOG
|
||||
|
||||
# download latest graphql engine release
|
||||
log "downloading latest release of graphql engine"
|
||||
download_with_etag_check 'https://graphql-engine-cdn.hasura.io/server/latest/linux-amd64' "$LATEST_SERVER_BINARY"
|
||||
|
||||
cur_server_version() {
|
||||
echo "$(curl http://localhost:${HASURA_GRAPHQL_SERVER_PORT}/v1/version -q 2>/dev/null)"
|
||||
}
|
||||
|
||||
log "Run pytests with server upgrade"
|
||||
|
||||
PYTEST_DIR="server/tests-py"
|
||||
|
||||
WORKTREE_DIR="$(mktemp -d)"
|
||||
RELEASE_VERSION="$($LATEST_SERVER_BINARY version | cut -d':' -f2 | awk '{print $1}')"
|
||||
rm_worktree() {
|
||||
rm -rf "$WORKTREE_DIR"
|
||||
}
|
||||
trap rm_worktree ERR
|
||||
|
||||
make_latest_release_worktree() {
|
||||
git worktree add --detach "$WORKTREE_DIR" "$RELEASE_VERSION"
|
||||
}
|
||||
|
||||
cleanup_hasura_metadata_if_present() {
|
||||
set -x
|
||||
psql "$HASURA_GRAPHQL_DATABASE_URL" -c 'drop schema if exists hdb_catalog cascade;
|
||||
drop schema if exists hdb_views cascade' >/dev/null 2>/dev/null
|
||||
set +x
|
||||
}
|
||||
|
||||
get_tables_of_interest() {
|
||||
psql $HASURA_GRAPHQL_DATABASE_URL -P pager=off -c "
|
||||
select table_schema as schema, table_name as name
|
||||
from information_schema.tables
|
||||
where table_schema not in ('hdb_catalog','hdb_views', 'pg_catalog', 'information_schema','topology', 'tiger')
|
||||
and (table_schema <> 'public'
|
||||
or table_name not in ('geography_columns','geometry_columns','spatial_ref_sys','raster_columns','raster_overviews')
|
||||
);
|
||||
"
|
||||
}
|
||||
|
||||
get_current_catalog_version() {
|
||||
psql $HASURA_GRAPHQL_DATABASE_URL -P pager=off -c "SELECT version FROM hdb_catalog.hdb_version"
|
||||
}
|
||||
|
||||
# Return the list of tests over which we will perform a
|
||||
# test-upgrade-test-downgrade-test sequence in run_server_upgrade_pytest().
|
||||
#
|
||||
# See pytest_report_collectionfinish() for the logic that determines what is an
|
||||
# "upgrade test", namely presence of particular markers.
|
||||
get_server_upgrade_tests() {
|
||||
cd $PYTEST_DIR
|
||||
tmpfile="$(mktemp --dry-run)"
|
||||
set -x
|
||||
# NOTE: any tests deselected in run_server_upgrade_pytest need to be filtered out here too
|
||||
#
|
||||
# FIX ME: Deselecting some introspection tests and event trigger tests from the previous test suite
|
||||
# which throw errors on the latest build. Even when the output of the current build is more accurate.
|
||||
# Remove these deselects after the next stable release
|
||||
#
|
||||
# NOTE: test_events.py involves presistent state and probably isn't
|
||||
# feasible to run here
|
||||
# FIXME: re-enable test_graphql_queries.py::TestGraphQLQueryFunctions
|
||||
# (fixing "already exists" error) if possible
|
||||
#
|
||||
# FIXME: add back `test_limit_orderby_column_query` after next release
|
||||
python3 -m pytest -q --collect-only --collect-upgrade-tests-to-file "$tmpfile" \
|
||||
-m 'allow_server_upgrade_test and not skip_server_upgrade_test' \
|
||||
--deselect test_schema_stitching.py::TestRemoteSchemaBasic::test_introspection \
|
||||
--deselect test_schema_stitching.py::TestAddRemoteSchemaCompareRootQueryFields::test_schema_check_arg_default_values_and_field_and_arg_types \
|
||||
--deselect test_graphql_mutations.py::TestGraphqlInsertPermission::test_user_with_no_backend_privilege \
|
||||
--deselect test_graphql_mutations.py::TestGraphqlInsertPermission::test_backend_user_no_admin_secret_fail \
|
||||
--deselect test_graphql_mutations.py::TestGraphqlMutationCustomSchema::test_update_article \
|
||||
--deselect test_graphql_queries.py::TestGraphQLQueryEnums::test_introspect_user_role \
|
||||
--deselect test_schema_stitching.py::TestRemoteSchemaQueriesOverWebsocket::test_remote_query_error \
|
||||
--deselect test_events.py::TestCreateAndDelete::test_create_reset \
|
||||
--deselect test_events.py::TestUpdateEvtQuery::test_update_basic \
|
||||
--deselect test_schema_stitching.py::TestAddRemoteSchemaTbls::test_add_schema \
|
||||
--deselect test_schema_stitching.py::TestAddRemoteSchemaTbls::test_add_conflicting_table \
|
||||
--deselect test_events.py \
|
||||
--deselect test_graphql_queries.py::TestGraphQLQueryFunctions \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainCommon::test_limit_orderby_relationship_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainCommon::test_limit_offset_orderby_relationship_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_limit_orderby_column_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLQueryBoolExpBasicPostgres::test_select_cast_test_where_cast_string \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_simple_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_permissions_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_limit_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_orderby_array_relationship_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_documented_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_documented_subscription \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQL::test_documented_subscription \
|
||||
1>/dev/null 2>/dev/null
|
||||
set +x
|
||||
# Choose the subset of jobs to run based on possible parallelism in this buildkite job
|
||||
# NOTE: BUILDKITE_PARALLEL_JOB starts from 0:
|
||||
cat "$tmpfile" | sort |\
|
||||
awk -v C=${BUILDKITE_PARALLEL_JOB_COUNT:-1} -v J=${BUILDKITE_PARALLEL_JOB:-0} 'NR % C == J'
|
||||
cd - >/dev/null
|
||||
rm "$tmpfile"
|
||||
}
|
||||
|
||||
# The test-upgrade-test-downgrade-test sequence, run for each of many sets of
|
||||
# tests passed as the argument.
|
||||
run_server_upgrade_pytest() {
|
||||
HGE_PID=""
|
||||
cleanup_hge() {
|
||||
kill $HGE_PID || true
|
||||
wait $HGE_PID || true
|
||||
# cleanup_hasura_metadata_if_present
|
||||
rm_worktree
|
||||
}
|
||||
trap cleanup_hge ERR
|
||||
local HGE_URL="http://localhost:${HASURA_GRAPHQL_SERVER_PORT}"
|
||||
local tests_to_run="$1"
|
||||
|
||||
[ -n "$tests_to_run" ] || (echo "Got no test as input" && false)
|
||||
|
||||
run_pytest() {
|
||||
cd $PYTEST_DIR
|
||||
set -x
|
||||
|
||||
# With --avoid-error-message-checks, we are only going to throw warnings if the error message has changed between releases
|
||||
pytest --hge-urls "${HGE_URL}" --pg-urls "$HASURA_GRAPHQL_DATABASE_URL" \
|
||||
--avoid-error-message-checks "$@" \
|
||||
-m 'allow_server_upgrade_test and not skip_server_upgrade_test' \
|
||||
--deselect test_graphql_mutations.py::TestGraphqlInsertPermission::test_user_with_no_backend_privilege \
|
||||
--deselect test_graphql_mutations.py::TestGraphqlMutationCustomSchema::test_update_article \
|
||||
--deselect test_graphql_queries.py::TestGraphQLQueryEnums::test_introspect_user_role \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainCommon::test_limit_orderby_relationship_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainCommon::test_limit_offset_orderby_relationship_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_limit_orderby_column_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLQueryBoolExpBasicPostgres::test_select_cast_test_where_cast_string \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_simple_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_permissions_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_limit_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_orderby_array_relationship_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_documented_query \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQLMySQL::test_documented_subscription \
|
||||
--deselect test_graphql_queries.py::TestGraphQLExplainPostgresMSSQL::test_documented_subscription \
|
||||
-v $tests_to_run
|
||||
set +x
|
||||
cd -
|
||||
}
|
||||
|
||||
############## Tests for latest release GraphQL engine #########################
|
||||
|
||||
# Start the old (latest release) GraphQL Engine
|
||||
log "starting latest graphql engine release"
|
||||
$LATEST_SERVER_BINARY serve >$LATEST_SERVER_LOG 2>&1 &
|
||||
HGE_PID=$!
|
||||
|
||||
# Wait for server start
|
||||
wait_for_port $HASURA_GRAPHQL_SERVER_PORT $HGE_PID $LATEST_SERVER_LOG
|
||||
|
||||
log "Catalog version for $(cur_server_version)"
|
||||
get_current_catalog_version
|
||||
|
||||
log "Run pytest for latest graphql-engine release $(cur_server_version) while skipping schema teardown"
|
||||
run_pytest --skip-schema-teardown
|
||||
|
||||
log "kill the api server $(cur_server_version)"
|
||||
kill $HGE_PID || true
|
||||
wait $HGE_PID || true
|
||||
|
||||
log "the tables of interest in the database are: "
|
||||
get_tables_of_interest
|
||||
|
||||
############## Tests for the current build GraphQL engine #########################
|
||||
|
||||
if [[ "$1" =~ "test_schema_stitching" ]]; then
|
||||
# In this case, Hasura metadata will have GraphQL servers defined as remote.
|
||||
# We need to have remote GraphQL server running for the graphql-engine to avoid
|
||||
# inconsistent metadata error
|
||||
python3 server/tests-py/graphql_server.py &
|
||||
REMOTE_GQL_PID=$!
|
||||
wait_for_port 5000
|
||||
fi
|
||||
|
||||
log "start the current build"
|
||||
set -x
|
||||
rm -f graphql-engine.tix
|
||||
$SERVER_BINARY serve >$CURRENT_SERVER_LOG 2>&1 &
|
||||
HGE_PID=$!
|
||||
set +x
|
||||
|
||||
# Wait for server start
|
||||
wait_for_port $HASURA_GRAPHQL_SERVER_PORT $HGE_PID $CURRENT_SERVER_LOG
|
||||
|
||||
log "Catalog version for $(cur_server_version)"
|
||||
get_current_catalog_version
|
||||
|
||||
if [[ "$1" =~ "test_schema_stitching" ]]; then
|
||||
kill $REMOTE_GQL_PID || true
|
||||
wait $REMOTE_GQL_PID || true
|
||||
fi
|
||||
|
||||
log "Run pytest for the current build $(cur_server_version) without modifying schema"
|
||||
run_pytest --skip-schema-setup --skip-schema-teardown
|
||||
|
||||
log "kill the api server $(cur_server_version)"
|
||||
kill $HGE_PID || true
|
||||
wait $HGE_PID || true
|
||||
|
||||
#################### Downgrade to release version ##########################
|
||||
|
||||
log "Downgrade graphql-engine to $RELEASE_VERSION"
|
||||
$SERVER_BINARY downgrade "--to-$RELEASE_VERSION"
|
||||
|
||||
############## Tests for latest release GraphQL engine once more after downgrade #########################
|
||||
|
||||
if [[ "$1" =~ "test_schema_stitching" ]]; then
|
||||
python3 server/tests-py/graphql_server.py &
|
||||
REMOTE_GQL_PID=$!
|
||||
wait_for_port 5000
|
||||
fi
|
||||
|
||||
# Start the old (latest release) GraphQL Engine
|
||||
log "starting latest graphql engine release"
|
||||
$LATEST_SERVER_BINARY serve >$LATEST_SERVER_LOG 2>&1 &
|
||||
HGE_PID=$!
|
||||
|
||||
# Wait for server start
|
||||
wait_for_port $HASURA_GRAPHQL_SERVER_PORT $HGE_PID $LATEST_SERVER_LOG
|
||||
|
||||
log "Catalog version for $(cur_server_version)"
|
||||
get_current_catalog_version
|
||||
|
||||
if [[ "$1" =~ "test_schema_stitching" ]]; then
|
||||
kill $REMOTE_GQL_PID || true
|
||||
wait $REMOTE_GQL_PID || true
|
||||
fi
|
||||
|
||||
log "Run pytest for latest graphql-engine release $(cur_server_version) (once more) while skipping schema setup"
|
||||
run_pytest --skip-schema-setup
|
||||
|
||||
log "kill the api server $(cur_server_version)"
|
||||
kill $HGE_PID || true
|
||||
wait $HGE_PID || true
|
||||
|
||||
}
|
||||
|
||||
make_latest_release_worktree
|
||||
|
||||
# This seems to flake out relatively often; try a mirror if so.
|
||||
# Might also need to disable ipv6 or use a longer --timeout
|
||||
# cryptography 3.4.7 version requires Rust dependencies by default. But we don't need them for our tests, hence disabling them via the following env var => https://stackoverflow.com/a/66334084
|
||||
export CRYPTOGRAPHY_DONT_BUILD_RUST=1
|
||||
|
||||
pip3 -q install -r "${PYTEST_DIR}/requirements.txt" ||
|
||||
pip3 -q install -i http://mirrors.digitalocean.com/pypi/web/simple --trusted-host mirrors.digitalocean.com -r "${PYTEST_DIR}/requirements.txt"
|
||||
|
||||
|
||||
wait_for_postgres "$HASURA_GRAPHQL_DATABASE_URL"
|
||||
cleanup_hasura_metadata_if_present
|
||||
|
||||
# We run_server_upgrade_pytest over each test individually to minimize the
|
||||
# chance of breakage (e.g. where two different tests have conflicting
|
||||
# setup.yaml which create the same table)
|
||||
# This takes a long time.
|
||||
for pytest in $(get_server_upgrade_tests); do
|
||||
log "Running pytest $pytest"
|
||||
run_server_upgrade_pytest "$pytest"
|
||||
done
|
||||
|
||||
cleanup_hasura_metadata_if_present
|
||||
|
||||
exit 0
|
@ -71,44 +71,6 @@ def pytest_addoption(parser):
|
||||
required=False,
|
||||
help="Accept any failing test cases from YAML files as correct, and write the new files out to disk."
|
||||
)
|
||||
parser.addoption(
|
||||
"--skip-schema-teardown",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
help="""
|
||||
Skip tearing down the schema/Hasura metadata after tests. This option may result in test failures if the schema
|
||||
has to change between the list of tests to be run
|
||||
"""
|
||||
)
|
||||
parser.addoption(
|
||||
"--skip-schema-setup",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
help="""
|
||||
Skip setting up schema/Hasura metadata before tests.
|
||||
This option may result in test failures if the schema has to change between the list of tests to be run
|
||||
"""
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--avoid-error-message-checks",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
help="""
|
||||
This option when set will ignore disparity in error messages between expected and response outputs.
|
||||
Used basically in version upgrade/downgrade tests where the error messages may change
|
||||
"""
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--collect-upgrade-tests-to-file",
|
||||
metavar="<path>",
|
||||
required=False,
|
||||
help="When used along with collect-only, it will write the list of upgrade tests into the file specified"
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--redis-url",
|
||||
@ -169,42 +131,6 @@ def pytest_configure(config):
|
||||
assert config.getoption('--hge-bin') or xdist_threads <= len(config.hge_url_list), "Not enough hge_urls specified, Required " + str(xdist_threads) + ", got " + str(len(config.hge_url_list))
|
||||
assert xdist_threads <= len(config.pg_url_list), "Not enough pg_urls specified, Required " + str(xdist_threads) + ", got " + str(len(config.pg_url_list))
|
||||
|
||||
@pytest.hookimpl()
|
||||
def pytest_report_collectionfinish(config, startdir, items):
|
||||
"""
|
||||
Collect server upgrade tests to the given file
|
||||
"""
|
||||
tests_file = config.getoption('--collect-upgrade-tests-to-file')
|
||||
tests = collections.OrderedDict()
|
||||
if tests_file:
|
||||
def is_upgrade_test(item):
|
||||
# Check if allow_server_upgrade_tests marker are present
|
||||
# skip_server_upgrade_tests marker is not present
|
||||
return item.get_closest_marker('allow_server_upgrade_test') \
|
||||
and not item.get_closest_marker('skip_server_upgrade_test')
|
||||
with open(tests_file,'w') as f:
|
||||
upgrade_items = filter(is_upgrade_test, items)
|
||||
for item in upgrade_items:
|
||||
# This test should be run separately,
|
||||
# since its schema setup has function scope
|
||||
if 'per_method_tests_db_state' in item.fixturenames:
|
||||
tests[item.nodeid] = True
|
||||
elif any([ (x in item.fixturenames)
|
||||
for x in
|
||||
[ 'per_class_tests_db_state',
|
||||
'per_class_db_schema_for_mutation_tests'
|
||||
]
|
||||
]):
|
||||
# For this test, schema setup has class scope
|
||||
# We can run a class of these tests at a time
|
||||
tests[item.parent.nodeid] = True
|
||||
# Assume tests can only be run separately
|
||||
else:
|
||||
tests[item.nodeid] = True
|
||||
for test in tests.keys():
|
||||
f.write(test + '\n')
|
||||
return ''
|
||||
|
||||
@pytest.hookimpl(optionalhook=True)
|
||||
def pytest_configure_node(node):
|
||||
if is_help_option_present(node.config):
|
||||
@ -861,7 +787,6 @@ def per_method_db_data_for_mutation_tests(request, hge_ctx, per_class_db_schema_
|
||||
request, hge_ctx,
|
||||
'values_setup_files', values_setup,
|
||||
'values_teardown_files', values_teardown,
|
||||
skip_setup=False, skip_teardown=False
|
||||
)
|
||||
|
||||
def db_state_context(request, hge_ctx):
|
||||
@ -910,15 +835,10 @@ def db_context_with_schema_common(
|
||||
setup_files_attr, setup_default_file,
|
||||
teardown_files_attr, teardown_default_file,
|
||||
):
|
||||
(skip_setup, skip_teardown) = [
|
||||
request.config.getoption('--' + x)
|
||||
for x in ['skip-schema-setup', 'skip-schema-teardown']
|
||||
]
|
||||
yield from db_context_common(
|
||||
request, hge_ctx,
|
||||
setup_files_attr, setup_default_file,
|
||||
teardown_files_attr, teardown_default_file,
|
||||
skip_setup, skip_teardown
|
||||
)
|
||||
|
||||
def db_context_with_schema_common_new(
|
||||
@ -928,23 +848,17 @@ def db_context_with_schema_common_new(
|
||||
setup_sql_file, teardown_sql_file,
|
||||
pre_setup_file, post_teardown_file,
|
||||
):
|
||||
(skip_setup, skip_teardown) = [
|
||||
request.config.getoption('--' + x)
|
||||
for x in ['skip-schema-setup', 'skip-schema-teardown']
|
||||
]
|
||||
yield from db_context_common_new(
|
||||
request, hge_ctx,
|
||||
setup_files_attr, setup_default_file, setup_sql_file,
|
||||
teardown_files_attr, teardown_default_file, teardown_sql_file,
|
||||
pre_setup_file, post_teardown_file,
|
||||
skip_setup, skip_teardown
|
||||
)
|
||||
|
||||
def db_context_common(
|
||||
request, hge_ctx,
|
||||
setup_files_attr, setup_default_file,
|
||||
teardown_files_attr, teardown_default_file,
|
||||
skip_setup=True, skip_teardown=True
|
||||
):
|
||||
def get_files(attr, default_file):
|
||||
files = getattr(request.cls, attr, None)
|
||||
@ -957,13 +871,11 @@ def db_context_common(
|
||||
yield from setup_and_teardown_v1q(
|
||||
request, hge_ctx,
|
||||
setup, teardown,
|
||||
skip_setup, skip_teardown
|
||||
)
|
||||
else:
|
||||
yield from setup_and_teardown_v2q(
|
||||
request, hge_ctx,
|
||||
setup, teardown,
|
||||
skip_setup, skip_teardown
|
||||
)
|
||||
|
||||
|
||||
@ -972,7 +884,6 @@ def db_context_common_new(
|
||||
setup_files_attr, setup_default_file, setup_default_sql_file,
|
||||
teardown_files_attr, teardown_default_file, teardown_default_sql_file,
|
||||
pre_setup_file, post_teardown_file,
|
||||
skip_setup=True, skip_teardown=True
|
||||
):
|
||||
def get_files(attr, default_file):
|
||||
files = getattr(request.cls, attr, None)
|
||||
@ -990,13 +901,11 @@ def db_context_common_new(
|
||||
setup, teardown,
|
||||
setup_default_sql_file, teardown_default_sql_file,
|
||||
pre_setup_default_file, post_teardown_default_file,
|
||||
skip_setup, skip_teardown
|
||||
)
|
||||
|
||||
def setup_and_teardown_v1q(
|
||||
request, hge_ctx,
|
||||
setup_files, teardown_files,
|
||||
skip_setup=False, skip_teardown=False
|
||||
):
|
||||
if PytestConf.config.getoption("--port-to-haskell"):
|
||||
backend = hge_ctx.backend.title()
|
||||
@ -1015,17 +924,13 @@ def setup_and_teardown_v1q(
|
||||
if os.path.isfile(filepath):
|
||||
return hge_ctx.v1q_f(filepath)
|
||||
|
||||
if not skip_setup:
|
||||
run_on_elem_or_list(v1q_f, setup_files)
|
||||
run_on_elem_or_list(v1q_f, setup_files)
|
||||
yield
|
||||
# Teardown anyway if any of the tests have failed
|
||||
if request.session.testsfailed > 0 or not skip_teardown:
|
||||
run_on_elem_or_list(v1q_f, teardown_files)
|
||||
run_on_elem_or_list(v1q_f, teardown_files)
|
||||
|
||||
def setup_and_teardown_v2q(
|
||||
request, hge_ctx,
|
||||
setup_files, teardown_files,
|
||||
skip_setup=False, skip_teardown=False
|
||||
):
|
||||
if PytestConf.config.getoption("--port-to-haskell"):
|
||||
backend = hge_ctx.backend.title()
|
||||
@ -1044,19 +949,15 @@ def setup_and_teardown_v2q(
|
||||
if os.path.isfile(filepath):
|
||||
return hge_ctx.v2q_f(filepath)
|
||||
|
||||
if not skip_setup:
|
||||
run_on_elem_or_list(v2q_f, setup_files)
|
||||
run_on_elem_or_list(v2q_f, setup_files)
|
||||
yield
|
||||
# Teardown anyway if any of the tests have failed
|
||||
if request.session.testsfailed > 0 or not skip_teardown:
|
||||
run_on_elem_or_list(v2q_f, teardown_files)
|
||||
run_on_elem_or_list(v2q_f, teardown_files)
|
||||
|
||||
def setup_and_teardown(
|
||||
request, hge_ctx,
|
||||
setup_files, teardown_files,
|
||||
sql_schema_setup_file, sql_schema_teardown_file,
|
||||
pre_setup_file, post_teardown_file,
|
||||
skip_setup=False, skip_teardown=False
|
||||
):
|
||||
if PytestConf.config.getoption("--port-to-haskell"):
|
||||
backend = hge_ctx.backend.title()
|
||||
@ -1101,16 +1002,13 @@ def setup_and_teardown(
|
||||
def pre_post_metadataq_f(f):
|
||||
if os.path.isfile(f):
|
||||
hge_ctx.v1metadataq_f(f)
|
||||
if not skip_setup:
|
||||
run_on_elem_or_list(pre_post_metadataq_f, pre_setup_file)
|
||||
run_on_elem_or_list(v2q_f, sql_schema_setup_file)
|
||||
run_on_elem_or_list(metadataq_f, setup_files)
|
||||
run_on_elem_or_list(pre_post_metadataq_f, pre_setup_file)
|
||||
run_on_elem_or_list(v2q_f, sql_schema_setup_file)
|
||||
run_on_elem_or_list(metadataq_f, setup_files)
|
||||
yield
|
||||
# Teardown anyway if any of the tests have failed
|
||||
if request.session.testsfailed > 0 or not skip_teardown:
|
||||
run_on_elem_or_list(metadataq_f, teardown_files)
|
||||
run_on_elem_or_list(v2q_f, sql_schema_teardown_file)
|
||||
run_on_elem_or_list(pre_post_metadataq_f, post_teardown_file)
|
||||
run_on_elem_or_list(metadataq_f, teardown_files)
|
||||
run_on_elem_or_list(v2q_f, sql_schema_teardown_file)
|
||||
run_on_elem_or_list(pre_post_metadataq_f, post_teardown_file)
|
||||
|
||||
def run_on_elem_or_list(f, x):
|
||||
if isinstance(x, str):
|
||||
|
@ -845,7 +845,6 @@ class HGECtx:
|
||||
self.meta = sqlalchemy.schema.MetaData()
|
||||
|
||||
self.hge_scale_url = config.getoption('--test-hge-scale-url')
|
||||
self.avoid_err_msg_checks = config.getoption('--avoid-error-message-checks')
|
||||
self.pro_tests = config.getoption('--pro-tests')
|
||||
|
||||
self.ws_client = GQLWsClient(self, '/v1/graphql')
|
||||
@ -865,7 +864,7 @@ class HGECtx:
|
||||
result = subprocess.run(['../../scripts/get-version.sh'], shell=False, stdout=subprocess.PIPE, check=True)
|
||||
self.version = result.stdout.decode('utf-8').strip()
|
||||
# TODO: remove once parallelization work is completed
|
||||
if clear_dbs and self.is_default_backend and (not enabled_apis or 'metadata' in enabled_apis) and not config.getoption('--skip-schema-setup'):
|
||||
if clear_dbs and self.is_default_backend and (not enabled_apis or 'metadata' in enabled_apis):
|
||||
try:
|
||||
self.v2q_f("queries/" + self.backend_suffix("clear_db")+ ".yaml")
|
||||
except requests.exceptions.RequestException as e:
|
||||
|
@ -15,7 +15,5 @@ markers =
|
||||
tls_webhook_server: Only run the webhook server with TLS enabled
|
||||
no_tls_webhook_server: Only run the webhook server with TLS disabled
|
||||
tls_insecure_certificate: Create an insecure (self-signed) certificate for the webhook server
|
||||
skip_server_upgrade_test: Tests with this marker should not be run as part of server upgrade test
|
||||
allow_server_upgrade_test: Add tests with this marker to server upgrade test, as far as they do not have the `skip_server_upgrade_test` marker
|
||||
capture_hge_logs: Enable to capture HGE logs for later inspection in a test
|
||||
value: A value used by self-tests
|
||||
|
@ -1,7 +1,5 @@
|
||||
import os
|
||||
import pytest
|
||||
import queue
|
||||
import sqlalchemy
|
||||
import time
|
||||
|
||||
import fixtures.postgres
|
||||
@ -12,9 +10,7 @@ from validate import check_query_f, check_event, check_event_transformed, check_
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
# Every test in this class requires the events webhook to be running first
|
||||
# We are also going to mark as server upgrade tests are allowed
|
||||
# A few tests are going to be excluded with skip_server_upgrade_test mark
|
||||
pytestmark = [usefixtures('evts_webhook'), pytest.mark.allow_server_upgrade_test]
|
||||
pytestmark = usefixtures('evts_webhook')
|
||||
|
||||
def select_last_event_fromdb(hge_ctx):
|
||||
q = {
|
||||
@ -118,8 +114,6 @@ class TestEventCreateAndDelete:
|
||||
def test_create_reset(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/create_and_reset.yaml")
|
||||
|
||||
# Can't run server upgrade tests, as this test has a schema change
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
def test_create_operation_spec_not_provider_err(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/create_trigger_operation_specs_not_provided_err.yaml")
|
||||
|
||||
@ -190,8 +184,6 @@ class TestEventCreateAndDeleteMSSQL:
|
||||
|
||||
check_query_f(hge_ctx, self.dir() + "/create_and_reset_mssql_2.yaml")
|
||||
|
||||
# Can't run server upgrade tests, as this test has a schema change
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
def test_create_operation_spec_not_provider_err(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/create_trigger_operation_specs_not_provided_err_mssql.yaml")
|
||||
|
||||
@ -874,7 +866,6 @@ class TestEventSelCols:
|
||||
delete(hge_ctx, table, where_exp)
|
||||
check_event(hge_ctx, evts_webhook, "t1_cols", table, "DELETE", exp_ev_data)
|
||||
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
def test_selected_cols_dep(self, hge_ctx, evts_webhook):
|
||||
resp = hge_ctx.v1q({
|
||||
"type": "run_sql",
|
||||
@ -940,7 +931,6 @@ class TestEventSelColsMSSQL:
|
||||
print("----- RESP 4 -----", resp)
|
||||
check_event(hge_ctx, evts_webhook, "t1_cols", table, "DELETE", exp_ev_data)
|
||||
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
def test_selected_cols_dep(self, hge_ctx, evts_webhook):
|
||||
# Dropping Primary Key is not allowed
|
||||
resp = hge_ctx.v2q({
|
||||
|
@ -3,10 +3,6 @@ import pytest
|
||||
from validate import check_query_f, check_query, get_conf_f
|
||||
|
||||
|
||||
# Marking all tests in this module that server upgrade tests can be run
|
||||
# Few of them cannot be run, which will be marked skip_server_upgrade_test
|
||||
pytestmark = pytest.mark.allow_server_upgrade_test
|
||||
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
use_mutation_fixtures = usefixtures(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
import ruamel.yaml as yaml
|
||||
import textwrap
|
||||
@ -8,9 +7,6 @@ import warnings
|
||||
from context import PytestConf
|
||||
from validate import assert_response_code, check_query_f, get_conf_f
|
||||
|
||||
# Mark that all tests in this module can be run as server upgrade tests
|
||||
pytestmark = pytest.mark.allow_server_upgrade_test
|
||||
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
|
||||
@ -152,8 +148,6 @@ class TestGraphQLQueryBasicMSSQL:
|
||||
@pytest.mark.backend('postgres')
|
||||
@usefixtures('per_class_tests_db_state')
|
||||
class TestGraphQLQueryBasicPostgres:
|
||||
# Can't run server upgrade tests, as this test has a schema change
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
def test_select_various_postgres_types(self, hge_ctx, transport):
|
||||
check_query_f(hge_ctx, self.dir() + '/select_query_test_types_postgres.yaml', transport)
|
||||
|
||||
@ -989,13 +983,9 @@ class TestGraphQLExplainPostgresMSSQL:
|
||||
def test_limit_orderby_column_query(self, hge_ctx):
|
||||
self.with_admin_secret("query", hge_ctx, self.dir() + '/limit_orderby_column_query.yaml')
|
||||
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
# skipping due to https://github.com/hasura/graphql-engine/issues/7936
|
||||
def test_limit_orderby_relationship_query(self, hge_ctx):
|
||||
self.with_admin_secret("query", hge_ctx, self.dir() + '/limit_orderby_relationship_query.yaml')
|
||||
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
# skipping due to https://github.com/hasura/graphql-engine/issues/7936
|
||||
def test_limit_offset_orderby_relationship_query(self, hge_ctx):
|
||||
self.with_admin_secret("query", hge_ctx, self.dir() + '/limit_offset_orderby_relationship_query.yaml')
|
||||
|
||||
@ -1241,7 +1231,6 @@ class TestGraphQLQueryBoolExpLtree:
|
||||
@pytest.mark.backend('mssql')
|
||||
@usefixtures('per_class_tests_db_state')
|
||||
class TestGraphQLQueryBoolExpSpatialMSSQL:
|
||||
@pytest.mark.skip_server_upgrade_test
|
||||
def test_select_spatial_mssql_types(self, hge_ctx, transport):
|
||||
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_mssql.yaml', transport)
|
||||
|
||||
|
@ -1,16 +1,10 @@
|
||||
import os
|
||||
import pytest
|
||||
import sqlalchemy
|
||||
from typing import Optional
|
||||
import urllib.parse
|
||||
|
||||
from context import HGECtx, PytestConf
|
||||
from context import HGECtx
|
||||
import fixtures.postgres
|
||||
from validate import check_query_f
|
||||
|
||||
# Mark that all tests in this module can be run as server upgrade tests
|
||||
pytestmark = pytest.mark.allow_server_upgrade_test
|
||||
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
@pytest.mark.parametrize('transport', ['http', 'websocket'])
|
||||
|
@ -1,13 +1,9 @@
|
||||
import pytest
|
||||
import os
|
||||
import redis
|
||||
|
||||
from validate import check_query_f, check_query, get_conf_f
|
||||
from validate import check_query_f
|
||||
from context import PytestConf
|
||||
|
||||
# Mark that all tests in this module can be run as server upgrade tests
|
||||
pytestmark = pytest.mark.allow_server_upgrade_test
|
||||
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
@pytest.mark.skipif(not PytestConf.config.getoption('--redis-url'), reason="Must enable redis")
|
||||
|
@ -75,16 +75,11 @@ class TestRemoteSchemaBasic:
|
||||
dir = 'queries/remote_schemas'
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
# This is needed for supporting server upgrade tests
|
||||
# Some marked tests in this class will be run as server upgrade tests
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
q = mk_add_remote_q('simple 1', f'{gql_server.url}/hello-graphql')
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
q = mk_add_remote_q('simple 1', f'{gql_server.url}/hello-graphql')
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
def test_add_schema(self, hge_ctx):
|
||||
""" check if the remote schema is added in the metadata """
|
||||
@ -159,7 +154,6 @@ class TestRemoteSchemaBasic:
|
||||
q = mk_update_remote_q('simple 1', f'{gql_server.url}/hello-graphql', None, False, 60)
|
||||
hge_ctx.v1q(q)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_introspection(self, hge_ctx):
|
||||
#check_query_f(hge_ctx, 'queries/graphql_introspection/introspection.yaml')
|
||||
with open('queries/graphql_introspection/introspection.yaml') as f:
|
||||
@ -167,11 +161,9 @@ class TestRemoteSchemaBasic:
|
||||
resp, _ = check_query(hge_ctx, query)
|
||||
assert check_introspection_result(resp, ['String'], ['hello'])
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_introspection_as_user(self, hge_ctx):
|
||||
check_query_f(hge_ctx, 'queries/graphql_introspection/introspection_user_role.yaml')
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_query(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir + '/basic_query.yaml')
|
||||
|
||||
@ -184,34 +176,29 @@ class TestRemoteSchemaBasic:
|
||||
resp = hge_ctx.v1q(q, expected_status_code = 400)
|
||||
assert resp['code'] == 'unexpected'
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remove_schema_error(self, hge_ctx):
|
||||
"""remove remote schema which is not added"""
|
||||
q = mk_delete_remote_q('random name')
|
||||
resp = hge_ctx.v1q(q, expected_status_code = 400)
|
||||
assert resp['code'] == 'not-exists'
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_reload_remote_schema(self, hge_ctx):
|
||||
"""reload a remote schema"""
|
||||
q = mk_reload_remote_q('simple 1')
|
||||
hge_ctx.v1q(q)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_second_remote_schema(self, hge_ctx, gql_server):
|
||||
"""add 2 remote schemas with different node and types"""
|
||||
q = mk_add_remote_q('my remote', f'{gql_server.url}/user-graphql')
|
||||
hge_ctx.v1q(q)
|
||||
hge_ctx.v1q(mk_delete_remote_q('my remote'))
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_json_scalar_dict(self, hge_ctx, gql_server):
|
||||
q = mk_add_remote_q('my remote', f'{gql_server.url}/json-scalar-graphql')
|
||||
hge_ctx.v1q(q)
|
||||
check_query_f(hge_ctx, self.dir + '/json_scalar.yaml')
|
||||
hge_ctx.v1q(mk_delete_remote_q('my remote'))
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_remote_schema_with_interfaces(self, hge_ctx, gql_server):
|
||||
"""add a remote schema with interfaces in it"""
|
||||
q = mk_add_remote_q('my remote interface one', f'{gql_server.url}/character-iface-graphql')
|
||||
@ -254,7 +241,6 @@ class TestRemoteSchemaBasic:
|
||||
having extra non_null argument"""
|
||||
check_query_f(hge_ctx, self.dir + '/add_remote_schema_with_iface_err_extra_non_null_arg.yaml')
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_remote_schema_with_union(self, hge_ctx, gql_server):
|
||||
"""add a remote schema with union in it"""
|
||||
q = mk_add_remote_q('my remote union one', f'{gql_server.url}/union-graphql')
|
||||
@ -288,16 +274,11 @@ class TestRemoteSchemaBasicExtensions:
|
||||
dir = 'queries/remote_schemas'
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
# This is needed for supporting server upgrade tests
|
||||
# Some marked tests in this class will be run as server upgrade tests
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
q = mk_add_remote_q('simple 1', f'{gql_server.url}/hello-graphql-extensions')
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
q = mk_add_remote_q('simple 1', f'{gql_server.url}/hello-graphql-extensions')
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
def test_remote_query(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir + '/basic_query.yaml')
|
||||
@ -314,7 +295,6 @@ class TestAddRemoteSchemaTbls:
|
||||
yield
|
||||
hge_ctx.v1q_f('queries/remote_schemas/tbls_teardown.yaml')
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_schema(self, hge_ctx):
|
||||
""" check if the remote schema is added in the metadata """
|
||||
resp = hge_ctx.v1q(export_metadata_q)
|
||||
@ -326,7 +306,6 @@ class TestAddRemoteSchemaTbls:
|
||||
resp = hge_ctx.v1q(q, expected_status_code = 400)
|
||||
assert resp['code'] == 'invalid-configuration'
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_second_remote_schema(self, hge_ctx, gql_server):
|
||||
"""add 2 remote schemas with different node and types"""
|
||||
q = mk_add_remote_q('my remote2', f'{gql_server.url}/country-graphql')
|
||||
@ -339,7 +318,6 @@ class TestAddRemoteSchemaTbls:
|
||||
def test_remote_mutation(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir + '/simple2_mutation.yaml')
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_conflicting_table(self, hge_ctx):
|
||||
resp = hge_ctx.v1q_f(self.dir + '/create_conflicting_table.yaml', expected_status_code = 400)
|
||||
assert resp['code'] == 'remote-schema-conflicts'
|
||||
@ -357,7 +335,6 @@ class TestAddRemoteSchemaTbls:
|
||||
resp = hge_ctx.v1q(q, expected_status_code = 400)
|
||||
assert resp['code'] == 'already-exists'
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_add_schema_same_type_containing_same_scalar(self, hge_ctx, gql_server):
|
||||
"""
|
||||
test types get merged when remote schema has type with same name and
|
||||
@ -370,7 +347,6 @@ class TestAddRemoteSchemaTbls:
|
||||
hge_ctx.v1q_f(self.dir + '/drop_person_table.yaml')
|
||||
hge_ctx.v1q({"type": "remove_remote_schema", "args": {"name": "person-graphql"}})
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_schema_forward_headers(self, hge_ctx, gql_server):
|
||||
"""
|
||||
test headers from client and conf and resolved info gets passed
|
||||
@ -418,7 +394,6 @@ class TestRemoteSchemaQueriesOverWebsocket:
|
||||
hge_ctx.v1q_f('queries/remote_schemas/tbls_teardown.yaml')
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_query(self, ws_client):
|
||||
query = """
|
||||
query {
|
||||
@ -438,7 +413,6 @@ class TestRemoteSchemaQueriesOverWebsocket:
|
||||
finally:
|
||||
ws_client.stop(query_id)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_query_error(self, ws_client):
|
||||
query = """
|
||||
query {
|
||||
@ -461,7 +435,6 @@ class TestRemoteSchemaQueriesOverWebsocket:
|
||||
finally:
|
||||
ws_client.stop(query_id)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_mutation(self, ws_client):
|
||||
query = """
|
||||
mutation {
|
||||
@ -496,7 +469,6 @@ class TestRemoteSchemaResponseHeaders():
|
||||
yield
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_response_headers_from_remote(self, hge_ctx):
|
||||
headers = {}
|
||||
if hge_ctx.hge_key:
|
||||
@ -520,7 +492,6 @@ class TestAddRemoteSchemaCompareRootQueryFields:
|
||||
yield
|
||||
hge_ctx.v1q(mk_delete_remote_q('default_value_test'))
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_schema_check_arg_default_values_and_field_and_arg_types(self, hge_ctx, gql_server):
|
||||
remote = f'{gql_server.url}/default-value-echo-graphql'
|
||||
with open('queries/graphql_introspection/introspection.yaml') as f:
|
||||
@ -551,7 +522,6 @@ class TestRemoteSchemaTimeout:
|
||||
yield
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_query_timeout(self, hge_ctx):
|
||||
with open(self.dir + '/basic_timeout_query.yaml') as f:
|
||||
query = yaml.load(f)
|
||||
@ -708,16 +678,11 @@ class TestRemoteSchemaTypePrefix:
|
||||
dir = 'queries/remote_schemas'
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
# This is needed for supporting server upgrade tests
|
||||
# Some marked tests in this class will be run as server upgrade tests
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
q = mk_add_remote_q('simple 2', f'{gql_server.url}/user-graphql', customization=type_prefix_customization("Foo"))
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
q = mk_add_remote_q('simple 2', f'{gql_server.url}/user-graphql', customization=type_prefix_customization("Foo"))
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
def test_add_schema(self, hge_ctx):
|
||||
""" check if the remote schema is added in the metadata """
|
||||
@ -725,7 +690,6 @@ class TestRemoteSchemaTypePrefix:
|
||||
found = [schema for schema in resp['remote_schemas'] if schema['name'] == 'simple 2']
|
||||
assert len(found) == 1, resp
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_introspection(self, hge_ctx):
|
||||
#check_query_f(hge_ctx, 'queries/graphql_introspection/introspection.yaml')
|
||||
with open('queries/graphql_introspection/introspection.yaml') as f:
|
||||
@ -738,14 +702,11 @@ class TestValidateRemoteSchemaTypePrefixQuery:
|
||||
teardown = {"type": "clear_metadata", "args": {}}
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=type_prefix_customization("Foo"))
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=type_prefix_customization("Foo"))
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -759,15 +720,12 @@ class TestValidateRemoteSchemaFieldPrefixQuery:
|
||||
teardown = {"type": "clear_metadata", "args": {}}
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
customization = { "field_names": [{"parent_type": "Character", "prefix": "foo_"},{"parent_type": "Human", "prefix": "foo_"},{"parent_type": "Droid", "prefix": "foo_"}] }
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=customization)
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
customization = { "field_names": [{"parent_type": "Character", "prefix": "foo_"},{"parent_type": "Human", "prefix": "foo_"},{"parent_type": "Droid", "prefix": "foo_"}] }
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=customization)
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -789,15 +747,12 @@ class TestValidateRemoteSchemaNamespaceQuery:
|
||||
teardown = {"type": "clear_metadata", "args": {}}
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
customization = { "root_fields_namespace": "foo" }
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=customization)
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
customization = { "root_fields_namespace": "foo" }
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=customization)
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -814,24 +769,21 @@ class TestValidateRemoteSchemaCustomizeAllTheThings:
|
||||
teardown = {"type": "clear_metadata", "args": {}}
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, hge_ctx, gql_server):
|
||||
config = request.config
|
||||
if not config.getoption('--skip-schema-setup'):
|
||||
customization = {
|
||||
"root_fields_namespace": "star_wars",
|
||||
"type_names": {"prefix": "Foo", "suffix": "_x", "mapping": { "Droid": "Android", "Int": "MyInt"}},
|
||||
"field_names": [
|
||||
{"parent_type": "Character", "prefix": "foo_", "suffix": "_f", "mapping": {"id": "ident"}},
|
||||
{"parent_type": "Human", "mapping": {"id": "ident", "name": "foo_name_f", "droid": "android"}},
|
||||
{"parent_type": "Droid", "prefix": "foo_", "suffix": "_f", "mapping": {"id": "ident"}},
|
||||
{"parent_type": "CharacterIFaceQuery", "prefix": "super_" }
|
||||
]
|
||||
}
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=customization)
|
||||
hge_ctx.v1q(q)
|
||||
def transact(self, hge_ctx, gql_server):
|
||||
customization = {
|
||||
"root_fields_namespace": "star_wars",
|
||||
"type_names": {"prefix": "Foo", "suffix": "_x", "mapping": { "Droid": "Android", "Int": "MyInt"}},
|
||||
"field_names": [
|
||||
{"parent_type": "Character", "prefix": "foo_", "suffix": "_f", "mapping": {"id": "ident"}},
|
||||
{"parent_type": "Human", "mapping": {"id": "ident", "name": "foo_name_f", "droid": "android"}},
|
||||
{"parent_type": "Droid", "prefix": "foo_", "suffix": "_f", "mapping": {"id": "ident"}},
|
||||
{"parent_type": "CharacterIFaceQuery", "prefix": "super_" }
|
||||
]
|
||||
}
|
||||
q = mk_add_remote_q('character-foo', f'{gql_server.url}/character-iface-graphql', customization=customization)
|
||||
hge_ctx.v1q(q)
|
||||
yield
|
||||
if request.session.testsfailed > 0 or not config.getoption('--skip-schema-teardown'):
|
||||
hge_ctx.v1q(self.teardown)
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -851,7 +803,6 @@ class TestRemoteSchemaRequestPayload:
|
||||
yield
|
||||
hge_ctx.v1q(self.teardown)
|
||||
|
||||
@pytest.mark.allow_server_upgrade_test
|
||||
def test_remote_schema_operation_name_in_response(self, hge_ctx):
|
||||
|
||||
with open('queries/remote_schemas/basic_query_with_op_name.yaml') as f:
|
||||
|
@ -345,7 +345,7 @@ def validate_gql_ws_q(hge_ctx, conf, headers, retry=False, via_subscription=Fals
|
||||
resp_done = next(query_resp)
|
||||
assert resp_done['type'] == 'complete'
|
||||
|
||||
return assert_graphql_resp_expected(resp['payload'], exp_http_response, query, skip_if_err_msg=hge_ctx.avoid_err_msg_checks)
|
||||
return assert_graphql_resp_expected(resp['payload'], exp_http_response, query)
|
||||
|
||||
def assert_response_code(url, query, code, exp_code, resp, body=None):
|
||||
assert code == exp_code, \
|
||||
@ -368,7 +368,7 @@ def validate_http_anyq(hge_ctx, url, query, headers, exp_code, exp_response, exp
|
||||
assert_response_code(url, query, code, exp_code, resp, body)
|
||||
|
||||
if exp_response:
|
||||
return assert_graphql_resp_expected(resp, exp_response, query, resp_hdrs, hge_ctx.avoid_err_msg_checks, exp_resp_hdrs=exp_resp_hdrs)
|
||||
return assert_graphql_resp_expected(resp, exp_response, query, resp_hdrs, exp_resp_hdrs=exp_resp_hdrs)
|
||||
else:
|
||||
return resp, True
|
||||
|
||||
@ -384,7 +384,7 @@ def validate_http_anyq_with_allowed_responses(hge_ctx, url, query, headers, exp_
|
||||
dict_resp = json.loads(json.dumps(response))
|
||||
exp_resp = dict_resp['response']
|
||||
exp_resp_hdrs = dict_resp.get('resp_headers')
|
||||
resp_result, pass_test = assert_graphql_resp_expected(resp, exp_resp, query, resp_hdrs, hge_ctx.avoid_err_msg_checks, True, exp_resp_hdrs)
|
||||
resp_result, pass_test = assert_graphql_resp_expected(resp, exp_resp, query, resp_hdrs, True, exp_resp_hdrs)
|
||||
if pass_test == True:
|
||||
test_passed = True
|
||||
resp_res = resp_result
|
||||
@ -404,7 +404,7 @@ def validate_http_anyq_with_allowed_responses(hge_ctx, url, query, headers, exp_
|
||||
#
|
||||
# Returns 'resp' and a bool indicating whether the test passed or not (this
|
||||
# will always be True unless we are `--accepting`)
|
||||
def assert_graphql_resp_expected(resp_orig, exp_response_orig, query, resp_hdrs={}, skip_if_err_msg=False, skip_assertion=False, exp_resp_hdrs={}):
|
||||
def assert_graphql_resp_expected(resp_orig, exp_response_orig, query, resp_hdrs={}, skip_assertion=False, exp_resp_hdrs={}):
|
||||
print('Reponse Headers: ', resp_hdrs)
|
||||
print(exp_resp_hdrs)
|
||||
|
||||
@ -440,12 +440,7 @@ def assert_graphql_resp_expected(resp_orig, exp_response_orig, query, resp_hdrs=
|
||||
'diff': (stringify_keys(jsondiff.diff(exp_resp_hdrs, diff_hdrs)))
|
||||
}
|
||||
yml.dump(test_output, stream=dump_str)
|
||||
if not skip_if_err_msg:
|
||||
if skip_assertion:
|
||||
return resp, matched
|
||||
else:
|
||||
assert matched, '\n' + dump_str.getvalue()
|
||||
elif matched:
|
||||
if matched:
|
||||
return resp, matched
|
||||
else:
|
||||
def is_err_msg(msg):
|
||||
|
Loading…
Reference in New Issue
Block a user