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.
9 var ControllableSignalStrategy = function(jid, stateChangeCallback) {
11 this.stateChangeCallback_ = stateChangeCallback;
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
26 ControllableSignalStrategy.prototype.getState = function(message) {
30 ControllableSignalStrategy.prototype.getError = function(message) {
31 return remoting.Error.UNKNOWN;
34 ControllableSignalStrategy.prototype.getJid = function(message) {
38 ControllableSignalStrategy.prototype.setExternalCallbackForTesting =
39 function(externalCallback) {
40 this.externalCallback_ = externalCallback;
43 ControllableSignalStrategy.prototype.setStateForTesting =
44 function(state, expectExternalCallback) {
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);
53 ok(!this.externalCallback_.called);
57 var createControllableSignalStrategy = function(jid, callback) {
58 return new ControllableSignalStrategy(jid, callback);
61 var onStateChange = null;
62 var onProgressCallback = null;
63 var onIncomingStanzaCallback = null;
68 module('fallback_signal_strategy', {
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'),
78 strategy.setIncomingStanzaCallback(onIncomingStanzaCallback);
79 primary = strategy.primary_;
80 secondary = strategy.secondary_;
81 primary.setExternalCallbackForTesting(onStateChange);
82 secondary.setExternalCallbackForTesting(onStateChange);
84 teardown: function() {
86 onProgressCallback = null;
87 onIncomingStanzaCallback = null;
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();
101 test('primary succeeds; send & receive routed to it',
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,
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);
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);
134 ok(primary.dispose.calledOnce);
135 ok(secondary.dispose.calledOnce);
139 test('primary fails; secondary succeeds; send & receive routed to it',
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,
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'));
155 remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED);
157 secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
159 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
161 secondary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
163 ok(!onProgressCallback.called);
164 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
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'));
183 test('primary fails; secondary fails',
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,
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'));
198 remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED);
199 secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
201 primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING, false);
202 secondary.setStateForTesting(remoting.SignalStrategy.State.FAILED, true);
204 remoting.FallbackSignalStrategy.Progress.SECONDARY_FAILED);
208 test('primary times out; secondary succeeds',
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,
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);
222 ok(secondary.connect.calledWith('server', 'username', 'authToken'));
224 remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
225 secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
227 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
229 secondary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
230 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
232 remoting.FallbackSignalStrategy.Progress.SECONDARY_SUCCEEDED);
233 secondary.setStateForTesting(remoting.SignalStrategy.State.CLOSED, true);
234 primary.setStateForTesting(remoting.SignalStrategy.State.FAILED, false);
236 remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED_LATE);
240 test('primary times out; secondary fails',
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,
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);
254 ok(secondary.connect.calledWith('server', 'username', 'authToken'));
256 remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
257 secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
259 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
261 secondary.setStateForTesting(remoting.SignalStrategy.State.FAILED, true);
263 remoting.FallbackSignalStrategy.Progress.SECONDARY_FAILED);
267 test('primary times out; secondary succeeds; primary succeeds late',
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,
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'));
280 remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
281 secondary.setStateForTesting(remoting.SignalStrategy.State.NOT_CONNECTED,
283 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTING,
285 secondary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, true);
286 secondary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, true);
288 remoting.FallbackSignalStrategy.Progress.SECONDARY_SUCCEEDED);
289 primary.setStateForTesting(remoting.SignalStrategy.State.HANDSHAKE, false);
290 primary.setStateForTesting(remoting.SignalStrategy.State.CONNECTED, false);
292 remoting.FallbackSignalStrategy.Progress.PRIMARY_SUCCEEDED_LATE);