syndicate-nim/tests/test_chat.nim

75 lines
1.9 KiB
Nim

# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[oserrors, parseopt, posix, strutils]
import pkg/sys/[files, handles, ioqueue]
import preserves, syndicate, syndicate/relays
type
Present {.preservesRecord: "Present".} = object
username: string
Says {.preservesRecord: "Says".} = object
who, what: string
proc syncAndStop(facet: Facet; cap: Cap) =
## Stop the actor responsible for `facet` after
## synchronizing with `cap`.
run(facet) do (turn: Turn):
sync(turn, cap, stopActor)
proc readStdin(facet: Facet; ds: Cap; username: string) {.asyncio.} =
let
fd = stdin.getOsFileHandle()
flags = fcntl(fd.cint, F_GETFL, 0)
if flags < 0:
raiseOSError(osLastError())
if fcntl(fd.cint, F_SETFL, flags or O_NONBLOCK) < 0:
raiseOSError(osLastError())
let
file = newAsyncFile(FD fd)
buf = new string
buf[].setLen(0x1000)
while true:
let n = read(file, buf)
if n < 1:
stderr.writeLine "test_chat calls stopsActor ", facet.actor
syncAndStop(facet, ds)
return
else:
var msg = buf[][0..<n].strip
proc send(turn: Turn) =
message(turn, ds, Says(who: username, what: msg))
run(facet, send)
proc chat(turn: Turn; ds: Cap; username: string) =
during(turn, ds, ?:Present) do (who: string):
echo who, " joined"
do:
echo who, " left"
onMessage(turn, ds, ?:Says) do (who: string, what: string):
echo who, ": ", what
discard publish(turn, ds, Present(username: username))
discard trampoline:
whelp readStdin(turn.facet, ds, username)
proc main =
var username = ""
for kind, key, val in getopt():
if kind == cmdLongOption:
case key
of "user", "username":
username = val
if username == "":
stderr.writeLine "--user: unspecified"
else:
runActor("chat") do (turn: Turn):
resolveEnvironment(turn) do (turn: Turn; ds: Cap):
chat(turn, ds, username)
main()