add comments to the bind channel requests as they're somewhat complex
This commit is contained in:
parent
1ecaeae744
commit
f401eb95f8
|
@ -112,8 +112,10 @@
|
||||||
|
|
||||||
(deftest create-session-and-open-backchannel-test
|
(deftest create-session-and-open-backchannel-test
|
||||||
(let [options default-options
|
(let [options default-options
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (-> (mock/request
|
back-resp (app (-> (mock/request
|
||||||
:get "/channel/bind")
|
:get "/channel/bind")
|
||||||
(mock/query-string
|
(mock/query-string
|
||||||
|
@ -126,15 +128,17 @@
|
||||||
"TYPE" "xmlhttp"
|
"TYPE" "xmlhttp"
|
||||||
"zx" (random-string)
|
"zx" (random-string)
|
||||||
"t" 1})))
|
"t" 1})))
|
||||||
|
; 3. get backchannel response so far (basically nothing other then headers at this point)
|
||||||
async-resp @async-output]
|
async-resp @async-output]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(let [status (get-status session-id)]
|
(let [status (get-status session-id)]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
(is (= 200 (:status async-resp)))
|
(is (= 200 (:status async-resp)))
|
||||||
|
; 4. verify session is still connected, backchannel request still alive
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
(is (contains-all-of? (:headers async-resp)
|
(is (contains-all-of? (:headers async-resp)
|
||||||
(dissoc (:headers options) "Content-Type")))
|
(dissoc (:headers options) "Content-Type")))
|
||||||
(is (:connected? status))
|
(is (connected? session-id))
|
||||||
(is (:has-back-channel? status)))))
|
(is (:has-back-channel? status)))))
|
||||||
|
|
||||||
(defn ->new-backchannel-request
|
(defn ->new-backchannel-request
|
||||||
|
@ -154,12 +158,16 @@
|
||||||
|
|
||||||
(deftest send-data-to-client-test
|
(deftest send-data-to-client-test
|
||||||
(let [options default-options
|
(let [options default-options
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. send data to client along backchannel
|
||||||
(send-data session-id {:foo "bar"})
|
(send-data session-id {:foo "bar"})
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 4. get async response so far from the backchannel
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
|
@ -167,18 +175,23 @@
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
(is (contains-all-of? (:headers async-resp)
|
(is (contains-all-of? (:headers async-resp)
|
||||||
(dissoc (:headers options) "Content-Type")))
|
(dissoc (:headers options) "Content-Type")))
|
||||||
|
; 5. verify data was sent
|
||||||
(is (= (-> arrays ffirst second (get "__edn") (edn/read-string))
|
(is (= (-> arrays ffirst second (get "__edn") (edn/read-string))
|
||||||
{:foo "bar"})))))
|
{:foo "bar"})))))
|
||||||
|
|
||||||
(deftest send-multiple-data-to-client-test
|
(deftest send-multiple-data-to-client-test
|
||||||
(let [options default-options
|
(let [options default-options
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. send data to client along backchannel
|
||||||
(send-data session-id {:foo "bar"})
|
(send-data session-id {:foo "bar"})
|
||||||
(send-data session-id "hello, world")
|
(send-data session-id "hello, world")
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 4. get async response so far from the backchannel
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
|
@ -186,6 +199,7 @@
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
(is (contains-all-of? (:headers async-resp)
|
(is (contains-all-of? (:headers async-resp)
|
||||||
(dissoc (:headers options) "Content-Type")))
|
(dissoc (:headers options) "Content-Type")))
|
||||||
|
; 5. verify data was sent
|
||||||
(is (= (get-edn-from-arrays arrays 0)
|
(is (= (get-edn-from-arrays arrays 0)
|
||||||
{:foo "bar"}))
|
{:foo "bar"}))
|
||||||
(is (= (get-edn-from-arrays arrays 1)
|
(is (= (get-edn-from-arrays arrays 1)
|
||||||
|
@ -193,13 +207,18 @@
|
||||||
|
|
||||||
(deftest send-data-to-client-before-backchannel-created
|
(deftest send-data-to-client-before-backchannel-created
|
||||||
(let [options default-options
|
(let [options default-options
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)]
|
session-id (get-session-id create-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 2. send data to client. no backchannel yet, so it should be queued in a buffer
|
||||||
(send-data session-id {:foo "bar"})
|
(send-data session-id {:foo "bar"})
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. backchannel request (long request, async response).
|
||||||
|
; queued buffer of messages is flushed to backchannel when it first opens
|
||||||
(let [back-resp (app (->new-backchannel-request session-id))]
|
(let [back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 4. get async response so far from the backchannel
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
|
@ -207,48 +226,61 @@
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
(is (contains-all-of? (:headers async-resp)
|
(is (contains-all-of? (:headers async-resp)
|
||||||
(dissoc (:headers options) "Content-Type")))
|
(dissoc (:headers options) "Content-Type")))
|
||||||
|
; 5. verify data was sent
|
||||||
(is (= (get-edn-from-arrays arrays 0)
|
(is (= (get-edn-from-arrays arrays 0)
|
||||||
{:foo "bar"}))))))
|
{:foo "bar"}))))))
|
||||||
|
|
||||||
(deftest send-data-to-client-after-backchannel-reconnect
|
(deftest send-data-to-client-after-backchannel-reconnect
|
||||||
(let [options default-options
|
(let [options default-options
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
; close backchannel
|
; 3. close backchannel. we do it via clear-back-channel directly as it better
|
||||||
|
; simulates either a network disconnect or connection timeout (which can and will happen)
|
||||||
(send-off (get @sessions session-id) clear-back-channel)
|
(send-off (get @sessions session-id) clear-back-channel)
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
; nothing should have been written
|
; 4. get async response so far from the backchannel. nothing should have been written at this point.
|
||||||
|
; also, verify backchannel request has indeed been closed
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status async-resp)))
|
(is (= 200 (:status async-resp)))
|
||||||
(is (:closed? async-resp))
|
(is (:closed? async-resp))
|
||||||
(is (empty? arrays)))
|
(is (empty? arrays)))
|
||||||
|
; reset async response output. hacky necessity due to the way we capture this output
|
||||||
(reset! async-output {})
|
(reset! async-output {})
|
||||||
; open second backchannel
|
; 5. second backchannel request
|
||||||
(let [back-resp (app (->new-backchannel-request session-id))]
|
(let [back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 6. send data to client along backchannel
|
||||||
(send-data session-id {:foo "bar"})
|
(send-data session-id {:foo "bar"})
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 7. get async response so far from the backchannel
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
(is (= 200 (:status async-resp)))
|
(is (= 200 (:status async-resp)))
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
|
; 8. verify data was sent
|
||||||
(is (= (get-edn-from-arrays arrays 0)
|
(is (= (get-edn-from-arrays arrays 0)
|
||||||
{:foo "bar"}))))))
|
{:foo "bar"}))))))
|
||||||
|
|
||||||
(deftest heartbeat-interval-when-active-backchannel-test
|
(deftest heartbeat-interval-when-active-backchannel-test
|
||||||
(let [options (-> default-options
|
(let [options (-> default-options
|
||||||
(assoc :keep-alive-interval 2))
|
(assoc :keep-alive-interval 2))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (:heartbeat-timeout @(get @sessions session-id)))
|
(is (:heartbeat-timeout @(get @sessions session-id)))
|
||||||
|
; 3. wait for heartbeat/keepalive interval to elapse
|
||||||
(wait-for-scheduled-interval (:keep-alive-interval options))
|
(wait-for-scheduled-interval (:keep-alive-interval options))
|
||||||
|
; 4. get async response so far from the backchannel
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
|
@ -256,17 +288,21 @@
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
(is (contains-all-of? (:headers async-resp)
|
(is (contains-all-of? (:headers async-resp)
|
||||||
(dissoc (:headers options) "Content-Type")))
|
(dissoc (:headers options) "Content-Type")))
|
||||||
|
; 5. verify data was sent ("noop" is the standard keepalive message that is sent)
|
||||||
(is (= (get-raw-from-arrays arrays 0)
|
(is (= (get-raw-from-arrays arrays 0)
|
||||||
["noop"])))))
|
["noop"])))))
|
||||||
|
|
||||||
(deftest no-heartbeat-interval-without-active-backchannel-test
|
(deftest no-heartbeat-interval-without-active-backchannel-test
|
||||||
(let [options (-> default-options
|
(let [options (-> default-options
|
||||||
(assoc :keep-alive-interval 2))
|
(assoc :keep-alive-interval 2))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)]
|
session-id (get-session-id create-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
(is (not (:heartbeat-timeout @(get @sessions session-id))))
|
(is (not (:heartbeat-timeout @(get @sessions session-id))))
|
||||||
|
; 2. wait for heartbeat/keepalive interval to elapse. since there should be no
|
||||||
|
; scheduled job for it, nothing should have changed after this wait
|
||||||
(wait-for-scheduled-interval (:keep-alive-interval options))
|
(wait-for-scheduled-interval (:keep-alive-interval options))
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
(is (not (:heartbeat-timeout @(get @sessions session-id))))))
|
(is (not (:heartbeat-timeout @(get @sessions session-id))))))
|
||||||
|
@ -274,70 +310,91 @@
|
||||||
(deftest heartbeat-interval-is-reactivated-when-backchannel-reconnects-test
|
(deftest heartbeat-interval-is-reactivated-when-backchannel-reconnects-test
|
||||||
(let [options (-> default-options
|
(let [options (-> default-options
|
||||||
(assoc :keep-alive-interval 2))
|
(assoc :keep-alive-interval 2))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (:heartbeat-timeout @(get @sessions session-id)))
|
(is (:heartbeat-timeout @(get @sessions session-id)))
|
||||||
; close backchannel
|
; 3. close backchannel. we do it via clear-back-channel directly as it better
|
||||||
|
; simulates either a network disconnect or connection timeout (which can and will happen)
|
||||||
(send-off (get @sessions session-id) clear-back-channel)
|
(send-off (get @sessions session-id) clear-back-channel)
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
; nothing should have been written
|
; 4. get async response so far from the backchannel. nothing should have been written at this point.
|
||||||
|
; also, verify backchannel request has indeed been closed
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status async-resp)))
|
(is (= 200 (:status async-resp)))
|
||||||
(is (:closed? async-resp))
|
(is (:closed? async-resp))
|
||||||
(is (empty? arrays)))
|
(is (empty? arrays)))
|
||||||
|
; reset async response output. hacky necessity due to the way we capture this output
|
||||||
(reset! async-output {})
|
(reset! async-output {})
|
||||||
; open second backchannel
|
; 5. second backchannel request
|
||||||
(let [back-resp (app (->new-backchannel-request session-id))]
|
(let [back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (:heartbeat-timeout @(get @sessions session-id)))
|
(is (:heartbeat-timeout @(get @sessions session-id)))
|
||||||
|
; 6. wait for heartbeat/keepalive interval to elapse
|
||||||
(wait-for-scheduled-interval (:keep-alive-interval options))
|
(wait-for-scheduled-interval (:keep-alive-interval options))
|
||||||
|
; 7. get async response so far from the backchannel
|
||||||
(let [async-resp @async-output
|
(let [async-resp @async-output
|
||||||
arrays (get-response-arrays (:body async-resp))]
|
arrays (get-response-arrays (:body async-resp))]
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
(is (= 200 (:status async-resp)))
|
(is (= 200 (:status async-resp)))
|
||||||
(is (not (:closed? async-resp)))
|
(is (not (:closed? async-resp)))
|
||||||
|
; 8. verify data was sent ("noop" is the standard keepalive message that is sent)
|
||||||
(is (= (get-raw-from-arrays arrays 0)
|
(is (= (get-raw-from-arrays arrays 0)
|
||||||
["noop"]))))))
|
["noop"]))))))
|
||||||
|
|
||||||
(deftest session-timeout-without-active-backchannel-test
|
(deftest session-timeout-without-active-backchannel-test
|
||||||
(let [options (-> default-options
|
(let [options (-> default-options
|
||||||
(assoc :session-timeout-interval 3))
|
(assoc :session-timeout-interval 3))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)]
|
session-id (get-session-id create-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
(is (:session-timeout @(get @sessions session-id)))
|
(is (:session-timeout @(get @sessions session-id)))
|
||||||
|
; 2. wait for session timeout interval to elapse
|
||||||
(wait-for-scheduled-interval (:session-timeout-interval options))
|
(wait-for-scheduled-interval (:session-timeout-interval options))
|
||||||
|
; 3. verify the session is no longer connected (timed out and closed)
|
||||||
(is (not (connected? session-id)))))
|
(is (not (connected? session-id)))))
|
||||||
|
|
||||||
(deftest no-session-timeout-when-backchannel-active-test
|
(deftest no-session-timeout-when-backchannel-active-test
|
||||||
(let [options (-> default-options
|
(let [options (-> default-options
|
||||||
(assoc :session-timeout-interval 3))
|
(assoc :session-timeout-interval 3))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
(is (not (:session-timeout @(get @sessions session-id))))
|
(is (not (:session-timeout @(get @sessions session-id))))
|
||||||
|
; 2. wait for session timeout interval to elapse. since there should be no
|
||||||
|
; scheduled job for it, nothing should have happened by the time this wait finishes
|
||||||
(wait-for-scheduled-interval (:session-timeout-interval options))
|
(wait-for-scheduled-interval (:session-timeout-interval options))
|
||||||
|
; 3. should still have an active session
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
(is (not (:session-timeout @(get @sessions session-id))))))
|
(is (not (:session-timeout @(get @sessions session-id))))))
|
||||||
|
|
||||||
(deftest session-timeout-is-reactivated-after-backchannel-close-test
|
(deftest session-timeout-is-reactivated-after-backchannel-close-test
|
||||||
(let [options default-options
|
(let [options default-options
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
|
; 3. no session timeout interval active because backchannel is active
|
||||||
(is (not (:session-timeout @(get @sessions session-id))))
|
(is (not (:session-timeout @(get @sessions session-id))))
|
||||||
; close backchannel
|
; 4. close backchannel. we do it via clear-back-channel directly as it better
|
||||||
|
; simulates either a network disconnect or connection timeout (which can and will happen)
|
||||||
(send-off (get @sessions session-id) clear-back-channel)
|
(send-off (get @sessions session-id) clear-back-channel)
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
|
; 5. session timeout interval now active because backchannel was disconnected
|
||||||
(is (:session-timeout @(get @sessions session-id)))))
|
(is (:session-timeout @(get @sessions session-id)))))
|
||||||
|
|
||||||
(deftest open-and-close-event-handlers-test
|
(deftest open-and-close-event-handlers-test
|
||||||
|
@ -352,18 +409,27 @@
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-open on-open
|
(assoc :events {:on-open on-open
|
||||||
:on-close on-close}))
|
:on-close on-close}))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. verify that on-open event was fired and was passed correct arguments
|
||||||
|
; (see on-open function defined above)
|
||||||
(is (= (get-in @event-output [:on-open :session-id])
|
(is (= (get-in @event-output [:on-open :session-id])
|
||||||
session-id))
|
session-id))
|
||||||
(is (map? (get-in @event-output [:on-open :request])))
|
(is (map? (get-in @event-output [:on-open :request])))
|
||||||
|
; 4. on-close not fired yet
|
||||||
(is (nil? (:on-close @event-output)))
|
(is (nil? (:on-close @event-output)))
|
||||||
; close session
|
; 5. disconnect the session. this does the same basic thing as disconnect!, but we
|
||||||
|
; call send-off and close directly like this so we can test passing a (fake) request
|
||||||
|
; map just to verify that it makes it to the on-close function
|
||||||
(send-off (get @sessions session-id) close {:fake-request-map true} "close")
|
(send-off (get @sessions session-id) close {:fake-request-map true} "close")
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (not (connected? session-id)))
|
(is (not (connected? session-id)))
|
||||||
|
; 6. verify that on-close event was fired and passed correct arguments
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= (:on-close @event-output)
|
(is (= (:on-close @event-output)
|
||||||
{:session-id session-id
|
{:session-id session-id
|
||||||
:request {:fake-request-map true}
|
:request {:fake-request-map true}
|
||||||
|
@ -377,10 +443,13 @@
|
||||||
:data data}))
|
:data data}))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-receive on-receive}))
|
(assoc :events {:on-receive on-receive}))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. forwardchannel request so simulate sending data from client to server
|
||||||
(let [forward-resp (app (-> (mock/request
|
(let [forward-resp (app (-> (mock/request
|
||||||
:post "/channel/bind")
|
:post "/channel/bind")
|
||||||
(mock/query-string
|
(mock/query-string
|
||||||
|
@ -395,17 +464,22 @@
|
||||||
{"count" "1"
|
{"count" "1"
|
||||||
"ofs" "0"
|
"ofs" "0"
|
||||||
"req0___edn" (pr-str {:foo "bar"})})))
|
"req0___edn" (pr-str {:foo "bar"})})))
|
||||||
|
; 4. parse response body
|
||||||
[len status] (string/split (:body forward-resp) #"\n" 2)
|
[len status] (string/split (:body forward-resp) #"\n" 2)
|
||||||
[backchannel-present last-bkch-array-id outstanding-bytes] (json/parse-string status)]
|
[backchannel-present last-bkch-array-id outstanding-bytes] (json/parse-string status)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 5. verify that the response was correct
|
||||||
(is (= 200 (:status forward-resp)))
|
(is (= 200 (:status forward-resp)))
|
||||||
(is (> (Long/parseLong len) 0))
|
(is (> (Long/parseLong len) 0))
|
||||||
(is (= 1 backchannel-present))
|
(is (= 1 backchannel-present))
|
||||||
(is (= 0 last-bkch-array-id))
|
(is (= 0 last-bkch-array-id))
|
||||||
(is (= 0 outstanding-bytes))
|
(is (= 0 outstanding-bytes))
|
||||||
|
; 6. verify that the on-receive event was fired and passed correct arguments
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= 1 (count @received)))
|
(is (= 1 (count @received)))
|
||||||
(is (= session-id (:session-id (first @received))))
|
(is (= session-id (:session-id (first @received))))
|
||||||
(is (map? (:request (first @received))))
|
(is (map? (:request (first @received))))
|
||||||
|
; the received data
|
||||||
(is (= (:data (first @received))
|
(is (= (:data (first @received))
|
||||||
{:foo "bar"}))
|
{:foo "bar"}))
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
|
@ -419,10 +493,14 @@
|
||||||
:data data}))
|
:data data}))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-receive on-receive}))
|
(assoc :events {:on-receive on-receive}))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. forwardchannel request so simulate sending data from client to server
|
||||||
|
; (2 maps included)
|
||||||
(let [forward-resp (app (-> (mock/request
|
(let [forward-resp (app (-> (mock/request
|
||||||
:post "/channel/bind")
|
:post "/channel/bind")
|
||||||
(mock/query-string
|
(mock/query-string
|
||||||
|
@ -438,19 +516,24 @@
|
||||||
"ofs" "0"
|
"ofs" "0"
|
||||||
"req0___edn" (pr-str {:foo "bar"})
|
"req0___edn" (pr-str {:foo "bar"})
|
||||||
"req1___edn" (pr-str {:second "map"})})))
|
"req1___edn" (pr-str {:second "map"})})))
|
||||||
|
; 4. parse response body
|
||||||
[len status] (string/split (:body forward-resp) #"\n" 2)
|
[len status] (string/split (:body forward-resp) #"\n" 2)
|
||||||
[backchannel-present last-bkch-array-id outstanding-bytes] (json/parse-string status)]
|
[backchannel-present last-bkch-array-id outstanding-bytes] (json/parse-string status)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 5. verify that the response was correct
|
||||||
(is (= 200 (:status forward-resp)))
|
(is (= 200 (:status forward-resp)))
|
||||||
(is (> (Long/parseLong len) 0))
|
(is (> (Long/parseLong len) 0))
|
||||||
(is (= 1 backchannel-present))
|
(is (= 1 backchannel-present))
|
||||||
(is (= 0 last-bkch-array-id))
|
(is (= 0 last-bkch-array-id))
|
||||||
(is (= 0 outstanding-bytes))
|
(is (= 0 outstanding-bytes))
|
||||||
|
; 6. verify that the on-receive event was fired and passed correct arguments
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= 2 (count @received)))
|
(is (= 2 (count @received)))
|
||||||
(is (= session-id (:session-id (first @received))))
|
(is (= session-id (:session-id (first @received))))
|
||||||
(is (= session-id (:session-id (second @received))))
|
(is (= session-id (:session-id (second @received))))
|
||||||
(is (map? (:request (first @received))))
|
(is (map? (:request (first @received))))
|
||||||
(is (map? (:request (second @received))))
|
(is (map? (:request (second @received))))
|
||||||
|
; the received data
|
||||||
(is (= (:data (first @received))
|
(is (= (:data (first @received))
|
||||||
{:foo "bar"}))
|
{:foo "bar"}))
|
||||||
(is (= (:data (second @received))
|
(is (= (:data (second @received))
|
||||||
|
@ -496,18 +579,24 @@
|
||||||
(swap! received conj data))
|
(swap! received conj data))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-receive on-receive}))
|
(assoc :events {:on-receive on-receive}))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
|
; 2. backchannel request (long request, async response)
|
||||||
back-resp (app (->new-backchannel-request session-id))]
|
back-resp (app (->new-backchannel-request session-id))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. forwardchannel request to send data from client to server
|
||||||
(let [forward-resp (app (->new-forwardchannel-request session-id 0 "hello 1"))
|
(let [forward-resp (app (->new-forwardchannel-request session-id 0 "hello 1"))
|
||||||
result1 (parse-forward-response forward-resp)]
|
result1 (parse-forward-response forward-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 4. a second forwardchannel request to send more data from client to server
|
||||||
(let [forward2-resp (app (->new-forwardchannel-request session-id 0 "hello 2"))
|
(let [forward2-resp (app (->new-forwardchannel-request session-id 0 "hello 2"))
|
||||||
result2 (parse-forward-response forward2-resp)]
|
result2 (parse-forward-response forward2-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (= 0 (:last-bkch-array-id result1)))
|
(is (= 0 (:last-bkch-array-id result1)))
|
||||||
(is (= 0 (:last-bkch-array-id result2)))
|
(is (= 0 (:last-bkch-array-id result2)))
|
||||||
|
; 5. verify that the on-receive event was fired for both pieces of data sent
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= 2 (count @received)))
|
(is (= 2 (count @received)))
|
||||||
(is (= (first @received)
|
(is (= (first @received)
|
||||||
"hello 1"))
|
"hello 1"))
|
||||||
|
@ -522,15 +611,19 @@
|
||||||
(swap! received conj data))
|
(swap! received conj data))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-receive on-receive}))
|
(assoc :events {:on-receive on-receive}))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)]
|
session-id (get-session-id create-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 2. forwardchannel request to send data from client to server
|
||||||
(let [forward-resp (app (->new-forwardchannel-request session-id 0 :foobar))
|
(let [forward-resp (app (->new-forwardchannel-request session-id 0 :foobar))
|
||||||
result (parse-forward-response forward-resp)]
|
result (parse-forward-response forward-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (= 0 (:backchannel-present result)))
|
(is (= 0 (:backchannel-present result)))
|
||||||
(is (= 0 (:last-bkch-array-id result)))
|
(is (= 0 (:last-bkch-array-id result)))
|
||||||
(is (= 0 (:outstanding-bytes result)))
|
(is (= 0 (:outstanding-bytes result)))
|
||||||
|
; 5. verify that the on-receive event was fired
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= 1 (count @received)))
|
(is (= 1 (count @received)))
|
||||||
(is (= (first @received)
|
(is (= (first @received)
|
||||||
:foobar))
|
:foobar))
|
||||||
|
@ -544,6 +637,9 @@
|
||||||
:data data}))
|
:data data}))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-receive on-receive}))
|
(assoc :events {:on-receive on-receive}))
|
||||||
|
; 1. forwardchannel request to create session. encode a map to be sent as part
|
||||||
|
; of this request (encoded in same format as any other forwardchannel request
|
||||||
|
; would do to send client->server data)
|
||||||
create-resp (app (-> (mock/request
|
create-resp (app (-> (mock/request
|
||||||
:post "/channel/bind")
|
:post "/channel/bind")
|
||||||
(mock/query-string
|
(mock/query-string
|
||||||
|
@ -560,6 +656,8 @@
|
||||||
session-id (get-session-id create-resp)]
|
session-id (get-session-id create-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
|
; 2. verify that the on-receive event was fired
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= 1 (count @received)))
|
(is (= 1 (count @received)))
|
||||||
(is (= session-id (:session-id (first @received))))
|
(is (= session-id (:session-id (first @received))))
|
||||||
(is (map? (:request (first @received))))
|
(is (map? (:request (first @received))))
|
||||||
|
@ -572,19 +670,26 @@
|
||||||
(swap! received conj data))
|
(swap! received conj data))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :events {:on-receive on-receive}))
|
(assoc :events {:on-receive on-receive}))
|
||||||
|
; 1. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)
|
session-id (get-session-id create-resp)
|
||||||
str-to-send "this will get queued but not sent because no backchannel is open"
|
str-to-send "this will get queued but not sent because no backchannel is open"
|
||||||
queued-str (pr-str (encode-map str-to-send))]
|
queued-str (pr-str (encode-map str-to-send))]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 2. send data to client. no backchannel is active, so data will be queued in the buffer
|
||||||
(send-data session-id str-to-send)
|
(send-data session-id str-to-send)
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. forwardchannel request to send data from client to server
|
||||||
(let [forward-resp (app (->new-forwardchannel-request session-id 0 42))
|
(let [forward-resp (app (->new-forwardchannel-request session-id 0 42))
|
||||||
result (parse-forward-response forward-resp)]
|
result (parse-forward-response forward-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 4. verify that the response to the forwardchannel request contained correct backchannel
|
||||||
|
; data buffer info (e.g. reflecting the fact that we have queued data to be sent)
|
||||||
(is (= 0 (:backchannel-present result)))
|
(is (= 0 (:backchannel-present result)))
|
||||||
(is (= 0 (:last-bkch-array-id result)))
|
(is (= 0 (:last-bkch-array-id result)))
|
||||||
(is (= (count queued-str) (:outstanding-bytes result)))
|
(is (= (count queued-str) (:outstanding-bytes result)))
|
||||||
|
; 5. verify that the on-receive event was fired
|
||||||
|
; (see on-close function defined above)
|
||||||
(is (= 1 (count @received)))
|
(is (= 1 (count @received)))
|
||||||
(is (= (first @received)
|
(is (= (first @received)
|
||||||
42))
|
42))
|
||||||
|
@ -592,6 +697,8 @@
|
||||||
|
|
||||||
(deftest flush-buffer-write-failure-resends-buffer
|
(deftest flush-buffer-write-failure-resends-buffer
|
||||||
(let [failed-once? (atom false)
|
(let [failed-once? (atom false)
|
||||||
|
; 1. hacky way to trigger a backchannel write failure
|
||||||
|
; this is made possible by test-only options via wrap-test-async-adapter
|
||||||
fail-fn (fn [data]
|
fail-fn (fn [data]
|
||||||
(if (and (not @failed-once?)
|
(if (and (not @failed-once?)
|
||||||
(string? data)
|
(string? data)
|
||||||
|
@ -599,20 +706,26 @@
|
||||||
(reset! failed-once? true)))
|
(reset! failed-once? true)))
|
||||||
options (-> default-options
|
options (-> default-options
|
||||||
(assoc :fail-fn fail-fn))
|
(assoc :fail-fn fail-fn))
|
||||||
|
; 2. forwardchannel request to create session
|
||||||
create-resp (app (->new-session-request) options)
|
create-resp (app (->new-session-request) options)
|
||||||
session-id (get-session-id create-resp)]
|
session-id (get-session-id create-resp)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 3. queue up a bunch of data to be sent. no backchannel has been created yet,
|
||||||
|
; so this will all sit in the buffer and get flushed once the backchannel
|
||||||
|
; is opened
|
||||||
(send-data session-id :first-queued)
|
(send-data session-id :first-queued)
|
||||||
(send-data session-id :second-queued)
|
(send-data session-id :second-queued)
|
||||||
(send-data session-id "fail")
|
(send-data session-id "fail")
|
||||||
(send-data session-id :fourth-queued)
|
(send-data session-id :fourth-queued)
|
||||||
; send-data flushes the buffer after each call, so we just delay
|
; 4. backchannel request (long request, async response)
|
||||||
; opening a backchannel so that we can fill up the buffer with
|
|
||||||
; more then one message at a time easier
|
|
||||||
(let [back-resp (app (->new-backchannel-request session-id) options)]
|
(let [back-resp (app (->new-backchannel-request session-id) options)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 5. an exception should have been thrown during the flush-buffer call, but
|
||||||
|
; we should have sent out some of the data before then
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
(let [arrays-up-till-fail (get-response-arrays (:body @async-output))]
|
(let [arrays-up-till-fail (get-response-arrays (:body @async-output))]
|
||||||
|
; 6. verify that the backchannel was closed (because of the exception),
|
||||||
|
; and that the first 2 pieces of data were sent
|
||||||
(is (= 200 (:status @async-output)))
|
(is (= 200 (:status @async-output)))
|
||||||
(is (:closed? @async-output))
|
(is (:closed? @async-output))
|
||||||
(is (connected? session-id))
|
(is (connected? session-id))
|
||||||
|
@ -620,8 +733,12 @@
|
||||||
(is (= :second-queued (get-edn-from-arrays arrays-up-till-fail 1)))
|
(is (= :second-queued (get-edn-from-arrays arrays-up-till-fail 1)))
|
||||||
; hacky requirement for this unit test due to the way we capture async response output
|
; hacky requirement for this unit test due to the way we capture async response output
|
||||||
(reset! async-output {})
|
(reset! async-output {})
|
||||||
|
; 7. re-open backchannel. all 4 items should still be in the buffer and will
|
||||||
|
; get flushed again at this point
|
||||||
(let [back-resp (app (->new-backchannel-request session-id) options)]
|
(let [back-resp (app (->new-backchannel-request session-id) options)]
|
||||||
(wait-for-agent-send-offs)
|
(wait-for-agent-send-offs)
|
||||||
|
; 8. at this point, all 4 items should have been sent and the backchannel request
|
||||||
|
; should still be active
|
||||||
(is (= 200 (:status back-resp)))
|
(is (= 200 (:status back-resp)))
|
||||||
(let [arrays (get-response-arrays (:body @async-output))]
|
(let [arrays (get-response-arrays (:body @async-output))]
|
||||||
(is (= 200 (:status @async-output)))
|
(is (= 200 (:status @async-output)))
|
||||||
|
|
Reference in a new issue