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:
Wolfgang Walther
2021-01-14 16:40:29 +01:00
committed by Wolfgang Walther
parent ab6f90aa78
commit 97d8456382
5 changed files with 251 additions and 12 deletions
@@ -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"
+4
View File
@@ -0,0 +1,4 @@
yaml:
is:
not:
supported:
+16
View File
@@ -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
+142
View File
@@ -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
View File
@@ -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")
)