nandi/frqpublic Fork 0
ec74784743600d5adda1b7d2ec1f9eb2a6bc23ca
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

tsession.nim · 106 lines · 4.0 KBNim Blame HistoryRaw
Ask for the backlog, and survive hanging up 6214c7e nandi 17h ago1## What this client says back to a server, given what a server says to it.
2##
3## The reducer's answer to an incoming line was the largest untested thing in
4## the program: reachable only through a real socket, so nothing checked it.
5## That is where the missing CHATHISTORY request sat through the whole port —
6## every room came back with no history and the only comment about it was in
7## another module, describing behaviour that had never been ported.
8##
9## `conn.feed` puts a line in as though the server had sent it; `tryOutbound`
10## reads what went out. No socket at either end.
11
12import std/[sequtils, strutils, tables, unittest]
13import frq/[cells, model, reducer, rooms]
14import frq/conn as tr
15
16proc sent(): seq[string] =
17 ## Everything queued to go out, drained.
18 while true:
19 let (ok, line) = tr.tryOutbound()
20 if not ok: break
21 result.add line
22
23proc say(lines: varargs[string]) =
24 for l in lines: tr.feed(l)
25 drain()
26
27proc reset() =
28 app = initState()
29 app.formNick = "alice"
30 discard sent()
31
32proc joined(room: string) =
33 ## The server putting us in a room, which is how every one of them starts —
34 ## a JOIN we sent, or one freeq made for a signed-in account at
35 ## registration. A 366 for a room this client has never heard of is not
36 ## ours and is left alone.
37 say(":alice!a@h JOIN " & room)
38 discard sent()
39
40suite "asking for the backlog":
41 setup: reset()
42
43 test "end of NAMES in an empty room asks for history":
44 joined("#freeq")
45 # freeq re-joins an authenticated user's channels at registration and
46 # leaves the backlog for the client to ask for. A room that arrives this
47 # way has no history coming unless we ask, which is why a signed-in
48 # connection showed new lines and nothing else.
49 say(":server 366 alice #freeq :End of /NAMES list")
50 check app.rooms.hasKey("#freeq")
51 check sent().anyIt(it.startsWith("CHATHISTORY LATEST #freeq * "))
52
53 test "and asks for a hundred lines of it":
54 joined("#freeq")
55 say(":server 366 alice #freeq :End of /NAMES list")
56 check "CHATHISTORY LATEST #freeq * 100" in sent()
57
58 test "a room that already has lines is not asked twice":
59 # The replay comes back as ordinary PRIVMSGs; asking again is a second
60 # copy of the same history crossing the wire to be thrown away.
61 joined("#freeq")
62 say(":bob!b@h PRIVMSG #freeq :already here")
63 discard sent()
64 say(":server 366 alice #freeq :End of /NAMES list")
65 check not sent().anyIt(it.startsWith("CHATHISTORY"))
66
67 test "a room this client was never put in is not asked about":
68 # Not a room of ours: 366 for it arrives before any JOIN, and answering
69 # it would ask a server for the history of somewhere we are not.
70 say(":server 366 alice #nowhere :End of /NAMES list")
71 check not app.rooms.hasKey("#nowhere")
72 check not sent().anyIt(it.startsWith("CHATHISTORY"))
73
74suite "the rest of the conversation":
75 setup: reset()
76
77 test "a PING is answered with its own token":
78 say("PING :abc123")
79 check "PONG :abc123" in sent()
80
81 test "our own JOIN marks the room joined; somebody else's adds a name":
82 say(":alice!a@h JOIN #freeq")
83 check app.rooms["#freeq"].joined
84 say(":bob!b@h JOIN #freeq")
85 check app.rooms["#freeq"].users.hasKey("bob")
86
87 test "NAMES arrives over several lines and lands in one go":
88 joined("#freeq")
89 say(":server 353 alice = #freeq :alice @bob",
90 ":server 353 alice = #freeq :carol")
91 # Still pending: replacing the list per line empties the panel and
92 # refills it a name at a time.
93 check app.rooms["#freeq"].users.len == 0
94 say(":server 366 alice #freeq :End of /NAMES list")
95 check app.rooms["#freeq"].users.len == 3
96
97 test "a replayed line lands in the room it names":
98 joined("#freeq")
99 say(":server 366 alice #freeq :End of /NAMES list",
100 ":bob!b@h PRIVMSG #freeq :an old line")
101 check app.rooms["#freeq"].messages.anyIt(it.text == "an old line")
102
103 test "a message to us is filed under whoever sent it":
104 say(":bob!b@h PRIVMSG alice :a direct word")
105 check app.rooms.hasKey("bob")
106 check app.rooms["bob"].messages[^1].text == "a direct word"