luv

Workshop wiki

client-tests.lisp

lobby/client-tests.lisp

system luv/lobby/test · 13 definitions · on GitHub

defpackage#:luv.lobby.tests
:use#:cl#:rove
in-package#:luv.lobby.tests
defclassscripted-lobby-transport
lock:initform
sb-thread:make-mutex:name"scripted lobby transport"
:readerscripted-transport-lock
fail-opens:initarg:fail-opens:initform0:accessorscripted-transport-fail-opens
opens:initform0:accessorscripted-transport-opens
closes:initform0:accessorscripted-transport-closes
published:initformnil:accessorscripted-transport-published
defmethodluv.lobby:open-lobby-transport
declare
ignoreclient
sb-thread:with-mutex
scripted-transport-locktransport
incf
scripted-transport-openstransport
when
plusp
scripted-transport-fail-openstransport
decf
scripted-transport-fail-openstransport
error"scripted connection failure"
scripted-transport-openstransport
defmethodluv.lobby:subscribe-lobby-transport
connectionclient
declare
ignoretransportclient
connection
defmethodluv.lobby:publish-lobby-transport
connectionclientpayload
declare
ignoreconnectionclient
sb-thread:with-mutex
scripted-transport-locktransport
pushpayload
scripted-transport-publishedtransport
payload
defmethodluv.lobby:next-lobby-publication
connectionclient
declare
ignoretransportconnectionclient

A real transport has the same bounded idle poll. This tiny pause keeps the fake worker cooperative without turning the test into a busy loop.

sleep1/100
nil
defmethodluv.lobby:close-lobby-transport
connectionclient
declare
ignoreconnectionclient
sb-thread:with-mutex
scripted-transport-locktransport
incf
scripted-transport-closestransport
defunwait-for-lobby-test
predicate&key
timeout1.0
loopwithdeadline=
+
get-internal-real-time
*timeoutinternal-time-units-per-second
when
funcallpredicate
returntwhen
>=
get-internal-real-time
deadline
returnnildo
sleep1/200
deftestlobby-snapshot-is-semantic-and-does-not-revise-for-duplicates
let
client
luv.lobby:make-lobby-client:name"Mikael":client-id-prefix"test":transport
luv.lobby:receive-lobby-publicationclient
formatnil"luv/presence/~A"
luv.lobby:lobby-client-idclient
"Mikael"
luv.lobby:receive-lobby-publicationclient"luv/presence/game-2""Daniel"
let*
revision
luv.lobby:lobby-snapshot-revisionsnapshot
ok
eq:stopped
luv.lobby:lobby-snapshot-statussnapshot
ok
equal'
"Daniel"
mapcar#'luv.lobby:lobby-peer-name
luv.lobby:lobby-snapshot-peerssnapshot
luv.lobby:receive-lobby-publicationclient"luv/presence/game-2""Daniel"
ok
=revision
luv.lobby:lobby-snapshot-revision
ok
null
luv.lobby:lobby-snapshot-peers
deftestlobby-summary-is-a-constant-work-frame-boundary-view
let
client
luv.lobby:make-lobby-client:client-id-prefix"summary":transport
luv.lobby:receive-lobby-publicationclient"luv/presence/game-2""Daniel"
multiple-value-bind
statuspeer-countlast-errorrevision
ok
eq:stoppedstatus
ok
=1peer-count
ok
nulllast-error
ok
plusprevision

A duplicate publication changes neither the count nor the cheap semantic revision.

luv.lobby:receive-lobby-publicationclient"luv/presence/game-2""Daniel"
multiple-value-bind
later-statuslater-countlater-errorlater-revision
ok
eqstatuslater-status
ok
=peer-countlater-count
ok
eqlast-errorlater-error
ok
=revisionlater-revision
multiple-value-bind
statuspeer-countlast-errorrevision
ok
equal'
:stopped0nil0
liststatuspeer-countlast-errorrevision
deftestlobby-cache-is-connection-scoped
let
client
luv.lobby:make-lobby-client:client-id-prefix"test":transport
luv.lobby:receive-lobby-publicationclient"luv/presence/game-2""Daniel"
luv.lobby:receive-lobby-publicationclient"luv/store/OPENAI_API_KEY""secret"
ok
string="secret"
luv.lobby:lobby-client-valueclient"OPENAI_API_KEY"

A connecting transition begins a new subscription epoch. Both peer presence and retained values must be reconstructed by that connection.

luv.lobby::publish-lobby-statusclient:connecting:clear-cache-pt
let
ok
null
luv.lobby:lobby-snapshot-peerssnapshot
ok
null
luv.lobby:lobby-client-valueclient"OPENAI_API_KEY"
luv.lobby:receive-lobby-publicationclient"luv/store/OPENAI_API_KEY""new-secret"
luv.lobby:receive-lobby-publicationclient"luv/store/OPENAI_API_KEY"""
ok
null
luv.lobby:lobby-client-valueclient"OPENAI_API_KEY"
deftestlobby-worker-retries-stops-and-restarts
let*
transport
make-instance'scripted-lobby-transport:fail-opens1
client
luv.lobby:make-lobby-client:name"Mikael":client-id-prefix"luft":transporttransport
unwind-protect
progn
ok
wait-for-lobby-test
lambda
eq:online
luv.lobby:lobby-snapshot-status
ok
=2
scripted-transport-openstransport
ok
eq:stopped
luv.lobby:lobby-snapshot-status
ok
=1
scripted-transport-closestransport
ok
member"Mikael"
scripted-transport-publishedtransport
:test#'string=
ok
member""
scripted-transport-publishedtransport
:test#'string=

Restart reuses the semantic owner but starts a fresh worker and subscription epoch instead of retaining STOPPING-P forever.

ok
wait-for-lobby-test
lambda
=3
scripted-transport-openstransport
ok
=2
scripted-transport-closestransport
ignore-errors
deftestlobby-stop-interrupts-backoff-without-network-work-on-caller
let*
transport
make-instance'scripted-lobby-transport:fail-opens100
client
luv.lobby:make-lobby-client:client-id-prefix"test":transporttransport
unwind-protect
progn
ok
wait-for-lobby-test
lambda
eq:offline
luv.lobby:lobby-snapshot-status
let
started
get-internal-real-time
ok
<
/
-
get-internal-real-time
started
internal-time-units-per-second
0.25
ok
zerop
scripted-transport-closestransport
ignore-errors