135 lines
4.6 KiB
Erlang
135 lines
4.6 KiB
Erlang
-module(infra_cleanup_tests).
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-include("records.hrl").
|
|
|
|
-define(TABLES, [notification, auth_session, admin_audit]).
|
|
|
|
setup() ->
|
|
eh_test_support:start_mnesia(),
|
|
eh_test_support:ensure_tables(?TABLES),
|
|
ok.
|
|
|
|
cleanup(_) ->
|
|
eh_test_support:clear_tables(?TABLES),
|
|
eh_test_support:delete_tables(?TABLES),
|
|
eh_test_support:stop_mnesia(),
|
|
ok.
|
|
|
|
infra_cleanup_test_() ->
|
|
{foreach, fun setup/0, fun cleanup/1, [
|
|
{"cutoff_datetime is in the past", fun test_cutoff_datetime/0},
|
|
{"keeps unread notifications", fun test_keeps_unread_notifications/0},
|
|
{"deletes old read notifications", fun test_deletes_old_read_notifications/0},
|
|
{"keeps active non-expired sessions", fun test_keeps_active_sessions/0},
|
|
{"deletes old revoked sessions", fun test_deletes_old_revoked_sessions/0},
|
|
{"deletes old admin_audit", fun test_deletes_old_admin_audit/0}
|
|
]}.
|
|
|
|
test_cutoff_datetime() ->
|
|
Cutoff = infra_cleanup:cutoff_datetime(30),
|
|
NowSecs = calendar:datetime_to_gregorian_seconds(calendar:universal_time()),
|
|
CutoffSecs = calendar:datetime_to_gregorian_seconds(Cutoff),
|
|
?assert(CutoffSecs < NowSecs),
|
|
%% ~30 days (± a few seconds for test runtime)
|
|
DiffDays = (NowSecs - CutoffSecs) / 86400,
|
|
?assert(DiffDays > 29.9),
|
|
?assert(DiffDays < 30.1).
|
|
|
|
test_keeps_unread_notifications() ->
|
|
Old = infra_cleanup:cutoff_datetime(60),
|
|
write_notification(<<"n_unread">>, false, Old),
|
|
write_notification(<<"n_read_recent">>, true, calendar:universal_time()),
|
|
#{notifications := N} = infra_cleanup:run_once(),
|
|
?assertEqual(0, N),
|
|
?assertMatch([_], mnesia:dirty_read(notification, <<"n_unread">>)),
|
|
?assertMatch([_], mnesia:dirty_read(notification, <<"n_read_recent">>)).
|
|
|
|
test_deletes_old_read_notifications() ->
|
|
Old = infra_cleanup:cutoff_datetime(60),
|
|
write_notification(<<"n_old_read">>, true, Old),
|
|
write_notification(<<"n_unread">>, false, Old),
|
|
#{notifications := N} = infra_cleanup:run_once(),
|
|
?assertEqual(1, N),
|
|
?assertEqual([], mnesia:dirty_read(notification, <<"n_old_read">>)),
|
|
?assertMatch([_], mnesia:dirty_read(notification, <<"n_unread">>)).
|
|
|
|
test_keeps_active_sessions() ->
|
|
Now = calendar:universal_time(),
|
|
Future = days_offset(Now, 7),
|
|
Recent = days_offset(Now, -1),
|
|
write_auth_session(<<"s_active">>, false, Future, Recent),
|
|
#{auth_sessions := N} = infra_cleanup:run_once(),
|
|
?assertEqual(0, N),
|
|
?assertMatch([_], mnesia:dirty_read(auth_session, <<"s_active">>)).
|
|
|
|
test_deletes_old_revoked_sessions() ->
|
|
Now = calendar:universal_time(),
|
|
Old = days_offset(Now, -14),
|
|
Future = days_offset(Now, 7),
|
|
write_auth_session(<<"s_revoked_old">>, true, Future, Old),
|
|
write_auth_session(<<"s_active">>, false, Future, Old),
|
|
#{auth_sessions := N} = infra_cleanup:run_once(),
|
|
?assert(N >= 1),
|
|
?assertEqual([], mnesia:dirty_read(auth_session, <<"s_revoked_old">>)),
|
|
%% Active but old created_at with future expiry must stay
|
|
?assertMatch([_], mnesia:dirty_read(auth_session, <<"s_active">>)).
|
|
|
|
test_deletes_old_admin_audit() ->
|
|
Now = calendar:universal_time(),
|
|
Old = days_offset(Now, -120),
|
|
write_admin_audit(<<"a_old">>, Old),
|
|
write_admin_audit(<<"a_new">>, Now),
|
|
#{admin_audit := N} = infra_cleanup:run_once(),
|
|
?assertEqual(1, N),
|
|
?assertEqual([], mnesia:dirty_read(admin_audit, <<"a_old">>)),
|
|
?assertMatch([_], mnesia:dirty_read(admin_audit, <<"a_new">>)).
|
|
|
|
%%%===================================================================
|
|
%%% Helpers
|
|
%%%===================================================================
|
|
|
|
write_notification(Id, IsRead, CreatedAt) ->
|
|
mnesia:dirty_write(#notification{
|
|
id = Id,
|
|
user_id = <<"u1">>,
|
|
type = custom,
|
|
title = <<"t">>,
|
|
body = <<"b">>,
|
|
is_read = IsRead,
|
|
created_at = CreatedAt
|
|
}).
|
|
|
|
write_auth_session(Id, Revoked, ExpiresAt, CreatedAt) ->
|
|
mnesia:dirty_write(#auth_session{
|
|
session_id = Id,
|
|
family_id = <<"fam">>,
|
|
subject_id = <<"subj">>,
|
|
subject_type = user,
|
|
client_type = <<"web">>,
|
|
current_jti = <<"jti">>,
|
|
expires_at = ExpiresAt,
|
|
revoked = Revoked,
|
|
created_at = CreatedAt,
|
|
updated_at = CreatedAt,
|
|
device_name = <<>>,
|
|
user_agent = <<>>
|
|
}).
|
|
|
|
write_admin_audit(Id, Timestamp) ->
|
|
mnesia:dirty_write(#admin_audit{
|
|
id = Id,
|
|
admin_id = <<"adm">>,
|
|
email = <<"a@test.local">>,
|
|
role = admin,
|
|
action = <<"test">>,
|
|
entity_type = <<"user">>,
|
|
entity_id = <<"u1">>,
|
|
timestamp = Timestamp,
|
|
ip = <<"127.0.0.1">>,
|
|
reason = <<>>
|
|
}).
|
|
|
|
days_offset(Datetime, Days) ->
|
|
Secs = calendar:datetime_to_gregorian_seconds(Datetime),
|
|
calendar:gregorian_seconds_to_datetime(Secs + Days * 86400).
|