cov: Add io tests for basic cli commands and invalid config options
Full code coverage for Config.hs except expected overlays.
This commit is contained in:
committed by
Wolfgang Walther
parent
ab6f90aa78
commit
97d8456382
@@ -0,0 +1,25 @@
|
||||
db-anon-role = "required"
|
||||
db-channel = "pgrst"
|
||||
db-channel-enabled = false
|
||||
db-extra-search-path = "public"
|
||||
db-max-rows = ""
|
||||
db-pool = 10
|
||||
db-pool-timeout = 10
|
||||
db-pre-request = ""
|
||||
db-prepared-statements = true
|
||||
db-root-spec = ""
|
||||
db-schemas = "required"
|
||||
db-tx-end = "commit"
|
||||
db-uri = "required"
|
||||
jwt-aud = ""
|
||||
jwt-role-claim-key = ".\"role\""
|
||||
jwt-secret = ""
|
||||
jwt-secret-is-base64 = false
|
||||
log-level = "error"
|
||||
openapi-server-proxy-uri = ""
|
||||
raw-media-types = ""
|
||||
server-host = "!4"
|
||||
server-port = 3000
|
||||
server-unix-socket = ""
|
||||
server-unix-socket-mode = "660"
|
||||
app.settings.test = "Bool False"
|
||||
@@ -0,0 +1,4 @@
|
||||
yaml:
|
||||
is:
|
||||
not:
|
||||
supported:
|
||||
@@ -0,0 +1,16 @@
|
||||
# tests how config options fall back with invalid types
|
||||
db-anon-role = "required"
|
||||
db-schemas = "required"
|
||||
db-uri = "required"
|
||||
|
||||
# expects string
|
||||
app.settings.test = false
|
||||
|
||||
# expects boolean or string
|
||||
db-channel-enabled = 13
|
||||
|
||||
# expects integer or string
|
||||
db-max-rows = true
|
||||
|
||||
# expects string
|
||||
raw-media-types = true
|
||||
@@ -1,3 +1,144 @@
|
||||
cli:
|
||||
# success: valid commands
|
||||
- name: help long
|
||||
args: ['--help']
|
||||
- name: help short
|
||||
args: ['-h']
|
||||
- name: example long
|
||||
args: ['--example']
|
||||
- name: example short
|
||||
args: ['-e']
|
||||
- name: dump config
|
||||
args: ['--dump-config']
|
||||
use_defaultenv: true
|
||||
- name: dump schema
|
||||
args: ['--dump-schema']
|
||||
use_defaultenv: true
|
||||
# failures: config files
|
||||
- name: no config
|
||||
expect: error
|
||||
- name: non-existant config file
|
||||
expect: error
|
||||
args: ['does_not_exist.conf']
|
||||
- name: invalid config file
|
||||
expect: error
|
||||
args: ['test/io-tests/configs/invalid.yaml']
|
||||
# failures: required config options
|
||||
- name: missing db-anon-role
|
||||
expect: error
|
||||
env:
|
||||
PGRST_DB_URI: required
|
||||
PGRST_DB_SCHEMAS: required
|
||||
- name: missing db-schemas
|
||||
expect: error
|
||||
env:
|
||||
PGRST_DB_ANON_ROLE: required
|
||||
PGRST_DB_URI: required
|
||||
- name: missing db-uri
|
||||
expect: error
|
||||
env:
|
||||
PGRST_DB_ANON_ROLE: required
|
||||
PGRST_DB_SCHEMAS: required
|
||||
# failures: wrong config values
|
||||
- name: invalid server-unix-socket-mode not octal
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_SERVER_UNIX_SOCKET_MODE: '800'
|
||||
- name: invalid server-unix-socket-mode < 600
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_SERVER_UNIX_SOCKET_MODE: '599'
|
||||
- name: invalid server-unix-socket-mode > 777
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_SERVER_UNIX_SOCKET_MODE: '778'
|
||||
# TODO: Bug needs to be fixed
|
||||
# - name: invalid jwt-aud
|
||||
# expect: error
|
||||
# use_defaultenv: true
|
||||
# env:
|
||||
# PGRST_JWT_AUD: 'htp:/@@localhorst.invalid'
|
||||
- name: invalid log-level
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_LOG_LEVEL: never
|
||||
- name: invalid db-tx-end
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_DB_TX_END: random
|
||||
- name: invalid openapi-server-proxy-uri
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_OPENAPI_SERVER_PROXY_URI: 'htp:/@@localhorst.invalid'
|
||||
- name: invalid jwt-secret not base64
|
||||
expect: error
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_JWT_SECRET_IS_BASE64: 'true'
|
||||
PGRST_JWT_SECRET: 'no base-64!'
|
||||
# success: parsing config values
|
||||
- name: log-level=
|
||||
expect: 'log-level = "error"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_LOG_LEVEL: ""
|
||||
- name: log-level=crit
|
||||
expect: 'log-level = "crit"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_LOG_LEVEL: crit
|
||||
- name: log-level=error
|
||||
expect: 'log-level = "error"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_LOG_LEVEL: error
|
||||
- name: log-level=warn
|
||||
expect: 'log-level = "warn"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_LOG_LEVEL: warn
|
||||
- name: log-level=info
|
||||
expect: 'log-level = "info"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_LOG_LEVEL: info
|
||||
- name: db-tx-end=
|
||||
expect: 'db-tx-end = "commit"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_DB_TX_END: ""
|
||||
- name: db-tx-end=commit
|
||||
expect: 'db-tx-end = "commit"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_DB_TX_END: commit
|
||||
- name: db-tx-end=commit-allow-override
|
||||
expect: 'db-tx-end = "commit-allow-override"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_DB_TX_END: commit-allow-override
|
||||
- name: db-tx-end=rollback-allow-override
|
||||
expect: 'db-tx-end = "rollback-allow-override"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_DB_TX_END: rollback-allow-override
|
||||
- name: db-tx-end=rollback
|
||||
expect: 'db-tx-end = "rollback"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_DB_TX_END: rollback
|
||||
- name: raw-media-types list
|
||||
expect: 'raw-media-types = "image/png,image/jpeg"'
|
||||
use_defaultenv: true
|
||||
env:
|
||||
PGRST_RAW_MEDIA_TYPES: ' image/png , image/jpeg '
|
||||
|
||||
roleclaims:
|
||||
- key: '.postgrest.a_role'
|
||||
data:
|
||||
@@ -26,6 +167,7 @@ roleclaims:
|
||||
data:
|
||||
role: postgrest_test_author
|
||||
expected_status: 401
|
||||
|
||||
invalidroleclaimkeys:
|
||||
- 'role.other'
|
||||
- '.role##'
|
||||
|
||||
+64
-12
@@ -3,6 +3,7 @@
|
||||
import contextlib
|
||||
import dataclasses
|
||||
from datetime import datetime
|
||||
from itertools import repeat
|
||||
from operator import attrgetter
|
||||
import os
|
||||
import pathlib
|
||||
@@ -28,6 +29,22 @@ POSTGREST_BIN = shutil.which("postgrest")
|
||||
SECRET = "reallyreallyreallyreallyverysafe"
|
||||
|
||||
|
||||
def itemgetter(*items):
|
||||
"operator.itemgetter with None as fallback when key does not exist"
|
||||
if len(items) == 1:
|
||||
item = items[0]
|
||||
|
||||
def g(obj):
|
||||
return obj.get(item)
|
||||
|
||||
else:
|
||||
|
||||
def g(obj):
|
||||
return tuple(obj.get(item) for item in items)
|
||||
|
||||
return g
|
||||
|
||||
|
||||
class PostgrestTimedOut(Exception):
|
||||
"Connecting to PostgREST endpoint timed out."
|
||||
|
||||
@@ -83,27 +100,36 @@ def hpctixfile():
|
||||
return tixfile.with_suffix(f".{test}.tix")
|
||||
|
||||
|
||||
def dumpconfig(configpath=None, env=None, stdin=None):
|
||||
"Dump the config as parsed by PostgREST."
|
||||
def cli(args, env=None, stdin=None):
|
||||
"Run PostgREST and return stdout."
|
||||
env = env or {}
|
||||
|
||||
command = [POSTGREST_BIN, "--dump-config"]
|
||||
command = [POSTGREST_BIN] + args
|
||||
env["HPCTIXFILE"] = hpctixfile()
|
||||
|
||||
if configpath:
|
||||
command.append(configpath)
|
||||
|
||||
process = subprocess.Popen(
|
||||
command, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||
)
|
||||
|
||||
process.stdin.write(stdin or b"")
|
||||
result = process.communicate(timeout=5)[0]
|
||||
process.kill()
|
||||
process.wait()
|
||||
if process.returncode != 0:
|
||||
raise PostgrestError()
|
||||
return result.decode("utf-8")
|
||||
try:
|
||||
result = process.communicate(timeout=5)[0]
|
||||
if process.returncode != 0:
|
||||
raise PostgrestError()
|
||||
return result.decode("utf-8")
|
||||
finally:
|
||||
process.kill()
|
||||
process.wait()
|
||||
|
||||
|
||||
def dumpconfig(configpath=None, env=None, stdin=None):
|
||||
"Dump the config as parsed by PostgREST."
|
||||
args = ["--dump-config"]
|
||||
|
||||
if configpath:
|
||||
args.append(configpath)
|
||||
|
||||
return cli(args, env=env, stdin=stdin)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
@@ -181,6 +207,32 @@ def jwtauthheader(claim, secret):
|
||||
return authheader(jwt.encode(claim, secret).decode("utf-8"))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"args,env,use_defaultenv,expect",
|
||||
map(itemgetter("args", "env", "use_defaultenv", "expect"), FIXTURES["cli"]),
|
||||
ids=map(itemgetter("name"), FIXTURES["cli"]),
|
||||
)
|
||||
def test_cli(args, env, use_defaultenv, expect, defaultenv):
|
||||
"""
|
||||
When PostgREST is run with <args> arguments and <env>/<defaultenv> environment variabales
|
||||
it should return. Exit code should be according to <expect_error>.
|
||||
"""
|
||||
# use --dump-config by default to make sure that the postgrest process will terminate for sure
|
||||
args = args or ["--dump-config"]
|
||||
|
||||
env = env or {}
|
||||
if use_defaultenv:
|
||||
env = {**defaultenv, **env}
|
||||
|
||||
if expect == "error":
|
||||
with pytest.raises(PostgrestError):
|
||||
print(cli(args, env=env))
|
||||
else:
|
||||
dump = cli(args, env=env).split("\n")
|
||||
if expect:
|
||||
assert expect in dump
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"expectedconfig", (CONFIGSDIR / "expected").iterdir(), ids=attrgetter("name")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user