From c32f7a892f2da42b44b12d104e9eedc91b57e259 Mon Sep 17 00:00:00 2001 From: anatoly Date: Tue, 8 Dec 2015 22:07:26 -0500 Subject: [PATCH] cljs var-to-str + parts test --- project.clj | 6 ++-- src/mount/core.cljc | 21 ++++++++--- test/clj/app/conf.clj | 13 +++++++ test/clj/app/example.clj | 65 ++++++++++++++++++++++++++++++++++ test/clj/app/nyse.clj | 21 +++++++++++ test/clj/app/utils/datomic.clj | 11 ++++++ test/clj/app/utils/logging.clj | 46 ++++++++++++++++++++++++ test/mount/test.cljc | 21 ++++++----- test/mount/test/helper.cljc | 11 ++++++ test/mount/test/parts.cljc | 36 +++++++++++++++++++ 10 files changed, 237 insertions(+), 14 deletions(-) create mode 100644 test/clj/app/conf.clj create mode 100644 test/clj/app/example.clj create mode 100644 test/clj/app/nyse.clj create mode 100644 test/clj/app/utils/datomic.clj create mode 100644 test/clj/app/utils/logging.clj create mode 100644 test/mount/test/helper.cljc create mode 100644 test/mount/test/parts.cljc diff --git a/project.clj b/project.clj index a58d1d8..5874693 100644 --- a/project.clj +++ b/project.clj @@ -6,7 +6,7 @@ :source-paths ["src"] - :dependencies [] ;; yep + :dependencies [] ;; for visual clarity :profiles {:dev {:source-paths ["dev" "dev/clj" "test"] :dependencies [[org.clojure/clojure "1.7.0"] @@ -53,4 +53,6 @@ {:source-paths ["src" "test"] :compiler {:output-to "dev/resources/public/js/compiled/mount.js" :optimizations :advanced - :pretty-print false}}}}}}) + :pretty-print false}}}}} + + :test {:source-paths ["dev" "test/clj" "test"]}}) diff --git a/src/mount/core.cljc b/src/mount/core.cljc index 9e7994c..59da9ec 100644 --- a/src/mount/core.cljc +++ b/src/mount/core.cljc @@ -174,10 +174,22 @@ all) (sort-by :order)))) + +#?(:clj + (defn- var-to-str [v] + (str v))) + +#?(:cljs + (defn var-to-str [v] + (if (var? v) + (let [{:keys [ns name]} (meta v)] + (with-ns ns name)) + v))) + (defn- bring [states fun order] (let [done (atom [])] (as-> states $ - (map str $) + (map var-to-str $) (select-keys @meta-state $) (sort-by (comp :order val) order $) (doseq [[k v] $] (fun k v done))) @@ -226,7 +238,7 @@ (defn stop-except [& states] (let [all (set (find-all-states)) - states (map str states) + states (map var-to-str states) states (remove (set states) all)] (apply stop states))) @@ -238,13 +250,14 @@ (defn start-with [with] (doseq [[from to] with] - (substitute! (str from) (str to))) + (substitute! (var-to-str from) + (var-to-str to))) (start)) (defn start-without [& states] (if (first states) (let [app (set (all-without-subs)) - states (map str states) + states (map var-to-str states) without (remove (set states) app)] (apply start without)) (start))) diff --git a/test/clj/app/conf.clj b/test/clj/app/conf.clj new file mode 100644 index 0000000..3273a95 --- /dev/null +++ b/test/clj/app/conf.clj @@ -0,0 +1,13 @@ +(ns app.conf + (:require [mount.core :as mount :refer [defstate]] + [clojure.edn :as edn] + [clojure.tools.logging :refer [info]])) + +(defn load-config [path] + (info "loading config from" path) + (-> path + slurp + edn/read-string)) + +(defstate config + :start (load-config "dev/resources/config.edn")) diff --git a/test/clj/app/example.clj b/test/clj/app/example.clj new file mode 100644 index 0000000..028d406 --- /dev/null +++ b/test/clj/app/example.clj @@ -0,0 +1,65 @@ +(ns app.example + (:require [datomic.api :as d] + [clojure.tools.nrepl.server :refer [start-server stop-server]] + [mount.core :as mount :refer [defstate]] + [app.utils.datomic :refer [touch]] + [app.conf :refer [config]] + [app.nyse :as nyse])) + +;; example on creating a network REPL +(defn- start-nrepl [{:keys [host port]}] + (start-server :bind host :port port)) + +;; nREPL is just another simple state +(defstate nrepl :start (start-nrepl (:nrepl @config)) + :stop (stop-server @nrepl)) + +;; datomic schema +(defn create-schema [conn] + (let [schema [{:db/id #db/id [:db.part/db] + :db/ident :order/symbol + :db/valueType :db.type/string + :db/cardinality :db.cardinality/one + :db/index true + :db.install/_attribute :db.part/db} + + {:db/id #db/id [:db.part/db] + :db/ident :order/bid + :db/valueType :db.type/bigdec + :db/cardinality :db.cardinality/one + :db.install/_attribute :db.part/db} + + {:db/id #db/id [:db.part/db] + :db/ident :order/qty + :db/valueType :db.type/long + :db/cardinality :db.cardinality/one + :db.install/_attribute :db.part/db} + + {:db/id #db/id [:db.part/db] + :db/ident :order/offer + :db/valueType :db.type/bigdec + :db/cardinality :db.cardinality/one + :db.install/_attribute :db.part/db}]] + + @(d/transact conn schema))) + +(defn add-order [ticker bid offer qty] ;; can take connection as param + @(d/transact @nyse/conn [{:db/id (d/tempid :db.part/user) + :order/symbol ticker + :order/bid bid + :order/offer offer + :order/qty qty}])) + + +(defn find-orders [ticker] ;; can take connection as param + (let [orders (d/q '[:find ?e :in $ ?ticker + :where [?e :order/symbol ?ticker]] + (d/db @nyse/conn) ticker)] + (touch @nyse/conn orders))) + +(defn create-nyse-schema [] + (create-schema @nyse/conn)) + +;; example of an app entry point +(defn -main [& args] + (mount/start)) diff --git a/test/clj/app/nyse.clj b/test/clj/app/nyse.clj new file mode 100644 index 0000000..374cba7 --- /dev/null +++ b/test/clj/app/nyse.clj @@ -0,0 +1,21 @@ +(ns app.nyse + (:require [mount.core :as mount :refer [defstate]] + [datomic.api :as d] + [clojure.tools.logging :refer [info]] + [app.conf :refer [config]])) + +(defn- new-connection [conf] + (info "conf: " conf) + (let [uri (get-in @conf [:datomic :uri])] + (info "creating a connection to datomic:" uri) + (d/create-database uri) + (d/connect uri))) + +(defn disconnect [conf conn] + (let [uri (get-in @conf [:datomic :uri])] + (info "disconnecting from " uri) + (.release @conn) ;; usually it's not released, here just to illustrate the access to connection on (stop) + (d/delete-database uri))) + +(defstate conn :start (new-connection config) + :stop (disconnect config conn)) diff --git a/test/clj/app/utils/datomic.clj b/test/clj/app/utils/datomic.clj new file mode 100644 index 0000000..836f9b9 --- /dev/null +++ b/test/clj/app/utils/datomic.clj @@ -0,0 +1,11 @@ +(ns app.utils.datomic + (:require [datomic.api :as d])) + +(defn entity [conn id] + (d/entity (d/db conn) id)) + +(defn touch [conn results] + "takes 'entity ids' results from a query + e.g. '#{[272678883689461] [272678883689462] [272678883689459] [272678883689457]}'" + (let [e (partial entity conn)] + (map #(-> % first e d/touch) results))) diff --git a/test/clj/app/utils/logging.clj b/test/clj/app/utils/logging.clj new file mode 100644 index 0000000..2d8c64d --- /dev/null +++ b/test/clj/app/utils/logging.clj @@ -0,0 +1,46 @@ +(ns app.utils.logging ;; << change to your namespace/path + (:require [mount.core] + [robert.hooke :refer [add-hook clear-hooks]] + [clojure.string :refer [split]] + [clojure.tools.logging :refer [info]])) + +(alter-meta! *ns* assoc ::load false) + +(defn- f-to-action [f] + (let [fname (-> (str f) + (split #"@") + first)] + (case fname + "mount.core$up" :up + "mount.core$down" :down + "mount.core$sigstop" :suspend + "mount.core$sigcont" :resume + :noop))) + +(defn whatcha-doing? [{:keys [status suspend]} action] + (case action + :up (if (status :suspended) ">> resuming" + (if-not (status :started) ">> starting")) + :down (if (or (status :started) (status :suspended)) "<< stopping") + :suspend (if (and (status :started) suspend) "<< suspending") + :resume (if (status :suspended) ">> resuming"))) + +(defn log-status [f & args] + (let [{:keys [var] :as state} (second args) + action (f-to-action f)] + (when-let [taking-over-the-world (whatcha-doing? state action)] + (info (str taking-over-the-world ".. " var))) + (apply f args))) + +(defonce lifecycle-fns + #{#'mount.core/up + #'mount.core/down + #'mount.core/sigstop + #'mount.core/sigcont}) + +(defn without-logging-status [] + (doall (map #(clear-hooks %) lifecycle-fns))) + +(defn with-logging-status [] + (without-logging-status) + (doall (map #(add-hook % log-status) lifecycle-fns))) diff --git a/test/mount/test.cljc b/test/mount/test.cljc index b36c5b1..3fe3b53 100644 --- a/test/mount/test.cljc +++ b/test/mount/test.cljc @@ -3,18 +3,23 @@ #?@(:cljs [[cljs.test :as t] [doo.runner :refer-macros [doo-tests]]] :clj [[clojure.test :as t]]) - [mount.core :as mount] - - mount.test.fun-with-values - mount.test.private-fun)) + mount.core -(mount/in-cljc-mode) + mount.test.fun-with-values + mount.test.private-fun + mount.test.parts + )) + +(mount.core/in-cljc-mode) #?(:cljs - (doo-tests 'mount.test.fun-with-values - 'mount.test.private-fun)) -;; (doo.runner/do-all-tests) + ;; (doo.runner/do-all-tests) + (doo-tests + 'mount.test.fun-with-values + 'mount.test.private-fun + 'mount.test.parts + )) (defn run-tests [] (t/run-all-tests #"mount.test.*")) diff --git a/test/mount/test/helper.cljc b/test/mount/test/helper.cljc new file mode 100644 index 0000000..b85f92a --- /dev/null +++ b/test/mount/test/helper.cljc @@ -0,0 +1,11 @@ +(ns mount.test.helper + (:require mount.core)) + +(defn dval + "returns a value of DerefableState without deref'ing it" + [d] + (-> (@@(var mount.core/meta-state) + #?(:clj (.name d) + :cljs (.-name d))) + :inst + deref)) diff --git a/test/mount/test/parts.cljc b/test/mount/test/parts.cljc new file mode 100644 index 0000000..20a503f --- /dev/null +++ b/test/mount/test/parts.cljc @@ -0,0 +1,36 @@ +(ns mount.test.parts + (:require + #?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]] + [mount.core :as mount :refer-macros [defstate]] + [app.websockets :refer [system-a]] + [app.conf :refer [config]] + [app.audit-log :refer [log]]] + :clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]] + [mount.core :as mount :refer [defstate]] + [app.nyse :refer [conn]]]) + [mount.test.helper :refer [dval]])) + +(defstate should-not-start :start (constantly 42)) + +#?(:clj + (defn with-parts [f] + (mount/start #'app.conf/config #'app.nyse/conn) + (f) + (mount/stop))) + +(use-fixtures :once + #?(:cljs {:before #(mount/start #'app.conf/config #'app.audit-log/log) + :after mount/stop} + :clj with-parts)) + +#?(:clj + (deftest start-only-parts + (is (instance? datomic.peer.LocalConnection (dval conn))) + (is (instance? mount.core.NotStartedState (dval should-not-start))))) + +#?(:cljs + (deftest start-only-parts + (is (instance? datascript.db/DB @(dval log))) + (is (map? (dval config))) + (is (instance? mount.core.NotStartedState (dval should-not-start))) + (is (instance? mount.core.NotStartedState (dval system-a)))))