// 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. // Tests launched by extensions/renderer/api/serial/data_sender_unittest.cc var test = require('test').binding; var unittestBindings = require('test_environment_specific_bindings'); var BUFFER_SIZE = 11; var FATAL_ERROR = 2; function generateData(size, pattern) { if (!pattern) pattern = 'a'; var buffer = new ArrayBuffer(size); var intView = new Int8Array(buffer); for (var i = 0; i < size; i++) { intView[i] = pattern.charCodeAt(i % pattern.length); } return buffer; } // Returns a promise to a newly created DataSender. function createSender() { return Promise.all([ requireAsync('content/public/renderer/frame_service_registry'), requireAsync('data_sender'), requireAsync('device/serial/data_stream.mojom'), ]).then(function(modules) { var serviceProvider = modules[0]; var dataSender = modules[1]; var dataStream = modules[2]; return new dataSender.DataSender( serviceProvider.connectToService(dataStream.DataSink.name), BUFFER_SIZE, FATAL_ERROR); }); } // Returns a function that sends data to a provided DataSender |sender|, // checks that the send completes successfully and returns a promise that will // resolve to |sender|. function sendAndExpectSuccess(data) { return function(sender) { return sender.send(data).then(function(bytesSent) { test.assertEq(data.byteLength, bytesSent); return sender; }); }; } // Returns a function that sends data to a provided DataSender |sender|, // checks that the send fails with the expected error and expected number of // bytes sent, and returns a promise that will resolve to |sender|. function sendAndExpectError(data, expectedError, expectedBytesSent) { return function(sender) { return sender.send(data).catch(function(result) { test.assertEq(expectedError, result.error); test.assertEq(expectedBytesSent, result.bytesSent); return sender; }); }; } // Returns a function that cancels sends on the provided DataSender |sender| // with error |cancelReason|, returning a promise that will resolve to |sender| // once the cancel completes. function cancelSend(cancelReason) { return function(sender) { return sender.cancel(cancelReason).then(function() { return sender; }); }; } // Checks that attempting to start a send with |sender| fails. function sendAfterClose(sender) { test.assertThrows(sender.send, sender, [], 'DataSender has been closed'); } // Checks that the provided promises resolve in order, returning the result of // the first. function expectOrder(promises) { var nextIndex = 0; function createOrderChecker(promise, expectedIndex) { return promise.then(function(sender) { test.assertEq(nextIndex, expectedIndex); nextIndex++; return sender; }); } var wrappedPromises = []; for (var i = 0; i < promises.length; i++) { wrappedPromises.push(createOrderChecker(promises[i], i)); } return Promise.all(wrappedPromises).then(function(results) { return results[0]; }); } // Serializes and deserializes the provided DataSender |sender|, returning a // promise that will resolve to the newly deserialized DataSender. function serializeRoundTrip(sender) { return Promise.all([ sender.serialize(), requireAsync('data_sender'), ]).then(function(promises) { var serialized = promises[0]; var dataSenderModule = promises[1]; return dataSenderModule.DataSender.deserialize(serialized); }); } function closeSender(sender) { sender.close(); return sender; } unittestBindings.exportTests([ function testSend() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectSuccess(generateData(1))), sender.then(sendAndExpectSuccess(generateData(1))), ]) .then(closeSender) .then(test.succeed, test.fail); }, function testLargeSend() { createSender() .then(sendAndExpectSuccess(generateData(BUFFER_SIZE * 3, '123'))) .then(closeSender) .then(test.succeed, test.fail); }, function testSendError() { createSender() .then(sendAndExpectError(generateData(BUFFER_SIZE * 3, 'b'), 1, 0)) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testSendErrorPartialSuccess() { createSender() .then(sendAndExpectError(generateData(BUFFER_SIZE * 3, 'b'), 1, 5)) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testSendErrorBetweenPackets() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectError(generateData(2, 'b'), 1, 2)), sender.then(sendAndExpectError(generateData(2, 'b'), 1, 0)), ]) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testSendErrorInSecondPacket() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectSuccess(generateData(2, 'b'))), sender.then(sendAndExpectError(generateData(2, 'b'), 1, 1)), ]) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testSendErrorInLargeSend() { createSender() .then(sendAndExpectError( generateData(BUFFER_SIZE * 3, '1234567890'), 1, 12)) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testSendErrorBeforeLargeSend() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectError(generateData(5, 'b'), 1, 2)), sender.then(sendAndExpectError( generateData(BUFFER_SIZE * 3, '1234567890'), 1, 0)), ]) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testCancelWithoutSend() { createSender() .then(cancelSend(3)) .then(closeSender) .then(test.succeed, test.fail); }, function testCancel() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectError(generateData(1, 'b'), 3, 0)), sender.then(cancelSend(3)), ]) .then(closeSender) .then(test.succeed, test.fail); sender.then(function(sender) { test.assertThrows( sender.cancel, sender, [], 'Cancel already in progress'); test.assertThrows(sender.send, sender, [], 'Cancel in progress'); }); }, function testClose() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectError(generateData(1, 'b'), FATAL_ERROR, 0)), sender.then(cancelSend(3)), ]); sender .then(closeSender) .then(sendAfterClose) .then(test.succeed, test.fail); }, function testSendAfterSerialization() { var sender = createSender().then(serializeRoundTrip); expectOrder([ sender.then(sendAndExpectSuccess(generateData(1))), sender.then(sendAndExpectSuccess(generateData(1))), ]) .then(closeSender) .then(test.succeed, test.fail); }, function testSendErrorAfterSerialization() { createSender() .then(serializeRoundTrip) .then(sendAndExpectError(generateData(BUFFER_SIZE * 3, 'b'), 1, 0)) .then(sendAndExpectSuccess(generateData(1))) .then(closeSender) .then(test.succeed, test.fail); }, function testCancelAfterSerialization() { var sender = createSender().then(serializeRoundTrip); expectOrder([ sender.then(sendAndExpectError(generateData(1, 'b'), 4, 0)), sender.then(cancelSend(4)), ]) .then(closeSender) .then(test.succeed, test.fail); }, function testSerializeCancelsSendsInProgress() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectError(generateData(1, 'b'), FATAL_ERROR, 0)), sender.then(sendAndExpectError(generateData(1, 'b'), FATAL_ERROR, 0)), sender.then(serializeRoundTrip), ]) .then(closeSender) .then(test.succeed, test.fail); }, function testSerializeWaitsForCancel() { var sender = createSender(); expectOrder([ sender.then(sendAndExpectError(generateData(1, 'b'), 3, 0)), sender.then(cancelSend(3)), sender.then(serializeRoundTrip), ]) .then(closeSender) .then(test.succeed, test.fail); }, function testSerializeAfterClose() { createSender() .then(closeSender) .then(serializeRoundTrip) .then(sendAfterClose) .then(test.succeed, test.fail); }, ], test.runTests, exports);