Add back sync integration tests

This commit is contained in:
Nicholas Kariniemi 2014-10-21 22:58:56 +03:00
parent 8fe22b9a52
commit 79e64596ae
2 changed files with 92 additions and 62 deletions

View file

@ -24,18 +24,22 @@
{:type :diff
:diff diff}))
(defmulti handle-event (fn [event] (:type event)))
(defmulti handle-event (fn [event]
(:type event)))
(defn apply-diff [states diff shadow]
(let [new-states (swap! states update-states diff)
new-state (state/get-latest new-states)
new-shadow (diff/patch-state shadow diff true)]
{:out-event (when-not (state/state= shadow new-state)
(diff-msg new-shadow new-state))
:new-states new-states
:new-shadow new-shadow}))
(defmethod handle-event :diff [{:keys [diff states shadow client?]}]
(let [history-shadow (state/get-tagged @states (:shadow-tag diff))]
(if history-shadow
(let [new-states (swap! states update-states diff)
new-state (state/get-latest new-states)
new-shadow (diff/patch-state history-shadow diff true)]
{:out-event (when-not (state/state= history-shadow new-state)
(diff-msg new-shadow new-state))
:new-states new-states
:new-shadow new-shadow})
(apply-diff states diff history-shadow)
(if client?
{:out-event full-sync-request
:new-shadow shadow}

View file

@ -1,5 +1,6 @@
(ns grub.test.integration.synchronization
(:require [grub.sync :as sync]
[grub.state :as state]
[clojure.test :refer :all]
[midje.sweet :refer :all]
[clojure.core.async :as a :refer [<!! >!! chan go]]))
@ -8,58 +9,83 @@
(let [[v p] (a/alts!! [c (a/timeout 100)])]
v))
;; (fact "Client-only changes synced with server"
;; (let [client-shadow {:grubs {"1" {:text "2 apples" :completed true}} :recipes {}}
;; client-states (states-atom
;; {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
;; {:grubs {"1" {:text "2 apples" :completed true}} :recipes {}})
;; server-shadow {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
;; server-states (states-atom server-shadow)
;; client-in (chan)
;; client-out (chan)
;; server-in (chan)
;; server-out (chan)
;; client-state-changes (chan 1)
;; msg {:type :new-state
;; :state {:grubs {"1" {:text "2 apples" :completed true}} :recipes {}}}]
;; (a/pipe client-out server-in)
;; (a/pipe server-out client-in)
;; (sync/make-client-agent client-in client-out client-states server-shadow)
;; (sync/make-server-agent server-in server-out server-states client-shadow)
;; (add-watch client-states :test (fn [_ _ _ new-states] (a/put! client-state-changes new-states)))
;; (>!! client-in msg)
;; (<!!? client-state-changes)
;; (:state (last @client-states)) => {:grubs {"1" {:completed true, :text "2 apples"}}
;; :recipes {}}
;; (:state (last @server-states)) => {:grubs {"1" {:completed true, :text "2 apples"}}
;; :recipes {}}))
(defn client-server [client-states server-states]
(let [server-shadow (last @server-states)
client-shadow (last @client-states)
new-client-states (chan)
>client (chan)
new-server-states (chan)
>server (chan)]
(sync/make-client-agent >server >client new-client-states client-states server-shadow)
(sync/make-server-agent >client >server new-server-states server-states client-shadow)
{:new-client-states new-client-states
:new-server-states new-server-states}))
(defn states-in-sync? [a b]
(state/state= (last a) (last b)))
(defn last-state [states]
(-> states
(last)
(dissoc :tag)))
(defn short-delay []
(<!! (a/timeout 300)))
(fact "Client-only changes sync with server"
(let [client (atom [{:tag 1
:grubs {"1" {:text "2 apples" :completed false}}
:recipes {}}])
server (atom [{:tag 44 :grubs {"1" {:text "2 apples" :completed false}}
:recipes {}}])
{:keys [new-client-states]} (client-server client server)
client-change {:tag 2
:grubs {"1" {:text "2 apples" :completed true}}
:recipes {}}]
(swap! client conj client-change)
(>!! new-client-states client-change)
(short-delay)
(states-in-sync? @client @server) => true
(last-state @client) => {:grubs {"1" {:text "2 apples" :completed true}}
:recipes {}}))
(fact "Other client changes synced with client"
(let [client (atom [{:tag 1
:grubs {"1" {:text "2 apples" :completed false}}
:recipes {}}])
server (atom [{:tag 44 :grubs {"1" {:text "2 apples" :completed false}}
:recipes {}}])
{:keys [new-server-states]} (client-server client server)
server-change {:tag 2
:grubs {"1" {:text "2 apples" :completed true}}
:recipes {}}]
(swap! server conj server-change)
(>!! new-server-states server-change)
(short-delay)
(states-in-sync? @client @server) => true
(last-state @client) => {:grubs {"1" {:text "2 apples" :completed true}}
:recipes {}}))
(fact "Client changes and simultaneous server changes synced"
(let [client (atom [{:tag 1
:grubs {"1" {:text "2 apples" :completed false}}
:recipes {}}])
server (atom [{:tag 44 :grubs {"1" {:text "2 apples" :completed false}}
:recipes {}}])
{:keys [new-client-states]} (client-server client server)
client-change {:tag 2
:grubs {"1" {:text "2 apples" :completed true}}
:recipes {}}
server-change {:tag 45
:grubs {"1" {:text "2 apples" :completed false}
"2" {:text "milk" :completed false}}
:recipes {}}]
(swap! client conj client-change)
(swap! server conj server-change)
(>!! new-client-states client-change)
(short-delay)
(states-in-sync? @client @server) => true
(last-state @client) => {:grubs {"1" {:text "2 apples" :completed true}
"2" {:text "milk" :completed false}}
:recipes {}}))
;; (fact "Client and server changes synced"
;; (let [client-shadow {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
;; client-states (states-atom
;; {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
;; {:grubs {"1" {:text "2 apples" :completed true}} :recipes {}})
;; server-shadow {:grubs {"1" {:text "2 apples" :completed false}} :recipes {}}
;; server-states (states-atom
;; server-shadow
;; {:grubs {"1" {:text "4 apples" :completed false}} :recipes {}})
;; client-in (chan)
;; client-out (chan)
;; server-in (chan)
;; server-out (chan)
;; msg {:type :new-state
;; :state {:grubs {"1" {:text "2 apples" :completed true}} :recipes {}}}
;; client-state-changes (chan 1)]
;; (a/pipe client-out server-in)
;; (a/pipe server-out client-in)
;; (sync/make-client-agent client-in client-out client-states server-shadow)
;; (sync/make-server-agent server-in server-out server-states client-shadow)
;; (add-watch client-states :test (fn [_ _ _ new-states] (a/put! client-state-changes new-states)))
;; (>!! client-in msg)
;; (<!!? client-state-changes)
;; @client-states => (hashed-states
;; {:grubs {"1" {:completed true, :text "4 apples"}}, :recipes {}})
;; @server-states => (hashed-states
;; {:grubs {"1" {:completed false, :text "2 apples"}}, :recipes {}}
;; {:grubs {"1" {:completed false, :text "4 apples"}}, :recipes {}}
;; {:grubs {"1" {:completed true, :text "4 apples"}}, :recipes {}})))