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_POOL="1"
export PGRST_DB_TX_END="rollback-allow-override" export PGRST_DB_TX_END="rollback-allow-override"
export PGRST_LOG_LEVEL="crit" export PGRST_LOG_LEVEL="crit"
export PGRST_JWT_SECRET="reallyreallyreallyreallyverysafe"
export PGRST_JWT_CACHE_MAX_LIFETIME="86400"
mkdir -p "$(dirname "$_arg_output")" mkdir -p "$(dirname "$_arg_output")"
abs_output="$(realpath "$_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 assert exitCode == 1
def test_server_timing_jwt_should_decrease_on_subsequent_requests(defaultenv): def test_jwt_cache_server_timing(defaultenv):
"assert that server-timing duration for JWT should decrease on subsequent requests" "server-timing duration is exposed for JWT with expiry"
env = { env = {
**defaultenv, **defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true", "PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400", "PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin", "PGRST_JWT_SECRET": SECRET,
"PGRST_DB_CONFIG": "false", "PGRST_DB_CONFIG": "false",
} }
@@ -1331,102 +1331,66 @@ def test_server_timing_jwt_should_decrease_on_subsequent_requests(defaultenv):
SECRET, SECRET,
) )
with run(stdin=SECRET.encode(), env=env) as postgrest: with run(env=env) as postgrest:
first_timings = postgrest.session.get("/authors_only", headers=headers).headers[ first = postgrest.session.get("/authors_only", headers=headers)
"Server-Timing" second = postgrest.session.get("/authors_only", headers=headers)
]
second_timings = postgrest.session.get(
"/authors_only", headers=headers
).headers["Server-Timing"]
first_dur = parse_server_timings_header(first_timings)["jwt"] assert first.status_code == 200
second_dur = parse_server_timings_header(second_timings)["jwt"] assert second.status_code == 200
# their difference should be atleast 0.3ms, implying first_dur = parse_server_timings_header(first.headers["Server-Timing"])["jwt"]
# that JWT Caching is working as expected second_dur = parse_server_timings_header(second.headers["Server-Timing"])["jwt"]
assert (first_dur - second_dur) > 0.3
assert first_dur >= 0
assert second_dur >= 0
# just added to complete code coverage def test_jwt_cache_without_server_timing(defaultenv):
def test_jwt_caching_works_with_db_plan_disabled(defaultenv): "JWT cache does not break requests without server-timing enabled"
"assert that JWT caching words even when Server-Timing header is not returned"
env = { env = {
**defaultenv, **defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true", "PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400", "PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin", "PGRST_JWT_SECRET": SECRET,
"PGRST_DB_CONFIG": "false", "PGRST_DB_CONFIG": "false",
} }
headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET) headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET)
with run(stdin=SECRET.encode(), env=env) as postgrest: with run(env=env) as postgrest:
first_request = postgrest.session.get("/authors_only", headers=headers) first = postgrest.session.get("/authors_only", headers=headers)
second_request = 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 assert first.status_code == 200
# so we can't compare durations, we just check if request succeeds assert second.status_code == 200
assert first_request.status_code == 200 and second_request.status_code == 200
def test_server_timing_jwt_should_not_decrease_when_caching_disabled(defaultenv): def test_jwt_cache_without_exp_claim(defaultenv):
"assert than jwt duration should not decrease when disabled" "server-timing duration is exposed for JWT without expiry"
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"
env = { env = {
**defaultenv, **defaultenv,
"PGRST_SERVER_TIMING_ENABLED": "true", "PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400", "PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin", "PGRST_JWT_SECRET": SECRET,
"PGRST_DB_CONFIG": "false", "PGRST_DB_CONFIG": "false",
} }
headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET) # no exp headers = jwtauthheader({"role": "postgrest_test_author"}, SECRET) # no exp
with run(stdin=SECRET.encode(), env=env) as postgrest: with run(env=env) as postgrest:
first_timings = postgrest.session.get("/authors_only", headers=headers).headers[ first = postgrest.session.get("/authors_only", headers=headers)
"Server-Timing" second = postgrest.session.get("/authors_only", headers=headers)
]
second_timings = postgrest.session.get(
"/authors_only", headers=headers
).headers["Server-Timing"]
first_dur = parse_server_timings_header(first_timings)["jwt"] assert first.status_code == 200
second_dur = parse_server_timings_header(second_timings)["jwt"] assert second.status_code == 200
# their difference should be atleast 0.3ms, implying first_dur = parse_server_timings_header(first.headers["Server-Timing"])["jwt"]
# that JWT Caching is working as expected second_dur = parse_server_timings_header(second.headers["Server-Timing"])["jwt"]
assert (first_dur - second_dur) > 0.3
assert first_dur >= 0
assert second_dur >= 0
def test_preflight_request_with_cors_allowed_origin_config(defaultenv): def test_preflight_request_with_cors_allowed_origin_config(defaultenv):
+6
View File
@@ -1,10 +1,12 @@
GET http://postgrest/ GET http://postgrest/
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=commit Prefer: tx=commit
HEAD http://postgrest/actors?actor=eq.1 HEAD http://postgrest/actors?actor=eq.1
Prefer: tx=commit Prefer: tx=commit
GET http://postgrest/actors?select=*,roles(*,films(*)) GET http://postgrest/actors?select=*,roles(*,films(*))
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=commit Prefer: tx=commit
POST http://postgrest/films?columns=id,title POST http://postgrest/films?columns=id,title
@@ -12,6 +14,7 @@ Prefer: tx=rollback
@post.json @post.json
POST http://postgrest/films?columns=id,title,year,runtime,genres,director,actors,plot,posterUrl POST http://postgrest/films?columns=id,title,year,runtime,genres,director,actors,plot,posterUrl
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=rollback Prefer: tx=rollback
# this bulk.json was obtained from https://github.com/erik-sytnyk/movies-list/blob/master/db.json # this bulk.json was obtained from https://github.com/erik-sytnyk/movies-list/blob/master/db.json
@bulk.json @bulk.json
@@ -21,6 +24,7 @@ Prefer: tx=rollback
@put.json @put.json
PATCH http://postgrest/actors?actor=eq.1 PATCH http://postgrest/actors?actor=eq.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
Prefer: tx=rollback Prefer: tx=rollback
@patch.json @patch.json
@@ -28,8 +32,10 @@ DELETE http://postgrest/roles
Prefer: tx=rollback Prefer: tx=rollback
GET http://postgrest/rpc/call_me?name=John GET http://postgrest/rpc/call_me?name=John
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk
POST http://postgrest/rpc/call_me POST http://postgrest/rpc/call_me
@rpc.json @rpc.json
OPTIONS http://postgrest/actors OPTIONS http://postgrest/actors
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.CUIP5V9thWsGGFsFyGijSZf1fJMfarLHI9CEJL-TGNk