Files
rose-ash/lib/identity/tests/session.sx
giles 1c6b80404e
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 48s
identity: session-as-process — create/lookup/expire/revoke + idle timeout (11 tests)
Session is an Erlang process holding {subject, client, status}. lookup/
touch/expire/revoke are messages; expiry is the process's own
`receive ... after Ttl` timeout (RFC-agnostic; no global sweep), which
notifies the owner and tombstones. Tombstoned sessions answer lookups
with an explicit {error, expired|revoked}, never a silent dead mailbox.
Adds the conformance harness + scoreboard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 23:45:50 +00:00

119 lines
4.7 KiB
Plaintext

;; identity/tests/session.sx — session-as-process: create, lookup,
;; touch, explicit expire, revoke, and idle-timeout self-expiry.
;; Negative paths are tested as first-class: a tombstoned session
;; answers {error, Status}, it does not go silent.
(define id-session-test-count 0)
(define id-session-test-pass 0)
(define id-session-test-fails (list))
(define
id-session-test
(fn
(name actual expected)
(set! id-session-test-count (+ id-session-test-count 1))
(if
(= actual expected)
(set! id-session-test-pass (+ id-session-test-pass 1))
(append! id-session-test-fails {:name name :expected expected :actual actual}))))
(define id-ev erlang-eval-ast)
(define idnm (fn (v) (get v :name)))
(identity-load-session!)
;; ── create + lookup ──────────────────────────────────────────────
(id-session-test
"lookup of live session is active"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n case identity_session:lookup(S) of {ok, {_,_,_,St}} -> St end"))
"active")
(id-session-test
"lookup preserves subject"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n case identity_session:lookup(S) of {ok, {_,Subject,_,_}} -> Subject end"))
"alice")
(id-session-test
"lookup preserves client"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n case identity_session:lookup(S) of {ok, {_,_,Client,_}} -> Client end"))
"web")
;; ── touch keeps a live session ───────────────────────────────────
(id-session-test
"touch on live session is ok"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n identity_session:touch(S)"))
"ok")
;; ── explicit expire ──────────────────────────────────────────────
(id-session-test
"expire then lookup is error expired"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n identity_session:expire(S),\n case identity_session:lookup(S) of {error, St} -> St end"))
"expired")
(id-session-test
"touch on expired session is error"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n identity_session:expire(S),\n case identity_session:touch(S) of {error, St} -> St end"))
"expired")
;; ── revoke is immediate ──────────────────────────────────────────
(id-session-test
"revoke then lookup is error revoked"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n identity_session:revoke(S),\n case identity_session:lookup(S) of {error, St} -> St end"))
"revoked")
;; ── idle-timeout self-expiry ─────────────────────────────────────
(id-session-test
"idle timeout notifies owner"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, 50),\n _ = identity_session:lookup(S),\n receive {session_expired, Sid} -> Sid end"))
"s1")
(id-session-test
"lookup after idle timeout is error expired"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, 50),\n _ = identity_session:lookup(S),\n receive {session_expired, _} -> ok end,\n case identity_session:lookup(S) of {error, St} -> St end"))
"expired")
;; ── isolation: sessions are independent processes ────────────────
(id-session-test
"expiring one session leaves the other active"
(idnm
(id-ev
"Me = self(),\n A = identity_session:start(s1, alice, web, Me, infinity),\n B = identity_session:start(s2, bob, web, Me, infinity),\n identity_session:expire(A),\n case identity_session:lookup(B) of {ok, {_,_,_,St}} -> St end"))
"active")
;; ── clean stop ───────────────────────────────────────────────────
(id-session-test
"stop returns ok"
(idnm
(id-ev
"Me = self(),\n S = identity_session:start(s1, alice, web, Me, infinity),\n identity_session:stop(S)"))
"ok")
(define
id-session-test-summary
(str "session " id-session-test-pass "/" id-session-test-count))