test: Rewrite JWT cache tests

Timing dependent tests in the IO tests don't work too well when the next
commit increases the JWT parsing performance.

The remaining IO tests are for coverage and basic breakage. Loadtests
are adapted so that performance regressions for JWT caching would be
detected that way.
This commit is contained in:
Wolfgang Walther
2024-06-17 08:55:32 +02:00
committed by Wolfgang Walther
parent f69ef6c42d
commit 0948d38863
3 changed files with 42 additions and 70 deletions
+2
View File
@@ -55,6 +55,8 @@ let
export PGRST_DB_POOL="1"
export PGRST_DB_TX_END="rollback-allow-override"
export PGRST_LOG_LEVEL="crit"
export PGRST_JWT_SECRET="reallyreallyreallyreallyverysafe"
export PGRST_JWT_CACHE_MAX_LIFETIME="86400"
mkdir -p "$(dirname "$_arg_output")"
abs_output="$(realpath "$_arg_output")"
+34 -70
View File
@@ -1310,14 +1310,14 @@ def test_fail_with_automatic_recovery_disabled_and_terminated_using_query(defaul
assert exitCode == 1
def test_server_timing_jwt_should_decrease_on_subsequent_requests(defaultenv):
"assert that server-timing duration for JWT should decrease on subsequent requests"
def test_jwt_cache_server_timing(defaultenv):
"server-timing duration is exposed for JWT with expiry"
env = {
**defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_JWT_SECRET": SECRET,
"PGRST_DB_CONFIG": "false",
}
@@ -1331,102 +1331,66 @@ def test_server_timing_jwt_should_decrease_on_subsequent_requests(defaultenv):
SECRET,
)
with run(stdin=SECRET.encode(), env=env) as postgrest:
first_timings = postgrest.session.get("/authors_only", headers=headers).headers[
"Server-Timing"
]
second_timings = postgrest.session.get(
"/authors_only", headers=headers
).headers["Server-Timing"]
with run(env=env) as postgrest:
first = postgrest.session.get("/authors_only", headers=headers)
second = postgrest.session.get("/authors_only", headers=headers)
first_dur = parse_server_timings_header(first_timings)["jwt"]
second_dur = parse_server_timings_header(second_timings)["jwt"]
assert first.status_code == 200
assert second.status_code == 200
# their difference should be atleast 0.3ms, implying
# that JWT Caching is working as expected
assert (first_dur - second_dur) > 0.3
first_dur = parse_server_timings_header(first.headers["Server-Timing"])["jwt"]
second_dur = parse_server_timings_header(second.headers["Server-Timing"])["jwt"]
assert first_dur >= 0
assert second_dur >= 0
# just added to complete code coverage
def test_jwt_caching_works_with_db_plan_disabled(defaultenv):
"assert that JWT caching words even when Server-Timing header is not returned"
def test_jwt_cache_without_server_timing(defaultenv):
"JWT cache does not break requests without server-timing enabled"
env = {
**defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_JWT_SECRET": SECRET,
"PGRST_DB_CONFIG": "false",
}
headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET)
with run(stdin=SECRET.encode(), env=env) as postgrest:
first_request = postgrest.session.get("/authors_only", headers=headers)
second_request = postgrest.session.get("/authors_only", headers=headers)
with run(env=env) as postgrest:
first = postgrest.session.get("/authors_only", headers=headers)
second = postgrest.session.get("/authors_only", headers=headers)
# in this case we don't get server-timing in response headers
# so we can't compare durations, we just check if request succeeds
assert first_request.status_code == 200 and second_request.status_code == 200
assert first.status_code == 200
assert second.status_code == 200
def test_server_timing_jwt_should_not_decrease_when_caching_disabled(defaultenv):
"assert than jwt duration should not decrease when disabled"
env = {
**defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "0", # cache disabled
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_DB_CONFIG": "false",
}
headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET)
with run(stdin=SECRET.encode(), env=env) as postgrest:
warmup_req = postgrest.session.get("/authors_only", headers=headers)
first_timings = postgrest.session.get("/authors_only", headers=headers).headers[
"Server-Timing"
]
second_timings = postgrest.session.get(
"/authors_only", headers=headers
).headers["Server-Timing"]
first_dur = parse_server_timings_header(first_timings)["jwt"]
second_dur = parse_server_timings_header(second_timings)["jwt"]
# their difference should be less than 150
# implying that token is not cached
assert (first_dur - second_dur) < 150.0
def test_jwt_cache_with_no_exp_claim(defaultenv):
"assert than jwt duration should decrease"
def test_jwt_cache_without_exp_claim(defaultenv):
"server-timing duration is exposed for JWT without expiry"
env = {
**defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_JWT_SECRET": SECRET,
"PGRST_DB_CONFIG": "false",
}
headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET) # no exp
with run(stdin=SECRET.encode(), env=env) as postgrest:
first_timings = postgrest.session.get("/authors_only", headers=headers).headers[
"Server-Timing"
]
second_timings = postgrest.session.get(
"/authors_only", headers=headers
).headers["Server-Timing"]
with run(env=env) as postgrest:
first = postgrest.session.get("/authors_only", headers=headers)
second = postgrest.session.get("/authors_only", headers=headers)
first_dur = parse_server_timings_header(first_timings)["jwt"]
second_dur = parse_server_timings_header(second_timings)["jwt"]
assert first.status_code == 200
assert second.status_code == 200
# their difference should be atleast 0.3ms, implying
# that JWT Caching is working as expected
assert (first_dur - second_dur) > 0.3
first_dur = parse_server_timings_header(first.headers["Server-Timing"])["jwt"]
second_dur = parse_server_timings_header(second.headers["Server-Timing"])["jwt"]
assert first_dur >= 0
assert second_dur >= 0
def test_preflight_request_with_cors_allowed_origin_config(defaultenv):
+6
View File
@@ -1,10 +1,12 @@
GET http://postgrest/
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=commit
HEAD http://postgrest/actors?actor=eq.1
Prefer: tx=commit
GET http://postgrest/actors?select=*,roles(*,films(*))
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=commit
POST http://postgrest/films?columns=id,title
@@ -12,6 +14,7 @@ Prefer: tx=rollback
@post.json
POST http://postgrest/films?columns=id,title,year,runtime,genres,director,actors,plot,posterUrl
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=rollback
# this bulk.json was obtained from https://github.com/erik-sytnyk/movies-list/blob/master/db.json
@bulk.json
@@ -21,6 +24,7 @@ Prefer: tx=rollback
@put.json
PATCH http://postgrest/actors?actor=eq.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=rollback
@patch.json
@@ -28,8 +32,10 @@ DELETE http://postgrest/roles
Prefer: tx=rollback
GET http://postgrest/rpc/call_me?name=John
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
POST http://postgrest/rpc/call_me
@rpc.json
OPTIONS http://postgrest/actors
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk