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_sender_unittest.cc
6
7var test = require('test').binding;
8var unittestBindings = require('test_environment_specific_bindings');
9
10var BUFFER_SIZE = 11;
11var FATAL_ERROR = 2;
12
13function generateData(size, pattern) {
14  if (!pattern)
15    pattern = 'a';
16  var buffer = new ArrayBuffer(size);
17  var intView = new Int8Array(buffer);
18  for (var i = 0; i < size; i++) {
19    intView[i] = pattern.charCodeAt(i % pattern.length);
20  }
21  return buffer;
22}
23
24// Returns a promise to a newly created DataSender.
25function createSender() {
26  return Promise.all([
27    requireAsync('content/public/renderer/service_provider'),
28    requireAsync('data_sender'),
29    requireAsync('device/serial/data_stream.mojom'),
30  ]).then(function(modules) {
31    var serviceProvider = modules[0];
32    var dataSender = modules[1];
33    var dataStream = modules[2];
34    return new dataSender.DataSender(
35        serviceProvider.connectToService(dataStream.DataSinkProxy.NAME_),
36        BUFFER_SIZE,
37        FATAL_ERROR);
38  });
39}
40
41// Returns a function that sends data to a provided DataSender |sender|,
42// checks that the send completes successfully and returns a promise that will
43// resolve to |sender|.
44function sendAndExpectSuccess(data) {
45  return function(sender) {
46    return sender.send(data).then(function(bytesSent) {
47      test.assertEq(data.byteLength, bytesSent);
48      return sender;
49    });
50  };
51}
52
53// Returns a function that sends data to a provided DataSender |sender|,
54// checks that the send fails with the expected error and expected number of
55// bytes sent, and returns a promise that will resolve to |sender|.
56function sendAndExpectError(data, expectedError, expectedBytesSent) {
57  return function(sender) {
58    return sender.send(data).catch(function(result) {
59      test.assertEq(expectedError, result.error);
60      test.assertEq(expectedBytesSent, result.bytesSent);
61      return sender;
62    });
63  };
64}
65
66// Returns a function that cancels sends on the provided DataSender |sender|
67// with error |cancelReason|, returning a promise that will resolve to |sender|
68// once the cancel completes.
69function cancelSend(cancelReason) {
70  return function(sender) {
71    return sender.cancel(cancelReason).then(function() {
72      return sender;
73    });
74  };
75}
76
77// Checks that attempting to start a send with |sender| fails.
78function sendAfterClose(sender) {
79  test.assertThrows(sender.send, sender, [], 'DataSender has been closed');
80}
81
82// Checks that the provided promises resolve in order, returning the result of
83// the first.
84function expectOrder(promises) {
85  var nextIndex = 0;
86  function createOrderChecker(promise, expectedIndex) {
87    return promise.then(function(sender) {
88      test.assertEq(nextIndex, expectedIndex);
89      nextIndex++;
90      return sender;
91    });
92  }
93  var wrappedPromises = [];
94  for (var i = 0; i < promises.length; i++) {
95    wrappedPromises.push(createOrderChecker(promises[i], i));
96  }
97  return Promise.all(wrappedPromises).then(function(results) {
98    return results[0];
99  });
100}
101
102// Serializes and deserializes the provided DataSender |sender|, returning a
103// promise that will resolve to the newly deserialized DataSender.
104function serializeRoundTrip(sender) {
105  return Promise.all([
106    sender.serialize(),
107    requireAsync('data_sender'),
108  ]).then(function(promises) {
109    var serialized = promises[0];
110    var dataSenderModule = promises[1];
111    return dataSenderModule.DataSender.deserialize(serialized);
112  });
113}
114
115function closeSender(sender) {
116  sender.close();
117  return sender;
118}
119
120unittestBindings.exportTests([
121  function testSend() {
122    var sender = createSender();
123    expectOrder([
124        sender.then(sendAndExpectSuccess(generateData(1))),
125        sender.then(sendAndExpectSuccess(generateData(1))),
126    ])
127        .then(closeSender)
128        .then(test.succeed, test.fail);
129  },
130
131  function testLargeSend() {
132    createSender()
133        .then(sendAndExpectSuccess(generateData(BUFFER_SIZE * 3, '123')))
134        .then(closeSender)
135        .then(test.succeed, test.fail);
136  },
137
138  function testSendError() {
139    createSender()
140        .then(sendAndExpectError(generateData(BUFFER_SIZE * 3, 'b'), 1, 0))
141        .then(sendAndExpectSuccess(generateData(1)))
142        .then(closeSender)
143        .then(test.succeed, test.fail);
144  },
145
146  function testSendErrorPartialSuccess() {
147    createSender()
148        .then(sendAndExpectError(generateData(BUFFER_SIZE * 3, 'b'), 1, 5))
149        .then(sendAndExpectSuccess(generateData(1)))
150        .then(closeSender)
151        .then(test.succeed, test.fail);
152  },
153
154  function testSendErrorBetweenPackets() {
155    var sender = createSender();
156    expectOrder([
157        sender.then(sendAndExpectError(generateData(2, 'b'), 1, 2)),
158        sender.then(sendAndExpectError(generateData(2, 'b'), 1, 0)),
159    ])
160        .then(sendAndExpectSuccess(generateData(1)))
161        .then(closeSender)
162        .then(test.succeed, test.fail);
163  },
164
165  function testSendErrorInSecondPacket() {
166    var sender = createSender();
167    expectOrder([
168        sender.then(sendAndExpectSuccess(generateData(2, 'b'))),
169        sender.then(sendAndExpectError(generateData(2, 'b'), 1, 1)),
170    ])
171        .then(sendAndExpectSuccess(generateData(1)))
172        .then(closeSender)
173        .then(test.succeed, test.fail);
174  },
175
176  function testSendErrorInLargeSend() {
177    createSender()
178        .then(sendAndExpectError(
179            generateData(BUFFER_SIZE * 3, '1234567890'), 1, 12))
180        .then(sendAndExpectSuccess(generateData(1)))
181        .then(closeSender)
182        .then(test.succeed, test.fail);
183  },
184
185  function testSendErrorBeforeLargeSend() {
186    var sender = createSender();
187    expectOrder([
188        sender.then(sendAndExpectError(generateData(5, 'b'), 1, 2)),
189        sender.then(sendAndExpectError(
190            generateData(BUFFER_SIZE * 3, '1234567890'), 1, 0)),
191    ])
192        .then(sendAndExpectSuccess(generateData(1)))
193        .then(closeSender)
194        .then(test.succeed, test.fail);
195  },
196
197  function testCancelWithoutSend() {
198    createSender()
199        .then(cancelSend(3))
200        .then(closeSender)
201        .then(test.succeed, test.fail);
202  },
203
204  function testCancel() {
205    var sender = createSender();
206    expectOrder([
207        sender.then(sendAndExpectError(generateData(1, 'b'), 3, 0)),
208        sender.then(cancelSend(3)),
209    ])
210        .then(closeSender)
211        .then(test.succeed, test.fail);
212    sender.then(function(sender) {
213      test.assertThrows(
214          sender.cancel, sender, [], 'Cancel already in progress');
215      test.assertThrows(sender.send, sender, [], 'Cancel in progress');
216    });
217  },
218
219  function testClose() {
220    var sender = createSender();
221    expectOrder([
222        sender.then(sendAndExpectError(generateData(1, 'b'), FATAL_ERROR, 0)),
223        sender.then(cancelSend(3)),
224    ]);
225    sender
226        .then(closeSender)
227        .then(sendAfterClose)
228        .then(test.succeed, test.fail);
229  },
230
231  function testSendAfterSerialization() {
232    var sender = createSender().then(serializeRoundTrip);
233    expectOrder([
234        sender.then(sendAndExpectSuccess(generateData(1))),
235        sender.then(sendAndExpectSuccess(generateData(1))),
236    ])
237        .then(closeSender)
238        .then(test.succeed, test.fail);
239  },
240
241  function testSendErrorAfterSerialization() {
242    createSender()
243        .then(serializeRoundTrip)
244        .then(sendAndExpectError(generateData(BUFFER_SIZE * 3, 'b'), 1, 0))
245        .then(sendAndExpectSuccess(generateData(1)))
246        .then(closeSender)
247        .then(test.succeed, test.fail);
248  },
249
250
251  function testCancelAfterSerialization() {
252    var sender = createSender().then(serializeRoundTrip);
253    expectOrder([
254        sender.then(sendAndExpectError(generateData(1, 'b'), 4, 0)),
255        sender.then(cancelSend(4)),
256    ])
257        .then(closeSender)
258        .then(test.succeed, test.fail);
259  },
260
261  function testSerializeCancelsSendsInProgress() {
262    var sender = createSender();
263    expectOrder([
264        sender.then(sendAndExpectError(generateData(1, 'b'), FATAL_ERROR, 0)),
265        sender.then(sendAndExpectError(generateData(1, 'b'), FATAL_ERROR, 0)),
266        sender.then(serializeRoundTrip),
267    ])
268        .then(closeSender)
269        .then(test.succeed, test.fail);
270  },
271
272  function testSerializeWaitsForCancel() {
273    var sender = createSender();
274    expectOrder([
275        sender.then(sendAndExpectError(generateData(1, 'b'), 3, 0)),
276        sender.then(cancelSend(3)),
277        sender.then(serializeRoundTrip),
278    ])
279        .then(closeSender)
280        .then(test.succeed, test.fail);
281  },
282
283  function testSerializeAfterClose() {
284    createSender()
285        .then(closeSender)
286        .then(serializeRoundTrip)
287        .then(sendAfterClose)
288        .then(test.succeed, test.fail);
289  },
290
291], test.runTests, exports);
292