eleven / messenger Public

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

Plain git — no account needed to clone.

Download

Download this file

1import XCTest
2@testable import LChatCore
3
4// The reverse-direction gate: message-payload-vector proves the web's bytes
5// open natively; THIS fixture proves native-encrypted bytes open on the web
6// (test/nativeblob.test.mjs decrypts it with crypto.js). Together they pin the
7// native send path — a native message must render for every web member.
8//
9// Regenerate after changing the outgoing envelope or GroupKey:
10// RECORD_VECTORS=1 swift test --filter NativeMessageVectorTests
11// then re-run `npm test` (the JS side must still pass) and commit the fixture.
12final class NativeMessageVectorTests: XCTestCase {
13 // A fixed key (bytes 0..31, like the thread-key vector) + a payload shaped
14 // exactly like ChatFeedModel's Outgoing envelope.
15 private static let keyRaw = Data((0 ..< 32).map { UInt8($0) })
16 private static let expect: [String: Any] = [
17 "text": "Hello from native! 🎉",
18 "name": "Fable",
19 "ts": 1751830000000 as Int64,
20 "uid": "u_native",
21 ]
22
23 private var fixtureURL: URL {
24 URL(fileURLWithPath: #filePath)
25 .deletingLastPathComponent()
26 .appending(path: "Fixtures/native-message-vector.json")
27 }
28
29 func testRecordFixtureIfRequested() throws {
30 guard ProcessInfo.processInfo.environment["RECORD_VECTORS"] == "1" else {
31 throw XCTSkip("set RECORD_VECTORS=1 to regenerate the fixture")
32 }
33 struct Payload: Encodable {
34 let text: String; let name: String; let ts: Int64; let uid: String
35 }
36 let key = try GroupKey(rawKey: Self.keyRaw)
37 let blob = try key.encryptJSON(Payload(text: Self.expect["text"] as! String,
38 name: Self.expect["name"] as! String,
39 ts: Self.expect["ts"] as! Int64,
40 uid: Self.expect["uid"] as! String))
41 let fixture: [String: Any] = [
42 "_comment": "Native-encrypted message vector. Generated by NativeMessageVectorTests "
43 + "(RECORD_VECTORS=1 swift test) from LChatCore's GroupKey.encryptJSON — "
44 + "test/nativeblob.test.mjs must decrypt it with web/static/crypto.js, proving "
45 + "native sends render for web members. base64url throughout.",
46 "keyB64": Self.keyRaw.base64urlEncodedString(),
47 "blob": blob,
48 "expect": Self.expect,
49 ]
50 let json = try JSONSerialization.data(withJSONObject: fixture, options: [.prettyPrinted, .sortedKeys])
51 try (String(data: json, encoding: .utf8)! + "\n").write(to: fixtureURL, atomically: true, encoding: .utf8)
52 print("wrote", fixtureURL.path)
53 }
54
55 func testCommittedFixtureDecryptsNatively() throws {
56 // Self-check on the committed fixture (the JS gate is the real point).
57 let data = try Data(contentsOf: fixtureURL)
58 let fx = try JSONSerialization.jsonObject(with: data) as! [String: Any]
59 let key = try GroupKey(rawKey: try XCTUnwrap(Data(base64urlEncoded: fx["keyB64"] as! String)))
60 let p = try key.decryptJSON(MessagePayload.self, blob: fx["blob"] as! String)
61 let expect = fx["expect"] as! [String: Any]
62 XCTAssertEqual(p.text, expect["text"] as? String)
63 XCTAssertEqual(p.name, expect["name"] as? String)
64 XCTAssertEqual(p.uid, expect["uid"] as? String)
65 XCTAssertEqual(p.ts, (expect["ts"] as? NSNumber)?.int64Value)
66 }
67}
68