p2p-cljs / test / ird / p2p / live / smoke_test.cljs
603 words
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
(ns ird.p2p.live.smoke-test
  "Live smoke tests against a real ird p2p app, mirroring the Swift SDK's
  LiveSmokeTests. Gated on IRD_P2P_HOST (the app hostname) and
  IRD_P2P_ORIGIN (an origin its allowlist admits); every test skips itself
  silently when they are not set. Read-mostly: it fetches the descriptor,
  joins a room from two peers over the relay, exchanges one message, opens
  a real data channel between two peers (node-datachannel through the
  app's signaling and TURN) and round-trips 50,000 bytes over it, and —
  if the app has a mailbox — round-trips one deposit.

  Run with `npm run test:live`."
  (:require [cljs.test :refer [deftest is]]
            [cljs.core.async :as async :refer [<!]]
            [ird.p2p :as p2p]
            [ird.p2p.crypto :as crypto]
            [ird.p2p.descriptor :as desc]
            [ird.p2p.impl.bytes :as bytes]
            [ird.p2p.impl.wrtc :as wrtc]
            [ird.p2p.mailbox]
            [ird.p2p.test-util :as tu :refer [deftest-async]]))

(def host (tu/env "IRD_P2P_HOST"))
(def origin (tu/env "IRD_P2P_ORIGIN"))
(def enabled? (some? host))
(def app-salt "ird-cljs-live/v1")
(def low "00000000000000000000000000000001")
(def high "0f1e2d3c4b5a69788796a5b4c3d2e1f0")

(defn- app [] (p2p/make-app {:host host :app-salt app-salt :origin origin}))
(defn- direct-app [] (p2p/make-app {:host host :app-salt app-salt :origin origin :pc-factory (wrtc/wrtc-factory)}))

(deftest-async descriptor-join-and-relay-message
  {:timeout-ms 40000}
  (if-not enabled?
    (is true "IRD_P2P_HOST not set — skipping the live smoke test")
    (let [a (app)
          d (<! (p2p/fetch-descriptor a))]
      (is (false? (:is-fallback d)) "the descriptor is served, not synthesized")
      (is (= "1" (:version d)))
      (is (= "ap2p-signal" (:protocol d)))
      (is (= (str "wss://" host "/ws") (get-in d [:endpoints :ws])))
      ;; two peers join over the relay and exchange a message (data channels off)
      (let [secret (crypto/random-secret)
            ra (<! (p2p/join a secret {:peer-id low :options {:prefer-data-channel? false}}))
            ca (tu/collector (p2p/events ra))]
        (is (not (tu/error? ra)) (some-> ra ex-message))
        (is (some? (<! (tu/wait-for ca #(and (= :status (:type %)) (= :joined (get-in % [:status :state]))) 10000))))
        (let [rb (<! (p2p/join a secret {:peer-id high :options {:prefer-data-channel? false}}))
              cb (tu/collector (p2p/events rb))]
          (is (some? (<! (tu/wait-for ca #(= {:type :peer-ready :peer high :via :relayed} %) 15000))))
          (is (some? (<! (tu/wait-for cb #(= {:type :peer-ready :peer low :via :relayed} %) 15000))))
          (is (true? (<! (p2p/send ra high (p2p/json {:text "live"})))))
          (is (some? (<! (tu/wait-for cb #(= "live" (get-in % [:message :value :text])) 15000))))
          (<! (p2p/leave rb))
          (is (some? (<! (tu/wait-for ca #(= {:type :peer-left :peer high} %) 10000))))
          (<! (p2p/leave ra)))))))

(deftest-async direct-data-channel-over-the-internet
  {:timeout-ms 90000}
  (if-not enabled?
    (is true "IRD_P2P_HOST not set — skipping the live data-channel test")
    ;; data-channel preference is on by default once a real :pc-factory is set
    (let [a (direct-app)
          secret (crypto/random-secret)
          ra (<! (p2p/join a secret {:peer-id low}))
          ca (tu/collector (p2p/events ra))]
      (is (not (tu/error? ra)) (some-> ra ex-message))
      (let [rb (<! (p2p/join a secret {:peer-id high}))
            cb (tu/collector (p2p/events rb))]
        (is (not (tu/error? rb)) (some-> rb ex-message))
        (is (some? (<! (tu/wait-for ca #(= {:type :peer-ready :peer high :via :direct} %) 30000))))
        (is (some? (<! (tu/wait-for cb #(= {:type :peer-ready :peer low :via :direct} %) 30000))))
        ;; 50,000 bytes patterned like the Swift smoke test's (0..<50_000).map { $0 % 253 }
        (let [big (bytes/bytes->b64 (map #(mod % 253) (range 50000)))]
          (is (true? (<! (p2p/send ra high (p2p/data big)))))
          (is (some? (<! (tu/wait-for cb #(and (= low (:from %)) (= (p2p/data big) (:message %))) 20000)))))
        (<! (p2p/leave ra))
        (<! (p2p/leave rb))))))

(deftest-async mailbox-round-trip
  {:timeout-ms 40000}
  (if-not enabled?
    (is true "IRD_P2P_HOST not set — skipping the live mailbox test")
    (let [a (app)
          d (<! (p2p/fetch-descriptor a))]
      (if-not (desc/mailbox-enabled? d)
        (is true "the app has no mailbox — skipping the mailbox round trip")
        (let [mbx (<! (p2p/open-mailbox a (crypto/random-secret)))]
          (is (not (tu/error? mbx)) (some-> mbx ex-message))
          (let [r (<! (ird.p2p.mailbox/deposit mbx (p2p/json {:text "offline"})))]
            (is (not (tu/error? r)) (some-> r ex-message))
            (is (false? (:deduped r)))
            (let [{:keys [items]} (<! (ird.p2p.mailbox/replay-all mbx nil))]
              (is (= [{:kind :json :value {:text "offline"}}] (mapv :message items))))))))))

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/p2p-cljs.git