;;;; The clock and the environment. ;;;; ;;;; Every line of output here is an invariant and not a reading, and that is ;;;; forced rather than chosen: this file is in the corpus @x86 builds twice ;;;; and diffs, and the acceptance table matches its stdout exactly, so a ;;;; timestamp or an elapsed count would fail a correct compiler on the second ;;;; run. What is left is what a clock actually has to promise — that it does ;;;; not go backwards, that a sleep does not return early, that the two faces ;;;; of one clock describe one instant — and those are the properties worth ;;;; pinning anyway. A test that asserted "this took under 3ms" would be a ;;;; test of the machine's load. (defn main [] i32 ;; Monotonic, twice. The whole contract in one line: it never goes ;; backwards. Equal is allowed and is not a bug — two reads inside one tick ;; of a coarse timer are the same nanosecond. (let [t1 (monotonic-ns) t2 (monotonic-ns)] (println (>= t2 t1))) ;; And the origin is the first read rather than boot, so the first readings ;; a program takes are small. Bounded rather than pinned: the number is ;; whatever this process spent between the calls above and this one, which ;; is not a second on any machine that can run the suite at all. (println (< (monotonic-ns) ns-per-second)) ;; The f64 face is the i64 one divided, and what is checked is that the two ;; describe the same instant: a later reading in seconds is at or past an ;; earlier reading in nanoseconds converted the same way. A clock whose two ;; faces came from different sources fails this. (let [a (/ (f64 (monotonic-ns)) 1000000000.0) b (monotonic-seconds)] (println (>= b a))) ;; The wall clock is a date, so the invariant is a date one: it is after ;; 2020 and before 2100. That pins the epoch and the unit at once — a clock ;; counting microseconds, or counting from boot, fails both halves. (let [now (unix-seconds)] (println (and (> now 1577836800.0) (< now 4102444800.0)))) ;; Sleep is specified as *at least*, so at-least is what is asserted; the ;; upper bound belongs to the scheduler and not to this language. Two ;; milliseconds because the shortest sleep a default kernel actually ;; performs is a timer tick, and a shorter request would make this a test of ;; how that kernel was configured. (let [before (monotonic-ns)] (sleep-ns (* 2 ns-per-millisecond)) (println (>= (- (monotonic-ns) before) (* 2 ns-per-millisecond)))) ;; Zero and negative return at once rather than being refused, which is what ;; a deadline already passed produces. That they return at all is the ;; assertion; nothing here is timed. (sleep-ns 0) (sleep-ns -1) (sleep-seconds 0.0) (println "slept") ;; ── The environment ────────────────────────────────────────────── ;; A variable nothing sets. None is the answer, and it is a different answer ;; from a variable set to nothing. (match (getenv "FLAN_NO_SUCH_VARIABLE_AT_ALL") (Some v) (println "unexpectedly set") None (println "unset")) ;; PATH is set for every process that gets as far as running this, and the ;; only portable thing about its contents is that there are some. (match (getenv "PATH") (Some v) (println (> (len v) 0)) None (println "no PATH")) 0)