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))))