oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

1import XCTest
2
3@testable import CallsKit
4
5/// "<name> is connecting and can't hear you yet" (spec §15.24). Paul,
6/// 2026-10-01, asking for Zoom's "… is connecting to audio and cannot hear
7/// you yet": the gap after someone joins, said rather than talked into.
8final class ConnectingWatchTests: XCTestCase {
9 private typealias Peer = ConnectingWatch.Peer
10 private let waiting = Peer(epoch: 1, hearsMe: false, reported: true, connected: false, acked: false)
11
12 /// Runs the watch at 5 Hz from `from` to `to` seconds; when Sam's words
13 /// showed, and when they cleared with "can hear you now". `sam` nil is
14 /// Sam not in the roster.
15 private func run(
16 _ watch: inout ConnectingWatch, from: Double, to: Double, sam: (Double) -> Peer?
17 ) -> (shown: [Double], cleared: [Double]) {
18 var shown: [Double] = []
19 var cleared: [Double] = []
20 var t = from
21 while t < to {
22 let people = sam(t).map { ["sam": $0] } ?? [:]
23 if watch.observe(at: t, people: people).contains("sam") { cleared.append(t) }
24 if watch.shown.contains("sam") { shown.append(t) }
25 t = (t * 10 + 2).rounded() / 10
26 }
27 return (shown, cleared)
28 }
29
30 func testTheTimingsAreTheOnesTheSpecNames() {
31 XCTAssertEqual(ConnectingWatch.grace, 1)
32 XCTAssertEqual(ConnectingWatch.cap, 20)
33 }
34
35 func testAnOrdinaryJoinHeardWithinTheGraceSaysNothing() {
36 var watch = ConnectingWatch()
37 var sam = waiting
38 let seen = run(&watch, from: 0, to: 10) { t in
39 sam.connected = t >= 0.4
40 sam.hearsMe = t >= 0.8
41 return sam
42 }
43 XCTAssertEqual(seen.shown, [])
44 XCTAssertEqual(seen.cleared, [], "nothing was said, so \"can hear you now\" is not said either")
45 XCTAssertFalse(watch.joining.contains("sam"))
46 }
47
48 func testASlowJoinIsSaidAfterTheGraceAndClearsWhenTheyHearYou() {
49 var watch = ConnectingWatch()
50 var sam = waiting
51 let seen = run(&watch, from: 0, to: 12) { t in
52 sam.connected = t >= 5
53 sam.hearsMe = t >= 6
54 return sam
55 }
56 XCTAssertEqual(seen.shown.first, 1)
57 XCTAssertEqual(seen.shown.last, 5.8)
58 XCTAssertEqual(seen.cleared, [6])
59 }
60
61 func testOnceClearedItStaysClearedWhateverTheirListDoes() {
62 var watch = ConnectingWatch()
63 var sam = waiting
64 sam.connected = true
65 let seen = run(&watch, from: 0, to: 30) { t in
66 sam.hearsMe = t >= 3 && t < 10
67 return sam
68 }
69 XCTAssertEqual(seen.cleared, [3])
70 XCTAssertEqual(seen.shown.last, 2.8)
71 }
72
73 func testItIsGivenUpAtTheCapSilently() {
74 var watch = ConnectingWatch()
75 let seen = run(&watch, from: 0, to: 40) { _ in self.waiting }
76 XCTAssertEqual(seen.shown.first, 1)
77 XCTAssertEqual(seen.shown.last, 19.8)
78 XCTAssertEqual(seen.cleared, [], "a cap is not their hearing you")
79 XCTAssertTrue(watch.joining.isEmpty)
80 }
81
82 func testAClientThatDoesNotSayIsLetGoOnItsFirstReportAndAConnection() {
83 var watch = ConnectingWatch()
84 let seen = run(&watch, from: 0, to: 10) { t in
85 Peer(epoch: 1, hearsMe: nil, reported: t >= 4, connected: t >= 2, acked: false)
86 }
87 XCTAssertEqual(seen.cleared, [4])
88 }
89
90 func testOrOnAConnectionAndReceiverReportsShowingYourAudioReachesThem() {
91 var watch = ConnectingWatch()
92 let seen = run(&watch, from: 0, to: 10) { t in
93 Peer(epoch: 1, hearsMe: nil, reported: false, connected: t >= 2, acked: t >= 3)
94 }
95 XCTAssertEqual(seen.cleared, [3])
96 var unconnected = ConnectingWatch()
97 let never = run(&unconnected, from: 0, to: 10) { _ in
98 Peer(epoch: 1, hearsMe: nil, reported: true, connected: false, acked: true)
99 }
100 XCTAssertEqual(never.cleared, [], "never without a connection")
101 }
102
103 func testAClientThatSaysWhoItHearsIsBelievedOverYourOwnEvidence() {
104 var watch = ConnectingWatch()
105 let seen = run(&watch, from: 0, to: 10) { _ in
106 Peer(epoch: 1, hearsMe: false, reported: true, connected: true, acked: true)
107 }
108 XCTAssertEqual(seen.cleared, [])
109 XCTAssertFalse(seen.shown.isEmpty)
110 }
111
112 func testARejoinStartsItAgainAndSoDoesANewConnection() {
113 var watch = ConnectingWatch()
114 var sam = waiting
115 let seen = run(&watch, from: 0, to: 20) { t in
116 if t >= 5 && t < 6 { return nil }
117 sam.connected = true
118 sam.hearsMe = t < 5 ? t >= 2 : t >= 9
119 return sam
120 }
121 XCTAssertEqual(seen.cleared, [2, 9])
122 XCTAssertTrue(seen.shown.contains(7))
123 XCTAssertFalse(seen.shown.contains(6.8), "the grace again from the moment they are back")
124
125 var rebuilt = ConnectingWatch()
126 var again = waiting
127 again.connected = true
128 let second = run(&rebuilt, from: 0, to: 20) { t in
129 again.epoch = t < 8 ? 1 : 2
130 again.hearsMe = t < 1 || t >= 12
131 return again
132 }
133 XCTAssertEqual(second.cleared, [12])
134 XCTAssertEqual(second.shown.first, 9)
135 }
136
137 func testAMoreSpecificReportReplacesConnectingAndReconnectingWaitsUntilAfter() {
138 let plain = PeerMedia(muted: false, cameraOff: false, hearing: [])
139 func tile(
140 _ media: PeerMedia, muted: Bool = false, joining: Bool = true, shown: Bool = true,
141 reconnecting: Bool = false
142 ) -> (notices: [String], connecting: String?) {
143 ConnectingWatch.tile(
144 name: "Sam", media: media, me: "me", muted: muted, joining: joining, shown: shown,
145 reconnecting: reconnecting)
146 }
147 XCTAssertNil(tile(plain, shown: false).connecting, "inside the grace")
148 XCTAssertEqual(tile(plain).connecting, "Sam is connecting and can’t hear you yet")
149 XCTAssertEqual(tile(plain).notices, [])
150 XCTAssertNotNil(tile(plain, muted: true).connecting, "your own mute does not matter")
151 XCTAssertEqual(
152 tile(plain, reconnecting: true).notices, [], "a connection that has never been up is not reconnecting")
153 let blocked = PeerMedia(muted: false, cameraOff: false, audioBlocked: true, hearing: [])
154 XCTAssertEqual(tile(blocked, shown: false).notices, [AudioWords.blocked("Sam")], "even inside the grace")
155 XCTAssertNil(tile(blocked).connecting)
156 let silent = PeerMedia(muted: false, cameraOff: false, noSoundFrom: ["me"], hearing: ["me"])
157 XCTAssertEqual(tile(silent).notices, [AudioWords.notHearingYou("Sam")])
158 XCTAssertNil(tile(silent).connecting)
159 XCTAssertNotNil(
160 tile(PeerMedia(muted: false, cameraOff: false, noSoundFrom: ["me"]), muted: true).connecting,
161 "no sound from you while you are muted is expected, so it replaces nothing")
162 XCTAssertEqual(
163 tile(plain, joining: false, shown: false, reconnecting: true).notices, [ReconnectWords.peer("Sam")])
164 XCTAssertEqual(
165 tile(blocked, joining: false, shown: false, reconnecting: true).notices,
166 [ReconnectWords.peer("Sam"), AudioWords.blocked("Sam")])
167 XCTAssertEqual(tile(plain, joining: false, shown: false).notices, [])
168 }
169
170 func testHearsYou() {
171 XCTAssertEqual(HearingRule.hearsYou(PeerMedia(muted: false, cameraOff: false, hearing: ["me"]), me: "me"), true)
172 XCTAssertEqual(HearingRule.hearsYou(PeerMedia(muted: false, cameraOff: false, hearing: []), me: "me"), false)
173 XCTAssertNil(HearingRule.hearsYou(PeerMedia(muted: false, cameraOff: false), me: "me"))
174 XCTAssertNil(HearingRule.hearsYou(nil, me: "me"))
175 }
176
177 /// This app's own half: when a path counts as heard. A muted sender must
178 /// not look unheard.
179 func testHeardIsArrivingAndDecodedOrAMutedSenderOnALiveConnection() {
180 let base = HearingRule.Facts(
181 connected: true, bad: false, hasReceiver: true, receiverLive: true, packets: 0, decoded: 0,
182 senderMuted: false)
183 func with(_ change: (inout HearingRule.Facts) -> Void) -> HearingRule.Facts {
184 var f = base
185 change(&f)
186 return f
187 }
188 XCTAssertFalse(HearingRule.heard(was: false, base), "nothing has arrived")
189 XCTAssertFalse(HearingRule.heard(was: false, with { $0.packets = 10 }), "packets, nothing decoded")
190 XCTAssertTrue(HearingRule.heard(was: false, with { $0.packets = 10; $0.decoded = 3 }))
191 XCTAssertFalse(
192 HearingRule.heard(was: false, with { $0.packets = 10; $0.decoded = 3; $0.connected = false }),
193 "not before the connection is up")
194 XCTAssertTrue(HearingRule.heard(was: false, with { $0.senderMuted = true }), "a muted sender")
195 XCTAssertTrue(
196 HearingRule.heard(was: false, with { $0.senderMuted = true; $0.hasReceiver = false; $0.receiverLive = false }),
197 "nor one with no microphone at all")
198 XCTAssertFalse(
199 HearingRule.heard(was: false, with { $0.senderMuted = true; $0.receiverLive = false }), "but not a dead receiver")
200 XCTAssertTrue(HearingRule.heard(was: true, base), "once heard, kept")
201 XCTAssertTrue(HearingRule.heard(was: true, with { $0.connected = false }), "a blip is not losing them")
202 XCTAssertFalse(HearingRule.heard(was: true, with { $0.bad = true }), "a failed connection is")
203 }
204
205 func testTheHearingListDecodesAndAbsentIsNotEmpty() throws {
206 func media(_ json: String) throws -> PeerMedia? {
207 let state = try JSONDecoder().decode(
208 RoomState.self,
209 from: Data(
210 #"{"phase":"admitted","peer":"me","boot":"b","waiting":[],"peers":[{"peer":"sam","name":"Sam","kind":"member","gen":1,"media":\#(json)}]}"#
211 .utf8))
212 return Call.peerMedia("sam", in: state)
213 }
214 XCTAssertEqual(try media(#"{"muted":false,"cameraOff":false,"hearing":["me"]}"#)?.hearing, ["me"])
215 XCTAssertEqual(try media(#"{"muted":false,"cameraOff":false,"hearing":[]}"#)?.hearing, [])
216 XCTAssertNil(try media(#"{"muted":false,"cameraOff":false}"#)?.hearing)
217 }
218
219 func testTheDotsTakeTurnsAndNeverGoOut() {
220 for dot in 0..<3 {
221 for step in 0..<28 {
222 let o = ConnectingText.opacity(at: Double(step) * 0.05, dot: dot)
223 XCTAssertGreaterThanOrEqual(o, 0.35)
224 XCTAssertLessThanOrEqual(o, 1.0001)
225 }
226 }
227 XCTAssertEqual(ConnectingText.opacity(at: 0.56, dot: 0), 1, accuracy: 0.001)
228 XCTAssertEqual(ConnectingText.opacity(at: 0.76, dot: 1), 1, accuracy: 0.001)
229 XCTAssertEqual(ConnectingText.opacity(at: 0.96, dot: 2), 1, accuracy: 0.001)
230 }
231
232 func testAHearingReportGoesForAGainOrALossOfSomeoneStillHereAndNotForADeparture() {
233 let here: Set<String> = ["a", "b"]
234 XCTAssertTrue(HearingRule.moved(from: [], to: ["a"], present: here))
235 XCTAssertTrue(HearingRule.moved(from: ["a"], to: ["a", "b"], present: here))
236 XCTAssertTrue(HearingRule.moved(from: ["a", "b"], to: ["a"], present: here))
237 XCTAssertFalse(HearingRule.moved(from: ["a", "c"], to: ["a"], present: here), "c has left")
238 XCTAssertFalse(HearingRule.moved(from: ["a"], to: ["a"], present: here))
239 }
240}
241