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
3// found in the LICENSE file.
4
5// Tests launched by extensions/renderer/api/serial/data_receiver_unittest.cc
6
7var test = require('test').binding;
8var unittestBindings = require('test_environment_specific_bindings');
9
10var BUFFER_SIZE = 10;
11var FATAL_ERROR = 2;
12
13// Returns a promise to a newly created DataReceiver.
14function createReceiver() {
15  return Promise.all([
16    requireAsync('content/public/renderer/service_provider'),
17    requireAsync('data_receiver'),
18    requireAsync('device/serial/data_stream.mojom'),
19  ]).then(function(modules) {
20    var serviceProvider = modules[0];
21    var dataReceiver = modules[1];
22    var dataStream = modules[2];
23    return new dataReceiver.DataReceiver(
24        serviceProvider.connectToService(dataStream.DataSourceProxy.NAME_),
25        BUFFER_SIZE,
26        FATAL_ERROR);
27  });
28}
29
30// Returns a promise that will resolve to |receiver| when it has received an
31// error from its DataSource.
32function waitForReceiveError(receiver) {
33  return new Promise(function(resolve, reject) {
34    var onError = receiver.onError;
35    receiver.onError = function() {
36      $Function.apply(onError, receiver, arguments);
37      resolve(receiver);
38    };
39  });
40}
41
42// Returns a function that receives data from a provided DataReceiver
43// |receiver|, checks that it matches the expected data and returns a promise
44// that will resolve to |receiver|.
45function receiveAndCheckData(expectedData) {
46  return function(receiver) {
47    return receiver.receive().then(function(data) {
48      test.assertEq(expectedData.length, data.byteLength);
49      for (var i = 0; i < expectedData.length; i++)
50        test.assertEq(expectedData.charCodeAt(i), new Int8Array(data)[i]);
51      return receiver;
52    });
53    test.assertThrows(
54        receiver.receive, receiver, [], 'Receive already in progress.');
55  };
56}
57
58// Returns a function that attempts to receive data from a provided DataReceiver
59// |receiver|, checks that the correct error is reported and returns a promise
60// that will resolve to |receiver|.
61function receiveAndCheckError(expectedError) {
62  return function(receiver) {
63    return receiver.receive().catch(function(error) {
64      test.assertEq(expectedError, error.error);
65      return receiver;
66    });
67    test.assertThrows(
68        receiver.receive, receiver, [], 'Receive already in progress.');
69  };
70}
71
72// Serializes and deserializes the provided DataReceiver |receiver|, returning
73// a promise that will resolve to the newly deserialized DataReceiver.
74function serializeRoundTrip(receiver) {
75  return Promise.all([
76    receiver.serialize(),
77    requireAsync('data_receiver'),
78  ]).then(function(promises) {
79    var serialized = promises[0];
80    var dataReceiverModule = promises[1];
81    return dataReceiverModule.DataReceiver.deserialize(serialized);
82  });
83}
84
85// Closes and returns the provided DataReceiver |receiver|.
86function closeReceiver(receiver) {
87  receiver.close();
88  return receiver;
89}
90
91unittestBindings.exportTests([
92  function testReceive() {
93    createReceiver()
94        .then(receiveAndCheckData('a'))
95        .then(closeReceiver)
96        .then(test.succeed, test.fail);
97  },
98
99  function testReceiveError() {
100    createReceiver()
101        .then(receiveAndCheckError(1))
102        .then(closeReceiver)
103        .then(test.succeed, test.fail);
104  },
105
106  function testReceiveDataAndError() {
107    createReceiver()
108        .then(receiveAndCheckData('a'))
109        .then(receiveAndCheckError(1))
110        .then(receiveAndCheckData('b'))
111        .then(closeReceiver)
112        .then(test.succeed, test.fail);
113  },
114
115  function testReceiveErrorThenData() {
116    createReceiver()
117        .then(receiveAndCheckError(1))
118        .then(receiveAndCheckData('a'))
119        .then(closeReceiver)
120        .then(test.succeed, test.fail);
121  },
122
123  function testReceiveBeforeAndAfterSerialization() {
124    createReceiver()
125        .then(receiveAndCheckData('a'))
126        .then(serializeRoundTrip)
127        .then(receiveAndCheckData('b'))
128        .then(closeReceiver)
129        .then(test.succeed, test.fail);
130  },
131
132  function testReceiveErrorSerialization() {
133    createReceiver()
134        .then(waitForReceiveError)
135        .then(serializeRoundTrip)
136        .then(receiveAndCheckError(1))
137        .then(receiveAndCheckError(3))
138        .then(closeReceiver)
139        .then(test.succeed, test.fail);
140  },
141
142  function testReceiveDataAndErrorSerialization() {
143    createReceiver()
144        .then(waitForReceiveError)
145        .then(receiveAndCheckData('a'))
146        .then(serializeRoundTrip)
147        .then(receiveAndCheckError(1))
148        .then(receiveAndCheckData('b'))
149        .then(receiveAndCheckError(3))
150        .then(closeReceiver)
151        .then(test.succeed, test.fail);
152  },
153
154  function testSerializeDuringReceive() {
155    var receiver = createReceiver();
156    Promise.all([
157        receiver.then(receiveAndCheckError(FATAL_ERROR)),
158        receiver
159            .then(serializeRoundTrip)
160            .then(receiveAndCheckData('a'))
161            .then(closeReceiver)
162    ]).then(test.succeed, test.fail);
163  },
164
165  function testSerializeAfterClose() {
166    function receiveAfterClose(receiver) {
167      test.assertThrows(
168          receiver.receive, receiver, [], 'DataReceiver has been closed');
169    }
170
171    createReceiver()
172        .then(closeReceiver)
173        .then(serializeRoundTrip)
174        .then(receiveAfterClose)
175        .then(test.succeed, test.fail);
176  },
177
178  function testSourceShutdown() {
179    createReceiver()
180        .then(receiveAndCheckError(FATAL_ERROR))
181        .then(closeReceiver)
182        .then(test.succeed, test.fail);
183  },
184
185], test.runTests, exports);
186