Back
now (clj)
(source)function
(now)
(now clock)
Returns a date time for the current instant.
Examples
chime
(ns chime-test
(:require
[chime :refer :all]
[clojure.core.async :as a :refer [<! go-loop]]
[clojure.test :refer :all]
[chime.core :as chime]
[chime.joda-time]
[clj-time.core :as t]
[clj-time.periodic])
(:import (java.time Instant)
(java.time.temporal ChronoUnit)))
(defn now
[]
(Instant/now))
(deftest test-chime-at
(let [will-be-omitted (.minusSeconds (now) 2)
t1 (.plusSeconds (now) 2)
t2 (.plusSeconds (now) 3)
proof (atom [])]
(chime-at [will-be-omitted t1 t2]
(fn [t]
(swap! proof conj [t
(chime-test/now)])))
(while (not (= (list t1 t2)
(map first @proof))))
(is (= [t1 t2]
(mapv first @proof)))
(check-timeliness! proof)))
(deftest test-error-handler
(testing "continues the schedule"
(let [proof (atom [])
!latch (promise)
sched (chime-at [(.plusMillis (Instant/now) 500)
(.plusMillis (Instant/now) 1000)]
(fn [time]
(throw (ex-info "boom!" {:time time})))
{:error-handler (fn [e]
(swap! proof conj e)
nil)
:on-finished (fn [] (deliver !latch nil))})]
(is (not= ::timeout (deref !latch 1500 ::timeout)))
(is (= 2 (count @proof)))
(is (every? ex-data @proof))))
(testing "rethrowing the error stops the schedule"
(let [proof (atom [])
!latch (promise)
sched (chime-at [(.plusMillis (Instant/now) 500)
(.plusMillis (Instant/now) 1000)]
(fn [time]
(throw (ex-info "boom!" {:time time})))
{:error-handler (fn [e]
(swap! proof conj e)
(throw e))
:on-finished (fn [] (deliver !latch nil))})]
(is (not= ::timeout (deref !latch 1500 ::timeout)))
(is (= 1 (count @proof)))
(is (every? ex-data @proof)))))
(deftest test-chime-ch
(let [will-be-omitted (.minusSeconds (now) 2)
t1 (.plusSeconds (now) 2)
t2 (.plusSeconds (now) 3)
chimes (chime-ch [will-be-omitted
t1
t2])
proof (atom [])]
(a/<!! (go-loop []
(when-let [msg (<! chimes)]
(swap! proof conj [msg (chime-test/now)])
(recur))))
(is (= [t1 t2]
(mapv first @proof)))
(check-timeliness! proof)))
(deftest test-channel-closing
(let [omitted (.minusSeconds (now) 2)
expected (.plusSeconds (now) 2)
dropped (.plusSeconds (now) 3)
chimes (chime-ch [omitted expected dropped])
proof (atom [])]
(a/<!!
(a/go
(swap! proof conj (<! chimes))
(a/close! chimes)
(when-let [v (<! chimes)]
(swap! proof conj v))))
(is (= [expected]
@proof))))
(deftest test-on-finished
(let [proof (atom false)]
(chime-at [(.plusSeconds (now) 2) (.plusSeconds (now) 4)]
(let [proof (atom [])
ch (chime-ch (->> (chime/periodic-seq (-> (.plusSeconds (chime-test/now) 2)
(.truncatedTo (ChronoUnit/SECONDS)))
(java.time.Duration/ofSeconds 1))
(take 3)))]
(swap! proof conj [(a/<!! ch)
(chime-test/now)])
(check-timeliness! proof)
(a/<!! (a/timeout 4000))
;; Pending timestamps come through in the past.
(is (a/<!! ch) "A time value is returned, and not nil")
(is (a/<!! ch) "A time value is returned, and not nil")))
(deftest test-cancellation-works-even-in-the-face-of-overrun-past-tasks
(let [proof (atom [])
do-stuff (fn [now]
;; some overrunning task:
(swap! proof conj now)
(Thread/sleep 5000))
cancel-stuff! (chime-at (rest (chime/periodic-seq (chime-test/now)
(java.time.Duration/ofSeconds 1)))
do-stuff)]
(Thread/sleep 3000)
(cancel-stuff!)
(is (= 1
(count @proof)))))
(deftest test-empty-or-completely-past-sequences-are-acceptable
(let [proof (atom false)]
(chime-at (map #(.minusSeconds (now) (* 60 %)) [5 4 3 2])
identity
{:on-finished (fn []
(reset! proof true))})
(while (not @proof))
(is @proof))
chime
(ns chime.core-test
(:require [chime.core :as chime]
[clojure.test :as t])
(:import (java.time Instant Duration)
(java.time.temporal ChronoUnit)))
(t/deftest test-chime-at
(let [times [(.minusSeconds (Instant/now) 2)
(.plusSeconds (Instant/now) 1)
(.plusSeconds (Instant/now) 2)]
proof (atom [])]
(with-open [sched (chime/chime-at times
(fn [t]
(swap! proof conj [t (Instant/now)])))]
(Thread/sleep 2500))
(t/is (= times (mapv first @proof)))
(check-timeliness! (rest @proof))))
(t/deftest test-on-finished
(let [proof (atom false)]
(chime/chime-at [(.plusMillis (Instant/now) 500) (.plusMillis (Instant/now) 1000)]
(fn [time])
{:on-finished (fn []
(Thread/sleep 100)
(reset! proof true))})
(Thread/sleep 1200)
(t/is @proof)))
(t/deftest test-error-handler
(t/testing "returning true continues the schedule"
(let [proof (atom [])
sched (chime/chime-at [(.plusMillis (Instant/now) 500)
(.plusMillis (Instant/now) 1000)]
(fn [time]
(throw (ex-info "boom!" {:time time})))
{:error-handler (fn [e]
(swap! proof conj e)
true)})]
(t/is (not= ::timeout (deref sched 1500 ::timeout)))
(t/is (= 2 (count @proof)))
(t/is (every? ex-data @proof))))
(t/testing "returning false stops the schedule"
(let [proof (atom [])
sched (chime/chime-at [(.plusMillis (Instant/now) 500)
(.plusMillis (Instant/now) 1000)]
(fn [time]
(throw (ex-info "boom!" {:time time})))
{:error-handler (fn [e]
(swap! proof conj e)
false)})]
(t/is (not= ::timeout (deref sched 1500 ::timeout)))
(t/is (= 1 (count @proof)))
(t/is (every? ex-data @proof)))))
(t/deftest test-long-running-jobs
(let [proof (atom [])
!latch (promise)
now (Instant/now)
times (->> (chime/periodic-seq now (Duration/ofMillis 500))
(take 3))
sched (chime/chime-at times
(fn [time]
(swap! proof conj [time (Instant/now)])
(Thread/sleep 750)))]
(t/is (not= ::nope (deref sched 4000 ::nope)))
(t/is (= times (map first @proof)))
(check-timeliness! (map vector
(->> (chime/periodic-seq now (Duration/ofMillis 750))
(take 3))
(map second @proof)))))
(t/deftest test-cancelling-overrunning-task
(let [!proof (atom [])
!error (atom nil)
!latch (promise)]
(with-open [sched (chime/chime-at (chime/periodic-seq (Instant/now) (Duration/ofSeconds 1))
(fn [now]
(swap! !proof conj now)
(Thread/sleep 3000))
{:error-handler (fn [e]
(reset! !error e))
:on-finished (fn []
(deliver !latch nil))})]
(Thread/sleep 2000))
(t/deftest test-only-call-on-finished-once-36
(let [!count (atom 0)
now (Instant/now)]
(with-open [chiming (chime/chime-at [(.plusMillis now 500)
(.plusMillis now 500)]
(fn [time])
{:on-finished #(swap! !count inc)})]
(Thread/sleep 1000))
chime
(ns chime.core-async-test
(:require [chime.core-async :as sut]
[chime.core-test :refer [check-timeliness!]]
[clojure.test :as t]
[clojure.core.async :as a :refer [go-loop]])
(:import [java.time Instant]))
(t/deftest test-chime-ch
(let [now (Instant/now)
times [(.minusSeconds now 2)
(.plusSeconds now 1)
(.plusSeconds now 2)]
chimes (sut/chime-ch times)
proof (atom [])]
(a/<!! (go-loop []
(when-let [msg (a/<! chimes)]
(swap! proof conj [msg (Instant/now)])
(recur))))
(t/deftest test-channel-closing
(let [now (Instant/now)
times [(.minusSeconds now 2)
(.plusSeconds now 1)
(.plusSeconds now 2)]
chimes (sut/chime-ch times)
proof (atom [])]
(a/<!! (a/go
(swap! proof conj (a/<! chimes))
(swap! proof conj (a/<! chimes))
(a/close! chimes)
(when-let [v (a/<! chimes)]
(swap! proof conj v))))
(t/is (= (butlast times) @proof))))