p2p-db / test / ird / p2p / db / test_util.cljs
299 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
(ns ird.p2p.db.test-util
  "Shared test tooling: `eventually` polling, collectors, temporary
  directories and the environment. Tests may use JS interop freely; the
  purity rule applies to src/ only."
  (:require-macros [ird.p2p.db.test-util])
  (:require [clojure.string :as str]
            [cljs.core.async :as async :refer [go go-loop <!]]
            [ird.p2p.async :as a]))

;; lazy: this namespace is shared with the browser test build, where these
;; are never touched (tmp-dir/rm-rf/env are Node-only)
(def ^:private fs (delay (js/require "node:fs")))
(def ^:private os (delay (js/require "node:os")))
(def ^:private path (delay (js/require "node:path")))

(defn env [name]
  (let [v (aget (.-env js/process) name)]
    (when (and (string? v) (not (str/blank? v))) v)))

(defn skip-nodes?
  "True when the real-node suites should skip themselves (a sandbox that
  cannot bind loopback sockets sets IRD_P2P_DB_NO_NODE=1)."
  []
  (some? (env "IRD_P2P_DB_NO_NODE")))

;; ---- files -------------------------------------------------------------------------

(defn tmp-dir
  "A fresh empty directory under the OS temp dir."
  [prefix]
  (let [^js fs @fs ^js path @path ^js os @os]
    (.mkdtempSync fs (.join path (.tmpdir os) (str prefix "-")))))

(defn rm-rf [dir]
  (let [^js fs @fs]
    (.rmSync fs dir #js {:recursive true :force true})))

;; ---- polling -------------------------------------------------------------------------

(defn eventually
  "Channel of true once (pred) is truthy, polling every 5 ms of real time
  up to TIMEOUT-MS (default 5000); false otherwise."
  ([pred] (eventually pred 5000))
  ([pred timeout-ms]
   (let [deadline (+ (js/Date.now) timeout-ms)]
     (go-loop []
       (cond
         (pred) true
         (>= (js/Date.now) deadline) (boolean (pred))
         :else (do (<! (async/timeout 5)) (recur)))))))

(defn collector
  "Drain CH into an atom vector; returns the atom."
  [ch]
  (let [seen (atom [])]
    (go-loop []
      (when-let [v (<! ch)]
        (swap! seen conj v)
        (recur)))
    seen))

(defn wait-for
  "Channel of the first collected event satisfying PRED (real-time polling), or nil."
  ([seen pred] (wait-for seen pred 5000))
  ([seen pred timeout-ms]
   (go
     (<! (eventually #(some pred @seen) timeout-ms))
     (some #(when (pred %) %) @seen))))

(defn count-of [seen pred] (count (filter pred @seen)))

(def error? a/error?)

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