mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 17:31:56 +03:00
7c452bfca1
When running using the "new" style (with a HGE binary, not a URL), a new PostgreSQL metadata and source database are created for each test. When we get this into CI, this should drastically reduce the flakiness. I have also enabled parallelization by default when using `run-new.sh`. It's much faster. I had to basically rewrite _server/tests-py/test_graphql_read_only_source.py_ so that it does two different things depending on how it's run. It's unfortunate, but it should eventually go away. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6879 GitOrigin-RevId: a121b9035f8da3e61a3e36d8b1fbc6ccae918fad
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
import os
|
|
import pytest
|
|
import sqlalchemy
|
|
from typing import Optional
|
|
import urllib.parse
|
|
|
|
from context import HGECtx, PytestConf
|
|
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
|
|
|
|
if not PytestConf.config.getoption('--test-read-only-source'):
|
|
pytest.skip('--test-read-only-source flag is missing, skipping read-only tests',
|
|
allow_module_level=True)
|
|
|
|
@pytest.mark.parametrize('transport', ['http', 'websocket'])
|
|
@pytest.mark.backend('postgres', 'citus')
|
|
@pytest.mark.admin_secret
|
|
@pytest.mark.hge_env('HASURA_GRAPHQL_ADMIN_INTERNAL_ERRORS', 'false')
|
|
@usefixtures('setup_schema_externally')
|
|
class TestGraphQLOnReadOnlySource:
|
|
|
|
@classmethod
|
|
def dir(cls):
|
|
return 'queries/graphql_query/read_only_source'
|
|
|
|
setup_metadata_api_version = 'v2'
|
|
|
|
def test_query_aves(self, hge_ctx, transport):
|
|
check_query_f(hge_ctx, self.dir() + '/select_query_aves.yaml', transport)
|
|
|
|
# graphql-engine's websocket response is different than in http on execution
|
|
# errors; so this test is run only on http
|
|
def test_mutation_aves(self, hge_ctx, transport):
|
|
check_query_f(hge_ctx, self.dir() + '/update_query_aves.yaml', 'http')
|
|
|
|
|
|
# As this is a read-only test, we can't create the schema/tables as part of the
|
|
# HGE metadata. Hence, we create it as a separate fixture, where we execute the
|
|
# DDLs directly on the database.
|
|
@pytest.fixture(scope='class')
|
|
def setup_schema_externally(
|
|
owner_engine: sqlalchemy.engine.Engine,
|
|
hge_ctx: HGECtx,
|
|
source_backend: Optional[fixtures.postgres.Backend],
|
|
):
|
|
# TODO: remove once parallelization work is completed
|
|
# just use the default source, and get rid of this environment variable entirely
|
|
readonly_db_url = os.getenv('HASURA_READONLY_DB_URL')
|
|
|
|
if source_backend:
|
|
engine = source_backend.engine
|
|
elif readonly_db_url:
|
|
engine = fixtures.postgres.switch_schema(owner_engine, urllib.parse.urlparse(readonly_db_url).path.lstrip('/'))
|
|
else:
|
|
raise Exception('No database available.')
|
|
|
|
source = 'default'
|
|
# TODO: remove once parallelization work is completed
|
|
if readonly_db_url:
|
|
source = 'pg_readonly'
|
|
hge_ctx.v1metadataq({
|
|
'type': 'pg_add_source',
|
|
'args': {
|
|
'name': source,
|
|
'configuration': {
|
|
'connection_info': {
|
|
'database_url': {
|
|
'from_env': 'HASURA_READONLY_DB_URL',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
with engine.connect() as connection:
|
|
connection.execute("CREATE TABLE aves (id serial PRIMARY KEY, name TEXT)")
|
|
connection.execute("INSERT INTO aves (name) VALUES ('Booted Eagle'), ('Hooded Merganser')")
|
|
|
|
# TODO: remove once parallelization work is completed
|
|
# `source_backend` will no longer be optional
|
|
if source_backend:
|
|
# Revoke all write privileges from the given user
|
|
with fixtures.postgres.switch_schema(owner_engine, source_backend.name).connect() as connection:
|
|
username = source_backend.engine.url.username
|
|
connection.execute(f'REVOKE ALL PRIVILEGES ON SCHEMA public FROM {username}')
|
|
connection.execute(f'REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM {username}')
|
|
connection.execute(f'GRANT USAGE ON SCHEMA public TO {username}')
|
|
connection.execute(f'GRANT SELECT ON ALL TABLES IN SCHEMA public TO {username}')
|
|
connection.execute(f'GRANT SELECT ON ALL TABLES IN SCHEMA pg_catalog TO {username}')
|
|
connection.execute(f'GRANT SELECT ON ALL TABLES IN SCHEMA information_schema TO {username}')
|
|
connection.execute(f'ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO {username}')
|
|
|
|
hge_ctx.v1metadataq({
|
|
'type': 'pg_track_table',
|
|
'args': {
|
|
'source': source,
|
|
'table': {
|
|
'name': 'aves',
|
|
},
|
|
},
|
|
})
|
|
|
|
yield
|
|
|
|
# TODO: remove once parallelization work is completed
|
|
if readonly_db_url:
|
|
hge_ctx.v1metadataq({
|
|
'type': 'pg_drop_source',
|
|
'args': {
|
|
'name': source,
|
|
},
|
|
})
|
|
|
|
# TODO: remove once parallelization work is completed
|
|
# we can just drop the whole database
|
|
with engine.connect() as connection:
|
|
connection.execute('DROP TABLE aves')
|