Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 * Unit tests for the JS serial service client. | 6 * Unit tests for the JS serial service client. |
| 7 * | 7 * |
| 8 * These test that configuration and data are correctly transmitted between the | 8 * These test that configuration and data are correctly transmitted between the |
| 9 * client and the service. | 9 * client and the service. They are launched by |
| 10 * extensions/renderer/api/serial/serial_api_unittest.cc. | |
| 10 */ | 11 */ |
| 11 | 12 |
| 12 var test = require('test').binding; | 13 var test = require('test').binding; |
| 13 var serial = require('serial').binding; | 14 var serial = require('serial').binding; |
| 14 var unittestBindings = require('test_environment_specific_bindings'); | 15 var unittestBindings = require('test_environment_specific_bindings'); |
| 16 var utils = require('utils'); | |
| 17 | |
| 18 var timeoutManager = new unittestBindings.TimeoutManager(); | |
| 19 timeoutManager.installGlobals(); | |
| 20 | |
| 21 var BUFFER_SIZE = 10; | |
| 15 | 22 |
| 16 var connectionId = null; | 23 var connectionId = null; |
| 17 | 24 |
| 18 function connect(callback, options) { | 25 function connect(callback, options) { |
| 19 options = options || { | 26 options = options || { |
| 20 name: 'test connection', | 27 name: 'test connection', |
| 21 bufferSize: 8192, | 28 bufferSize: BUFFER_SIZE, |
| 22 receiveTimeout: 12345, | 29 receiveTimeout: 12345, |
| 23 sendTimeout: 6789, | 30 sendTimeout: 6789, |
| 24 persistent: true, | 31 persistent: true, |
| 25 } | 32 }; |
| 26 serial.connect('device', options, test.callbackPass(function(connectionInfo) { | 33 serial.connect('device', options, test.callbackPass(function(connectionInfo) { |
| 27 connectionId = connectionInfo.connectionId; | 34 connectionId = connectionInfo.connectionId; |
| 28 callback(connectionInfo); | 35 if (callback) |
| 36 callback(connectionInfo); | |
| 29 })); | 37 })); |
| 30 } | 38 } |
| 31 | 39 |
| 40 // Sets a function to be called once when data is received. Returns a promise | |
| 41 // that will resolve once the hook is installed. | |
| 42 function addReceiveHook(callback) { | |
| 43 return requireAsync('serial_service').then(function(serialService) { | |
| 44 var called = false; | |
| 45 var dataReceived = serialService.Connection.prototype.onDataReceived_; | |
| 46 serialService.Connection.prototype.onDataReceived_ = function() { | |
| 47 var result = $Function.apply(dataReceived, this, arguments); | |
| 48 if (!called) | |
| 49 callback(); | |
| 50 called = true; | |
| 51 return result; | |
| 52 }; | |
| 53 }); | |
| 54 } | |
| 55 | |
| 56 // Sets a function to be called once when a receive error is received. Returns a | |
| 57 // promise that will resolve once the hook is installed. | |
| 58 function addReceiveErrorHook(callback) { | |
| 59 return requireAsync('serial_service').then(function(serialService) { | |
| 60 var called = false; | |
| 61 var receiveError = serialService.Connection.prototype.onReceiveError_; | |
| 62 serialService.Connection.prototype.onReceiveError_ = function() { | |
| 63 var result = $Function.apply(receiveError, this, arguments); | |
| 64 if (!called) | |
| 65 callback(); | |
| 66 called = true; | |
| 67 return result; | |
| 68 }; | |
| 69 }); | |
| 70 } | |
| 71 | |
| 32 function disconnect() { | 72 function disconnect() { |
| 33 serial.disconnect(connectionId, test.callbackPass(function(success) { | 73 serial.disconnect(connectionId, test.callbackPass(function(success) { |
| 34 test.assertTrue(success); | 74 test.assertTrue(success); |
| 35 connectionId = null; | 75 connectionId = null; |
| 36 })); | 76 })); |
| 37 } | 77 } |
| 38 | 78 |
| 39 function checkClientConnectionInfo(connectionInfo) { | 79 function checkClientConnectionInfo(connectionInfo) { |
| 40 test.assertFalse(connectionInfo.persistent); | 80 test.assertFalse(connectionInfo.persistent); |
| 41 test.assertEq('test connection', connectionInfo.name); | 81 test.assertEq('test connection', connectionInfo.name); |
| 42 test.assertEq(12345, connectionInfo.receiveTimeout); | 82 test.assertEq(12345, connectionInfo.receiveTimeout); |
| 43 test.assertEq(6789, connectionInfo.sendTimeout); | 83 test.assertEq(6789, connectionInfo.sendTimeout); |
| 44 test.assertEq(8192, connectionInfo.bufferSize); | 84 test.assertEq(BUFFER_SIZE, connectionInfo.bufferSize); |
| 45 test.assertFalse(connectionInfo.paused); | 85 test.assertFalse(connectionInfo.paused); |
| 46 } | 86 } |
| 47 | 87 |
| 48 function checkServiceConnectionInfo(connectionInfo) { | 88 function checkServiceConnectionInfo(connectionInfo) { |
| 49 test.assertEq(9600, connectionInfo.bitrate); | 89 test.assertEq(9600, connectionInfo.bitrate); |
| 50 test.assertEq('eight', connectionInfo.dataBits); | 90 test.assertEq('eight', connectionInfo.dataBits); |
| 51 test.assertEq('no', connectionInfo.parityBit); | 91 test.assertEq('no', connectionInfo.parityBit); |
| 52 test.assertEq('one', connectionInfo.stopBits); | 92 test.assertEq('one', connectionInfo.stopBits); |
| 53 test.assertFalse(connectionInfo.ctsFlowControl); | 93 test.assertFalse(connectionInfo.ctsFlowControl); |
| 54 } | 94 } |
| 55 | 95 |
| 56 function checkConnectionInfo(connectionInfo) { | 96 function checkConnectionInfo(connectionInfo) { |
| 57 checkClientConnectionInfo(connectionInfo); | 97 checkClientConnectionInfo(connectionInfo); |
| 58 checkServiceConnectionInfo(connectionInfo); | 98 checkServiceConnectionInfo(connectionInfo); |
| 59 } | 99 } |
| 60 | 100 |
| 101 function runReceiveErrorTest(expectedError) { | |
| 102 connect(); | |
| 103 test.listenOnce(serial.onReceiveError, function(result) { | |
| 104 serial.getInfo(connectionId, test.callbackPass(function(connectionInfo) { | |
| 105 disconnect(); | |
| 106 test.assertTrue(connectionInfo.paused); | |
| 107 })); | |
| 108 test.assertEq(connectionId, result.connectionId); | |
| 109 test.assertEq(expectedError, result.error); | |
| 110 }); | |
| 111 } | |
| 112 | |
| 113 function runSendErrorTest(expectedError) { | |
| 114 connect(function() { | |
| 115 var buffer = new ArrayBuffer(1); | |
| 116 serial.send(connectionId, buffer, test.callbackPass(function(sendInfo) { | |
| 117 disconnect(); | |
| 118 test.assertEq(0, sendInfo.bytesSent); | |
| 119 test.assertEq(expectedError, sendInfo.error); | |
| 120 })); | |
| 121 }); | |
| 122 } | |
| 123 | |
| 124 function sendData() { | |
| 125 var data = 'data'; | |
| 126 var buffer = new ArrayBuffer(data.length); | |
| 127 var byteBuffer = new Int8Array(buffer); | |
| 128 for (var i = 0; i < data.length; i++) { | |
| 129 byteBuffer[i] = data.charCodeAt(i); | |
| 130 } | |
| 131 return utils.promise(serial.send, connectionId, buffer); | |
| 132 } | |
| 133 | |
| 134 function checkReceivedData(result) { | |
| 135 var data = 'data'; | |
| 136 test.assertEq(connectionId, result.connectionId); | |
| 137 test.assertEq(data.length, result.data.byteLength); | |
| 138 var resultByteBuffer = new Int8Array(result.data); | |
| 139 for (var i = 0; i < data.length; i++) { | |
| 140 test.assertEq(data.charCodeAt(i), resultByteBuffer[i]); | |
| 141 } | |
| 142 } | |
| 143 | |
| 61 unittestBindings.exportTests([ | 144 unittestBindings.exportTests([ |
| 62 function testGetDevices() { | 145 function testGetDevices() { |
| 63 serial.getDevices(test.callbackPass(function(devices) { | 146 serial.getDevices(test.callbackPass(function(devices) { |
| 64 test.assertEq(3, devices.length); | 147 test.assertEq(3, devices.length); |
| 65 test.assertEq(4, $Object.keys(devices[0]).length); | 148 test.assertEq(4, $Object.keys(devices[0]).length); |
| 66 test.assertEq('device', devices[0].path); | 149 test.assertEq('device', devices[0].path); |
| 67 test.assertEq(1234, devices[0].vendorId); | 150 test.assertEq(1234, devices[0].vendorId); |
| 68 test.assertEq(5678, devices[0].productId); | 151 test.assertEq(5678, devices[0].productId); |
| 69 test.assertEq('foo', devices[0].displayName); | 152 test.assertEq('foo', devices[0].displayName); |
| 70 test.assertEq(1, $Object.keys(devices[1]).length); | 153 test.assertEq(1, $Object.keys(devices[1]).length); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 test.assertFalse(info.paused); | 353 test.assertFalse(info.paused); |
| 271 disconnect(); | 354 disconnect(); |
| 272 })); | 355 })); |
| 273 })); | 356 })); |
| 274 test.assertTrue(info.paused); | 357 test.assertTrue(info.paused); |
| 275 })); | 358 })); |
| 276 })); | 359 })); |
| 277 }); | 360 }); |
| 278 }, | 361 }, |
| 279 | 362 |
| 363 function testEcho() { | |
| 364 connect(function() { | |
| 365 sendData().then(test.callbackPass(function(sendInfo) { | |
| 366 test.assertEq(4, sendInfo.bytesSent); | |
| 367 test.assertEq(undefined, sendInfo.error); | |
| 368 })); | |
| 369 test.listenOnce(serial.onReceive, function(result) { | |
| 370 checkReceivedData(result); | |
| 371 disconnect(); | |
| 372 }); | |
| 373 }); | |
| 374 }, | |
| 375 | |
| 376 function testSendDuringExistingSend() { | |
| 377 connect(function() { | |
| 378 sendData().then(test.callbackPass(function(sendInfo) { | |
| 379 test.assertEq(4, sendInfo.bytesSent); | |
| 380 test.assertEq(undefined, sendInfo.error); | |
| 381 disconnect(); | |
| 382 })); | |
| 383 sendData().then(test.callbackPass(function(sendInfo) { | |
| 384 test.assertEq(0, sendInfo.bytesSent); | |
| 385 test.assertEq('pending', sendInfo.error); | |
| 386 })); | |
| 387 }); | |
| 388 }, | |
| 389 | |
| 390 function testSendAfterSuccessfulSend() { | |
| 391 connect(function() { | |
| 392 sendData().then(test.callbackPass(function(sendInfo) { | |
| 393 test.assertEq(4, sendInfo.bytesSent); | |
| 394 test.assertEq(undefined, sendInfo.error); | |
| 395 // Test that a second send started after the first completes succeeds. | |
| 396 return sendData(); | |
| 397 })).then(test.callbackPass(function(sendInfo) { | |
| 398 test.assertEq(4, sendInfo.bytesSent); | |
| 399 test.assertEq(undefined, sendInfo.error); | |
| 400 })); | |
| 401 // Check that the correct data is echoed twice. | |
| 402 test.listenOnce(serial.onReceive, function(result) { | |
| 403 checkReceivedData(result); | |
| 404 test.listenOnce(serial.onReceive, function(result) { | |
| 405 checkReceivedData(result); | |
| 406 disconnect(); | |
| 407 }); | |
| 408 }); | |
| 409 }); | |
| 410 }, | |
| 411 | |
| 412 function testSendPartialSuccessWithError() { | |
| 413 connect(function() { | |
| 414 sendData().then(test.callbackPass(function(sendInfo) { | |
| 415 test.assertEq(2, sendInfo.bytesSent); | |
| 416 test.assertEq('system_error', sendInfo.error); | |
| 417 return sendData(); | |
| 418 })).then(test.callbackPass(function(sendInfo) { | |
| 419 test.assertEq(4, sendInfo.bytesSent); | |
| 420 test.assertEq(undefined, sendInfo.error); | |
| 421 disconnect(); | |
| 422 })); | |
| 423 }); | |
| 424 }, | |
| 425 | |
| 426 function testSendTimeout() { | |
| 427 connect(function() { | |
| 428 sendData().then(test.callbackPass(function(sendInfo) { | |
| 429 test.assertEq(0, sendInfo.bytesSent); | |
| 430 test.assertEq('timeout', sendInfo.error); | |
| 431 test.assertEq(5, timeoutManager.currentTime); | |
| 432 disconnect(); | |
| 433 timeoutManager.disableAutorun(); | |
| 434 })); | |
| 435 // Changing the timeout does not effect a send in progress. | |
| 436 serial.update(connectionId, {sendTimeout: 10}, test.callbackPass( | |
| 437 timeoutManager.enableAutorun.bind(timeoutManager))); | |
|
raymes
2014/09/02 04:59:32
What about calling these timeoutManager.pause() an
Sam McNally
2014/09/02 07:41:13
Done. For testReceiveTimeout, leaving it running c
raymes
2014/09/03 01:28:32
Hmm do you know why that is the case? This seems s
Sam McNally
2014/09/03 01:56:13
Removed the need to pause as discussed.
| |
| 438 }, {sendTimeout: 5}); | |
| 439 }, | |
| 440 | |
| 441 function testDisableSendTimeout() { | |
| 442 connect(function() { | |
| 443 sendData().then(test.callbackPass(function(sendInfo) { | |
| 444 test.assertEq(0, sendInfo.bytesSent); | |
| 445 test.assertEq('timeout', sendInfo.error); | |
| 446 test.assertEq(6, timeoutManager.currentTime); | |
| 447 disconnect(); | |
| 448 timeoutManager.disableAutorun(); | |
| 449 })); | |
| 450 // Disabling the timeout does not effect a send in progress. | |
| 451 serial.update(connectionId, {sendTimeout: 0}, test.callbackPass( | |
| 452 timeoutManager.enableAutorun.bind(timeoutManager))); | |
| 453 }, {sendTimeout: 6}); | |
| 454 }, | |
| 455 | |
| 456 function testPausedReceive() { | |
| 457 // Wait until the receive hook is installed, then start the test. | |
| 458 addReceiveHook(function() { | |
| 459 // Unpause the connection after the connection has queued the received | |
| 460 // data to ensure the queued data is dispatched when the connection is | |
| 461 // unpaused. | |
| 462 serial.setPaused(connectionId, false, test.callbackPass()); | |
| 463 // Check that setPaused(false) is idempotent. | |
| 464 serial.setPaused(connectionId, false, test.callbackPass()); | |
| 465 }).then(function() { | |
| 466 connect(function() { | |
| 467 // Check that setPaused(true) is idempotent. | |
| 468 serial.setPaused(connectionId, true, test.callbackPass()); | |
| 469 serial.setPaused(connectionId, true, test.callbackPass()); | |
| 470 }); | |
| 471 }); | |
| 472 test.listenOnce(serial.onReceive, function(result) { | |
| 473 checkReceivedData(result); | |
| 474 disconnect(); | |
| 475 }); | |
| 476 }, | |
| 477 | |
| 478 function testPausedReceiveError() { | |
| 479 addReceiveErrorHook(function() { | |
| 480 // Unpause the connection after the connection has queued the receive | |
| 481 // error to ensure the queued error is dispatched when the connection is | |
| 482 // unpaused. | |
| 483 serial.setPaused(connectionId, false, test.callbackPass()); | |
| 484 }).then(test.callbackPass(function() { | |
| 485 connect(function() { | |
| 486 serial.setPaused(connectionId, true, test.callbackPass()); | |
| 487 }); | |
| 488 })); | |
| 489 | |
| 490 test.listenOnce(serial.onReceiveError, function(result) { | |
| 491 serial.getInfo(connectionId, test.callbackPass(function(connectionInfo) { | |
| 492 disconnect(); | |
| 493 test.assertTrue(connectionInfo.paused); | |
| 494 })); | |
| 495 test.assertEq(connectionId, result.connectionId); | |
| 496 test.assertEq('device_lost', result.error); | |
| 497 }); | |
| 498 serial.onReceive.addListener(function() { | |
| 499 test.fail('unexpected onReceive event'); | |
| 500 }); | |
| 501 }, | |
| 502 | |
| 503 function testReceiveTimeout() { | |
| 504 connect(function() { | |
| 505 test.listenOnce(serial.onReceiveError, function(result) { | |
| 506 test.assertEq(connectionId, result.connectionId); | |
| 507 test.assertEq('timeout', result.error); | |
| 508 test.assertEq(20, timeoutManager.currentTime); | |
| 509 serial.getInfo(connectionId, test.callbackPass( | |
| 510 function(connectionInfo) { | |
| 511 test.assertFalse(connectionInfo.paused); | |
| 512 disconnect(); | |
| 513 })); | |
| 514 timeoutManager.disableAutorun(); | |
| 515 }); | |
| 516 // Changing the timeout does not take effect until the current timeout | |
| 517 // expires or a receive completes. | |
| 518 serial.update(connectionId, {receiveTimeout: 10}, test.callbackPass( | |
| 519 timeoutManager.enableAutorun.bind(timeoutManager))); | |
| 520 }, {receiveTimeout: 20}); | |
| 521 }, | |
| 522 | |
| 523 function testDisableReceiveTimeout() { | |
| 524 connect(function() { | |
| 525 test.listenOnce(serial.onReceiveError, function(result) { | |
| 526 test.assertEq(connectionId, result.connectionId); | |
| 527 test.assertEq('timeout', result.error); | |
| 528 test.assertEq(30, timeoutManager.currentTime); | |
| 529 serial.getInfo(connectionId, test.callbackPass( | |
| 530 function(connectionInfo) { | |
| 531 disconnect(); | |
| 532 test.assertFalse(connectionInfo.paused); | |
| 533 })); | |
| 534 timeoutManager.disableAutorun(); | |
| 535 }); | |
| 536 // Disabling the timeout does not take effect until the current timeout | |
| 537 // expires or a receive completes. | |
| 538 serial.update(connectionId, {receiveTimeout: 0}, test.callbackPass( | |
| 539 timeoutManager.enableAutorun.bind(timeoutManager))); | |
| 540 }, {receiveTimeout: 30}); | |
| 541 }, | |
| 542 | |
| 543 function testReceiveErrorDisconnected() { | |
| 544 runReceiveErrorTest('disconnected'); | |
| 545 }, | |
| 546 | |
| 547 function testReceiveErrorTimeout() { | |
| 548 // Note: this tests that a timeout error from the service pauses the | |
| 549 // connection, but in production, the service never sends a timeout error - | |
| 550 // the timeout error is generated internally by the connection and in that | |
| 551 // case doesn't trigger a pause. | |
|
raymes
2014/09/02 04:59:32
Should this comment also be on testSendErrorTimeou
Sam McNally
2014/09/02 07:41:13
Removed these tests.
| |
| 552 runReceiveErrorTest('timeout'); | |
| 553 }, | |
| 554 | |
| 555 function testReceiveErrorDeviceLost() { | |
| 556 runReceiveErrorTest('device_lost'); | |
| 557 }, | |
| 558 | |
| 559 function testReceiveErrorSystemError() { | |
| 560 runReceiveErrorTest('system_error'); | |
| 561 }, | |
| 562 | |
| 563 function testSendErrorDisconnected() { | |
| 564 runSendErrorTest('disconnected'); | |
| 565 }, | |
| 566 | |
| 567 function testSendErrorTimeout() { | |
| 568 runSendErrorTest('timeout'); | |
| 569 }, | |
| 570 | |
| 571 function testSendErrorSystemError() { | |
| 572 runSendErrorTest('system_error'); | |
| 573 }, | |
| 574 | |
| 280 function testDisconnectUnknownConnectionId() { | 575 function testDisconnectUnknownConnectionId() { |
| 281 serial.disconnect(-1, test.callbackFail('Serial connection not found.')); | 576 serial.disconnect(-1, test.callbackFail('Serial connection not found.')); |
| 282 }, | 577 }, |
| 283 | 578 |
| 284 function testGetInfoUnknownConnectionId() { | 579 function testGetInfoUnknownConnectionId() { |
| 285 serial.getInfo(-1, test.callbackFail('Serial connection not found.')); | 580 serial.getInfo(-1, test.callbackFail('Serial connection not found.')); |
| 286 }, | 581 }, |
| 287 | 582 |
| 288 function testUpdateUnknownConnectionId() { | 583 function testUpdateUnknownConnectionId() { |
| 289 serial.update(-1, {}, test.callbackFail('Serial connection not found.')); | 584 serial.update(-1, {}, test.callbackFail('Serial connection not found.')); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 302 function testFlushUnknownConnectionId() { | 597 function testFlushUnknownConnectionId() { |
| 303 serial.flush(-1, test.callbackFail('Serial connection not found.')); | 598 serial.flush(-1, test.callbackFail('Serial connection not found.')); |
| 304 }, | 599 }, |
| 305 | 600 |
| 306 function testSetPausedUnknownConnectionId() { | 601 function testSetPausedUnknownConnectionId() { |
| 307 serial.setPaused( | 602 serial.setPaused( |
| 308 -1, true, test.callbackFail('Serial connection not found.')); | 603 -1, true, test.callbackFail('Serial connection not found.')); |
| 309 serial.setPaused( | 604 serial.setPaused( |
| 310 -1, false, test.callbackFail('Serial connection not found.')); | 605 -1, false, test.callbackFail('Serial connection not found.')); |
| 311 }, | 606 }, |
| 607 | |
| 608 function testSendUnknownConnectionId() { | |
| 609 var buffer = new ArrayBuffer(1); | |
| 610 serial.send(-1, buffer, test.callbackFail('Serial connection not found.')); | |
| 611 }, | |
| 312 ], test.runTests, exports); | 612 ], test.runTests, exports); |
| OLD | NEW |