2015-11-20 03:28:49 +00:00
( ns check.suspend-resume-test
( :require [ mount.core :as mount :refer [ defstate ] ]
[ app.config :refer [ app-config ] ]
[ app.nyse :refer [ conn ] ]
[ app :refer [ nrepl ] ]
[ clojure.test :refer :all ] ) )
2015-11-21 16:23:24 +00:00
( defn koncat [ k s ]
( -> ( name k )
( str "-" ( name s ) )
keyword ) )
( defn start [ s ] ( koncat s :started ) )
( defn stop [ s ] ( koncat s :stopped ) )
( defn suspend [ s ] ( koncat s :suspended ) )
( defn resume [ s ] ( koncat s :resumed ) )
2015-11-30 22:23:03 +00:00
( defstate web-server :start ( start :w )
:stop ( stop :w )
:suspend ( suspend :w )
:resume ( resume :w ) )
2015-11-27 17:48:35 +00:00
2015-11-30 22:23:03 +00:00
( defstate q-listener :start ( start :q )
:stop ( stop :q )
:suspend ( suspend :q )
:resume ( resume :q ) )
2015-11-21 16:23:24 +00:00
2015-11-30 22:23:03 +00:00
( defstate randomizer :start ( rand-int 42 ) )
2015-11-20 03:28:49 +00:00
2015-11-29 18:27:26 +00:00
( deftest suspendable-lifecycle
2015-11-21 16:23:24 +00:00
( testing "should suspend _only suspendable_ states that are currently started"
( let [ _ ( mount/start )
_ ( mount/suspend ) ]
( is ( map? app-config ) )
( is ( instance? clojure.tools.nrepl.server.Server nrepl ) )
( is ( instance? datomic.peer.LocalConnection conn ) )
( is ( = web-server :w-suspended ) )
( mount/stop ) ) )
( testing "should resume _only suspendable_ states that are currently suspended"
( let [ _ ( mount/start )
_ ( mount/stop # 'app/nrepl )
_ ( mount/suspend )
_ ( mount/resume ) ]
( is ( map? app-config ) )
( is ( instance? mount.core.NotStartedState nrepl ) )
( is ( instance? datomic.peer.LocalConnection conn ) )
( is ( = web-server :w-resumed ) )
( mount/stop ) ) )
( testing "should start all the states, except the ones that are currently suspended, should resume them instead"
( let [ _ ( mount/start )
_ ( mount/suspend )
_ ( mount/start ) ]
( is ( map? app-config ) )
( is ( instance? clojure.tools.nrepl.server.Server nrepl ) )
( is ( instance? datomic.peer.LocalConnection conn ) )
( is ( = web-server :w-resumed ) )
( mount/stop ) ) )
( testing "should stop all: started and suspended"
( let [ _ ( mount/start )
_ ( mount/suspend )
_ ( mount/stop ) ]
( is ( instance? mount.core.NotStartedState app-config ) )
( is ( instance? mount.core.NotStartedState nrepl ) )
( is ( instance? mount.core.NotStartedState conn ) )
2015-11-29 18:27:26 +00:00
( is ( instance? mount.core.NotStartedState web-server ) ) ) ) )
2015-11-20 03:28:49 +00:00
2015-11-29 18:27:26 +00:00
( deftest suspendable-start-with
2015-11-21 16:23:24 +00:00
2015-11-20 03:28:49 +00:00
( testing " when replacing a non suspendable state with a suspendable one ,
the later should be able to suspend/resume ,
2015-11-21 16:23:24 +00:00
the original should not be suspendable after resume and preserve its lifecycle fns after rollback/stop "
( let [ _ ( mount/start-with { # 'app/nrepl # 'check.suspend-resume-test/web-server } )
_ ( mount/suspend ) ]
( is ( = nrepl :w-suspended ) )
( is ( instance? mount.core.NotStartedState web-server ) )
( mount/stop )
( mount/start )
( mount/suspend )
( is ( instance? clojure.tools.nrepl.server.Server nrepl ) )
( is ( = web-server :w-suspended ) )
( mount/stop ) ) )
2015-11-20 03:28:49 +00:00
2015-11-21 16:23:24 +00:00
;; this is a messy use case, but can still happen especially at REPL time
2015-11-29 18:27:26 +00:00
;; it also messy, because usually :stop function refers the _original_ state by name (i.e. #(disconnect conn))
;; (unchanged/not substituted in its lexical scope), and original state won't be started
( testing " when replacing a suspendable state with a non suspendable one ,
the later should not be suspendable ,
the original should still be suspendable and preserve its lifecycle fns after the rollback/stop "
( let [ _ ( mount/start-with { # 'check.suspend-resume-test/web-server # 'check.suspend-resume-test/randomizer } )
_ ( mount/suspend ) ]
( is ( integer? web-server ) )
( is ( instance? mount.core.NotStartedState randomizer ) )
( mount/stop )
( mount/start )
( mount/suspend )
( is ( integer? randomizer ) )
( is ( = web-server :w-suspended ) )
( mount/stop ) ) )
;; this is a messy use case, but can still happen especially at REPL time
( testing " when replacing a suspended state with a non suspendable started one ,
2015-11-20 03:28:49 +00:00
the later should not be suspendable ,
2015-11-21 16:23:24 +00:00
the original should still be suspended and preserve its lifecycle fns after the rollback/stop "
( let [ _ ( mount/start )
_ ( mount/suspend )
_ ( mount/start-with { # 'check.suspend-resume-test/web-server # 'app.nyse/conn } ) ;; TODO: good to WARN on started states during "start-with"
_ ( mount/suspend ) ]
( is ( instance? datomic.peer.LocalConnection conn ) )
2015-11-29 18:27:26 +00:00
( is ( = web-server :w-suspended ) ) ;; since the "conn" does not have a resume method, so web-server was not started
2015-11-21 16:23:24 +00:00
( mount/stop )
( mount/start )
( mount/suspend )
( is ( instance? datomic.peer.LocalConnection conn ) )
( is ( = web-server :w-suspended ) )
( mount/stop ) ) )
2015-11-20 03:28:49 +00:00
2015-11-21 16:23:24 +00:00
;; this is a messy use case, but can still happen especially at REPL time
2015-11-20 03:28:49 +00:00
( testing " when replacing a suspended state with a suspendable one ,
the later should be suspendable ,
2015-11-21 16:23:24 +00:00
the original should still be suspended and preserve its lifecycle fns after the rollback/stop "
( let [ _ ( mount/start )
_ ( mount/suspend )
_ ( mount/start-with { # 'check.suspend-resume-test/web-server # 'check.suspend-resume-test/q-listener } ) ] ;; TODO: good to WARN on started states during "start-with"
( is ( = q-listener :q-suspended ) )
( is ( = web-server :q-resumed ) )
( mount/suspend )
( is ( = q-listener :q-suspended ) )
( is ( = web-server :q-suspended ) )
( mount/stop )
( is ( instance? mount.core.NotStartedState web-server ) )
( is ( instance? mount.core.NotStartedState q-listener ) )
( mount/start )
( mount/suspend )
( is ( = q-listener :q-suspended ) )
( is ( = web-server :w-suspended ) )
( mount/stop ) ) ) )