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// 🤖 Pins the native fader math to home's web fader (home/test/fader.test.mjs
5// asserts the same values on the JS side) and the claim-side crypto helpers.
6final class SpaceCreateTests: XCTestCase {
7 // ---- fader math (twin of fader.test.mjs — keep the cases in lockstep) ----
8
9 func testFaderValueMapsTheSlotRunTo1Through10AndClampsBeyondIt() {
10 XCTAssertEqual(FaderMath.value(fraction: 0), 1)
11 XCTAssertEqual(FaderMath.value(fraction: 0.86), 10, "the end of the run (runEnd) is 10")
12 XCTAssertEqual(FaderMath.value(fraction: 1), 10,
13 "past the run still clamps to 10 — eleven is not reachable by position")
14 XCTAssertEqual(FaderMath.value(fraction: -0.5), 1, "before the slot clamps to 1")
15 let mid = FaderMath.value(fraction: 0.43)
16 XCTAssertTrue(mid > 5 && mid < 6.6, "mid-run lands mid-scale")
17 }
18
19 func testFaderLevelIsSilentBelow5HotBy10AndPressureAddsStrain() {
20 XCTAssertEqual(FaderMath.level(phase: .slide, value: 1, pressure: 0), 0)
21 XCTAssertEqual(FaderMath.level(phase: .slide, value: 5, pressure: 0), 0)
22 XCTAssertEqual(FaderMath.level(phase: .slide, value: 10, pressure: 0), 5.0 / 6, accuracy: 1e-9)
23 XCTAssertGreaterThan(FaderMath.level(phase: .slide, value: 10, pressure: 0.8),
24 FaderMath.level(phase: .slide, value: 10, pressure: 0),
25 "the hold adds strain")
26 }
27
28 func testFaderLevelHoldsPast1AtTheSnapAndThroughTheWholeBuild() {
29 XCTAssertEqual(FaderMath.level(phase: .snap, value: 10, pressure: 0), 1.2)
30 XCTAssertEqual(FaderMath.level(phase: .build, value: 10, pressure: 0), 1.2,
31 "the volume stays AT eleven while building")
32 }
33
34 func testFaderLevelCutsToZeroAtDone() {
35 XCTAssertEqual(FaderMath.level(phase: .done, value: 10, pressure: 0), 0,
36 "silence before the confetti")
37 }
38
39 // ---- claim crypto ---------------------------------------------------------
40
41 func testDerivedClaimSecretHashesToTheClaimHash() throws {
42 // The raw claim secret (sent on CLAIM) must be the exact preimage of the
43 // claim hash (stored on MINT) — the two sides of proof-of-possession.
44 let derived = try InviteCrypto.derive(InviteCrypto.randomSecret())
45 let hash = SHA256Hex(Data(derived.claimSecret.utf8))
46 XCTAssertEqual(hash, derived.claimHash)
47 XCTAssertFalse(derived.claimSecret.isEmpty)
48 }
49
50 func testGeneratedUserKeypairRoundTripsThroughECIES() throws {
51 // A fresh native identity must interoperate with the existing wrap paths:
52 // wrap a key to the new pubkey, unwrap it with the new private key.
53 let kp = ECIES.generateUserKeypair()
54 let raw = ECIES.randomAESKey()
55 let wrapped = try ECIES.wrap(rawKey: raw, recipientPubB64: kp.pub)
56 XCTAssertEqual(try ECIES.unwrap(wrappedB64: wrapped, privPkcs8B64: kp.priv), raw)
57 }
58
59 func testInviteSecretParsingStripsPrefixAndSuggestedName() {
60 XCTAssertEqual(SpaceClaim.inviteSecret(fromFragment: "e1.abc123"), "abc123")
61 XCTAssertEqual(SpaceClaim.inviteSecret(fromFragment: "e1.abc123~Paul"), "abc123")
62 XCTAssertEqual(SpaceClaim.inviteSecret(fromFragment: "abc123"), "abc123",
63 "older links carry no e1. hint")
64 XCTAssertNil(SpaceClaim.inviteSecret(fromFragment: ""))
65 XCTAssertNil(SpaceClaim.inviteSecret(fromFragment: "e1."))
66 }
67
68 // Sealed instances mint 3-slot links: e1.<T>~<name>~<branding key>
69 // (docs/no-plaintext.md). T parsing and the suggested name must both
70 // survive the new tail; the key is exposed for the sealed-branding path.
71 func testBrandingKeyFragmentSlots() {
72 let frag = "e1.abc123~Paul~k3m7p2qx4f"
73 XCTAssertEqual(SpaceClaim.inviteSecret(fromFragment: frag), "abc123")
74 XCTAssertEqual(SpaceClaim.suggestedName(fromFragment: frag), "Paul")
75 XCTAssertEqual(SpaceClaim.brandingKey(fromFragment: frag), "k3m7p2qx4f")
76
77 // Empty name slot (a sealed instance's admin link).
78 XCTAssertEqual(SpaceClaim.inviteSecret(fromFragment: "e1.abc123~~k3m7p2qx4f"), "abc123")
79 XCTAssertNil(SpaceClaim.suggestedName(fromFragment: "e1.abc123~~k3m7p2qx4f"))
80 XCTAssertEqual(SpaceClaim.brandingKey(fromFragment: "e1.abc123~~k3m7p2qx4f"), "k3m7p2qx4f")
81
82 // Two-slot legacy links: no key, name intact — even when a legacy raw
83 // "~" in the name makes a non-key-shaped tail.
84 XCTAssertNil(SpaceClaim.brandingKey(fromFragment: "e1.abc123~Paul"))
85 XCTAssertEqual(SpaceClaim.suggestedName(fromFragment: "e1.abc123~Zo%C3%AB%20~%20%E2%9C%A8"), "Zoë ~ ✨")
86 }
87}
88
89private func SHA256Hex(_ data: Data) -> String {
90 CryptoKit.SHA256.hash(data: data).map { String(format: "%02x", $0) }.joined()
91}
92
93import CryptoKit
94