summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/serial/serialPort_writable.https.any.js
blob: 087c881500732155b3b96eaaaf64c4a2e21f8a05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
// META: script=/resources/test-only-api.js
// META: script=/serial/resources/common.js
// META: script=resources/automation.js

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);

  assert_equals(port.writable, null);

  await port.open({baudRate: 9600});
  const writable = port.writable;
  assert_true(writable instanceof WritableStream);

  await port.close();
  assert_equals(port.writable, null);

  const writer = writable.getWriter();
  const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
  await promise_rejects_dom(t, 'InvalidStateError', writer.write(data));
}, 'open() and close() set and unset SerialPort.writable');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);

  await port.open({baudRate: 9600});
  assert_true(port.writable instanceof WritableStream);

  const writer = port.writable.getWriter();
  await promise_rejects_js(t, TypeError, port.close());

  writer.releaseLock();
  await port.close();
  assert_equals(port.writable, null);
}, 'Port cannot be closed while writable is locked');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);

  await port.open({baudRate: 9600});
  assert_true(port.writable instanceof WritableStream);

  const writer = port.writable.getWriter();
  const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
  let writePromise = writer.write(data);
  writer.releaseLock();

  await fakePort.readable();
  let {value, done} = await fakePort.read();
  await writePromise;
  compareArrays(value, data);

  await port.close();
  assert_equals(port.writable, null);
}, 'Can write a small amount of data');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  // Select a buffer size smaller than the amount of data transferred.
  await port.open({baudRate: 9600, bufferSize: 64});

  const writer = port.writable.getWriter();
  const data = new Uint8Array(1024);  // Much larger than bufferSize above.
  for (let i = 0; i < data.byteLength; ++i)
    data[i] = i & 0xff;
  writer.write(data);
  writer.releaseLock();

  await fakePort.readable();
  const value = await fakePort.readWithLength(data.byteLength);
  compareArrays(data, value);

  await port.close();
}, 'Can write a large amount of data');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  await port.open({baudRate: 9600});

  const writable = port.writable;
  assert_true(writable instanceof WritableStream);
  let writer = writable.getWriter();

  await fakePort.readable();
  fakePort.simulateSystemErrorOnWrite();
  const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
  await promise_rejects_dom(t, 'UnknownError', writer.write(data));

  assert_true(port.writable instanceof WritableStream);
  assert_not_equals(port.writable, writable);

  writer = port.writable.getWriter();
  let writePromise = writer.write(data);
  writer.releaseLock();
  await fakePort.readable();
  let {value, done} = await fakePort.read();
  await writePromise;
  compareArrays(value, data);

  await port.close();
  assert_equals(port.writable, null);
}, 'System error closes writable and replaces it with a new stream');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  await port.open({baudRate: 9600});

  assert_true(port.writable instanceof WritableStream);
  const writer = port.writable.getWriter();

  await fakePort.readable();
  fakePort.simulateDisconnectOnWrite();
  const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
  await promise_rejects_dom(t, 'NetworkError', writer.write(data));
  assert_equals(port.writable, null);

  await port.close();
}, 'Disconnect error closes writable and sets it to null');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);

  await port.open({baudRate: 9600, bufferSize: 64});
  const originalWritable = port.writable;
  assert_true(originalWritable instanceof WritableStream);

  let writer = originalWritable.getWriter();
  let data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
  // The buffer size is large enough to allow this write to complete without
  // the data being read from the fake port.
  await writer.write(data);
  await writer.abort();

  assert_true(port.writable instanceof WritableStream);
  assert_true(port.writable !== originalWritable);
  writer = port.writable.getWriter();
  data = new Uint8Array([9, 10, 11, 12, 13, 14, 15, 16]);
  const writePromise = writer.write(data);
  writer.releaseLock();

  await fakePort.readable();
  const {value, done} = await fakePort.read();
  await writePromise;
  compareArrays(value, data);

  await port.close();
  assert_equals(port.writable, null);
}, 'abort() discards the write buffer');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  // Select a buffer size smaller than the amount of data transferred.
  await port.open({baudRate: 9600, bufferSize: 64});

  const writer = port.writable.getWriter();
  // Wait for microtasks to execute in order to ensure that the WritableStream
  // has been set up completely.
  await Promise.resolve();

  const data = new Uint8Array(1024);  // Much larger than bufferSize above.
  for (let i = 0; i < data.byteLength; ++i)
    data[i] = i & 0xff;
  const writePromise =
      promise_rejects_exactly(t, 'Aborting.', writer.write(data));

  await writer.abort('Aborting.');
  await writePromise;
  await port.close();
  assert_equals(port.writable, null);
}, 'abort() does not wait for the write buffer to be cleared');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  // Select a buffer size smaller than the amount of data transferred.
  await port.open({baudRate: 9600, bufferSize: 64});

  const writer = port.writable.getWriter();
  const data = new Uint8Array(1024);  // Much larger than bufferSize above.
  for (let i = 0; i < data.byteLength; ++i)
    data[i] = i & 0xff;
  const closed = (async () => {
    await promise_rejects_exactly(t, 'Aborting.', writer.write(data));
    writer.releaseLock();
    await port.close();
    assert_equals(port.writable, null);
  })();

  await writer.abort('Aborting.');
  await closed;
}, 'Can close while aborting');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  // Select a buffer size smaller than the amount of data transferred.
  await port.open({baudRate: 9600, bufferSize: 64});

  const writer = port.writable.getWriter();
  const data = new Uint8Array(1024);  // Much larger than bufferSize above.
  for (let i = 0; i < data.byteLength; ++i)
    data[i] = i & 0xff;
  writer.write(data);

  let readComplete = false;
  let writePromise = writer.close().then(() => {
    assert_true(readComplete);
  });

  await fakePort.readable();
  let readPromise = fakePort.readWithLength(data.byteLength).then(result => {
    readComplete = true;
    return result;
  });
  const value = await readPromise;
  compareArrays(data, value);
  await writePromise;

  await port.close();
}, 'close() waits for the write buffer to be cleared');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);
  // Select a buffer size smaller than the amount of data transferred.
  await port.open({baudRate: 9600, bufferSize: 64});

  const writer = port.writable.getWriter();
  // Wait for microtasks to execute in order to ensure that the WritableStream
  // has been set up completely.
  await Promise.resolve();

  const data = new Uint8Array(1024);  // Much larger than bufferSize above.
  for (let i = 0; i < data.byteLength; ++i)
    data[i] = i & 0xff;
  const writePromise =
      promise_rejects_exactly(t, 'Aborting.', writer.write(data));
  const closePromise = promise_rejects_exactly(t, 'Aborting.', writer.close());

  await writer.abort('Aborting.');
  await writePromise;
  await closePromise;
  await port.close();
  assert_equals(port.writable, null);
}, 'Can abort while closing');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);

  await port.open({baudRate: 9600});
  assert_true(port.writable instanceof WritableStream);

  const encoder = new TextEncoderStream();
  const streamClosed = encoder.readable.pipeTo(port.writable);
  const writer = encoder.writable.getWriter();
  const writePromise = writer.write('Hello world!');

  await fakePort.readable();
  const {value, done} = await fakePort.read();
  await writePromise;
  assert_equals('Hello world!', new TextDecoder().decode(value));
  await writer.close();
  await streamClosed;

  await port.close();
  assert_equals(port.writable, null);
}, 'Can pipe a stream to writable');

serial_test(async (t, fake) => {
  const {port, fakePort} = await getFakeSerialPort(fake);

  await port.open({baudRate: 9600});
  assert_true(port.writable instanceof WritableStream);

  const transform = new TransformStream();
  const readable = transform.readable.pipeThrough(new TextEncoderStream())
                       .pipeThrough(new TransformStream())
                       .pipeThrough(new TransformStream())
                       .pipeThrough(new TransformStream());
  const streamClosed = readable.pipeTo(port.writable);
  const writer = transform.writable.getWriter();
  const writePromise = writer.write('Hello world!');

  await fakePort.readable();
  const {value, done} = await fakePort.read();
  await writePromise;
  assert_equals('Hello world!', new TextDecoder().decode(value));
  await writer.close();
  await streamClosed;

  await port.close();
  assert_equals(port.writable, null);
}, 'Stream closure is observable through a long chain of transformers');