Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /** | |
| 2 * @fileoverview | |
| 3 * Unit tests for host_controller.js. | |
| 4 */ | |
| 5 | |
| 6 (function() { | |
| 7 | |
| 8 'use strict'; | |
| 9 | |
| 10 /** @type {remoting.HostController} */ | |
| 11 var controller = null; | |
| 12 | |
| 13 /** @type {sinon.Mock} */ | |
| 14 var hostListMock = null; | |
| 15 | |
| 16 /** @type {sinon.TestStub} */ | |
| 17 var generateUuidStub; | |
| 18 | |
| 19 /** @type {remoting.MockHostDaemonFacade} */ | |
| 20 var mockHostDaemonFacade; | |
| 21 | |
| 22 /** @type {sinon.TestStub} */ | |
| 23 var hostDaemonFacadeCtorStub; | |
| 24 | |
| 25 var FAKE_HOST_PIN = '<FAKE_HOST_PIN>'; | |
| 26 var FAKE_USER_EMAIL = '<FAKE_USER_EMAIL>'; | |
| 27 var FAKE_USER_NAME = '<FAKE_USER_NAME>'; | |
| 28 var FAKE_UUID = '0bad0bad-0bad-0bad-0bad-0bad0bad0bad'; | |
| 29 var FAKE_DAEMON_VERSION = '1.2.3.4'; | |
| 30 var FAKE_HOST_NAME = '<FAKE_HOST_NAME>'; | |
| 31 var FAKE_PUBLIC_KEY = '<FAKE_PUBLIC_KEY>'; | |
| 32 var FAKE_PRIVATE_KEY = '<FAKE_PRIVATE_KEY>'; | |
| 33 var FAKE_AUTH_CODE = '<FAKE_AUTH_CODE>'; | |
| 34 var FAKE_REFRESH_TOKEN = '<FAKE_REFRESH_TOKEN>'; | |
| 35 var FAKE_PIN_HASH = '<FAKE_PIN_HASH>'; | |
| 36 | |
| 37 /** @type {sinon.Spy|Function} */ | |
| 38 var getCredentialsFromAuthCodeSpy; | |
| 39 | |
| 40 /** @type {sinon.Spy|Function} */ | |
| 41 var getPinHashSpy; | |
| 42 | |
| 43 /** @type {sinon.Spy|Function} */ | |
| 44 var startDaemonSpy; | |
| 45 | |
| 46 /** @type {sinon.Spy} */ | |
| 47 var unregisterHostByIdSpy; | |
| 48 | |
| 49 /** @type {sinon.Spy} */ | |
| 50 var onLocalHostStartedSpy; | |
| 51 | |
| 52 QUnit.module('host_controller', { | |
| 53 beforeEach: function(/** QUnit.Assert */ assert) { | |
| 54 chromeMocks.activate(['identity', 'runtime']); | |
| 55 chromeMocks.identity.mock$setToken('my_token'); | |
| 56 remoting.identity = new remoting.Identity(); | |
| 57 remoting.MockXhr.activate(); | |
| 58 base.debug.assert(remoting.oauth2 === null); | |
| 59 remoting.oauth2 = new remoting.OAuth2(); | |
| 60 base.debug.assert(remoting.hostList === null); | |
| 61 remoting.hostList = /** @type {remoting.HostList} */ | |
| 62 (Object.create(remoting.HostList.prototype)); | |
| 63 | |
| 64 // When the HostList's unregisterHostById method is called, make | |
| 65 // sure the argument is correct. | |
| 66 unregisterHostByIdSpy = | |
| 67 sinon.stub(remoting.hostList, 'unregisterHostById', function( | |
| 68 /** string */ hostId) { | |
| 69 assert.equal(hostId, FAKE_UUID); | |
| 70 }); | |
| 71 | |
| 72 // When the HostList's onLocalHostStarted method is called, make | |
| 73 // sure the arguments are correct. | |
| 74 onLocalHostStartedSpy = | |
| 75 sinon.stub( | |
| 76 remoting.hostList, 'onLocalHostStarted', function( | |
| 77 /** string */ hostName, | |
| 78 /** string */ newHostId, | |
| 79 /** string */ publicKey) { | |
| 80 assert.equal(hostName, FAKE_HOST_NAME); | |
| 81 assert.equal(newHostId, FAKE_UUID); | |
| 82 assert.equal(publicKey, FAKE_PUBLIC_KEY); | |
| 83 }); | |
| 84 | |
| 85 hostDaemonFacadeCtorStub = sinon.stub(remoting, 'HostDaemonFacade'); | |
| 86 mockHostDaemonFacade = new remoting.MockHostDaemonFacade(); | |
| 87 hostDaemonFacadeCtorStub.returns(mockHostDaemonFacade); | |
| 88 generateUuidStub = sinon.stub(base, 'generateUuid'); | |
| 89 generateUuidStub.returns(FAKE_UUID); | |
| 90 getCredentialsFromAuthCodeSpy = sinon.spy( | |
| 91 mockHostDaemonFacade, 'getCredentialsFromAuthCode'); | |
| 92 getPinHashSpy = sinon.spy(mockHostDaemonFacade, 'getPinHash'); | |
| 93 startDaemonSpy = sinon.spy(mockHostDaemonFacade, 'startDaemon'); | |
| 94 }, | |
| 95 afterEach: function() { | |
|
Jamie
2015/04/07 01:13:12
Blank line before afterEach for readability.
John Williams
2015/04/07 20:10:26
Done.
| |
| 96 controller = null; | |
| 97 getCredentialsFromAuthCodeSpy.restore(); | |
| 98 generateUuidStub.restore(); | |
| 99 hostDaemonFacadeCtorStub.restore(); | |
| 100 remoting.hostList = null; | |
| 101 remoting.oauth2 = null; | |
| 102 remoting.MockXhr.restore(); | |
| 103 chromeMocks.restore(); | |
| 104 remoting.identity = null; | |
| 105 } | |
| 106 }); | |
| 107 | |
| 108 // Check that hasFeature returns false by default. | |
| 109 QUnit.test('hasFeature returns false', function(assert) { | |
| 110 controller = new remoting.HostController(); | |
|
Jamie
2015/04/07 01:13:12
Can this be moved into beforeEach (for symmetry wi
John Williams
2015/04/07 20:10:25
Made local.
| |
| 111 return new Promise(function(resolve, reject) { | |
| 112 controller.hasFeature( | |
| 113 remoting.HostController.Feature.PAIRING_REGISTRY, | |
| 114 resolve); | |
| 115 }).then(function(/** boolean */ result) { | |
| 116 assert.equal(result, false); | |
| 117 }); | |
| 118 }); | |
| 119 | |
| 120 // Check what happens when the HostDaemonFacade's getHostName method | |
| 121 // fails. | |
| 122 QUnit.test('start with getHostName failure', function(assert) { | |
| 123 controller = new remoting.HostController(); | |
| 124 return new Promise(function(resolve, reject) { | |
| 125 controller.start(FAKE_HOST_PIN, true, function() { | |
| 126 reject(null); | |
| 127 }, function(/** remoting.Error */ e) { | |
| 128 assert.equal(e.getDetail(), 'getHostName'); | |
| 129 resolve(null); | |
| 130 }); | |
| 131 }); | |
| 132 }); | |
| 133 | |
| 134 // Prepare the to execute HostController.start up to the point where | |
|
Jamie
2015/04/07 01:13:12
Prepare the what? (here and below)
John Williams
2015/04/07 20:10:25
The word "the" wasn't supposed to be there.
| |
| 135 // the hostname is retreived. | |
| 136 function initThroughHostName() { | |
|
Jamie
2015/04/07 01:13:12
Using "through" to mean "until" is idiomatic to US
John Williams
2015/04/07 20:10:26
News to me. I'll keep that in mind.
| |
| 137 mockHostDaemonFacade.daemonVersion = FAKE_DAEMON_VERSION; | |
| 138 mockHostDaemonFacade.hostName = FAKE_HOST_NAME; | |
| 139 }; | |
| 140 | |
| 141 // Check what happens when the HostDaemonFacade's generateKeyPair | |
| 142 // method fails. | |
| 143 QUnit.test('start with generateKeyPair failure', function(assert) { | |
| 144 initThroughHostName(); | |
| 145 controller = new remoting.HostController(); | |
| 146 return new Promise(function(resolve, reject) { | |
| 147 controller.start(FAKE_HOST_PIN, true, function() { | |
| 148 reject(null); | |
| 149 }, function(/** remoting.Error */ e) { | |
| 150 assert.equal(e.getDetail(), 'generateKeyPair'); | |
|
Jamie
2015/04/07 01:13:12
Check the tag as well?
John Williams
2015/04/07 20:10:26
Seems redundant since it's always UNEXPECTED and t
Jamie
2015/04/08 00:16:14
It's only UNEXPECTED if the code is bug-free :) If
John Williams
2015/04/08 20:20:09
Done.
| |
| 151 resolve(null); | |
| 152 }); | |
| 153 }); | |
| 154 }); | |
| 155 | |
| 156 // Prepare the to execute HostController.start up to the point where | |
| 157 // a key pair is generated. | |
| 158 function initThroughPublicPrivateKey() { | |
| 159 initThroughHostName(); | |
| 160 mockHostDaemonFacade.privateKey = FAKE_PRIVATE_KEY; | |
| 161 mockHostDaemonFacade.publicKey = FAKE_PUBLIC_KEY; | |
| 162 } | |
| 163 | |
| 164 // Check what happens when the HostDaemonFacade's getHostClientId | |
| 165 // method fails. | |
| 166 QUnit.test('start with getHostClientId failure', function(assert) { | |
| 167 initThroughPublicPrivateKey(); | |
| 168 mockHostDaemonFacade.features = [ | |
| 169 remoting.HostController.Feature.OAUTH_CLIENT | |
|
Jamie
2015/04/07 01:13:12
Is there a reason why you don't want this Feature
John Williams
2015/04/07 20:10:25
Minimalism again. I want the tests to demonstrate
| |
| 170 ]; | |
| 171 controller = new remoting.HostController(); | |
| 172 return new Promise(function(resolve, reject) { | |
| 173 controller.start(FAKE_HOST_PIN, true, function() { | |
| 174 reject(null); | |
| 175 }, function(/** remoting.Error */ e) { | |
| 176 assert.equal(e.getDetail(), 'getHostClientId'); | |
| 177 resolve(null); | |
| 178 }); | |
| 179 }); | |
| 180 }); | |
| 181 | |
| 182 // Check what happens when the registry returns an HTTP when we try to | |
| 183 // register a host. | |
| 184 QUnit.test('start with host registration failure', function(assert) { | |
| 185 initThroughPublicPrivateKey(); | |
| 186 controller = new remoting.HostController(); | |
| 187 remoting.MockXhr.setEmptyResponseFor( | |
| 188 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts', 500); | |
| 189 return new Promise(function(resolve, reject) { | |
| 190 controller.start(FAKE_HOST_PIN, true, function() { | |
| 191 reject(null); | |
| 192 }, function(/** remoting.Error */ e) { | |
| 193 assert.equal(e.getTag(), remoting.Error.Tag.REGISTRATION_FAILED); | |
| 194 resolve(null); | |
| 195 }); | |
| 196 }); | |
| 197 }); | |
| 198 | |
| 199 // Check what happens when the HostDaemonFacade's | |
| 200 // getCredentialsFromAuthCode method fails. | |
| 201 QUnit.test('start with getCredentialsFromAuthCode failure', function(assert) { | |
| 202 initThroughPublicPrivateKey(); | |
| 203 remoting.MockXhr.setTextResponseFor( | |
| 204 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts', JSON.stringify({ | |
| 205 data: { | |
| 206 authorizationCode: FAKE_AUTH_CODE | |
| 207 } | |
| 208 })); | |
| 209 controller = new remoting.HostController(); | |
| 210 return new Promise(function(resolve, reject) { | |
| 211 controller.start(FAKE_HOST_PIN, true, function() { | |
| 212 reject(null); | |
| 213 }, function(/** remoting.Error */ e) { | |
| 214 assert.equal(e.getDetail(), 'getCredentialsFromAuthCode'); | |
| 215 resolve(null); | |
| 216 }); | |
| 217 }); | |
| 218 }); | |
| 219 | |
| 220 // Prepare the to execute HostController.start up to the point where | |
| 221 // a refresh token is generated. | |
| 222 function initThroughRefreshToken() { | |
| 223 initThroughPublicPrivateKey(); | |
| 224 sinon.stub(remoting.identity, 'getEmail').returns( | |
| 225 Promise.resolve(FAKE_USER_EMAIL)); | |
| 226 sinon.stub(remoting.oauth2, 'getRefreshToken').returns( | |
| 227 FAKE_REFRESH_TOKEN); | |
| 228 mockHostDaemonFacade.userEmail = FAKE_USER_EMAIL; | |
| 229 mockHostDaemonFacade.refreshToken = FAKE_REFRESH_TOKEN; | |
| 230 } | |
| 231 | |
| 232 // Check what happens when the HostDaemonFacade's getPinHash method | |
| 233 // fails, and verify that getPinHash is called when the registry | |
| 234 // does't return an auth code. | |
| 235 QUnit.test('start with getRefreshToken+getPinHash failure', function(assert) { | |
| 236 initThroughRefreshToken(); | |
| 237 remoting.MockXhr.setTextResponseFor( | |
| 238 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts', '{}'); | |
| 239 controller = new remoting.HostController(); | |
| 240 return new Promise(function(resolve, reject) { | |
| 241 controller.start(FAKE_HOST_PIN, true, function() { | |
| 242 reject(null); | |
| 243 }, function(/** remoting.Error */ e) { | |
| 244 assert.equal(unregisterHostByIdSpy.callCount, 0); | |
| 245 assert.equal(e.getDetail(), 'getPinHash'); | |
| 246 resolve(null); | |
| 247 }); | |
| 248 }); | |
| 249 }); | |
| 250 | |
| 251 // Check what happens when the HostController's getClientBaseJid_ | |
| 252 // method fails. | |
| 253 QUnit.test('start with getClientBaseJid_ failure', function(assert) { | |
| 254 initThroughRefreshToken(); | |
| 255 remoting.MockXhr.setTextResponseFor( | |
| 256 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts', JSON.stringify({ | |
| 257 data: { | |
| 258 authorizationCode: FAKE_AUTH_CODE | |
| 259 } | |
| 260 })); | |
| 261 controller = new remoting.HostController(); | |
| 262 sinon.stub(controller, 'getClientBaseJid_'). | |
| 263 callsArgWith(1, remoting.Error.unexpected('getClientBaseJid_')); | |
| 264 return new Promise(function(resolve, reject) { | |
| 265 controller.start(FAKE_HOST_PIN, true, function() { | |
| 266 reject(null); | |
| 267 }, function(/** remoting.Error */ e) { | |
| 268 assert.equal(unregisterHostByIdSpy.callCount, 1); | |
| 269 assert.equal(e.getDetail(), 'getClientBaseJid_'); | |
| 270 resolve(null); | |
| 271 }); | |
| 272 }); | |
| 273 }); | |
| 274 | |
| 275 // Prepare the to execute HostController.start up to the point where a | |
| 276 // PIN hash is generated. This function also installs a check to | |
| 277 // ensure that the registry is updated correctly. | |
| 278 function initThroughPinHash(/** QUnit.Assert */ assert) { | |
| 279 initThroughRefreshToken(); | |
| 280 remoting.MockXhr.setResponseFor( | |
| 281 'POST', 'DIRECTORY_API_BASE_URL/@me/hosts', | |
| 282 function(/** remoting.MockXhr */ xhr) { | |
| 283 assert.deepEqual( | |
| 284 xhr.params.jsonContent, | |
| 285 { data: { | |
| 286 hostId: FAKE_UUID, | |
| 287 hostName: FAKE_HOST_NAME, | |
| 288 publicKey: FAKE_PUBLIC_KEY | |
| 289 } }); | |
| 290 xhr.setTextResponse(200, JSON.stringify({ | |
| 291 data: { | |
| 292 authorizationCode: FAKE_AUTH_CODE | |
| 293 } | |
| 294 })); | |
| 295 }); | |
| 296 mockHostDaemonFacade.pinHash = FAKE_PIN_HASH; | |
| 297 }; | |
| 298 | |
| 299 // Check what happens when the HostDaemonFacade's startDaemon method | |
| 300 // fails and calls its onError argument. | |
| 301 QUnit.test('start with startDaemon failure', function(assert) { | |
| 302 initThroughPinHash(assert); | |
| 303 controller = new remoting.HostController(); | |
| 304 sinon.stub(controller, 'getClientBaseJid_').callsArgWith(0, FAKE_USER_EMAIL); | |
| 305 return new Promise(function(resolve, reject) { | |
| 306 controller.start(FAKE_HOST_PIN, true, function() { | |
| 307 reject(null); | |
| 308 }, function(/** remoting.Error */ e) { | |
| 309 assert.equal(unregisterHostByIdSpy.callCount, 1); | |
| 310 assert.equal(e.getDetail(), 'startDaemon'); | |
| 311 resolve(null); | |
| 312 }); | |
| 313 }); | |
| 314 }); | |
| 315 | |
| 316 // Check what happens when the HostDaemonFacade's startDaemon method | |
| 317 // calls is onDone method with an async error code. | |
| 318 QUnit.test('start with startDaemon cancelled', function(assert) { | |
| 319 initThroughPinHash(assert); | |
| 320 mockHostDaemonFacade.startDaemonResult = | |
| 321 remoting.HostController.AsyncResult.CANCELLED; | |
| 322 controller = new remoting.HostController(); | |
| 323 sinon.stub(controller, 'getClientBaseJid_').callsArgWith(0, FAKE_USER_EMAIL); | |
| 324 return new Promise(function(resolve, reject) { | |
| 325 controller.start(FAKE_HOST_PIN, true, function() { | |
| 326 reject(null); | |
| 327 }, function(/** remoting.Error */ e) { | |
| 328 assert.equal(unregisterHostByIdSpy.callCount, 1); | |
| 329 assert.equal(e.getTag(), remoting.Error.Tag.CANCELLED); | |
| 330 resolve(null); | |
| 331 }); | |
| 332 }); | |
| 333 }); | |
| 334 | |
| 335 // Check what happens when the entire host registration process | |
| 336 // succeeds. | |
| 337 [false, true].forEach(function(/** boolean */ consent) { | |
| 338 QUnit.test('start succeeds with consent=' + consent, function(assert) { | |
| 339 initThroughPinHash(assert); | |
| 340 mockHostDaemonFacade.startDaemonResult = | |
| 341 remoting.HostController.AsyncResult.OK; | |
| 342 controller = new remoting.HostController(); | |
| 343 sinon.stub(controller, 'getClientBaseJid_'). | |
| 344 callsArgWith(0, FAKE_USER_EMAIL); | |
| 345 return new Promise(function(resolve, reject) { | |
| 346 controller.start(FAKE_HOST_PIN, consent, function() { | |
| 347 assert.equal(getCredentialsFromAuthCodeSpy.callCount, 1); | |
| 348 assert.deepEqual( | |
| 349 getCredentialsFromAuthCodeSpy.args[0][0], | |
| 350 FAKE_AUTH_CODE); | |
| 351 assert.equal(getPinHashSpy.callCount, 1); | |
| 352 assert.deepEqual( | |
| 353 getPinHashSpy.args[0].slice(0, 2), | |
| 354 [FAKE_UUID, FAKE_HOST_PIN]); | |
| 355 | |
| 356 assert.equal(unregisterHostByIdSpy.callCount, 0); | |
| 357 assert.equal(onLocalHostStartedSpy.callCount, 1); | |
| 358 assert.equal(startDaemonSpy.callCount, 1); | |
| 359 assert.deepEqual( | |
| 360 startDaemonSpy.args[0].slice(0, 2), | |
| 361 [{ | |
| 362 xmpp_login: FAKE_USER_EMAIL, | |
| 363 oauth_refresh_token: FAKE_REFRESH_TOKEN, | |
| 364 host_id: FAKE_UUID, | |
| 365 host_name: FAKE_HOST_NAME, | |
| 366 host_secret_hash: FAKE_PIN_HASH, | |
| 367 private_key: FAKE_PRIVATE_KEY | |
| 368 }, consent]); | |
| 369 resolve(null); | |
| 370 }, reject); | |
| 371 }); | |
| 372 }); | |
| 373 }); | |
| 374 | |
| 375 // TODO(jrw): Add tests for |stop| method. | |
| 376 // TODO(jrw): Add tests for |updatePin| method. | |
| 377 // TODO(jrw): Add tests for |getLocalHostState| method. | |
| 378 // TODO(jrw): Add tests for |getLocalHostId| method. | |
| 379 // TODO(jrw): Add tests for |getPairedClients| method. | |
| 380 // TODO(jrw): Add tests for |deletePairedClient| method. | |
| 381 // TODO(jrw): Add tests for |clearPairedClients| method. | |
| 382 // TODO(jrw): Make sure getClientBaseJid_ method is tested. | |
| 383 | |
| 384 })(); | |
| OLD | NEW |