| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * TODO(garykac): Create interface for SignalStrategy. | 7 * TODO(garykac): Create interface for SignalStrategy. |
| 8 * @suppress {checkTypes|checkVars|reportUnknownTypes|visibility} | 8 * @suppress {checkTypes|checkVars|reportUnknownTypes|visibility} |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 (function() { | 11 (function() { |
| 12 | 12 |
| 13 'use strict'; | 13 'use strict'; |
| 14 | 14 |
| 15 /** @type {(sinon.Spy|function(remoting.SignalStrategy.State))} */ | 15 /** @type {(sinon.Spy|function(remoting.SignalStrategy.State))} */ |
| 16 var onStateChange = null; | 16 var onStateChange = null; |
| 17 | 17 |
| 18 /** @type {(sinon.Spy|function(Element):void)} */ | 18 /** @type {(sinon.Spy|function(Element):void)} */ |
| 19 var onIncomingStanzaCallback = null; | 19 var onIncomingStanzaCallback = null; |
| 20 | 20 |
| 21 /** @type {remoting.DnsBlackholeChecker} */ | 21 /** @type {remoting.DnsBlackholeChecker} */ |
| 22 var checker = null; | 22 var checker = null; |
| 23 | 23 |
| 24 /** @type {remoting.MockSignalStrategy} */ | 24 /** @type {remoting.MockSignalStrategy} */ |
| 25 var signalStrategy = null; | 25 var signalStrategy = null; |
| 26 var fakeXhrs; | |
| 27 | 26 |
| 28 module('dns_blackhole_checker', { | 27 var fakeXhr = null; |
| 28 |
| 29 QUnit.module('dns_blackhole_checker', { |
| 29 setup: function() { | 30 setup: function() { |
| 30 fakeXhrs = []; | |
| 31 sinon.useFakeXMLHttpRequest().onCreate = function(xhr) { | 31 sinon.useFakeXMLHttpRequest().onCreate = function(xhr) { |
| 32 fakeXhrs.push(xhr); | 32 QUnit.equal(fakeXhr, null, 'exactly one XHR is issued'); |
| 33 fakeXhr = xhr; |
| 33 }; | 34 }; |
| 34 | 35 |
| 35 onStateChange = sinon.spy(); | 36 onStateChange = sinon.spy(); |
| 36 onIncomingStanzaCallback = sinon.spy(); | 37 onIncomingStanzaCallback = sinon.spy(); |
| 37 signalStrategy = new remoting.MockSignalStrategy(); | 38 signalStrategy = new remoting.MockSignalStrategy(); |
| 38 checker = new remoting.DnsBlackholeChecker(signalStrategy); | 39 checker = new remoting.DnsBlackholeChecker(signalStrategy); |
| 39 | 40 |
| 40 checker.setStateChangedCallback(onStateChange); | 41 checker.setStateChangedCallback(onStateChange); |
| 41 checker.setIncomingStanzaCallback(onIncomingStanzaCallback); | 42 checker.setIncomingStanzaCallback(onIncomingStanzaCallback); |
| 42 | 43 |
| 43 sinon.assert.notCalled(onStateChange); | 44 sinon.assert.notCalled(onStateChange); |
| 44 sinon.assert.notCalled(signalStrategy.connect); | 45 sinon.assert.notCalled(signalStrategy.connect); |
| 45 checker.connect('server', 'username', 'authToken'); | 46 checker.connect('server', 'username', 'authToken'); |
| 46 sinon.assert.calledWith(signalStrategy.connect, 'server', 'username', | 47 sinon.assert.calledWith(signalStrategy.connect, 'server', 'username', |
| 47 'authToken'); | 48 'authToken'); |
| 48 | 49 |
| 49 QUnit.equal(fakeXhrs.length, 1, 'exactly one XHR is issued'); | |
| 50 QUnit.equal( | 50 QUnit.equal( |
| 51 fakeXhrs[0].url, remoting.DnsBlackholeChecker.URL_TO_REQUEST_, | 51 fakeXhr.url, remoting.DnsBlackholeChecker.URL_TO_REQUEST_, |
| 52 'the correct URL is requested'); | 52 'the correct URL is requested'); |
| 53 }, | 53 }, |
| 54 teardown: function() { | 54 teardown: function() { |
| 55 base.dispose(checker); | 55 base.dispose(checker); |
| 56 sinon.assert.calledWith(onStateChange, | 56 sinon.assert.calledWith(onStateChange, |
| 57 remoting.SignalStrategy.State.CLOSED); | 57 remoting.SignalStrategy.State.CLOSED); |
| 58 | 58 |
| 59 onStateChange = null; | 59 onStateChange = null; |
| 60 onIncomingStanzaCallback = null; | 60 onIncomingStanzaCallback = null; |
| 61 checker = null; | 61 checker = null; |
| 62 }, | 62 fakeXhr = null; |
| 63 } |
| 63 }); | 64 }); |
| 64 | 65 |
| 66 function await(condition) { |
| 67 function loop(count) { |
| 68 if (condition()) { |
| 69 return Promise.resolve(); |
| 70 } else if (count > 1000) { |
| 71 return Promise.reject('condition never became true'); |
| 72 } else { |
| 73 return Promise.resolve().then(loop.bind(null, count + 1)); |
| 74 } |
| 75 }; |
| 76 return loop(0); |
| 77 }; |
| 78 |
| 65 test('success', | 79 test('success', |
| 66 function() { | 80 function() { |
| 67 fakeXhrs[0].respond(200); | 81 function checkState(state) { |
| 68 sinon.assert.notCalled(onStateChange); | |
| 69 | |
| 70 [ | |
| 71 remoting.SignalStrategy.State.CONNECTING, | |
| 72 remoting.SignalStrategy.State.HANDSHAKE, | |
| 73 remoting.SignalStrategy.State.CONNECTED | |
| 74 ].forEach(function(state) { | |
| 75 signalStrategy.setStateForTesting(state); | 82 signalStrategy.setStateForTesting(state); |
| 76 sinon.assert.calledWith(onStateChange, state); | 83 sinon.assert.calledWith(onStateChange, state); |
| 77 equal(checker.getState(), state); | 84 equal(checker.getState(), state); |
| 85 } |
| 86 |
| 87 return base.SpyPromise.run(function() { |
| 88 fakeXhr.respond(200); |
| 89 }).then(function() { |
| 90 sinon.assert.notCalled(onStateChange); |
| 91 checkState(remoting.SignalStrategy.State.CONNECTING); |
| 92 checkState(remoting.SignalStrategy.State.HANDSHAKE); |
| 93 checkState(remoting.SignalStrategy.State.CONNECTED); |
| 94 }); |
| 95 }); |
| 96 |
| 97 test('http response after connected', |
| 98 function() { |
| 99 function checkState(state) { |
| 100 signalStrategy.setStateForTesting(state); |
| 101 sinon.assert.calledWith(onStateChange, state); |
| 102 equal(checker.getState(), state); |
| 103 } |
| 104 |
| 105 checkState(remoting.SignalStrategy.State.CONNECTING); |
| 106 checkState(remoting.SignalStrategy.State.HANDSHAKE); |
| 107 onStateChange.reset(); |
| 108 |
| 109 // Verify that DnsBlackholeChecker stays in HANDSHAKE state even if the |
| 110 // signal strategy has connected. |
| 111 return base.SpyPromise.run(function() { |
| 112 signalStrategy.setStateForTesting( |
| 113 remoting.SignalStrategy.State.CONNECTED); |
| 114 }).then(function() { |
| 115 sinon.assert.notCalled(onStateChange); |
| 116 equal(checker.getState(), remoting.SignalStrategy.State.HANDSHAKE); |
| 117 |
| 118 // Verify that DnsBlackholeChecker goes to CONNECTED state after the |
| 119 // the HTTP request has succeeded. |
| 120 return base.SpyPromise.run(function() { |
| 121 fakeXhr.respond(200); |
| 122 }); |
| 123 }).then(function() { |
| 124 sinon.assert.calledWith(onStateChange, |
| 125 remoting.SignalStrategy.State.CONNECTED); |
| 126 }); |
| 127 }); |
| 128 |
| 129 QUnit.test('connect failed', |
| 130 function() { |
| 131 function checkState(state) { |
| 132 signalStrategy.setStateForTesting(state); |
| 133 sinon.assert.calledWith(onStateChange, state); |
| 134 }; |
| 135 |
| 136 return base.SpyPromise.run(function() { |
| 137 fakeXhr.respond(200); |
| 138 }).then(function() { |
| 139 sinon.assert.notCalled(onStateChange); |
| 140 checkState(remoting.SignalStrategy.State.CONNECTING); |
| 141 checkState(remoting.SignalStrategy.State.FAILED); |
| 142 }); |
| 143 }); |
| 144 |
| 145 QUnit.test('blocked', |
| 146 function(assert) { |
| 147 function checkState(state) { |
| 148 onStateChange.reset(); |
| 149 signalStrategy.setStateForTesting(state); |
| 150 sinon.assert.notCalled(onStateChange); |
| 151 assert.equal( |
| 152 checker.getState(), |
| 153 remoting.SignalStrategy.State.FAILED, |
| 154 'checker state is still FAILED'); |
| 155 }; |
| 156 |
| 157 return base.SpyPromise.run(function() { |
| 158 fakeXhr.respond(400); |
| 159 }).then(function() { |
| 160 sinon.assert.calledWith( |
| 161 onStateChange, remoting.SignalStrategy.State.FAILED); |
| 162 assert.equal( |
| 163 checker.getError().getTag(), |
| 164 remoting.Error.Tag.NOT_AUTHORIZED, |
| 165 'checker error is NOT_AUTHORIZED'); |
| 166 checkState(remoting.SignalStrategy.State.CONNECTING); |
| 167 checkState(remoting.SignalStrategy.State.HANDSHAKE); |
| 168 checkState(remoting.SignalStrategy.State.FAILED); |
| 169 }); |
| 170 }); |
| 171 |
| 172 QUnit.test('blocked after connected', |
| 173 function() { |
| 174 function checkState(state) { |
| 175 signalStrategy.setStateForTesting(state); |
| 176 sinon.assert.calledWith(onStateChange, state); |
| 177 equal(checker.getState(), state); |
| 178 }; |
| 179 |
| 180 checkState(remoting.SignalStrategy.State.CONNECTING); |
| 181 checkState(remoting.SignalStrategy.State.HANDSHAKE); |
| 182 onStateChange.reset(); |
| 183 |
| 184 // Verify that DnsBlackholeChecker stays in HANDSHAKE state even |
| 185 // if the signal strategy has connected. |
| 186 return base.SpyPromise.run(function() { |
| 187 signalStrategy.setStateForTesting( |
| 188 remoting.SignalStrategy.State.CONNECTED); |
| 189 }).then(function() { |
| 190 sinon.assert.notCalled(onStateChange); |
| 191 equal(checker.getState(), remoting.SignalStrategy.State.HANDSHAKE); |
| 192 |
| 193 // Verify that DnsBlackholeChecker goes to FAILED state after it |
| 194 // gets the blocked HTTP response. |
| 195 return base.SpyPromise.run(function() { |
| 196 fakeXhr.respond(400); |
| 197 }); |
| 198 }).then(function() { |
| 199 sinon.assert.calledWith(onStateChange, |
| 200 remoting.SignalStrategy.State.FAILED); |
| 201 equal(checker.getError().getTag(), remoting.Error.Tag.NOT_AUTHORIZED); |
| 78 }); | 202 }); |
| 79 } | 203 } |
| 80 ); | 204 ); |
| 81 | 205 |
| 82 test('http response after connected', | |
| 83 function() { | |
| 84 [ | |
| 85 remoting.SignalStrategy.State.CONNECTING, | |
| 86 remoting.SignalStrategy.State.HANDSHAKE, | |
| 87 ].forEach(function(state) { | |
| 88 signalStrategy.setStateForTesting(state); | |
| 89 sinon.assert.calledWith(onStateChange, state); | |
| 90 equal(checker.getState(), state); | |
| 91 }); | |
| 92 onStateChange.reset(); | |
| 93 | |
| 94 // Verify that DnsBlackholeChecker stays in HANDSHAKE state even if the | |
| 95 // signal strategy has connected. | |
| 96 signalStrategy.setStateForTesting(remoting.SignalStrategy.State.CONNECTED); | |
| 97 sinon.assert.notCalled(onStateChange); | |
| 98 equal(checker.getState(), remoting.SignalStrategy.State.HANDSHAKE); | |
| 99 | |
| 100 // Verify that DnsBlackholeChecker goes to CONNECTED state after the | |
| 101 // the HTTP request has succeeded. | |
| 102 fakeXhrs[0].respond(200); | |
| 103 sinon.assert.calledWith(onStateChange, | |
| 104 remoting.SignalStrategy.State.CONNECTED); | |
| 105 } | |
| 106 ); | |
| 107 | |
| 108 test('connect failed', | |
| 109 function() { | |
| 110 fakeXhrs[0].respond(200); | |
| 111 sinon.assert.notCalled(onStateChange); | |
| 112 | |
| 113 [ | |
| 114 remoting.SignalStrategy.State.CONNECTING, | |
| 115 remoting.SignalStrategy.State.FAILED | |
| 116 ].forEach(function(state) { | |
| 117 signalStrategy.setStateForTesting(state); | |
| 118 sinon.assert.calledWith(onStateChange, state); | |
| 119 }); | |
| 120 } | |
| 121 ); | |
| 122 | |
| 123 test('blocked', | |
| 124 function() { | |
| 125 fakeXhrs[0].respond(400); | |
| 126 sinon.assert.calledWith(onStateChange, | |
| 127 remoting.SignalStrategy.State.FAILED); | |
| 128 equal(checker.getError().tag, remoting.Error.Tag.NOT_AUTHORIZED); | |
| 129 onStateChange.reset(); | |
| 130 | |
| 131 [ | |
| 132 remoting.SignalStrategy.State.CONNECTING, | |
| 133 remoting.SignalStrategy.State.HANDSHAKE, | |
| 134 remoting.SignalStrategy.State.CONNECTED | |
| 135 ].forEach(function(state) { | |
| 136 signalStrategy.setStateForTesting(state); | |
| 137 sinon.assert.notCalled(onStateChange); | |
| 138 equal(checker.getState(), remoting.SignalStrategy.State.FAILED); | |
| 139 }); | |
| 140 } | |
| 141 ); | |
| 142 | |
| 143 test('blocked after connected', | |
| 144 function() { | |
| 145 [ | |
| 146 remoting.SignalStrategy.State.CONNECTING, | |
| 147 remoting.SignalStrategy.State.HANDSHAKE, | |
| 148 ].forEach(function(state) { | |
| 149 signalStrategy.setStateForTesting(state); | |
| 150 sinon.assert.calledWith(onStateChange, state); | |
| 151 equal(checker.getState(), state); | |
| 152 }); | |
| 153 onStateChange.reset(); | |
| 154 | |
| 155 // Verify that DnsBlackholeChecker stays in HANDSHAKE state even if the | |
| 156 // signal strategy has connected. | |
| 157 signalStrategy.setStateForTesting(remoting.SignalStrategy.State.CONNECTED); | |
| 158 sinon.assert.notCalled(onStateChange); | |
| 159 equal(checker.getState(), remoting.SignalStrategy.State.HANDSHAKE); | |
| 160 | |
| 161 // Verify that DnsBlackholeChecker goes to FAILED state after it gets the | |
| 162 // blocked HTTP response. | |
| 163 fakeXhrs[0].respond(400); | |
| 164 sinon.assert.calledWith(onStateChange, | |
| 165 remoting.SignalStrategy.State.FAILED); | |
| 166 equal(checker.getError().tag, remoting.Error.Tag.NOT_AUTHORIZED); | |
| 167 } | |
| 168 ); | |
| 169 | |
| 170 })(); | 206 })(); |
| OLD | NEW |