update unit tests
This commit is contained in:
parent
280d91b12b
commit
3c1b145f2d
|
@ -4,95 +4,95 @@
|
|||
views.test-helpers
|
||||
views.protocols
|
||||
views.core
|
||||
views.test-memory-db)
|
||||
(:import (views.test_memory_db MemoryView)))
|
||||
views.test-view-system)
|
||||
(:import (views.test_view_system MemoryView)))
|
||||
|
||||
(defn reset-state-fixture! [f]
|
||||
(reset! view-system {})
|
||||
(f))
|
||||
|
||||
(use-fixtures :each reset-state-fixture!)
|
||||
(use-fixtures :each reset-test-views-system)
|
||||
|
||||
|
||||
(defn dummy-send-fn [subscriber-key [view-sig view-data]])
|
||||
|
||||
(def test-options (merge default-options
|
||||
{:views views
|
||||
:send-fn dummy-send-fn}))
|
||||
|
||||
|
||||
;; tests
|
||||
|
||||
(deftest inits-with-correct-config-and-shutsdown-correctly
|
||||
(let [options default-options]
|
||||
(is (empty? @view-system))
|
||||
(let [options test-options]
|
||||
(is (empty? @test-views-system))
|
||||
; 1. init views
|
||||
(init! views dummy-send-fn options)
|
||||
(is (seq @view-system))
|
||||
(is (= dummy-send-fn (:send-fn @view-system)))
|
||||
(is (and (contains-view? :foo)
|
||||
(contains-view? :bar)
|
||||
(contains-view? :baz)))
|
||||
(is (not (:logging? @view-system)))
|
||||
(is (not (collect-stats?)))
|
||||
(is (empty? (subscribed-views)))
|
||||
(let [refresh-watcher (:refresh-watcher @view-system)
|
||||
workers (:workers @view-system)]
|
||||
(init! test-views-system test-options)
|
||||
(is (seq @test-views-system))
|
||||
(is (= dummy-send-fn (:send-fn @test-views-system)))
|
||||
(is (and (contains-view? test-views-system :foo)
|
||||
(contains-view? test-views-system :bar)
|
||||
(contains-view? test-views-system :baz)))
|
||||
(is (not (:logging? @test-views-system)))
|
||||
(is (not (collect-stats? test-views-system)))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(let [refresh-watcher (:refresh-watcher @test-views-system)
|
||||
workers (:workers @test-views-system)]
|
||||
(is (.isAlive ^Thread refresh-watcher))
|
||||
(is (= (:worker-threads options) (count workers)))
|
||||
(doseq [^Thread t workers]
|
||||
(is (.isAlive t)))
|
||||
; 2. shutdown views (and wait for all threads to also finish)
|
||||
(shutdown! true)
|
||||
(is (empty? @view-system))
|
||||
(shutdown! test-views-system true)
|
||||
(is (empty? @test-views-system))
|
||||
(is (not (.isAlive ^Thread refresh-watcher)))
|
||||
(doseq [^Thread t workers]
|
||||
(is (not (.isAlive t)))))))
|
||||
|
||||
(deftest init-can-also-start-logger
|
||||
(let [options (-> default-options
|
||||
(let [options (-> test-options
|
||||
(assoc :stats-log-interval 10000))]
|
||||
; 1. init views
|
||||
(init! views dummy-send-fn options)
|
||||
(is (seq (:statistics @view-system)))
|
||||
(is (:logging? @view-system))
|
||||
(is (collect-stats?))
|
||||
(let [logger-thread (get-in @view-system [:statistics :logger])]
|
||||
(init! test-views-system options)
|
||||
(is (seq (:statistics @test-views-system)))
|
||||
(is (:logging? @test-views-system))
|
||||
(is (collect-stats? test-views-system))
|
||||
(let [logger-thread (get-in @test-views-system [:statistics :logger])]
|
||||
(is (.isAlive ^Thread logger-thread))
|
||||
; 2. shutdown views
|
||||
(shutdown! true)
|
||||
(is (nil? (get-in @view-system [:statistics :logger])))
|
||||
(shutdown! test-views-system true)
|
||||
(is (nil? (get-in @test-views-system [:statistics :logger])))
|
||||
(is (not (.isAlive ^Thread logger-thread))))))
|
||||
|
||||
(deftest can-add-new-views-after-init
|
||||
(let [options default-options]
|
||||
(let [options test-options]
|
||||
; 1. init views
|
||||
(init! views dummy-send-fn options)
|
||||
(is (and (contains-view? :foo)
|
||||
(contains-view? :bar)
|
||||
(contains-view? :baz)))
|
||||
(init! test-views-system options)
|
||||
(is (and (contains-view? test-views-system :foo)
|
||||
(contains-view? test-views-system :bar)
|
||||
(contains-view? test-views-system :baz)))
|
||||
; 2. add new views
|
||||
(add-views! [(MemoryView. :one [:one])
|
||||
(add-views! test-views-system
|
||||
[(MemoryView. :one [:one])
|
||||
(MemoryView. :two [:two])])
|
||||
(is (and (contains-view? :foo)
|
||||
(contains-view? :bar)
|
||||
(contains-view? :baz)
|
||||
(contains-view? :one)
|
||||
(contains-view? :two)))
|
||||
(is (and (contains-view? test-views-system :foo)
|
||||
(contains-view? test-views-system :bar)
|
||||
(contains-view? test-views-system :baz)
|
||||
(contains-view? test-views-system :one)
|
||||
(contains-view? test-views-system :two)))
|
||||
; 3. shutdown views
|
||||
(shutdown! true)))
|
||||
(shutdown! test-views-system true)))
|
||||
|
||||
(deftest can-replace-views-after-init
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
replacement-view (MemoryView. :foo [:new-foo])]
|
||||
; 1. init views
|
||||
(init! views dummy-send-fn options)
|
||||
(is (and (contains-view? :foo)
|
||||
(contains-view? :bar)
|
||||
(contains-view? :baz)))
|
||||
(is (not= replacement-view (get-in @view-system [:views :foo])))
|
||||
(init! test-views-system options)
|
||||
(is (and (contains-view? test-views-system :foo)
|
||||
(contains-view? test-views-system :bar)
|
||||
(contains-view? test-views-system :baz)))
|
||||
(is (not= replacement-view (get-in @test-views-system [:views :foo])))
|
||||
; 2. add view. has same id so should replace existing one
|
||||
(add-views! [replacement-view])
|
||||
(is (and (contains-view? :foo)
|
||||
(contains-view? :bar)
|
||||
(contains-view? :baz)))
|
||||
(is (= replacement-view (get-in @view-system [:views :foo])))
|
||||
(add-views! test-views-system [replacement-view])
|
||||
(is (and (contains-view? test-views-system :foo)
|
||||
(contains-view? test-views-system :bar)
|
||||
(contains-view? test-views-system :baz)))
|
||||
(is (= replacement-view (get-in @test-views-system [:views :foo])))
|
||||
; 3. shutdown views
|
||||
(shutdown! true)))
|
||||
(shutdown! test-views-system true)))
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
views.test-helpers
|
||||
views.protocols
|
||||
views.core
|
||||
views.test-memory-db))
|
||||
views.test-view-system)
|
||||
(:import (clojure.lang Atom)))
|
||||
|
||||
|
||||
(def test-sent-data
|
||||
|
@ -15,67 +16,65 @@
|
|||
:view-sig view-sig
|
||||
:view-data view-data}))
|
||||
|
||||
|
||||
; fixtures
|
||||
|
||||
(defn reset-system-fixture [f]
|
||||
(reset! view-system {})
|
||||
(f)
|
||||
(shutdown! true))
|
||||
(def test-options (merge default-options
|
||||
{:views views
|
||||
:send-fn test-send-fn}))
|
||||
|
||||
(defn clear-sent-data-fixture [f]
|
||||
(reset! test-sent-data [])
|
||||
(f))
|
||||
|
||||
(use-fixtures :each clear-sent-data-fixture reset-system-fixture reset-memory-db-fixture)
|
||||
(use-fixtures :each clear-sent-data-fixture reset-test-views-system reset-memory-db-fixture)
|
||||
|
||||
|
||||
|
||||
;; tests
|
||||
|
||||
(deftest refresh-views!-instantly-attempts-view-refresh-with-given-hints
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
hints-refreshed (atom [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; with a view subscription (any subscription will do)
|
||||
(with-redefs [subscribed-views (fn [] #{(->view-sig :namespace :fake-view [])})
|
||||
refresh-view! (fn [hints _] (swap! hints-refreshed into hints))]
|
||||
(with-redefs [subscribed-views (fn [_] #{(->view-sig :namespace :fake-view [])})
|
||||
refresh-view! (fn [_ hints _] (swap! hints-refreshed into hints))]
|
||||
; 2. trigger refresh by calling refresh-views! with hints
|
||||
(refresh-views! [(hint :namespace [:foo] :fake-type)])
|
||||
(refresh-views! test-views-system [(hint :namespace [:foo] :fake-type)])
|
||||
(is (contains-only? @hints-refreshed
|
||||
[(hint :namespace [:foo] :fake-type)]))
|
||||
(reset! hints-refreshed [])
|
||||
; 3. same thing again, but passing in multiple hints
|
||||
(refresh-views! [(hint :namespace [:foo] :fake-type)
|
||||
(refresh-views! test-views-system
|
||||
[(hint :namespace [:foo] :fake-type)
|
||||
(hint :namespace [:bar] :fake-type)])
|
||||
(is (contains-only? @hints-refreshed
|
||||
[(hint :namespace [:foo] :fake-type)
|
||||
(hint :namespace [:bar] :fake-type)]))
|
||||
(reset! hints-refreshed []))
|
||||
; now, without any view subscriptions
|
||||
(with-redefs [subscribed-views (fn [] #{})
|
||||
refresh-view! (fn [hints _] (swap! hints-refreshed into hints))]
|
||||
(with-redefs [subscribed-views (fn [_] #{})
|
||||
refresh-view! (fn [_ hints _] (swap! hints-refreshed into hints))]
|
||||
; 4. again trigger refresh by calling refresh-views! with hints
|
||||
(refresh-views! [(hint :namespace [:foo] :fake-type)])
|
||||
(refresh-views! test-views-system [(hint :namespace [:foo] :fake-type)])
|
||||
(is (empty? @hints-refreshed))
|
||||
(reset! hints-refreshed []))))
|
||||
|
||||
(deftest refresh-watcher-runs-at-specified-interval-and-picks-up-queued-hints
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
hints-refreshed (atom [])]
|
||||
(with-redefs [subscribed-views (fn [] #{(->view-sig :namespace :fake-view [])})
|
||||
refresh-view! (fn [hints _] (swap! hints-refreshed into hints))]
|
||||
(with-redefs [subscribed-views (fn [_] #{(->view-sig :namespace :fake-view [])})
|
||||
refresh-view! (fn [_ hints _] (swap! hints-refreshed into hints))]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. queue a hint and wait until the next refresh interval
|
||||
(queue-hints! [(hint :namespace [:foo] :fake-type)])
|
||||
(queue-hints! test-views-system [(hint :namespace [:foo] :fake-type)])
|
||||
(wait-for-refresh-interval options)
|
||||
(is (contains-only? @hints-refreshed
|
||||
[(hint :namespace [:foo] :fake-type)]))
|
||||
(reset! hints-refreshed [])
|
||||
; 3. queue multiple hints and wait again
|
||||
(queue-hints! [(hint :namespace [:foo] :fake-type)
|
||||
(queue-hints! test-views-system
|
||||
[(hint :namespace [:foo] :fake-type)
|
||||
(hint :namespace [:bar] :fake-type)])
|
||||
(wait-for-refresh-interval options)
|
||||
(is (contains-only? @hints-refreshed
|
||||
|
@ -87,25 +86,26 @@
|
|||
(reset! hints-refreshed []))))
|
||||
|
||||
(deftest refresh-worker-thread-processes-relevant-hints
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
views-refreshed (atom [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(with-redefs [subscribed-views (fn [] #{(->view-sig :a :foo [])})
|
||||
do-view-refresh! (fn [view-sig] (swap! views-refreshed into [view-sig]))]
|
||||
(init! test-views-system options)
|
||||
(with-redefs [subscribed-views (fn [_] #{(->view-sig :a :foo [])})
|
||||
do-view-refresh! (fn [_ view-sig] (swap! views-refreshed into [view-sig]))]
|
||||
; 2. trigger refresh by calling refresh-views! with relevant hint
|
||||
(refresh-views! [(hint :a [:foo] memory-view-hint-type)])
|
||||
(refresh-views! test-views-system [(hint :a [:foo] memory-view-hint-type)])
|
||||
(wait-for-refresh-views)
|
||||
(is (contains-only? @views-refreshed [(->view-sig :a :foo [])]))
|
||||
(reset! views-refreshed [])
|
||||
; 3. same thing again, but passing in multiple hints (1 relevant, 1 not)
|
||||
(refresh-views! [(hint :a [:foo] memory-view-hint-type)
|
||||
(refresh-views! test-views-system [(hint :a [:foo] memory-view-hint-type)
|
||||
(hint :a [:bar] memory-view-hint-type)])
|
||||
(wait-for-refresh-views)
|
||||
(is (contains-only? @views-refreshed [(->view-sig :a :foo [])]))
|
||||
(reset! views-refreshed [])
|
||||
; 4. and lastly, passing in only irrelevant hints
|
||||
(refresh-views! [(hint :b [:foo] memory-view-hint-type)
|
||||
(refresh-views! test-views-system
|
||||
[(hint :b [:foo] memory-view-hint-type)
|
||||
(hint :a [:foo] :some-other-type)])
|
||||
(wait-for-refresh-views)
|
||||
(is (empty? @views-refreshed))
|
||||
|
@ -114,17 +114,17 @@
|
|||
; this test is really just testing that our helper function memory-db-assoc-in! works as we expect it to
|
||||
; (otherwise, it is entirely redundant given the above tests)
|
||||
(deftest test-memory-db-operation-triggers-proper-refresh-hints
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
hints-refreshed (atom [])
|
||||
views-refreshed (atom [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; first tests verifying that correct hints are being sent out (don't care if relevant or not yet)
|
||||
(with-redefs [subscribed-views (fn [] #{(->view-sig :a :foo [])})
|
||||
refresh-view! (fn [hints _] (swap! hints-refreshed into hints))]
|
||||
(memory-db-assoc-in! :a [:foo] 42)
|
||||
(memory-db-assoc-in! :a [:bar] 3.14)
|
||||
(memory-db-assoc-in! :b [:baz] [10 20 30])
|
||||
(with-redefs [subscribed-views (fn [_] #{(->view-sig :a :foo [])})
|
||||
refresh-view! (fn [_ hints _] (swap! hints-refreshed into hints))]
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] 42)
|
||||
(memory-db-assoc-in! test-views-system :a [:bar] 3.14)
|
||||
(memory-db-assoc-in! test-views-system :b [:baz] [10 20 30])
|
||||
(wait-for-refresh-views)
|
||||
(is (contains-only? @hints-refreshed
|
||||
[(hint :a [:foo] memory-view-hint-type)
|
||||
|
@ -133,116 +133,116 @@
|
|||
(reset! views-refreshed []))
|
||||
; now we test that relevant views were recognized as relevant and forwarded on to be used to
|
||||
; trigger actual refreshes of view data
|
||||
(with-redefs [subscribed-views (fn [] #{(->view-sig :a :foo [])})
|
||||
do-view-refresh! (fn [view-sig] (swap! views-refreshed into [view-sig]))]
|
||||
(with-redefs [subscribed-views (fn [_] #{(->view-sig :a :foo [])})
|
||||
do-view-refresh! (fn [_ view-sig] (swap! views-refreshed into [view-sig]))]
|
||||
; 2. update memory database (in a location covered by the subscribed view)
|
||||
(memory-db-assoc-in! :a [:foo] 1337)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] 1337)
|
||||
(wait-for-refresh-interval options)
|
||||
(is (contains-only? @views-refreshed [(->view-sig :a :foo [])]))
|
||||
(reset! views-refreshed [])
|
||||
; 3. same thing again, but update a different location not covered by any subscription
|
||||
(memory-db-assoc-in! :a [:bar] 1234.5678)
|
||||
(memory-db-assoc-in! test-views-system :a [:bar] 1234.5678)
|
||||
(wait-for-refresh-interval options)
|
||||
(is (empty? @views-refreshed)))))
|
||||
|
||||
(deftest relevant-hints-cause-refreshed-data-to-be-sent-to-subscriber
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [original-view-data (get-view-data view-sig)
|
||||
(let [original-view-data (get-view-data test-views-system view-sig)
|
||||
updated-view-data 21
|
||||
subscribe-result (subscribe! view-sig subscriber-key nil)]
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key nil)]
|
||||
; 3. block until subscription finishes. we don't care about the initial view data refresh
|
||||
(while (not (realized? subscribe-result)))
|
||||
(reset! test-sent-data [])
|
||||
(is (= (hash original-view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= (hash original-view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
; 4. change some test data that is covered by the view subscription
|
||||
(memory-db-assoc-in! :a [:foo] updated-view-data)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] updated-view-data)
|
||||
(wait-for-refresh-views)
|
||||
(is (= (hash updated-view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= (hash updated-view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
:view-data updated-view-data}])))))
|
||||
|
||||
(deftest irrelevant-hints-dont-trigger-refreshes
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [subscribe-result (subscribe! view-sig subscriber-key nil)]
|
||||
(let [subscribe-result (subscribe! test-views-system view-sig subscriber-key nil)]
|
||||
; 3. block until subscription finishes. we don't care about the initial view data refresh
|
||||
(while (not (realized? subscribe-result)))
|
||||
(reset! test-sent-data [])
|
||||
; 4. change some test data that is NOT covered by the view subscription
|
||||
(memory-db-assoc-in! :b [:foo] 6)
|
||||
(memory-db-assoc-in! :a [:bar] 7)
|
||||
(memory-db-assoc-in! test-views-system :b [:foo] 6)
|
||||
(memory-db-assoc-in! test-views-system :a [:bar] 7)
|
||||
(wait-for-refresh-views)
|
||||
(is (empty? @test-sent-data)))))
|
||||
|
||||
(deftest refreshes-not-sent-if-view-data-is-unchanged-since-last-refresh
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [updated-view-data 1111
|
||||
subscribe-result (subscribe! view-sig subscriber-key nil)]
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key nil)]
|
||||
; 3. block until subscription finishes. we don't care about the initial view data refresh
|
||||
(while (not (realized? subscribe-result)))
|
||||
(reset! test-sent-data [])
|
||||
; 4. change some test data, will cause a refresh to be sent out
|
||||
(memory-db-assoc-in! :a [:foo] updated-view-data)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] updated-view-data)
|
||||
(wait-for-refresh-views)
|
||||
(is (= (hash updated-view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= (hash updated-view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
:view-data updated-view-data}]))
|
||||
(reset! test-sent-data [])
|
||||
; 5. manually trigger another refresh for the view
|
||||
(refresh-views! [(hint :a [:foo] memory-view-hint-type)])
|
||||
(refresh-views! test-views-system [(hint :a [:foo] memory-view-hint-type)])
|
||||
(wait-for-refresh-views)
|
||||
(is (empty? @test-sent-data))
|
||||
; 6. also try "updating" the db with the same values
|
||||
(memory-db-assoc-in! :a [:foo] updated-view-data)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] updated-view-data)
|
||||
(wait-for-refresh-views)
|
||||
(is (empty? @test-sent-data)))))
|
||||
|
||||
(deftest refresh-queue-drops-duplicate-hints
|
||||
(let [options (-> default-options
|
||||
(let [options (-> test-options
|
||||
; enable statistics collection
|
||||
(assoc :stats-log-interval 10000))
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. prematurely stop refresh worker threads so that we can more easily inspect the
|
||||
; internal refresh queue's entries. the refresh worker threads are what remove
|
||||
; hints from the refresh queue as they are added to it.
|
||||
(stop-refresh-worker-threads)
|
||||
(stop-refresh-worker-threads test-views-system)
|
||||
; 3. subscribe to a view
|
||||
(let [subscribe-result (subscribe! view-sig subscriber-key nil)]
|
||||
(let [subscribe-result (subscribe! test-views-system view-sig subscriber-key nil)]
|
||||
; 4. block until subscription finishes
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= 0 (get-in @view-system [:statistics :deduplicated])))
|
||||
(is (= 0 (get-in @test-views-system [:statistics :deduplicated])))
|
||||
; 5. add duplicate hints by changing the same set of data twice
|
||||
; (hints will stay in the queue forever because we stopped the worker threads)
|
||||
(memory-db-assoc-in! :a [:foo] 6)
|
||||
(memory-db-assoc-in! :a [:foo] 7)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] 6)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] 7)
|
||||
(wait-for-refresh-views)
|
||||
(is (= 1 (get-in @view-system [:statistics :deduplicated])))
|
||||
(is (= 1 (get-in @test-views-system [:statistics :deduplicated])))
|
||||
(is (= [view-sig]
|
||||
(vec (:refresh-queue @view-system)))))))
|
||||
(vec (:refresh-queue @test-views-system)))))))
|
||||
|
||||
(deftest refresh-queue-drops-hints-when-full
|
||||
(let [options (-> default-options
|
||||
(let [options (-> test-options
|
||||
; enable statistics collection
|
||||
(assoc :stats-log-interval 10000
|
||||
:refresh-queue-size 1))
|
||||
|
@ -250,26 +250,26 @@
|
|||
view-sig-a (->view-sig :a :foo [])
|
||||
view-sig-b (->view-sig :b :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. prematurely stop refresh worker threads so that we can more easily inspect the
|
||||
; internal refresh queue's entries. the refresh worker threads are what remove
|
||||
; hints from the refresh queue as they are added to it.
|
||||
(stop-refresh-worker-threads)
|
||||
(stop-refresh-worker-threads test-views-system)
|
||||
; 3. subscribe to a view
|
||||
; note: log* redef is to suppress error log output which will normally happen whenever
|
||||
; another item is added to the refresh queue when it's already full
|
||||
(with-redefs [clojure.tools.logging/log* (fn [& _])]
|
||||
(let [subscribe-a (subscribe! view-sig-a subscriber-key nil)
|
||||
subscribe-b (subscribe! view-sig-b subscriber-key nil)]
|
||||
(let [subscribe-a (subscribe! test-views-system view-sig-a subscriber-key nil)
|
||||
subscribe-b (subscribe! test-views-system view-sig-b subscriber-key nil)]
|
||||
; 4. block until subscription finishes
|
||||
(while (or (not (realized? subscribe-a))
|
||||
(not (realized? subscribe-b))))
|
||||
(is (= 0 (get-in @view-system [:statistics :dropped])))
|
||||
(is (= 0 (get-in @test-views-system [:statistics :dropped])))
|
||||
; 5. change some data affecting the subscribed view, resulting in more then 1 hint
|
||||
; being added to the refresh queue
|
||||
(memory-db-assoc-in! :a [:foo] 101010)
|
||||
(memory-db-assoc-in! :b [:foo] 010101)
|
||||
(memory-db-assoc-in! test-views-system :a [:foo] 101010)
|
||||
(memory-db-assoc-in! test-views-system :b [:foo] 010101)
|
||||
(wait-for-refresh-views)
|
||||
(is (= 1 (get-in @view-system [:statistics :dropped])))
|
||||
(is (= 1 (get-in @test-views-system [:statistics :dropped])))
|
||||
(is (= [view-sig-a]
|
||||
(vec (:refresh-queue @view-system))))))))
|
||||
(vec (:refresh-queue @test-views-system))))))))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
views.test-helpers
|
||||
views.protocols
|
||||
views.core
|
||||
views.test-memory-db))
|
||||
views.test-view-system))
|
||||
|
||||
|
||||
(def test-sent-data
|
||||
|
@ -15,105 +15,101 @@
|
|||
:view-sig view-sig
|
||||
:view-data view-data}))
|
||||
|
||||
|
||||
; fixtures
|
||||
|
||||
(defn reset-system-fixture [f]
|
||||
(reset! view-system {})
|
||||
(f)
|
||||
(shutdown! true))
|
||||
(def test-options (merge default-options
|
||||
{:views views
|
||||
:send-fn test-send-fn}))
|
||||
|
||||
(defn clear-sent-data-fixture [f]
|
||||
(reset! test-sent-data [])
|
||||
(f))
|
||||
|
||||
(use-fixtures :each clear-sent-data-fixture reset-system-fixture reset-memory-db-fixture)
|
||||
(use-fixtures :each clear-sent-data-fixture reset-test-views-system reset-memory-db-fixture)
|
||||
|
||||
|
||||
|
||||
;; tests
|
||||
|
||||
(deftest can-subscribe-to-a-view
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :namespace :foo [])
|
||||
context {:my-data "arbitrary application context data"}]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(let [subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
(is (future? subscribe-result))
|
||||
(is (= [subscriber-key] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= [subscriber-key] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @test-views-system [:subscribers view-sig])))
|
||||
; 3. block until subscription finishes (data retrieval + initial view refresh)
|
||||
; (in this particular unit test, there is really no point in waiting)
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= #{view-sig} (subscribed-views))))))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system))))))
|
||||
|
||||
(deftest subscribing-results-in-initial-view-data-being-sent
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])
|
||||
context {:my-data "arbitrary application context data"}]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data (get-view-data view-sig)
|
||||
subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(let [view-data (get-view-data test-views-system view-sig)
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
; 3. block until subscription finishes (data retrieval + initial view refresh)
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
:view-data view-data}])))))
|
||||
|
||||
(deftest can-unsubscribe-from-a-view
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])
|
||||
context {:my-data "arbitrary application context data"}]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data (get-view-data view-sig)
|
||||
subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(is (= [subscriber-key] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(let [view-data (get-view-data test-views-system view-sig)
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
(is (= [subscriber-key] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @test-views-system [:subscribers view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
; 3. block until subscription finishes
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
; 4. unsubscribe
|
||||
(unsubscribe! view-sig subscriber-key context)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key context)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest multiple-subscription-and-unsubscriptions
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key-a 123
|
||||
subscriber-key-b 456
|
||||
view-sig (->view-sig :a :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data (get-view-data view-sig)
|
||||
subscribe-a (subscribe! view-sig subscriber-key-a nil)
|
||||
subscribe-b (subscribe! view-sig subscriber-key-b nil)]
|
||||
(let [view-data (get-view-data test-views-system view-sig)
|
||||
subscribe-a (subscribe! test-views-system view-sig subscriber-key-a nil)
|
||||
subscribe-b (subscribe! test-views-system view-sig subscriber-key-b nil)]
|
||||
; 3. block until both subscriptions finish
|
||||
(while (or (not (realized? subscribe-a))
|
||||
(not (realized? subscribe-b))))
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(is (= [subscriber-key-a subscriber-key-b] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key-a])))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-a subscriber-key-b} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key-a subscriber-key-b] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key-a])))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-a subscriber-key-b} (get-in @test-views-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key-a
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
|
@ -122,43 +118,43 @@
|
|||
:view-sig (dissoc view-sig :namespace)
|
||||
:view-data view-data}]))
|
||||
; 4. have one of the subscribers unsubscribe
|
||||
(unsubscribe! view-sig subscriber-key-a nil)
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(is (= [subscriber-key-b] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-b} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key-a nil)
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key-b] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-b} (get-in @test-views-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
; 5. have the last subscriber also unsubscribe
|
||||
(unsubscribe! view-sig subscriber-key-b nil)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key-b nil)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest subscriptions-to-different-views
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key-a 123
|
||||
subscriber-key-b 456
|
||||
view-sig-a (->view-sig :a :foo [])
|
||||
view-sig-b (->view-sig :a :bar [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data-a (get-view-data view-sig-a)
|
||||
view-data-b (get-view-data view-sig-b)
|
||||
subscribe-a (subscribe! view-sig-a subscriber-key-a nil)
|
||||
subscribe-b (subscribe! view-sig-b subscriber-key-b nil)]
|
||||
(let [view-data-a (get-view-data test-views-system view-sig-a)
|
||||
view-data-b (get-view-data test-views-system view-sig-b)
|
||||
subscribe-a (subscribe! test-views-system view-sig-a subscriber-key-a nil)
|
||||
subscribe-b (subscribe! test-views-system view-sig-b subscriber-key-b nil)]
|
||||
; 3. block until both subscriptions finish
|
||||
(while (or (not (realized? subscribe-a))
|
||||
(not (realized? subscribe-b))))
|
||||
(is (= #{view-sig-a view-sig-b} (subscribed-views)))
|
||||
(is (= [subscriber-key-a subscriber-key-b] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig-a} (get-in @view-system [:subscribed subscriber-key-a])))
|
||||
(is (= #{view-sig-b} (get-in @view-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-a} (get-in @view-system [:subscribers view-sig-a])))
|
||||
(is (= #{subscriber-key-b} (get-in @view-system [:subscribers view-sig-b])))
|
||||
(is (= (hash view-data-a) (get-in @view-system [:hashes view-sig-a])))
|
||||
(is (= (hash view-data-b) (get-in @view-system [:hashes view-sig-b])))
|
||||
(is (= #{view-sig-a view-sig-b} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key-a subscriber-key-b] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig-a} (get-in @test-views-system [:subscribed subscriber-key-a])))
|
||||
(is (= #{view-sig-b} (get-in @test-views-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-a} (get-in @test-views-system [:subscribers view-sig-a])))
|
||||
(is (= #{subscriber-key-b} (get-in @test-views-system [:subscribers view-sig-b])))
|
||||
(is (= (hash view-data-a) (get-in @test-views-system [:hashes view-sig-a])))
|
||||
(is (= (hash view-data-b) (get-in @test-views-system [:hashes view-sig-b])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key-a
|
||||
:view-sig (dissoc view-sig-a :namespace)
|
||||
|
@ -167,40 +163,40 @@
|
|||
:view-sig (dissoc view-sig-b :namespace)
|
||||
:view-data view-data-b}]))
|
||||
; 4. have one of the subscribers unsubscribe
|
||||
(unsubscribe! view-sig-a subscriber-key-a nil)
|
||||
(is (= #{view-sig-b} (subscribed-views)))
|
||||
(is (= [subscriber-key-b] (keys (:subscribed @view-system))))
|
||||
(is (empty? (get-in @view-system [:subscribed subscriber-key-a])))
|
||||
(is (= #{view-sig-b} (get-in @view-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-b} (get-in @view-system [:subscribers view-sig-b])))
|
||||
(is (empty? (get-in @view-system [:subscribers view-sig-a])))
|
||||
(is (empty? (get-in @view-system [:hashes view-sig-a])))
|
||||
(is (= (hash view-data-b) (get-in @view-system [:hashes view-sig-b])))
|
||||
(unsubscribe! test-views-system view-sig-a subscriber-key-a nil)
|
||||
(is (= #{view-sig-b} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key-b] (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (get-in @test-views-system [:subscribed subscriber-key-a])))
|
||||
(is (= #{view-sig-b} (get-in @test-views-system [:subscribed subscriber-key-b])))
|
||||
(is (= #{subscriber-key-b} (get-in @test-views-system [:subscribers view-sig-b])))
|
||||
(is (empty? (get-in @test-views-system [:subscribers view-sig-a])))
|
||||
(is (empty? (get-in @test-views-system [:hashes view-sig-a])))
|
||||
(is (= (hash view-data-b) (get-in @test-views-system [:hashes view-sig-b])))
|
||||
; 5. have the last subscriber also unsubscribe
|
||||
(unsubscribe! view-sig-b subscriber-key-b nil)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(unsubscribe! test-views-system view-sig-b subscriber-key-b nil)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest duplicate-subscriptions-do-not-cause-problems
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data (get-view-data view-sig)
|
||||
first-subscribe (subscribe! view-sig subscriber-key nil)
|
||||
second-subscribe (subscribe! view-sig subscriber-key nil)]
|
||||
(let [view-data (get-view-data test-views-system view-sig)
|
||||
first-subscribe (subscribe! test-views-system view-sig subscriber-key nil)
|
||||
second-subscribe (subscribe! test-views-system view-sig subscriber-key nil)]
|
||||
; 3. block until both subscriptions finish
|
||||
(while (or (not (realized? first-subscribe))
|
||||
(not (realized? second-subscribe))))
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @test-views-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
|
@ -210,20 +206,20 @@
|
|||
:view-data view-data}]))
|
||||
; 4. unsubscribe. only need to do this once, since only one subscription
|
||||
; should exist in the view system
|
||||
(unsubscribe! view-sig subscriber-key nil)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key nil)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest subscribing-to-non-existant-view-raises-exception
|
||||
(let [options default-options
|
||||
(let [options test-options
|
||||
subscriber-key 123
|
||||
view-sig (->view-sig :namespace :non-existant-view [])]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(is (thrown? Exception (subscribe! view-sig subscriber-key nil)))))
|
||||
(is (thrown? Exception (subscribe! test-views-system view-sig subscriber-key nil)))))
|
||||
|
||||
(deftest subscribe-and-unsubscribe-use-namespace-fn-if-set-and-no-namespace-in-view-sig
|
||||
(let [subscriber-key 123
|
||||
|
@ -234,10 +230,10 @@
|
|||
(is (= subscriber-key subscriber-key*))
|
||||
(is (= context context*))
|
||||
:b)
|
||||
options (-> default-options
|
||||
options (-> test-options
|
||||
(assoc :namespace-fn namespace-fn))]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [; with the above namespace-fn, subscribe will internally use this view sig
|
||||
; when setting up subscription info within view-system. application code
|
||||
|
@ -246,16 +242,16 @@
|
|||
; such as right here, we need to use the actual namespace that was set in
|
||||
; view-system to pass in the same parameters that subscribe! will use for
|
||||
; the view during it's initial view data refresh
|
||||
view-data (get-view-data view-sig-with-ns)
|
||||
view-data (get-view-data test-views-system view-sig-with-ns)
|
||||
; passing in view-sig *without* namespace
|
||||
subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
; 3. block until subscription finishes
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= #{view-sig-with-ns} (subscribed-views)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig-with-ns} (get-in @view-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @view-system [:subscribers view-sig-with-ns])))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig-with-ns])))
|
||||
(is (= #{view-sig-with-ns} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig-with-ns} (get-in @test-views-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @test-views-system [:subscribers view-sig-with-ns])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig-with-ns])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
|
@ -266,11 +262,11 @@
|
|||
; return given the same inputs. ideal namespace-fn implementations will
|
||||
; also keep this in mind even if context could vary between subscribe!
|
||||
; and unsubscribe! calls.
|
||||
(unsubscribe! view-sig subscriber-key context)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key context)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest subscribe-and-unsubscribe-do-not-use-namespace-fn-if-namespace-included-in-view-sig
|
||||
(let [subscriber-key 123
|
||||
|
@ -279,30 +275,30 @@
|
|||
namespace-fn (fn [view-sig* subscriber-key* context*]
|
||||
; if this function is used, it will mess up several assertions in this unit test
|
||||
:b)
|
||||
options (-> default-options
|
||||
options (-> test-options
|
||||
(assoc :namespace-fn namespace-fn))]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data (get-view-data view-sig)
|
||||
subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(let [view-data (get-view-data test-views-system view-sig)
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
; 3. block until subscription finishes
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @test-views-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
:view-data view-data}]))
|
||||
; 4. unsubscribe.
|
||||
(unsubscribe! view-sig subscriber-key context)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key context)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest unauthorized-subscription-using-auth-fn
|
||||
(let [subscriber-key 123
|
||||
|
@ -314,17 +310,17 @@
|
|||
(is (= context context*))
|
||||
; false = unauthorized
|
||||
false)
|
||||
options (-> default-options
|
||||
options (-> test-options
|
||||
(assoc :auth-fn auth-fn))]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(let [subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
(is (nil? subscribe-result))
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest unauthorized-subscription-using-auth-fn-calls-on-unauth-fn-when-set
|
||||
(let [subscriber-key 123
|
||||
|
@ -342,19 +338,19 @@
|
|||
(is (= subscriber-key subscriber-key*))
|
||||
(is (= context context*))
|
||||
(reset! on-unauth-called? true))
|
||||
options (-> default-options
|
||||
options (-> test-options
|
||||
(assoc :auth-fn auth-fn
|
||||
:on-unauth-fn on-unauth-fn))]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(let [subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
(is (nil? subscribe-result))
|
||||
(is @on-unauth-called?)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system))))))
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system))))))
|
||||
|
||||
(deftest authorized-subscription-using-auth-fn
|
||||
(let [subscriber-key 123
|
||||
|
@ -365,19 +361,19 @@
|
|||
(is (= subscriber-key subscriber-key*))
|
||||
(is (= context context*))
|
||||
true)
|
||||
options (-> default-options
|
||||
options (-> test-options
|
||||
(assoc :auth-fn auth-fn))]
|
||||
; 1. init views
|
||||
(init! views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [view-data (get-view-data view-sig)
|
||||
subscribe-result (subscribe! view-sig subscriber-key context)]
|
||||
(let [view-data (get-view-data test-views-system view-sig)
|
||||
subscribe-result (subscribe! test-views-system view-sig subscriber-key context)]
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @view-system))))
|
||||
(is (= #{view-sig} (get-in @view-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @view-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @view-system [:hashes view-sig])))
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (= [subscriber-key] (keys (:subscribed @test-views-system))))
|
||||
(is (= #{view-sig} (get-in @test-views-system [:subscribed subscriber-key])))
|
||||
(is (= #{subscriber-key} (get-in @test-views-system [:subscribers view-sig])))
|
||||
(is (= (hash view-data) (get-in @test-views-system [:hashes view-sig])))
|
||||
(is (contains-only? @test-sent-data
|
||||
[{:subscriber-key subscriber-key
|
||||
:view-sig (dissoc view-sig :namespace)
|
||||
|
@ -386,25 +382,26 @@
|
|||
(deftest unsubscribe-before-subscription-finishes-does-not-result-in-stuck-view
|
||||
(let [subscriber-key 123
|
||||
view-sig (->view-sig :a :foo [])
|
||||
options default-options]
|
||||
options (-> test-options
|
||||
(assoc :views slow-views))]
|
||||
; 1. init views
|
||||
(init! slow-views test-send-fn options)
|
||||
(init! test-views-system options)
|
||||
; 2. subscribe to a view
|
||||
(let [subscribe-result (subscribe! view-sig subscriber-key nil)]
|
||||
(is (= #{view-sig} (subscribed-views)))
|
||||
(let [subscribe-result (subscribe! test-views-system view-sig subscriber-key nil)]
|
||||
(is (= #{view-sig} (subscribed-views test-views-system)))
|
||||
(is (not (realized? subscribe-result)))
|
||||
; 3. unsubscribe before subscription finishes (still waiting on initial data
|
||||
; retrieval to finish)
|
||||
(unsubscribe! view-sig subscriber-key nil)
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system)))
|
||||
(unsubscribe! test-views-system view-sig subscriber-key nil)
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system)))
|
||||
(is (empty? @test-sent-data))
|
||||
; 4. wait for subscription to finish finally
|
||||
(while (not (realized? subscribe-result)))
|
||||
(is (empty? (keys (:subscribed @view-system))))
|
||||
(is (empty? (keys (:subscribers @view-system))))
|
||||
(is (empty? (subscribed-views)))
|
||||
(is (empty? (:hashes @view-system)))
|
||||
(is (empty? (keys (:subscribed @test-views-system))))
|
||||
(is (empty? (keys (:subscribers @test-views-system))))
|
||||
(is (empty? (subscribed-views test-views-system)))
|
||||
(is (empty? (:hashes @test-views-system)))
|
||||
(is (empty? @test-sent-data)))))
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
(:use
|
||||
clojure.test
|
||||
views.protocols
|
||||
views.core))
|
||||
views.core)
|
||||
(:import (clojure.lang Atom)))
|
||||
|
||||
(defn contains-view?
|
||||
[view-id]
|
||||
[^Atom view-system view-id]
|
||||
(let [view (get (:views @view-system) view-id)]
|
||||
(and view
|
||||
(satisfies? IView view))))
|
||||
|
@ -29,7 +30,7 @@
|
|||
elements)))
|
||||
|
||||
(defn get-view-data
|
||||
[view-sig]
|
||||
[^Atom view-system view-sig]
|
||||
(data (get-in @view-system [:views (:view-id view-sig)])
|
||||
(:namespace view-sig)
|
||||
(:parameters view-sig)))
|
||||
|
@ -45,7 +46,8 @@
|
|||
; this is kind of a hack, but necessary for some tests where we want to inspect
|
||||
; the items being sent to the refresh queue without worker threads picking out
|
||||
; the added items almost instantly.
|
||||
(defn stop-refresh-worker-threads []
|
||||
(defn stop-refresh-worker-threads
|
||||
[^Atom view-system]
|
||||
(swap! view-system assoc :stop-workers? true)
|
||||
(doseq [^Thread t (:workers @view-system)]
|
||||
(.interrupt t)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns views.test-memory-db
|
||||
(ns views.test-view-system
|
||||
(:use
|
||||
views.protocols
|
||||
views.core))
|
||||
views.core)
|
||||
(:import (clojure.lang Atom)))
|
||||
|
||||
(def base-memory-db-contents
|
||||
{:a {:foo 1 :bar 200 :baz [1 2 3]}
|
||||
|
@ -10,10 +11,19 @@
|
|||
(def memory-database
|
||||
(atom base-memory-db-contents))
|
||||
|
||||
(def test-views-system
|
||||
(atom {}))
|
||||
|
||||
(defn reset-memory-db-fixture [f]
|
||||
(reset! memory-database base-memory-db-contents)
|
||||
(f))
|
||||
|
||||
(defn reset-test-views-system [f]
|
||||
(reset! test-views-system {})
|
||||
(f)
|
||||
(if (seq @test-views-system)
|
||||
(shutdown! test-views-system true)))
|
||||
|
||||
(def memory-view-hint-type :memory-db)
|
||||
|
||||
(defrecord MemoryView [id ks]
|
||||
|
@ -55,7 +65,7 @@
|
|||
(SlowMemoryView. :baz [:baz])])
|
||||
|
||||
(defn memory-db-assoc-in!
|
||||
[namespace ks v]
|
||||
[^Atom view-system namespace ks v]
|
||||
(let [ms (swap! memory-database assoc-in (into [namespace] ks) v)]
|
||||
(put-hints! [(hint namespace ks memory-view-hint-type)])
|
||||
(put-hints! view-system [(hint namespace ks memory-view-hint-type)])
|
||||
ms))
|
Loading…
Reference in a new issue