Implement FallbackSignalStrategy.
[chromium-blink-merge.git] / remoting / webapp / unittests / fallback_signal_strategy_unittest.js
blob18122fd23fff031daec0129a31ccd26ef054d24a
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 (function() {
7 'use strict';
9 var ControllableSignalStrategy = function(jid, stateChangeCallback) {
10   this.jid = jid;
11   this.stateChangeCallback_ = stateChangeCallback;
12   this.state_ = null;
13   this.onIncomingStanzaCallback = function() {};
14   this.dispose = sinon.spy();
15   this.connect = sinon.spy();
16   this.sendMessage = sinon.spy();
19 ControllableSignalStrategy.prototype.setIncomingStanzaCallback =
20     function(onIncomingStanzaCallback) {
21   this.onIncomingStanzaCallback =
22       onIncomingStanzaCallback ? onIncomingStanzaCallback
23                                : function() {};
26 ControllableSignalStrategy.prototype.getState = function(message) {
27   return this.state_;
30 ControllableSignalStrategy.prototype.getError = function(message) {
31   return remoting.Error.UNKNOWN;
34 ControllableSignalStrategy.prototype.getJid = function(message) {
35   return this.jid;
38 ControllableSignalStrategy.prototype.setExternalCallbackForTesting =
39     function(externalCallback) {
40   this.externalCallback_ = externalCallback;
43 ControllableSignalStrategy.prototype.setStateForTesting =
44     function(state, expectExternalCallback) {
45   this.state_ = state;
46   this.externalCallback_.reset();
47   this.stateChangeCallback_(state);
48   if (expectExternalCallback) {
49     equal(this.externalCallback_.callCount, 1);
50     ok(this.externalCallback_.calledWith(state));
51     equal(strategy.getState(), state);
52   } else {
53     ok(!this.externalCallback_.called);
54   }
57 var createControllableSignalStrategy = function(jid, callback) {
58   return new ControllableSignalStrategy(jid, callback);
61 var onStateChange = null;
62 var onProgressCallback = null;
63 var onIncomingStanzaCallback = null;
64 var strategy = null;
65 var primary = null;
66 var secondary = null;
68 module('fallback_signal_strategy', {
69   setup: function() {
70     onStateChange = sinon.spy();
71     onProgressCallback = sinon.spy();
72     onIncomingStanzaCallback = sinon.spy();
73     strategy = new remoting.FallbackSignalStrategy(
74         createControllableSignalStrategy.bind(null, 'primary-jid'),
75         createControllableSignalStrategy.bind(null, 'secondary-jid'),
76         onStateChange,
77         onProgressCallback);
78     strategy.setIncomingStanzaCallback(onIncomingStanzaCallback);
79     primary = strategy.primary_;
80     secondary = strategy.secondary_;
81     primary.setExternalCallbackForTesting(onStateChange);
82     secondary.setExternalCallbackForTesting(onStateChange);
83   },
84   teardown: function() {
85     onStateChange = null;
86     onProgressCallback = null;
87     onIncomingStanzaCallback = null;
88     strategy = null;
89     primary = null;
90     secondary = null;
91   },
92   // Assert that the progress callback has been called exactly once
93   // since the last call, and with the specified state.
94   assertProgress: function(state) {
95     ok(onProgressCallback.calledOnce);
96     ok(onProgressCallback.calledWith(state));
97     onProgressCallback.reset();
98   }
99 });
101 test('primary succeeds; send & receive routed to it',
102   function() {
103     ok(!onStateChange.called);
104     ok(!primary.connect.called);
105     strategy.connect('server', 'username', 'authToken');
106     ok(primary.connect.calledWith('server', 'username', 'authToken'));
108     primary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
109                                true);
110     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, true);
111     primary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
113     ok(!onProgressCallback.called);
114     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
115     this.assertProgress(
116         remoting.FallbackSignalStrategy.Progress.PRIMARY_SUCCEEDED);
117     equal(strategy.getJid(), 'primary-jid');
119     ok(!onIncomingStanzaCallback.called);
120     primary.onIncomingStanzaCallback('test-receive-primary');
121     secondary.onIncomingStanzaCallback('test-receive-secondary');
122     ok(onIncomingStanzaCallback.calledOnce);
123     ok(onIncomingStanzaCallback.calledWith('test-receive-primary'));
125     ok(!primary.sendMessage.called);
126     strategy.sendMessage('test-send');
127     ok(primary.sendMessage.calledOnce);
128     ok(primary.sendMessage.calledWith('test-send'));
130     ok(!primary.dispose.called);
131     ok(!secondary.dispose.called);
132     primary.setStateForTesting(remoting.SignalStrategy.State.CLOSED, true);
133     strategy.dispose();
134     ok(primary.dispose.calledOnce);
135     ok(secondary.dispose.calledOnce);
136   }
139 test('primary fails; secondary succeeds; send & receive routed to it',
140   function() {
141     ok(!onStateChange.called);
142     ok(!primary.connect.called);
143     strategy.connect('server', 'username', 'authToken');
144     ok(primary.connect.calledWith('server', 'username', 'authToken'));
146     primary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
147                                true);
148     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, true);
150     ok(!onProgressCallback.called);
151     ok(!secondary.connect.called);
152     primary.setStateForTesting(remoting.SignalStrategy.State.FAILED, false);
153     ok(secondary.connect.calledWith('server', 'username', 'authToken'));
154     this.assertProgress(
155         remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED);
157     secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
158                                  false);
159     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
160                                  false);
161     secondary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
163     ok(!onProgressCallback.called);
164     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
165     this.assertProgress(
166         remoting.FallbackSignalStrategy.Progress.SECONDARY_SUCCEEDED);
167     equal(strategy.getJid(), 'secondary-jid');
169     ok(!onIncomingStanzaCallback.called);
170     primary.onIncomingStanzaCallback('test-receive-primary');
171     secondary.onIncomingStanzaCallback('test-receive-secondary');
172     ok(onIncomingStanzaCallback.calledOnce);
173     ok(onIncomingStanzaCallback.calledWith('test-receive-secondary'));
175     ok(!secondary.sendMessage.called);
176     strategy.sendMessage('test-send');
177     ok(!primary.sendMessage.called);
178     ok(secondary.sendMessage.calledOnce);
179     ok(secondary.sendMessage.calledWith('test-send'));
180   }
183 test('primary fails; secondary fails',
184   function() {
185     ok(!onStateChange.called);
186     ok(!primary.connect.called);
187     strategy.connect('server', 'username', 'authToken');
188     ok(primary.connect.calledWith('server', 'username', 'authToken'));
190     primary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
191                                true);
192     ok(!onProgressCallback.called);
193     ok(!secondary.connect.called);
194     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, true);
195     primary.setStateForTesting(remoting.SignalStrategy.State.FAILED, false);
196     ok(secondary.connect.calledWith('server', 'username', 'authToken'));
197     this.assertProgress(
198         remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED);
199     secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
200                                  false);
201     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, false);
202     secondary.setStateForTesting(remoting.SignalStrategy.State.FAILED, true);
203     this.assertProgress(
204         remoting.FallbackSignalStrategy.Progress.SECONDARY_FAILED);
205   }
208 test('primary times out; secondary succeeds',
209   function() {
210     ok(!onStateChange.called);
211     ok(!primary.connect.called);
212     strategy.connect('server', 'username', 'authToken');
213     ok(primary.connect.calledWith('server', 'username', 'authToken'));
215     primary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
216                                true);
217     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, true);
218     this.clock.tick(strategy.PRIMARY_CONNECT_TIMEOUT_MS_ - 1);
219     ok(!secondary.connect.called);
220     ok(!onProgressCallback.called);
221     this.clock.tick(1);
222     ok(secondary.connect.calledWith('server', 'username', 'authToken'));
223     this.assertProgress(
224         remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
225     secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
226                                  false);
227     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
228                                  false);
229     secondary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
230     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
231     this.assertProgress(
232         remoting.FallbackSignalStrategy.Progress.SECONDARY_SUCCEEDED);
233     secondary.setStateForTesting(remoting.SignalStrategy.State.CLOSED, true);
234     primary.setStateForTesting(remoting.SignalStrategy.State.FAILED, false);
235     this.assertProgress(
236         remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED_LATE);
237   }
240 test('primary times out; secondary fails',
241   function() {
242     ok(!onStateChange.called);
243     ok(!primary.connect.called);
244     strategy.connect('server', 'username', 'authToken');
245     ok(primary.connect.calledWith('server', 'username', 'authToken'));
247     primary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
248                                true);
249     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, true);
250     this.clock.tick(strategy.PRIMARY_CONNECT_TIMEOUT_MS_ - 1);
251     ok(!secondary.connect.called);
252     ok(!onProgressCallback.called);
253     this.clock.tick(1);
254     ok(secondary.connect.calledWith('server', 'username', 'authToken'));
255     this.assertProgress(
256         remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
257     secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
258                                  false);
259     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
260                                  false);
261     secondary.setStateForTesting(remoting.SignalStrategy.State.FAILED, true);
262     this.assertProgress(
263         remoting.FallbackSignalStrategy.Progress.SECONDARY_FAILED);
264   }
267 test('primary times out; secondary succeeds; primary succeeds late',
268   function() {
269     ok(!onStateChange.called);
270     ok(!primary.connect.called);
271     strategy.connect('server', 'username', 'authToken');
272     ok(primary.connect.calledWith('server', 'username', 'authToken'));
274     primary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
275                                true);
276     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, true);
277     this.clock.tick(strategy.PRIMARY_CONNECT_TIMEOUT_MS_);
278     ok(secondary.connect.calledWith('server', 'username', 'authToken'));
279     this.assertProgress(
280         remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
281     secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
282                                  false);
283     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
284                                  false);
285     secondary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
286     secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
287     this.assertProgress(
288         remoting.FallbackSignalStrategy.Progress.SECONDARY_SUCCEEDED);
289     primary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, false);
290     primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, false);
291     this.assertProgress(
292         remoting.FallbackSignalStrategy.Progress.PRIMARY_SUCCEEDED_LATE);
293   }
296 })();