;; identity/tests/session_mgmt.sx — subject-wide session management:
;; enumerate a subject's sessions and \"log out everywhere\".

(define id-smgmt-test-count 0)
(define id-smgmt-test-pass 0)
(define id-smgmt-test-fails (list))

(define
  id-smgmt-test
  (fn
    (name actual expected)
    (set! id-smgmt-test-count (+ id-smgmt-test-count 1))
    (if
      (= actual expected)
      (set! id-smgmt-test-pass (+ id-smgmt-test-pass 1))
      (append! id-smgmt-test-fails {:name name :expected expected :actual actual}))))

(define idsm-ev erlang-eval-ast)
(define idsmnm (fn (v) (get v :name)))

(identity-load-all!)

;; ── enumerate a subject's sessions ───────────────────────────────

(id-smgmt-test
  "sessions lists all of a subject's sessions"
  (idsm-ev
    "Svc = identity:start(),\n     identity:login(Svc, alice, web, read),\n     identity:login(Svc, alice, cli, read),\n     length(identity:sessions(Svc, alice))")
  2)

(id-smgmt-test
  "sessions is empty for a subject with none"
  (idsm-ev
    "Svc = identity:start(),\n     length(identity:sessions(Svc, stranger))")
  0)

;; ── log out everywhere ───────────────────────────────────────────

(id-smgmt-test
  "logout_all ends every session of the subject"
  (idsmnm
    (idsm-ev
      "Svc = identity:start(),\n       {ok, S1, _} = identity:login(Svc, alice, web, read),\n       {ok, S2, _} = identity:login(Svc, alice, cli, read),\n       identity:logout_all(Svc, alice),\n       case {identity:session_status(Svc, S1), identity:session_status(Svc, S2)} of\n         {gone, gone} -> both_gone;\n         _ -> some_left\n       end"))
  "both_gone")

(id-smgmt-test
  "after logout_all the subject has no sessions"
  (idsm-ev
    "Svc = identity:start(),\n     identity:login(Svc, alice, web, read),\n     identity:login(Svc, alice, cli, read),\n     identity:logout_all(Svc, alice),\n     length(identity:sessions(Svc, alice))")
  0)

(id-smgmt-test
  "logout_all leaves other subjects' sessions intact"
  (idsm-ev
    "Svc = identity:start(),\n     identity:login(Svc, alice, web, read),\n     identity:login(Svc, bob, web, read),\n     identity:logout_all(Svc, alice),\n     length(identity:sessions(Svc, bob))")
  1)

(id-smgmt-test
  "logout_all on an unknown subject is ok, not a crash"
  (idsmnm
    (idsm-ev "Svc = identity:start(),\n       identity:logout_all(Svc, ghost)"))
  "ok")

;; ── logout_all is audited ────────────────────────────────────────

(id-smgmt-test
  "logout_all records a logout event"
  (idsmnm
    (idsm-ev
      "Svc = identity:start(),\n       identity:login(Svc, alice, web, read),\n       identity:logout_all(Svc, alice),\n       case identity:history(Svc, alice) of\n         [login, issue, logout] -> audited;\n         Other -> Other\n       end"))
  "audited")

(id-smgmt-test
  "logout_all audits each of several sessions"
  (idsm-ev
    "Svc = identity:start(),\n     identity:login(Svc, alice, web, read),\n     identity:login(Svc, alice, cli, read),\n     identity:logout_all(Svc, alice),\n     length(identity:history(Svc, alice))")
  6)

(define
  id-smgmt-test-summary
  (str "session-mgmt " id-smgmt-test-pass "/" id-smgmt-test-count))
