mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-04 20:06:35 +03:00
server: hasura on PG v13 (#125)
GitOrigin-RevId: 00fd91c250bcf3dc7ee638e3b152e0dab7281de7
This commit is contained in:
parent
3736a569ad
commit
f6bd354b40
@ -1,7 +1,7 @@
|
||||
# anchor refs to be used elsewhere
|
||||
refs:
|
||||
constants:
|
||||
- &server_builder_image hasura/graphql-engine-server-builder:2020-08-26
|
||||
- &server_builder_image hasura/graphql-engine-server-builder:2020-11-05
|
||||
skip_job_on_ciignore: &skip_job_on_ciignore
|
||||
run:
|
||||
name: checking if job should be terminated or not
|
||||
@ -79,7 +79,7 @@ refs:
|
||||
|
||||
setup_remote_docker: &setup_remote_docker
|
||||
setup_remote_docker:
|
||||
version: 17.09.0-ce
|
||||
version: 19.03.13
|
||||
docker_layer_caching: true
|
||||
|
||||
# ref pg environment for testing
|
||||
@ -105,7 +105,7 @@ refs:
|
||||
command: |
|
||||
mkdir -p /usr/share/man/man{1,7}
|
||||
apt-get update
|
||||
apt install --yes pgbouncer jq curl postgresql-client-12
|
||||
apt install --yes pgbouncer jq curl postgresql-client-13
|
||||
- run:
|
||||
name: Ensure databases are present
|
||||
environment:
|
||||
@ -171,7 +171,7 @@ jobs:
|
||||
name: Install latest postgresql client tools
|
||||
command: |
|
||||
apt-get -y update
|
||||
apt-get -y install postgresql-client-12
|
||||
apt-get -y install postgresql-client-13
|
||||
- run:
|
||||
name: Build the binary
|
||||
working_directory: ./server
|
||||
@ -236,6 +236,16 @@ jobs:
|
||||
command: echo 'all server tests passed!'
|
||||
|
||||
# pytest the server with postgres versions >= 9.5
|
||||
test_server_pg_13:
|
||||
<<: *test_server
|
||||
environment:
|
||||
PG_VERSION: "13"
|
||||
POSTGIS_VERSION: "3.0.0"
|
||||
docker:
|
||||
- image: *server_builder_image
|
||||
- image: hasura/postgres-13.0-alpine-postgis3
|
||||
<<: *test_pg_env
|
||||
|
||||
test_server_pg_12:
|
||||
<<: *test_server
|
||||
environment:
|
||||
@ -609,6 +619,10 @@ workflows:
|
||||
requires:
|
||||
- build_server
|
||||
- build_console
|
||||
- test_server_pg_13:
|
||||
<<: *filter_only_vtags
|
||||
requires:
|
||||
- build_server
|
||||
- test_server_pg_12:
|
||||
<<: *filter_only_vtags
|
||||
requires:
|
||||
@ -640,6 +654,7 @@ workflows:
|
||||
- all_server_tests_pass:
|
||||
<<: *filter_only_vtags
|
||||
requires:
|
||||
- test_server_pg_13
|
||||
- test_server_pg_12
|
||||
- test_server_pg_11
|
||||
- test_server_pg_10
|
||||
|
2
.circleci/postgres-13.0-alpine-postgis3/Dockerfile
Normal file
2
.circleci/postgres-13.0-alpine-postgis3/Dockerfile
Normal file
@ -0,0 +1,2 @@
|
||||
FROM circleci/postgres:13.0-postgis
|
||||
ENV POSTGRES_PASSWORD="postgres"
|
@ -1,9 +1,9 @@
|
||||
# Don't update this without updating the
|
||||
# packager imager of graphql-engine
|
||||
# packager image of graphql-engine
|
||||
FROM haskell:8.10.2-stretch
|
||||
|
||||
ARG docker_ver="17.09.0-ce"
|
||||
ARG postgres_ver="12"
|
||||
ARG docker_ver="19.03.13"
|
||||
ARG postgres_ver="13"
|
||||
ARG node_ver="12.x"
|
||||
|
||||
# Install GNU make, curl, git and docker client. Required to build the server
|
||||
|
@ -72,6 +72,7 @@ This release contains the [PDV refactor (#4111)](https://github.com/hasura/graph
|
||||
- console: select first operator by default on the browse rows screen (close #5729) (#6032)
|
||||
- cli: add missing global flags for seed command (#5565)
|
||||
- cli: allow seeds as alias for seed command (#5693)
|
||||
- build: add `test_server_pg_13` to the CI to run the server tests on Postgres v13 (#6070)
|
||||
|
||||
## v1.3.3
|
||||
|
||||
|
@ -5,7 +5,7 @@ export VERSION
|
||||
|
||||
registry := hasura
|
||||
packager_ver := 20190731
|
||||
pg_dump_ver := 12
|
||||
pg_dump_ver := 13
|
||||
build_output := /build/_server_output
|
||||
|
||||
# Getting access to the built products with the `cabal v2-*` commands is really awkward; see
|
||||
|
@ -13,9 +13,17 @@ query:
|
||||
}
|
||||
}
|
||||
|
||||
response:
|
||||
errors:
|
||||
- extensions:
|
||||
code: constraint-violation
|
||||
path: $.selectionSet.insert_address.args.objects
|
||||
message: "Not-NULL violation. null value in column \"door_no\" violates not-null constraint"
|
||||
allowed_responses:
|
||||
- response:
|
||||
errors:
|
||||
- extensions:
|
||||
code: constraint-violation
|
||||
path: $.selectionSet.insert_address.args.objects
|
||||
message: "Not-NULL violation. null value in column \"door_no\" violates not-null constraint"
|
||||
# postgres 13
|
||||
- response:
|
||||
errors:
|
||||
- extensions:
|
||||
code: constraint-violation
|
||||
path: $.selectionSet.insert_address.args.objects
|
||||
message: "Not-NULL violation. null value in column \"door_no\" of relation \"address\" violates not-null constraint"
|
||||
|
@ -379,9 +379,6 @@ class TestGraphqlUpdateBasic:
|
||||
def test_column_in_multiple_operators(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/article_column_multiple_operators.yaml")
|
||||
|
||||
def test_column_in_multiple_operators(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/article_column_multiple_operators.yaml")
|
||||
|
||||
def test_author_by_pk(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/author_by_pk.yaml")
|
||||
|
||||
|
@ -8,6 +8,7 @@ resp_pg_version_map = {
|
||||
'10': 'response_10_11',
|
||||
'11': 'response_10_11',
|
||||
'12': 'response_10_11',
|
||||
'13': 'response_10_11',
|
||||
'latest': 'response_10_11'
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,17 @@
|
||||
# tests are running correctly, or test our python test helpers.
|
||||
|
||||
import pytest
|
||||
from validate import check_query_f, collapse_order_not_selset
|
||||
from validate import (
|
||||
check_query_f,
|
||||
collapse_order_not_selset,
|
||||
validate_http_anyq_with_allowed_responses,
|
||||
)
|
||||
from ruamel.yaml.comments import CommentedMap
|
||||
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
@usefixtures('per_class_tests_db_state')
|
||||
|
||||
@usefixtures("per_class_tests_db_state")
|
||||
class TestTests1:
|
||||
"""
|
||||
Test various things about our test framework code. Validate that tests work
|
||||
@ -161,3 +166,90 @@ class TestTests2:
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/graphql_query/permissions'
|
||||
|
||||
@usefixtures("per_class_tests_db_state")
|
||||
class TestTests3:
|
||||
|
||||
"""
|
||||
This test case is about testing validate_http_anyq_with_allowed_responses
|
||||
with an empty list of allowed responses wherein it should throw an exception
|
||||
"""
|
||||
|
||||
@pytest.mark.xfail(reason="expected, validating function working")
|
||||
def test_tests_validate_http_anyq_with_allowed_responses_with_empty_list(
|
||||
self, hge_ctx
|
||||
):
|
||||
# These values are being set as they are in address_not_null_constraint_error.yaml
|
||||
|
||||
url = "/v1/graphql"
|
||||
query = {
|
||||
"query": 'mutation {\n insert_address(objects: [{street: "koramangala"}]){\n returning{\n id\n street\n }\n affected_rows\n }\n} \n'
|
||||
}
|
||||
|
||||
try:
|
||||
resp, pass_test = validate_http_anyq_with_allowed_responses(
|
||||
hge_ctx, url, query, {}, 200, []
|
||||
)
|
||||
except:
|
||||
print("FAIL!")
|
||||
assert 0, "Test failure, occurs as expected"
|
||||
# It reaches here only if the exception wasn't caught, in which case
|
||||
# this current test should fail
|
||||
|
||||
"""
|
||||
This test case is about testing validate_http_anyq_with_allowed_responses
|
||||
with a list of allowed responses which are incorrect wherein it should fail the test
|
||||
"""
|
||||
|
||||
@pytest.mark.xfail(reason="expected, validating test code")
|
||||
def test_tests_validate_http_anyq_with_allowed_responses_with_no_correct_response(
|
||||
self, hge_ctx
|
||||
):
|
||||
# These values are being set as they are in address_not_null_constraint_error.yaml
|
||||
|
||||
url = "/v1/graphql"
|
||||
query = {
|
||||
"query": 'mutation {\n insert_address(objects: [{street: "koramangala"}]){\n returning{\n id\n street\n }\n affected_rows\n }\n} \n'
|
||||
}
|
||||
allowed_response_1 = {
|
||||
"response": {
|
||||
"errors": [
|
||||
{
|
||||
"extensions": {
|
||||
"code": "constraint-violation",
|
||||
"path": "$.selectionSet.insert_address.args.objects",
|
||||
},
|
||||
"message": 'Not-NULL. null value in column "door_no" violates not-null constraint',
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
allowed_response_2 = {
|
||||
"response": {
|
||||
"errors": [
|
||||
{
|
||||
"extensions": {
|
||||
"code": "constraint-violation",
|
||||
"path": "$.selectionSet.insert_address.args.objects",
|
||||
},
|
||||
"message": 'Not-NULL violation. null value in column "door_no" of relation "address" not-null constraint',
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
allowed_responses = [allowed_response_1, allowed_response_2]
|
||||
|
||||
try:
|
||||
resp, err = validate_http_anyq_with_allowed_responses(
|
||||
hge_ctx, url, query, {}, 200, allowed_responses
|
||||
)
|
||||
except:
|
||||
print("FAIL!")
|
||||
assert 0, "Test failed, as expected"
|
||||
|
||||
|
||||
|
||||
# Re-use setup and teardown from where we adapted this test case:
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return "queries/graphql_mutation/insert/constraints"
|
||||
|
@ -199,7 +199,11 @@ def check_query(hge_ctx, conf, transport='http', add_auth=True, claims_namespace
|
||||
assert transport in ['http', 'websocket', 'subscription'], "Unknown transport type " + transport
|
||||
if transport == 'http':
|
||||
print('running on http')
|
||||
return validate_http_anyq(hge_ctx, conf['url'], conf['query'], headers,
|
||||
if 'allowed_responses' in conf:
|
||||
return validate_http_anyq_with_allowed_responses(hge_ctx, conf['url'], conf['query'], headers,
|
||||
conf['status'], conf.get('allowed_responses'))
|
||||
else:
|
||||
return validate_http_anyq(hge_ctx, conf['url'], conf['query'], headers,
|
||||
conf['status'], conf.get('response'))
|
||||
elif transport == 'websocket':
|
||||
print('running on websocket')
|
||||
@ -274,18 +278,44 @@ def validate_http_anyq(hge_ctx, url, query, headers, exp_code, exp_response):
|
||||
else:
|
||||
return resp, True
|
||||
|
||||
def validate_http_anyq_with_allowed_responses(hge_ctx, url, query, headers, exp_code, allowed_responses):
|
||||
code, resp, resp_hdrs = hge_ctx.anyq(url, query, headers)
|
||||
print(headers)
|
||||
assert code == exp_code, resp
|
||||
print('http resp: ', resp)
|
||||
if isinstance(allowed_responses, list) and len(allowed_responses) > 0:
|
||||
resp_res = {}
|
||||
test_passed = False
|
||||
|
||||
for response in allowed_responses:
|
||||
dict_resp = json.loads(json.dumps(response))
|
||||
exp_resp = dict_resp['response']
|
||||
resp_result, pass_test = assert_graphql_resp_expected(resp, exp_resp, query, resp_hdrs, hge_ctx.avoid_err_msg_checks, True)
|
||||
if pass_test == True:
|
||||
test_passed = True
|
||||
resp_res = resp_result
|
||||
break
|
||||
|
||||
if test_passed == True:
|
||||
return resp_res, test_passed
|
||||
else:
|
||||
# test should fail if none of the allowed responses work
|
||||
raise Exception("allowed_responses did not contain the response that was expected. Please check your allowed_responses")
|
||||
else:
|
||||
raise Exception("allowed_responses was not a list of permissible responses")
|
||||
|
||||
# Check the actual graphql response is what we expected, also taking into
|
||||
# consideration the ordering of keys that we expect to be preserved, based on
|
||||
# 'query'.
|
||||
#
|
||||
# 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):
|
||||
# Prepare actual and respected responses so comparison takes into
|
||||
def assert_graphql_resp_expected(resp_orig, exp_response_orig, query, resp_hdrs={}, skip_if_err_msg=False, skip_assertion=False):
|
||||
# Prepare actual and expected responses so comparison takes into
|
||||
# consideration only the ordering that we care about:
|
||||
resp = collapse_order_not_selset(resp_orig, query)
|
||||
exp_response = collapse_order_not_selset(exp_response_orig, query)
|
||||
matched = equal_CommentedMap(resp, exp_response)
|
||||
matched = equal_CommentedMap(resp, exp_response)
|
||||
|
||||
if PytestConf.config.getoption("--accept"):
|
||||
print('skipping assertion since we chose to --accept new output')
|
||||
@ -307,7 +337,10 @@ def assert_graphql_resp_expected(resp_orig, exp_response_orig, query, resp_hdrs=
|
||||
test_output['request id'] = resp_hdrs['x-request-id']
|
||||
yml.dump(test_output, stream=dump_str)
|
||||
if not skip_if_err_msg:
|
||||
assert matched, '\n' + dump_str.getvalue()
|
||||
if skip_assertion:
|
||||
return resp, matched
|
||||
else:
|
||||
assert matched, '\n' + dump_str.getvalue()
|
||||
elif matched:
|
||||
return resp, matched
|
||||
else:
|
||||
@ -323,7 +356,10 @@ def assert_graphql_resp_expected(resp_orig, exp_response_orig, query, resp_hdrs=
|
||||
warnings.warn("Response does not have the expected error message\n" + dump_str.getvalue())
|
||||
return resp, matched
|
||||
else:
|
||||
assert matched_, '\n' + dump_str.getvalue()
|
||||
if skip_assertion:
|
||||
return resp, matched_
|
||||
else:
|
||||
assert matched_, '\n' + dump_str.getvalue()
|
||||
return resp, matched # matched always True unless --accept
|
||||
|
||||
# This really sucks; newer ruamel made __eq__ ignore ordering:
|
||||
|
Loading…
Reference in New Issue
Block a user