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 CallsBroadcastKit
4@testable import CallsKit
5
6/// §5.4's receiving half. These are room-share.test.mjs's classifyTrack
7/// cases, case for case: the browser and the apps look at the same
8/// senders, and the day they disagree about which m-line is a screen, one
9/// of them captions a face as a screen. A case added there belongs here.
10final class ScreenShareTests: XCTestCase {
11 private let nothing = ScreenClues()
12 private let known = ScreenClues(cameraMid: "0", cameraStream: "cam", peerStream: "cam")
13 private func video(_ stream: String = "", mid: String = "", direction: String = "")
14 -> ArrivingTrack
15 {
16 ArrivingTrack(kind: "video", streamId: stream, mid: mid, direction: direction)
17 }
18
19 func testAudioIsNeverAScreen() {
20 let audio = ArrivingTrack(kind: "audio", streamId: "other", mid: "9")
21 XCTAssertEqual(classifyTrack(nothing, audio, hasVideo: true), .audio)
22 XCTAssertEqual(classifyTrack(known, audio, hasVideo: true), .audio)
23 }
24
25 func testTheFirstVideoTrackIsTheCamera() {
26 XCTAssertEqual(classifyTrack(nothing, video("cam", mid: "0"), hasVideo: false), .camera)
27 XCTAssertEqual(classifyTrack(nothing, video(), hasVideo: false), .camera)
28 }
29
30 func testASecondVideoTrackOnAnotherTransceiverIsTheScreen() {
31 XCTAssertEqual(classifyTrack(known, video("screen", mid: "2"), hasVideo: false), .screen)
32 }
33
34 func testTheCameraAgainIsStillTheCamera() {
35 XCTAssertEqual(classifyTrack(known, video("cam", mid: "0"), hasVideo: false), .camera)
36 // The mid decides when there is one, whatever the stream is now called.
37 XCTAssertEqual(classifyTrack(known, video("renamed", mid: "0"), hasVideo: false), .camera)
38 }
39
40 func testWithNoMidTheStreamDecides() {
41 let byStream = ScreenClues(cameraStream: "cam")
42 XCTAssertEqual(classifyTrack(byStream, video("cam"), hasVideo: false), .camera)
43 XCTAssertEqual(classifyTrack(byStream, video("screen"), hasVideo: false), .screen)
44 XCTAssertEqual(classifyTrack(known, video("cam"), hasVideo: false), .camera)
45 XCTAssertEqual(classifyTrack(known, video("screen"), hasVideo: false), .screen)
46 }
47
48 func testASecondVideoTrackWithNothingToCompareIsTheScreen() {
49 XCTAssertEqual(classifyTrack(known, video(), hasVideo: false), .screen)
50 }
51
52 func testRecvonlyIsTheScreenWhenThisSideSendsACamera() {
53 // The rule that decides in practice here: the apps always add a
54 // camera, so a video m-line arriving recvonly is one the far side
55 // added, and a screen is the only one it adds — even as the first
56 // video track that peer ever sends.
57 XCTAssertEqual(
58 classifyTrack(nothing, video("screen", mid: "2", direction: "recvonly"), hasVideo: true),
59 .screen)
60 }
61
62 func testRecvonlySaysNothingWithoutACameraOfOurOwn() {
63 XCTAssertEqual(
64 classifyTrack(nothing, video("cam", mid: "1", direction: "recvonly"), hasVideo: false),
65 .camera)
66 }
67
68 func testASendrecvCameraIsACamera() {
69 XCTAssertEqual(
70 classifyTrack(nothing, video("cam", mid: "1", direction: "sendrecv"), hasVideo: true),
71 .camera)
72 }
73
74 func testAVideoTrackOutsideTheMicrophonesStreamIsTheScreen() {
75 let audioOnly = ScreenClues(peerStream: "theirs")
76 XCTAssertEqual(classifyTrack(audioOnly, video("screen", mid: "2"), hasVideo: false), .screen)
77 XCTAssertEqual(classifyTrack(audioOnly, video("theirs", mid: "1"), hasVideo: false), .camera)
78 }
79
80 func testTheShareMessageBreaksTheTieAndOnlyTheTie() {
81 XCTAssertEqual(classifyTrack(ScreenClues(sharing: true), video(), hasVideo: false), .screen)
82 XCTAssertEqual(classifyTrack(ScreenClues(sharing: false), video(), hasVideo: false), .camera)
83 let sharing = ScreenClues(peerStream: "theirs", sharing: true)
84 XCTAssertEqual(classifyTrack(sharing, video("theirs", mid: "1"), hasVideo: false), .camera)
85 XCTAssertEqual(
86 classifyTrack(ScreenClues(cameraMid: "1", sharing: true), video(mid: "1"), hasVideo: false),
87 .camera)
88 }
89
90 func testTheCaptionIsTheBrowsers() {
91 // Typographic apostrophe, as room.js's shareCaption writes it.
92 XCTAssertEqual(screenCaption("Bea"), "Bea\u{2019}s screen")
93 }
94
95 func testAScreenIsFittedEvenAndNeverEnlarged() {
96 // A 5K display at 2x comes down to 1920 on its long side, keeping its
97 // shape; both sides even, for the encoders' 4:2:0 chroma.
98 let big = fitted(width: 5120, height: 2880, longest: 1920)
99 XCTAssertEqual(big.width, 1920)
100 XCTAssertEqual(big.height, 1080)
101 // A small window is sent at its own size, rounded down to even.
102 let small = fitted(width: 801, height: 601, longest: 1920)
103 XCTAssertEqual(small.width, 800)
104 XCTAssertEqual(small.height, 600)
105 // A portrait phone screen is fitted on its height.
106 let phone = fitted(width: 1179, height: 2556, longest: 1280)
107 XCTAssertEqual(phone.height, 1280)
108 XCTAssertEqual(phone.width % 2, 0)
109 XCTAssertEqual(fitted(width: 0, height: 100, longest: 1920).width, 2)
110 }
111
112 // ---------------------------------------------------------------
113 // The stage
114 // ---------------------------------------------------------------
115
116 func testTheStageIsTheFirstCameraWithNoScreens() {
117 XCTAssertEqual(Stage.speaker(pinned: nil, active: nil, others: ["a", "b"], screens: []), .camera("a"))
118 XCTAssertNil(Stage.speaker(pinned: nil, active: nil, others: [], screens: []))
119 }
120
121 func testTheNewestScreenTakesTheStage() {
122 XCTAssertEqual(Stage.speaker(pinned: nil, active: "a", others: ["a", "b"], screens: ["b"]), .screen("b"))
123 XCTAssertEqual(
124 Stage.speaker(pinned: nil, active: nil, others: ["a", "b"], screens: ["b", "a"]), .screen("a"))
125 }
126
127 func testAPinStandsWhileItIsThere() {
128 XCTAssertEqual(
129 Stage.speaker(pinned: .camera("a"), active: "b", others: ["a", "b"], screens: ["b"]), .camera("a"))
130 XCTAssertEqual(
131 Stage.speaker(pinned: .screen("a"), active: nil, others: ["a", "b"], screens: ["a", "b"]),
132 .screen("a"))
133 }
134
135 func testAPinThatWentAwayFallsBack() {
136 // A stopped screen, and a person who left: neither leaves the stage
137 // empty while there is something else to show.
138 XCTAssertEqual(
139 Stage.speaker(pinned: .screen("a"), active: nil, others: ["a", "b"], screens: []), .camera("a"))
140 XCTAssertEqual(
141 Stage.speaker(pinned: .camera("c"), active: nil, others: ["a"], screens: ["a"]), .screen("a"))
142 }
143}
144