eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

1import XCTest
2@testable import LChatCore
3
4// πŸ€– The notification-tap resolution ladder (NotificationRoute): NSE origin
5// stamp β†’ parked key β†’ snapshot scan β†’ only-space β†’ last-active space. The
6// silent-drop bug this pins: a stale or missing SharedThreadKeys park used to
7// strand the tap on the chat list.
8final class NotificationRouteTests: XCTestCase {
9
10 private func inst(_ origin: String, archived: Bool = false) -> SavedInstance {
11 var i = SavedInstance(origin: origin, deviceToken: "t", screenName: "s",
12 userPub: "pub", userPriv: "priv")
13 i.archived = archived
14 return i
15 }
16
17 func testStampedOriginWinsOverEverything() {
18 // The NSE stamped the banner at delivery time β€” the route trusts it
19 // before consulting any on-device state (which can churn between
20 // delivery and tap).
21 let a = inst("https://a.example"), b = inst("https://b.example")
22 let r = NotificationRoute.resolve(
23 threadID: "th1", origin: "https://b.example", instances: [a, b],
24 entryOrigin: { _ in XCTFail("park consulted despite stamp"); return "https://a.example" },
25 snapshotHasThread: { _, _ in XCTFail("snapshot consulted despite stamp"); return false })
26 guard case .stamped(let hit) = r else { return XCTFail("\(r)") }
27 XCTAssertEqual(hit.origin, b.origin)
28 }
29
30 func testStaleStampFallsDownTheLadder() {
31 // A stamp for a space that's since been signed out must not dead-end
32 // the tap β€” the ladder still runs beneath it.
33 let a = inst("https://a.example"), b = inst("https://b.example")
34 let r = NotificationRoute.resolve(
35 threadID: "th1", origin: "https://gone.example", instances: [a, b],
36 entryOrigin: { _ in "https://a.example" },
37 snapshotHasThread: { _, _ in false })
38 guard case .parkedKey(let hit) = r else { return XCTFail("\(r)") }
39 XCTAssertEqual(hit.origin, a.origin)
40 }
41
42 func testParkedKeyWins() {
43 let a = inst("https://a.example"), b = inst("https://b.example")
44 let r = NotificationRoute.resolve(
45 threadID: "th1", instances: [a, b],
46 entryOrigin: { _ in "https://b.example" },
47 snapshotHasThread: { _, _ in XCTFail("snapshot consulted despite park"); return false })
48 guard case .parkedKey(let hit) = r else { return XCTFail("\(r)") }
49 XCTAssertEqual(hit.origin, b.origin)
50 }
51
52 func testStaleParkFallsBackToSnapshot() {
53 // The park points at an origin that's no longer signed in (re-added
54 // space) β€” the snapshot scan must still find the thread's real home.
55 let a = inst("https://a.example"), b = inst("https://b.example")
56 let r = NotificationRoute.resolve(
57 threadID: "th1", instances: [a, b],
58 entryOrigin: { _ in "https://gone.example" },
59 snapshotHasThread: { origin, thread in origin == "https://b.example" && thread == "th1" })
60 guard case .snapshot(let hit) = r else { return XCTFail("\(r)") }
61 XCTAssertEqual(hit.origin, b.origin)
62 }
63
64 func testMissingParkFallsBackToSnapshot() {
65 let a = inst("https://a.example"), b = inst("https://b.example")
66 let r = NotificationRoute.resolve(
67 threadID: "th1", instances: [a, b],
68 entryOrigin: { _ in nil },
69 snapshotHasThread: { origin, _ in origin == "https://a.example" })
70 guard case .snapshot(let hit) = r else { return XCTFail("\(r)") }
71 XCTAssertEqual(hit.origin, a.origin)
72 }
73
74 func testSingleSpaceAlwaysResolves() {
75 // Nothing recorded anywhere (wiped keychain, brand-new thread): with
76 // one signed-in space the tap still routes there.
77 let a = inst("https://a.example")
78 let r = NotificationRoute.resolve(
79 threadID: "new-thread", instances: [a],
80 entryOrigin: { _ in nil },
81 snapshotHasThread: { _, _ in false })
82 guard case .onlySpace(let hit) = r else { return XCTFail("\(r)") }
83 XCTAssertEqual(hit.origin, a.origin)
84 }
85
86 func testSingleActiveSpaceSkipsArchived() {
87 let live = inst("https://live.example")
88 let parked = inst("https://old.example", archived: true)
89 let r = NotificationRoute.resolve(
90 threadID: "th1", instances: [live, parked],
91 entryOrigin: { _ in nil },
92 snapshotHasThread: { _, _ in false })
93 guard case .onlySpace(let hit) = r else { return XCTFail("\(r)") }
94 XCTAssertEqual(hit.origin, live.origin)
95 }
96
97 func testMultiSpaceNoEvidenceFallsBackToLastActive() {
98 // Undecryptable push for a brand-new thread, several spaces: the
99 // space this device was last in is the optimistic guess β€” the tap
100 // opens a chat screen there instead of dropping on the list.
101 let a = inst("https://a.example"), b = inst("https://b.example")
102 let r = NotificationRoute.resolve(
103 threadID: "th1", lastActiveID: "https://b.example", instances: [a, b],
104 entryOrigin: { _ in nil },
105 snapshotHasThread: { _, _ in false })
106 guard case .lastActive(let hit) = r else { return XCTFail("\(r)") }
107 XCTAssertEqual(hit.origin, b.origin)
108 }
109
110 func testMultiSpaceUnknownThreadStaysUnresolved() {
111 // No last-active record either (or it names a space that's gone) β€”
112 // only then does the tap drop.
113 let a = inst("https://a.example"), b = inst("https://b.example")
114 for last in [nil, "https://gone.example"] {
115 let r = NotificationRoute.resolve(
116 threadID: "th1", lastActiveID: last, instances: [a, b],
117 entryOrigin: { _ in nil },
118 snapshotHasThread: { _, _ in false })
119 guard case .unresolved = r else { return XCTFail("\(r)") }
120 }
121 }
122}
123