| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * Unit tests for the JS serial service client. |
| * |
| * These test that configuration and data are correctly transmitted between the |
| * client and the service. They are launched by |
| * extensions/renderer/api/serial/serial_api_unittest.cc. |
| */ |
| |
| var test = require('test').binding; |
| var serial = require('serial').binding; |
| var unittestBindings = require('test_environment_specific_bindings'); |
| var utils = require('utils'); |
| |
| var timeoutManager = new unittestBindings.TimeoutManager(); |
| timeoutManager.installGlobals(); |
| |
| var BUFFER_SIZE = 10; |
| |
| var connectionId = null; |
| |
| var OPTIONS_VALUES = [ |
| {}, // SetPortOptions is called once during connection. |
| {bitrate: 57600}, |
| {dataBits: 'seven'}, |
| {dataBits: 'eight'}, |
| {parityBit: 'no'}, |
| {parityBit: 'odd'}, |
| {parityBit: 'even'}, |
| {stopBits: 'one'}, |
| {stopBits: 'two'}, |
| {ctsFlowControl: false}, |
| {ctsFlowControl: true}, |
| {bufferSize: 1}, |
| {sendTimeout: 0}, |
| {receiveTimeout: 0}, |
| {persistent: false}, |
| {name: 'name'}, |
| ]; |
| |
| // Create a serial connection. That serial connection will be used by the other |
| // helper functions below. |
| function connect(options) { |
| options = options || { |
| name: 'test connection', |
| bufferSize: BUFFER_SIZE, |
| receiveTimeout: 12345, |
| sendTimeout: 6789, |
| persistent: true, |
| }; |
| return utils.promise(serial.connect, 'device', options).then(function(info) { |
| connectionId = info.connectionId; |
| return info; |
| }); |
| } |
| |
| // Serialize and deserialize all serial connections, preserving onData and |
| // onError event listeners. |
| function serializeRoundTrip() { |
| return requireAsync('serial_service').then(function(serialService) { |
| function serializeConnections(connections) { |
| var serializedConnections = []; |
| for (var connection of connections.values()) { |
| serializedConnections.push(serializeConnection(connection)); |
| } |
| return Promise.all(serializedConnections); |
| } |
| |
| function serializeConnection(connection) { |
| var onData = connection.onData; |
| var onError = connection.onError; |
| return connection.serialize().then(function(serialization) { |
| return { |
| serialization: serialization, |
| onData: onData, |
| onError: onError, |
| }; |
| }); |
| } |
| |
| function deserializeConnections(serializedConnections) { |
| $Array.forEach(serializedConnections, function(serializedConnection) { |
| var connection = serialService.Connection.deserialize( |
| serializedConnection.serialization); |
| connection.onData = serializedConnection.onData; |
| connection.onError = serializedConnection.onError; |
| connection.resumeReceives(); |
| }); |
| } |
| |
| return serialService.getConnections() |
| .then(serializeConnections) |
| .then(deserializeConnections); |
| }); |
| } |
| |
| // Returns a promise that will resolve to the connection info for the |
| // connection. |
| function getInfo() { |
| return utils.promise(serial.getInfo, connectionId); |
| } |
| |
| // Returns a function that checks that the values of keys contained within |
| // |expectedInfo| match the values of the same keys contained within |info|. |
| function checkInfo(expectedInfo) { |
| return function(info) { |
| for (var key in expectedInfo) { |
| test.assertEq(expectedInfo[key], info[key]); |
| } |
| }; |
| } |
| |
| // Returns a function that will update the options of the serial connection with |
| // those contained within |values|. |
| function update(values) { |
| return function() { |
| return utils.promise(serial.update, connectionId, values); |
| }; |
| } |
| |
| // Checks that the previous operation succeeded. |
| function expectSuccess(success) { |
| test.assertTrue(success); |
| } |
| |
| // Returns a function that checks that the send result matches |bytesSent| and |
| // |error|. If no error is expected, |error| may be omitted. |
| function expectSendResult(bytesSent, error) { |
| return function(sendInfo) { |
| test.assertEq(bytesSent, sendInfo.bytesSent); |
| test.assertEq(error, sendInfo.error); |
| }; |
| } |
| |
| // Returns a function that checks that the current time is |expectedTime|. |
| function expectCurrentTime(expectedTime) { |
| return function() { |
| test.assertEq(expectedTime, timeoutManager.currentTime); |
| } |
| } |
| |
| // Returns a promise that will resolve to the device control signals for the |
| // serial connection. |
| function getControlSignals() { |
| return utils.promise(serial.getControlSignals, connectionId); |
| } |
| |
| // Returns a function that will set the control signals for the serial |
| // connection to |signals|. |
| function setControlSignals(signals) { |
| return function() { |
| return utils.promise(serial.setControlSignals, connectionId, signals); |
| }; |
| } |
| |
| // Returns a function that will set the paused state of the serial connection to |
| // |paused|. |
| function setPaused(paused) { |
| return function() { |
| return utils.promise(serial.setPaused, connectionId, paused); |
| } |
| } |
| |
| // Sets a function to be called once when data is received. Returns a promise |
| // that will resolve once the hook is installed. |
| function addReceiveHook(callback) { |
| return requireAsync('serial_service').then(function(serialService) { |
| var called = false; |
| var dataReceived = serialService.Connection.prototype.onDataReceived_; |
| serialService.Connection.prototype.onDataReceived_ = function() { |
| var result = $Function.apply(dataReceived, this, arguments); |
| if (!called) |
| callback(); |
| called = true; |
| return result; |
| }; |
| }); |
| } |
| |
| // Sets a function to be called once when a receive error is received. Returns a |
| // promise that will resolve once the hook is installed. |
| function addReceiveErrorHook(callback) { |
| return requireAsync('serial_service').then(function(serialService) { |
| var called = false; |
| var receiveError = serialService.Connection.prototype.onReceiveError_; |
| serialService.Connection.prototype.onReceiveError_ = function() { |
| var result = $Function.apply(receiveError, this, arguments); |
| if (!called) |
| callback(); |
| called = true; |
| return result; |
| }; |
| }); |
| } |
| |
| function listenOnce(targetEvent) { |
| return new Promise(function(resolve, reject) { |
| targetEvent.addListener(function(result) { |
| resolve(result); |
| }); |
| }); |
| } |
| |
| function disconnect() { |
| return utils.promise(serial.disconnect, connectionId).then(function(success) { |
| test.assertTrue(success); |
| connectionId = null; |
| }); |
| } |
| |
| function checkClientConnectionInfo(connectionInfo) { |
| test.assertTrue(connectionInfo.persistent); |
| test.assertEq('test connection', connectionInfo.name); |
| test.assertEq(12345, connectionInfo.receiveTimeout); |
| test.assertEq(6789, connectionInfo.sendTimeout); |
| test.assertEq(BUFFER_SIZE, connectionInfo.bufferSize); |
| test.assertFalse(connectionInfo.paused); |
| } |
| |
| function checkServiceConnectionInfo(connectionInfo) { |
| test.assertEq(9600, connectionInfo.bitrate); |
| test.assertEq('eight', connectionInfo.dataBits); |
| test.assertEq('no', connectionInfo.parityBit); |
| test.assertEq('one', connectionInfo.stopBits); |
| test.assertFalse(connectionInfo.ctsFlowControl); |
| } |
| |
| function checkConnectionInfo(connectionInfo) { |
| checkClientConnectionInfo(connectionInfo); |
| checkServiceConnectionInfo(connectionInfo); |
| test.assertEq(12, $Object.keys(connectionInfo).length); |
| } |
| |
| function sendData() { |
| var data = 'data'; |
| var buffer = new ArrayBuffer(data.length); |
| var byteBuffer = new Int8Array(buffer); |
| for (var i = 0; i < data.length; i++) { |
| byteBuffer[i] = data.charCodeAt(i); |
| } |
| return utils.promise(serial.send, connectionId, buffer); |
| } |
| |
| function checkReceivedData(result) { |
| var data = 'data'; |
| test.assertEq(connectionId, result.connectionId); |
| test.assertEq(data.length, result.data.byteLength); |
| var resultByteBuffer = new Int8Array(result.data); |
| for (var i = 0; i < data.length; i++) { |
| test.assertEq(data.charCodeAt(i), resultByteBuffer[i]); |
| } |
| } |
| |
| function checkReceiveError(expectedError) { |
| return function(result) { |
| test.assertEq(connectionId, result.connectionId); |
| test.assertEq(expectedError, result.error); |
| } |
| } |
| |
| function runReceiveErrorTest(expectedError) { |
| var errorReceived = listenOnce(serial.onReceiveError); |
| Promise.all([ |
| connect(), |
| errorReceived |
| .then(checkReceiveError(expectedError)), |
| errorReceived |
| .then(getInfo) |
| .then(checkInfo({paused: true})), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| } |
| |
| function runSendErrorTest(expectedError) { |
| connect() |
| .then(sendData) |
| .then(expectSendResult(0, expectedError)) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| } |
| |
| unittestBindings.exportTests([ |
| // Test that getDevices correctly transforms the data returned by the |
| // SerialDeviceEnumerator. |
| function testGetDevices() { |
| utils.promise(serial.getDevices).then(function(devices) { |
| test.assertEq(3, devices.length); |
| test.assertEq(4, $Object.keys(devices[0]).length); |
| test.assertEq('device', devices[0].path); |
| test.assertEq(1234, devices[0].vendorId); |
| test.assertEq(5678, devices[0].productId); |
| test.assertEq('foo', devices[0].displayName); |
| test.assertEq(1, $Object.keys(devices[1]).length); |
| test.assertEq('another_device', devices[1].path); |
| test.assertEq(1, $Object.keys(devices[2]).length); |
| test.assertEq('', devices[2].path); |
| }).then(test.succeed, test.fail); |
| }, |
| |
| // Test that the correct error message is returned when an error occurs in |
| // connecting to the port. This test uses an IoHandler that fails to connect. |
| function testConnectFail() { |
| serial.connect('device', |
| test.callbackFail('Failed to connect to the port.')); |
| }, |
| |
| // Test that the correct error message is returned when an error occurs in |
| // calling getPortInfo after connecting to the port. This test uses an |
| // IoHandler that fails on calls to GetPortInfo. |
| function testGetInfoFailOnConnect() { |
| serial.connect('device', |
| test.callbackFail('Failed to connect to the port.')); |
| }, |
| |
| // Test that the correct error message is returned when an invalid bit-rate |
| // value is passed to connect. |
| function testConnectInvalidBitrate() { |
| serial.connect('device', {bitrate: -1}, test.callbackFail( |
| 'Failed to connect to the port.')); |
| }, |
| |
| // Test that a successful connect returns the expected connection info. |
| function testConnect() { |
| connect() |
| .then(checkConnectionInfo) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a connection created with no options has the correct default |
| // options. |
| function testConnectDefaultOptions() { |
| connect({}).then(function(connectionInfo) { |
| test.assertEq(9600, connectionInfo.bitrate); |
| test.assertEq('eight', connectionInfo.dataBits); |
| test.assertEq('no', connectionInfo.parityBit); |
| test.assertEq('one', connectionInfo.stopBits); |
| test.assertFalse(connectionInfo.ctsFlowControl); |
| test.assertFalse(connectionInfo.persistent); |
| test.assertEq('', connectionInfo.name); |
| test.assertEq(0, connectionInfo.receiveTimeout); |
| test.assertEq(0, connectionInfo.sendTimeout); |
| test.assertEq(4096, connectionInfo.bufferSize); |
| }) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a getInfo call correctly converts the service-side info from the |
| // Mojo format and returns both it and the client-side configuration. |
| function testGetInfo() { |
| connect() |
| .then(getInfo) |
| .then(checkConnectionInfo) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a getInfo call returns the correct info after serialization. |
| function testGetInfoAfterSerialization() { |
| connect() |
| .then(serializeRoundTrip) |
| .then(getInfo) |
| .then(checkConnectionInfo) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that only client-side options are returned when the service fails a |
| // getInfo call. This test uses an IoHandler that fails GetPortInfo calls |
| // after the initial call during connect. |
| function testGetInfoFailToGetPortInfo() { |
| var info = connect().then(getInfo); |
| Promise.all([ |
| info.then(function(connectionInfo) { |
| test.assertFalse('bitrate' in connectionInfo); |
| test.assertFalse('dataBits' in connectionInfo); |
| test.assertFalse('parityBit' in connectionInfo); |
| test.assertFalse('stopBit' in connectionInfo); |
| test.assertFalse('ctsFlowControl' in connectionInfo); |
| }), |
| info.then(checkClientConnectionInfo), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that getConnections returns an array containing the open connection. |
| function testGetConnections() { |
| connect().then(function() { |
| return utils.promise(serial.getConnections); |
| }).then(function(connections) { |
| test.assertEq(1, connections.length); |
| checkConnectionInfo(connections[0]); |
| }) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that getControlSignals correctly converts the Mojo format result. This |
| // test uses an IoHandler that returns values matching the pattern being |
| // tested. |
| function testGetControlSignals() { |
| function checkControlSignals(expectedBitfield) { |
| return function(signals) { |
| test.assertEq(!!(expectedBitfield & 1), signals.dcd); |
| test.assertEq(!!(expectedBitfield & 2), signals.cts); |
| test.assertEq(!!(expectedBitfield & 4), signals.ri); |
| test.assertEq(!!(expectedBitfield & 8), signals.dsr); |
| }; |
| } |
| var promiseChain = connect(); |
| for (var i = 0; i < 16; i++) { |
| promiseChain = promiseChain |
| .then(getControlSignals) |
| .then(checkControlSignals(i)); |
| } |
| promiseChain |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that setControlSignals correctly converts to the Mojo format result. |
| // This test uses an IoHandler that returns values following the same table of |
| // values as |signalsValues|. |
| function testSetControlSignals() { |
| var signalsValues = [ |
| {}, |
| {dtr: false}, |
| {dtr: true}, |
| {rts: false}, |
| {dtr: false, rts: false}, |
| {dtr: true, rts: false}, |
| {rts: true}, |
| {dtr: false, rts: true}, |
| {dtr: true, rts: true}, |
| ]; |
| var promiseChain = connect(); |
| for (var i = 0; i < signalsValues.length; i++) { |
| promiseChain = promiseChain.then(setControlSignals(signalsValues[i])); |
| } |
| promiseChain |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that update correctly passes values to the service only for |
| // service-side options and that all update calls are reflected by the result |
| // of getInfo calls. This test uses an IoHandler that expects corresponding |
| // ConfigurePort calls. |
| function testUpdate() { |
| var promiseChain = connect() |
| .then(getInfo) |
| .then(checkInfo(OPTIONS_VALUES[i])); |
| for (var i = 1; i < OPTIONS_VALUES.length; i++) { |
| promiseChain = promiseChain |
| .then(update(OPTIONS_VALUES[i])) |
| .then(expectSuccess) |
| .then(getInfo) |
| .then(checkInfo(OPTIONS_VALUES[i])); |
| } |
| promiseChain |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that options set by update persist after serialization. |
| function testUpdateAcrossSerialization() { |
| var promiseChain = connect() |
| .then(serializeRoundTrip) |
| .then(getInfo) |
| .then(checkInfo(OPTIONS_VALUES[i])); |
| for (var i = 1; i < OPTIONS_VALUES.length; i++) { |
| promiseChain = promiseChain |
| .then(update(OPTIONS_VALUES[i])) |
| .then(expectSuccess) |
| .then(serializeRoundTrip) |
| .then(getInfo) |
| .then(checkInfo(OPTIONS_VALUES[i])); |
| } |
| promiseChain |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that passing an invalid bit-rate reslts in an error. |
| function testUpdateInvalidBitrate() { |
| connect() |
| .then(update({bitrate: -1})) |
| .then(function(success) { |
| test.assertFalse(success); |
| }) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test flush. This test uses an IoHandler that counts the number of flush |
| // calls. |
| function testFlush() { |
| connect().then(function() { |
| return utils.promise(serial.flush, connectionId); |
| }) |
| .then(expectSuccess) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that setPaused values are reflected by the results returned by getInfo |
| // calls. |
| function testSetPaused() { |
| connect() |
| .then(setPaused(true)) |
| .then(getInfo) |
| .then(checkInfo({paused: true})) |
| .then(setPaused(false)) |
| .then(getInfo) |
| .then(checkInfo({paused: false})) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a send and a receive correctly echoes data. This uses an |
| // IoHandler that echoes data sent to it. |
| function testEcho() { |
| Promise.all([ |
| connect() |
| .then(sendData) |
| .then(expectSendResult(4)), |
| listenOnce(serial.onReceive) |
| .then(checkReceivedData), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a send while another send is in progress returns a pending error. |
| function testSendDuringExistingSend() { |
| var connected = connect(); |
| Promise.all([ |
| connected |
| .then(sendData) |
| .then(expectSendResult(4)), |
| connected |
| .then(sendData) |
| .then(expectSendResult(0, 'pending')), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a second send after the first finishes is successful. This uses |
| // an IoHandler that echoes data sent to it. |
| function testSendAfterSuccessfulSend() { |
| connect() |
| .then(sendData) |
| .then(expectSendResult(4)) |
| .then(sendData) |
| .then(expectSendResult(4)) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a second send after the first fails is successful. This uses an |
| // IoHandler that returns system_error for only the first send. |
| function testSendPartialSuccessWithError() { |
| connect() |
| .then(sendData) |
| .then(expectSendResult(2, 'system_error')) |
| .then(sendData) |
| .then(expectSendResult(4)) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a send and a receive correctly echoes data after serialization. |
| function testEchoAfterSerialization() { |
| Promise.all([ |
| connect() |
| .then(serializeRoundTrip) |
| .then(sendData) |
| .then(expectSendResult(4)), |
| listenOnce(serial.onReceive).then(checkReceivedData) |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a timed-out send returns a timeout error and that changing the |
| // send timeout during a send does not affect its timeout. This test uses an |
| // IoHandle that never completes sends. |
| function testSendTimeout() { |
| var connected = connect({sendTimeout: 5}); |
| var sent = connected.then(sendData); |
| Promise.all([ |
| sent.then(expectSendResult(0, 'timeout')), |
| sent.then(expectCurrentTime(5)), |
| connected.then(update({sendTimeout: 10})) |
| .then(expectSuccess) |
| .then(timeoutManager.run.bind(timeoutManager, 1)), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that send timeouts still function correctly after a serialization |
| // round trip. |
| function testSendTimeoutAfterSerialization() { |
| var connected = connect({sendTimeout: 5}).then(serializeRoundTrip); |
| var sent = connected.then(sendData); |
| Promise.all([ |
| sent.then(expectSendResult(0, 'timeout')), |
| sent.then(expectCurrentTime(5)), |
| connected.then(update({sendTimeout: 10})) |
| .then(expectSuccess) |
| .then(timeoutManager.run.bind(timeoutManager, 1)), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a timed-out send returns a timeout error and that disabling the |
| // send timeout during a send does not affect its timeout. This test uses an |
| // IoHandle that never completes sends. |
| function testDisableSendTimeout() { |
| var connected = connect({sendTimeout: 5}); |
| var sent = connected.then(sendData); |
| Promise.all([ |
| sent.then(expectSendResult(0, 'timeout')), |
| sent.then(expectCurrentTime(5)), |
| connected.then(update({sendTimeout: 0})) |
| .then(expectSuccess) |
| .then(timeoutManager.run.bind(timeoutManager, 1)), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that data received while the connection is paused is queued and |
| // dispatched once the connection is unpaused. |
| function testPausedReceive() { |
| Promise.all([ |
| // Wait until the receive hook is installed, then start the test. |
| addReceiveHook(function() { |
| // Unpause the connection after the connection has queued the received |
| // data to ensure the queued data is dispatched when the connection is |
| // unpaused. |
| Promise.all([ |
| utils.promise(serial.setPaused, connectionId, false), |
| // Check that setPaused(false) is idempotent. |
| utils.promise(serial.setPaused, connectionId, false), |
| ]).catch(test.fail); |
| }) |
| .then(connect) |
| .then(function() { |
| // Check that setPaused(true) is idempotent. |
| return Promise.all([ |
| utils.promise(serial.setPaused, connectionId, true), |
| utils.promise(serial.setPaused, connectionId, true), |
| ]); |
| }), |
| listenOnce(serial.onReceive).then(checkReceivedData), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a receive error received while the connection is paused is queued |
| // and dispatched once the connection is unpaused. |
| function testPausedReceiveError() { |
| Promise.all([ |
| // Wait until the receive hook is installed, then start the test. |
| addReceiveErrorHook(function() { |
| // Unpause the connection after the connection has queued the received |
| // data to ensure the queued data is dispatched when the connection is |
| // unpaused. |
| utils.promise(serial.setPaused, connectionId, false).catch(test.fail); |
| }) |
| .then(connect) |
| .then(setPaused(true)), |
| listenOnce(serial.onReceiveError) |
| .then(checkReceiveError('device_lost')), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| serial.onReceive.addListener(function() { |
| test.fail('unexpected onReceive event'); |
| }); |
| }, |
| |
| // Test that receive timeouts trigger after the timeout time elapses and that |
| // changing the receive timeout does not affect a wait in progress. |
| function testReceiveTimeout() { |
| var errorReceived = listenOnce(serial.onReceiveError); |
| Promise.all([ |
| errorReceived.then(checkReceiveError('timeout')), |
| errorReceived.then(expectCurrentTime(20)), |
| errorReceived |
| .then(getInfo) |
| .then(checkInfo({paused: false})), |
| connect({receiveTimeout: 20}) |
| // Changing the timeout does not take effect until the current |
| // timeout expires or a receive completes. |
| .then(update({receiveTimeout: 10})) |
| .then(expectSuccess) |
| .then(timeoutManager.run.bind(timeoutManager, 1)), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that receive timeouts still function correctly after a serialization |
| // round trip. |
| function testReceiveTimeoutAfterSerialization() { |
| var errorReceived = listenOnce(serial.onReceiveError); |
| Promise.all([ |
| errorReceived.then(checkReceiveError('timeout')), |
| errorReceived.then(expectCurrentTime(20)), |
| errorReceived |
| .then(getInfo) |
| .then(checkInfo({paused: false})), |
| connect({receiveTimeout: 20}) |
| .then(serializeRoundTrip) |
| .then(timeoutManager.run.bind(timeoutManager, 1)), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that receive timeouts trigger after the timeout time elapses and that |
| // disabling the receive timeout does not affect a wait in progress. |
| function testDisableReceiveTimeout() { |
| var errorReceived = listenOnce(serial.onReceiveError); |
| Promise.all([ |
| errorReceived.then(checkReceiveError('timeout')), |
| errorReceived.then(expectCurrentTime(20)), |
| errorReceived |
| .then(getInfo) |
| .then(checkInfo({paused: false})), |
| connect({receiveTimeout: 20}) |
| // Disabling the timeout does not take effect until the current |
| // timeout expires or a receive completes. |
| .then(update({receiveTimeout: 0})) |
| .then(expectSuccess) |
| .then(timeoutManager.run.bind(timeoutManager, 1)), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| // Test that a receive error from the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'disconnected' receive errors. |
| function testReceiveErrorDisconnected() { |
| runReceiveErrorTest('disconnected'); |
| }, |
| |
| // Test that a receive error from the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'device_lost' receive errors. |
| function testReceiveErrorDeviceLost() { |
| runReceiveErrorTest('device_lost'); |
| }, |
| |
| // Test that a receive from error the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'break' receive errors. |
| function testReceiveErrorBreak() { |
| runReceiveErrorTest('break'); |
| }, |
| |
| // Test that a receive from error the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'frame_error' receive errors. |
| function testReceiveErrorFrameError() { |
| runReceiveErrorTest('frame_error'); |
| }, |
| |
| // Test that a receive from error the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'overrun' receive errors. |
| function testReceiveErrorOverrun() { |
| runReceiveErrorTest('overrun'); |
| }, |
| |
| // Test that a receive from error the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'buffer_overflow' receive errors. |
| function testReceiveErrorBufferOverflow() { |
| runReceiveErrorTest('buffer_overflow'); |
| }, |
| |
| // Test that a receive from error the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'parity_error' receive errors. |
| function testReceiveErrorParityError() { |
| runReceiveErrorTest('parity_error'); |
| }, |
| |
| // Test that a receive from error the service is correctly dispatched. This |
| // test uses an IoHandler that only reports 'system_error' receive errors. |
| function testReceiveErrorSystemError() { |
| runReceiveErrorTest('system_error'); |
| }, |
| |
| // Test that a send error from the service is correctly returned as the send |
| // result. This test uses an IoHandler that only reports 'disconnected' send |
| // errors. |
| function testSendErrorDisconnected() { |
| runSendErrorTest('disconnected'); |
| }, |
| |
| // Test that a send error from the service is correctly returned as the send |
| // result. This test uses an IoHandler that only reports 'system_error' send |
| // errors. |
| function testSendErrorSystemError() { |
| runSendErrorTest('system_error'); |
| }, |
| |
| // Test that disconnect returns the correct error for a connection ID that |
| // does not exist. |
| function testDisconnectUnknownConnectionId() { |
| serial.disconnect(-1, test.callbackFail('Serial connection not found.')); |
| }, |
| |
| // Test that getInfo returns the correct error for a connection ID that does |
| // not exist. |
| function testGetInfoUnknownConnectionId() { |
| serial.getInfo(-1, test.callbackFail('Serial connection not found.')); |
| }, |
| |
| // Test that update returns the correct error for a connection ID that does |
| // not exist. |
| function testUpdateUnknownConnectionId() { |
| serial.update(-1, {}, test.callbackFail('Serial connection not found.')); |
| }, |
| |
| // Test that setControlSignals returns the correct error for a connection ID |
| // that does not exist. |
| function testSetControlSignalsUnknownConnectionId() { |
| serial.setControlSignals(-1, {}, test.callbackFail( |
| 'Serial connection not found.')); |
| }, |
| |
| // Test that getControlSignals returns the correct error for a connection ID |
| // that does not exist. |
| function testGetControlSignalsUnknownConnectionId() { |
| serial.getControlSignals(-1, test.callbackFail( |
| 'Serial connection not found.')); |
| }, |
| |
| // Test that flush returns the correct error for a connection ID that does not |
| // exist. |
| function testFlushUnknownConnectionId() { |
| serial.flush(-1, test.callbackFail('Serial connection not found.')); |
| }, |
| |
| // Test that setPaused returns the correct error for a connection ID that does |
| // not exist. |
| function testSetPausedUnknownConnectionId() { |
| serial.setPaused( |
| -1, true, test.callbackFail('Serial connection not found.')); |
| serial.setPaused( |
| -1, false, test.callbackFail('Serial connection not found.')); |
| }, |
| |
| // Test that send returns the correct error for a connection ID that does not |
| // exist. |
| function testSendUnknownConnectionId() { |
| var buffer = new ArrayBuffer(1); |
| serial.send(-1, buffer, test.callbackFail('Serial connection not found.')); |
| }, |
| |
| function testSendAndStash() { |
| connect() |
| .then(setPaused(true)) |
| .then(sendData) |
| .then(expectSendResult(4)) |
| .then(test.succeed, test.fail); |
| }, |
| |
| function testRestoreAndReceive() { |
| connectionId = 0; |
| Promise.all([ |
| utils.promise(serial.setPaused, connectionId, false), |
| listenOnce(serial.onReceive).then(checkReceivedData), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| function testRestoreAndReceiveErrorSetUp() { |
| connect().then(test.succeed, test.fail); |
| }, |
| |
| function testRestoreAndReceiveError() { |
| connectionId = 0; |
| Promise.all([ |
| utils.promise(serial.setPaused, connectionId, false), |
| listenOnce(serial.onReceiveError) |
| .then(checkReceiveError('device_lost')), |
| ]) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| function testStashNoConnections() { |
| connect({persistent: false}).then(test.succeed, test.fail); |
| }, |
| |
| function testRestoreNoConnections() { |
| connect() |
| .then(function(connectionInfo) { |
| test.assertEq(0, connectionInfo.connectionId); |
| return connectionInfo; |
| }) |
| .then(checkConnectionInfo) |
| .then(disconnect) |
| .then(test.succeed, test.fail); |
| }, |
| |
| ], test.runTests, exports); |