Bug 1539614 [wpt PR 16077] - HTML: move textarea tests together, a=testonly
[gecko.git] / testing / web-platform / tests / webusb / usbDevice.https.any.js
blobd043771df4a601b9a409c5b8c02f4bbb00feb823
1 // META: timeout=long
2 // META: script=/webusb/resources/fake-devices.js
3 // META: script=/webusb/resources/usb-helpers.js
4 'use strict';
6 function assertRejectsWithNotFoundError(promise) {
7   return assertRejectsWithError(promise, 'NotFoundError');
10 function assertRejectsWithTypeError(promise) {
11   return assertRejectsWithError(promise, 'TypeError');
14 function assertRejectsWithNotOpenError(promise) {
15   return assertRejectsWithError(
16       promise, 'InvalidStateError', 'The device must be opened first.');
19 function assertRejectsWithNotConfiguredError(promise) {
20   return assertRejectsWithError(
21       promise, 'InvalidStateError',
22       'The device must have a configuration selected.');
25 function assertRejectsWithDeviceStateChangeInProgressError(promise) {
26   return assertRejectsWithError(
27     promise, 'InvalidStateError',
28     'An operation that changes the device state is in progress.');
31 function assertRejectsWithInterfaceStateChangeInProgressError(promise) {
32   return assertRejectsWithError(
33     promise, 'InvalidStateError',
34     'An operation that changes interface state is in progress.');
37 usb_test(() => {
38   return getFakeDevice().then(({ device, fakeDevice }) => {
39     return waitForDisconnect(fakeDevice)
40       .then(() => assertRejectsWithNotFoundError(device.open()));
41   });
42 }, 'open rejects when called on a disconnected device');
44 usb_test(() => {
45   return getFakeDevice().then(({ device, fakeDevice }) => {
46     return device.open()
47       .then(() => waitForDisconnect(fakeDevice))
48       .then(() => {
49         assert_false(device.opened);
50       });
51   });
52 }, 'disconnection closes the device');
54 usb_test(() => {
55   return getFakeDevice().then(({ device }) => {
56     assert_false(device.opened);
57     return device.open().then(() => {
58       assert_true(device.opened);
59       return device.close().then(() => {
60         assert_false(device.opened);
61       });
62     });
63   });
64 }, 'a device can be opened and closed');
66 usb_test(() => {
67   return getFakeDevice().then(({ device }) => {
68     return device.open()
69       .then(() => device.open())
70       .then(() => device.open())
71       .then(() => device.open())
72       .then(() => device.close())
73       .then(() => device.close())
74       .then(() => device.close())
75       .then(() => device.close());
76   });
77 }, 'open and close can be called multiple times');
79 usb_test(async () => {
80   let { device } = await getFakeDevice();
81   await Promise.all([
82     device.open(),
83     assertRejectsWithDeviceStateChangeInProgressError(device.open()),
84     assertRejectsWithDeviceStateChangeInProgressError(device.close()),
85   ]);
86   await Promise.all([
87     device.close(),
88     assertRejectsWithDeviceStateChangeInProgressError(device.open()),
89     assertRejectsWithDeviceStateChangeInProgressError(device.close()),
90   ]);
91 }, 'open and close cannot be called again while open or close are in progress');
93 usb_test(async () => {
94   let { device } = await getFakeDevice();
95   await device.open();
96   return Promise.all([
97     device.selectConfiguration(1),
98     assertRejectsWithDeviceStateChangeInProgressError(
99         device.claimInterface(0)),
100     assertRejectsWithDeviceStateChangeInProgressError(
101         device.releaseInterface(0)),
102     assertRejectsWithDeviceStateChangeInProgressError(device.open()),
103     assertRejectsWithDeviceStateChangeInProgressError(
104         device.selectConfiguration(1)),
105     assertRejectsWithDeviceStateChangeInProgressError(device.reset()),
106     assertRejectsWithDeviceStateChangeInProgressError(
107         device.selectAlternateInterface(0, 0)),
108     assertRejectsWithDeviceStateChangeInProgressError(
109         device.controlTransferOut({
110           requestType: 'standard',
111           recipient: 'interface',
112           request: 0x42,
113           value: 0x1234,
114           index: 0x0000,
115         })),
116     assertRejectsWithDeviceStateChangeInProgressError(
117         device.controlTransferOut({
118           requestType: 'standard',
119           recipient: 'interface',
120           request: 0x42,
121           value: 0x1234,
122           index: 0x0000,
123         }, new Uint8Array([1, 2, 3]))),
124     assertRejectsWithDeviceStateChangeInProgressError(
125         device.controlTransferIn({
126           requestType: 'standard',
127           recipient: 'interface',
128           request: 0x42,
129           value: 0x1234,
130           index: 0x0000
131         }, 0)),
132     assertRejectsWithDeviceStateChangeInProgressError(device.close()),
133   ]);
134 }, 'device operations reject if an device state change is in progress');
136 usb_test(() => {
137   return getFakeDevice().then(({ device, fakeDevice }) => {
138     return device.open()
139       .then(() => waitForDisconnect(fakeDevice))
140       .then(() => assertRejectsWithNotFoundError(device.close()));
141   });
142 }, 'close rejects when called on a disconnected device');
144 usb_test(() => {
145   return getFakeDevice().then(({ device, fakeDevice }) => {
146     return device.open()
147       .then(() => waitForDisconnect(fakeDevice))
148       .then(() => assertRejectsWithNotFoundError(device.selectConfiguration(1)));
149   });
150 }, 'selectConfiguration rejects when called on a disconnected device');
152 usb_test(() => {
153   return getFakeDevice().then(({ device }) => Promise.all([
154       assertRejectsWithNotOpenError(device.selectConfiguration(1)),
155       assertRejectsWithNotOpenError(device.claimInterface(0)),
156       assertRejectsWithNotOpenError(device.releaseInterface(0)),
157       assertRejectsWithNotOpenError(device.selectAlternateInterface(0, 1)),
158       assertRejectsWithNotOpenError(device.controlTransferIn({
159           requestType: 'vendor',
160           recipient: 'device',
161           request: 0x42,
162           value: 0x1234,
163           index: 0x5678
164       }, 7)),
165       assertRejectsWithNotOpenError(device.controlTransferOut({
166           requestType: 'vendor',
167           recipient: 'device',
168           request: 0x42,
169           value: 0x1234,
170           index: 0x5678
171       }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]))),
172       assertRejectsWithNotOpenError(device.clearHalt('in', 1)),
173       assertRejectsWithNotOpenError(device.transferIn(1, 8)),
174       assertRejectsWithNotOpenError(
175           device.transferOut(1, new ArrayBuffer(8))),
176       assertRejectsWithNotOpenError(device.isochronousTransferIn(1, [8])),
177       assertRejectsWithNotOpenError(
178           device.isochronousTransferOut(1, new ArrayBuffer(8), [8])),
179       assertRejectsWithNotOpenError(device.reset())
180   ]));
181 }, 'methods requiring it reject when the device is not open');
183 usb_test(() => {
184   return getFakeDevice().then(({ device }) => {
185     assert_equals(device.configuration, null);
186     return device.open()
187       .then(() => {
188         assert_equals(device.configuration, null);
189         return device.selectConfiguration(1);
190       })
191       .then(() => {
192         assertDeviceInfoEquals(
193             device.configuration, fakeDeviceInit.configurations[0]);
194       })
195       .then(() => device.close());
196   });
197 }, 'device configuration can be set and queried');
199 usb_test(async () => {
200   let { device } = await getFakeDevice();
201   assert_equals(device.configuration, null);
202   await device.open();
203   assert_equals(device.configuration, null);
204   await device.selectConfiguration(1);
205   await device.selectConfiguration(1);
206   assertDeviceInfoEquals(
207       device.configuration, fakeDeviceInit.configurations[0]);
208   await device.selectConfiguration(2);
209   assertDeviceInfoEquals(
210       device.configuration, fakeDeviceInit.configurations[1]);
211   await device.close();
212 }, 'a device configuration value can be set again');
214 usb_test(() => {
215   return getFakeDevice().then(({ device }) => {
216     assert_equals(device.configuration, null);
217     return device.open()
218       .then(() => assertRejectsWithError(
219             device.selectConfiguration(3), 'NotFoundError',
220             'The configuration value provided is not supported by the device.'))
221       .then(() => device.close());
222   });
223 }, 'selectConfiguration rejects on invalid configurations');
225 usb_test(() => {
226   return getFakeDevice().then(({ device }) => {
227     assert_equals(device.configuration, null);
228     return device.open().then(() => Promise.all([
229         assertRejectsWithNotConfiguredError(device.claimInterface(0)),
230         assertRejectsWithNotConfiguredError(device.releaseInterface(0)),
231         assertRejectsWithNotConfiguredError(device.selectAlternateInterface(0, 1)),
232         assertRejectsWithNotConfiguredError(device.controlTransferIn({
233             requestType: 'vendor',
234             recipient: 'device',
235             request: 0x42,
236             value: 0x1234,
237             index: 0x5678
238         }, 7)),
239         assertRejectsWithNotConfiguredError(device.controlTransferOut({
240             requestType: 'vendor',
241             recipient: 'device',
242             request: 0x42,
243             value: 0x1234,
244             index: 0x5678
245         }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]))),
246         assertRejectsWithNotConfiguredError(device.clearHalt('in', 1)),
247         assertRejectsWithNotConfiguredError(device.transferIn(1, 8)),
248         assertRejectsWithNotConfiguredError(
249             device.transferOut(1, new ArrayBuffer(8))),
250         assertRejectsWithNotConfiguredError(
251             device.isochronousTransferIn(1, [8])),
252         assertRejectsWithNotConfiguredError(
253             device.isochronousTransferOut(1, new ArrayBuffer(8), [8])),
254     ])).then(() => device.close());
255   });
256 }, 'methods requiring it reject when the device is unconfigured');
258 usb_test(() => {
259   return getFakeDevice().then(({ device }) => {
260     return device.open()
261       .then(() => device.selectConfiguration(1))
262       .then(() => device.claimInterface(0))
263       .then(() => {
264         assert_true(device.configuration.interfaces[0].claimed);
265         return device.releaseInterface(0);
266       })
267       .then(() => {
268         assert_false(device.configuration.interfaces[0].claimed);
269         return device.close();
270       });
271   });
272 }, 'an interface can be claimed and released');
274 usb_test(async () => {
275   let { device } = await getFakeDevice()
276   await device.open();
277   await device.selectConfiguration(1);
278   await device.claimInterface(0);
279   assert_true(device.configuration.interfaces[0].claimed);
280   await device.claimInterface(0);
281   assert_true(device.configuration.interfaces[0].claimed);
282   await device.close();
283 }, 'an interface can be claimed multiple times');
285 usb_test(async () => {
286   let { device } = await getFakeDevice();
287   await device.open();
288   await device.selectConfiguration(1);
289   await device.claimInterface(0);
290   assert_true(device.configuration.interfaces[0].claimed);
291   await device.releaseInterface(0);
292   assert_false(device.configuration.interfaces[0].claimed);
293   await device.releaseInterface(0);
294   assert_false(device.configuration.interfaces[0].claimed);
295   await device.close();
296 }, 'an interface can be released multiple times');
298 usb_test(async () => {
299   let { device } = await getFakeDevice();
300   await device.open();
301   await device.selectConfiguration(1);
302   return Promise.all([
303     device.claimInterface(0),
304     assertRejectsWithInterfaceStateChangeInProgressError(
305         device.claimInterface(0)),
306     assertRejectsWithInterfaceStateChangeInProgressError(
307         device.releaseInterface(0)),
308     assertRejectsWithInterfaceStateChangeInProgressError(device.open()),
309     assertRejectsWithInterfaceStateChangeInProgressError(
310         device.selectConfiguration(1)),
311     assertRejectsWithInterfaceStateChangeInProgressError(device.reset()),
312     assertRejectsWithInterfaceStateChangeInProgressError(
313         device.selectAlternateInterface(0, 0)),
314     assertRejectsWithInterfaceStateChangeInProgressError(
315         device.controlTransferOut({
316           requestType: 'standard',
317           recipient: 'interface',
318           request: 0x42,
319           value: 0x1234,
320           index: 0x0000,
321         })),
322     assertRejectsWithInterfaceStateChangeInProgressError(
323         device.controlTransferOut({
324           requestType: 'standard',
325           recipient: 'interface',
326           request: 0x42,
327           value: 0x1234,
328           index: 0x0000,
329         }, new Uint8Array([1, 2, 3]))),
330     assertRejectsWithInterfaceStateChangeInProgressError(
331         device.controlTransferIn({
332           requestType: 'standard',
333           recipient: 'interface',
334           request: 0x42,
335           value: 0x1234,
336           index: 0x0000
337         }, 0)),
338     assertRejectsWithInterfaceStateChangeInProgressError(device.close()),
339   ]);
340 }, 'device operations reject if an interface state change is in progress');
342 usb_test(async () => {
343   let { device } = await getFakeDevice();
344   await device.open();
345   await device.selectConfiguration(1);
346   await device.claimInterface(0);
347   assert_true(device.configuration.interfaces[0].claimed);
348   await device.close(0);
349   assert_false(device.configuration.interfaces[0].claimed);
350 }, 'interfaces are released on close');
352 usb_test(() => {
353   return getFakeDevice().then(({ device }) => {
354     const message = 'The interface number provided is not supported by the ' +
355                     'device in its current configuration.';
356     return device.open()
357       .then(() => device.selectConfiguration(1))
358       .then(() => Promise.all([
359           assertRejectsWithError(
360               device.claimInterface(2), 'NotFoundError', message),
361           assertRejectsWithError(
362               device.releaseInterface(2), 'NotFoundError', message),
363       ]))
364       .then(() => device.close());
365   });
366 }, 'a non-existent interface cannot be claimed or released');
368 usb_test(() => {
369   return getFakeDevice().then(({ device, fakeDevice }) => {
370     return device.open()
371       .then(() => device.selectConfiguration(1))
372       .then(() => waitForDisconnect(fakeDevice))
373       .then(() => assertRejectsWithNotFoundError(device.claimInterface(0)));
374   });
375 }, 'claimInterface rejects when called on a disconnected device');
377 usb_test(() => {
378   return getFakeDevice().then(({ device, fakeDevice }) => {
379     return device.open()
380       .then(() => device.selectConfiguration(1))
381       .then(() => device.claimInterface(0))
382       .then(() => waitForDisconnect(fakeDevice))
383       .then(() => assertRejectsWithNotFoundError(device.releaseInterface(0)));
384   });
385 }, 'releaseInterface rejects when called on a disconnected device');
387 usb_test(() => {
388   return getFakeDevice().then(({ device }) => {
389     return device.open()
390       .then(() => device.selectConfiguration(2))
391       .then(() => device.claimInterface(0))
392       .then(() => device.selectAlternateInterface(0, 1))
393       .then(() => device.close());
394   });
395 }, 'can select an alternate interface');
397 usb_test(() => {
398   return getFakeDevice().then(({ device }) => {
399     return device.open()
400       .then(() => device.selectConfiguration(2))
401       .then(() => device.claimInterface(0))
402       .then(() => assertRejectsWithError(
403           device.selectAlternateInterface(0, 2), 'NotFoundError',
404           'The alternate setting provided is not supported by the device in ' +
405           'its current configuration.'))
406       .then(() => device.close());
407   });
408 }, 'cannot select a non-existent alternate interface');
410 usb_test(() => {
411   return getFakeDevice().then(({ device, fakeDevice }) => {
412     return device.open()
413       .then(() => device.selectConfiguration(2))
414       .then(() => device.claimInterface(0))
415       .then(() => waitForDisconnect(fakeDevice))
416       .then(() => assertRejectsWithNotFoundError(device.selectAlternateInterface(0, 1)));
417   });
418 }, 'selectAlternateInterface rejects when called on a disconnected device');
420 usb_test(async () => {
421   let { device } = await getFakeDevice();
422   let usbRequestTypes = ['standard', 'class', 'vendor'];
423   let usbRecipients = ['device', 'interface', 'endpoint', 'other'];
424   await device.open();
425   await device.selectConfiguration(1);
426   await device.claimInterface(0);
427   await device.selectAlternateInterface(0, 0);
428   for (const requestType of usbRequestTypes) {
429     for (const recipient of usbRecipients) {
430       let index = recipient === 'interface' ? 0x5600 : 0x5681;
431       let result = await device.controlTransferIn({
432         requestType: requestType,
433         recipient: recipient,
434         request: 0x42,
435         value: 0x1234,
436         index: index
437       }, 7);
438       assert_true(result instanceof USBInTransferResult);
439       assert_equals(result.status, 'ok');
440       assert_equals(result.data.byteLength, 7);
441       assert_equals(result.data.getUint16(0), 0x07);
442       assert_equals(result.data.getUint8(2), 0x42);
443       assert_equals(result.data.getUint16(3), 0x1234);
444       assert_equals(result.data.getUint16(5), index);
445     }
446   }
447   await device.close();
448 }, 'can issue all types of IN control transfers');
450 usb_test(() => {
451   return getFakeDevice().then(({ device, fakeDevice }) => {
452     return device.open()
453       .then(() => device.selectConfiguration(1))
454       .then(() => waitForDisconnect(fakeDevice))
455       .then(() => assertRejectsWithNotFoundError(device.controlTransferIn({
456           requestType: 'vendor',
457           recipient: 'device',
458           request: 0x42,
459           value: 0x1234,
460           index: 0x5678
461         }, 7)));
462   });
463 }, 'controlTransferIn rejects when called on a disconnected device');
465 usb_test(async () => {
466   let { device } = await getFakeDevice();
467   let usbRequestTypes = ['standard', 'class', 'vendor'];
468   let usbRecipients = ['device', 'interface', 'endpoint', 'other'];
469   let dataArray = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
470   let dataTypes = [dataArray, dataArray.buffer];
471   await device.open();
472   await device.selectConfiguration(1);
473   await device.claimInterface(0);
474   await device.selectAlternateInterface(0, 0);
475   for (const requestType of usbRequestTypes) {
476     for (const recipient of usbRecipients) {
477       let index = recipient === 'interface' ? 0x5600 : 0x5681;
478       let transferParams = {
479         requestType: requestType,
480         recipient: recipient,
481         request: 0x42,
482         value: 0x1234,
483         index: index
484       };
485       for (const data of dataTypes) {
486         let result = await device.controlTransferOut(transferParams, data);
487         assert_true(result instanceof USBOutTransferResult);
488         assert_equals(result.status, 'ok');
489         assert_equals(result.bytesWritten, 8);
490       }
491       let result = await device.controlTransferOut(transferParams);
492       assert_true(result instanceof USBOutTransferResult);
493       assert_equals(result.status, 'ok');
494     }
495   }
496   await device.close();
497 }, 'can issue all types of OUT control transfers');
499 usb_test(() => {
500   return getFakeDevice().then(({ device, fakeDevice }) => {
501     return device.open()
502       .then(() => device.selectConfiguration(1))
503       .then(() => waitForDisconnect(fakeDevice))
504       .then(() => assertRejectsWithNotFoundError(device.controlTransferOut({
505           requestType: 'vendor',
506           recipient: 'device',
507           request: 0x42,
508           value: 0x1234,
509           index: 0x5678
510         }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]))));
511   });
512 }, 'controlTransferOut rejects when called on a disconnected device');
514 usb_test(async () => {
515   let { device } = await getFakeDevice();
516   await device.open();
517   await device.selectConfiguration(1);
518   await device.claimInterface(0);
519   assertRejectsWithTypeError(device.controlTransferOut({
520     requestType: 'invalid',
521     recipient: 'device',
522     request: 0x42,
523     value: 0x1234,
524     index: 0x5678
525   }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])));
526   assertRejectsWithTypeError(device.controlTransferIn({
527     requestType: 'invalid',
528     recipient: 'device',
529     request: 0x42,
530     value: 0x1234,
531     index: 0x5678
532   }, 0));
533   await device.close();
534 }, 'control transfers with a invalid request type reject');
536 usb_test(async () => {
537   let { device } = await getFakeDevice();
538   await device.open();
539   await device.selectConfiguration(1);
540   await device.claimInterface(0);
541   assertRejectsWithTypeError(device.controlTransferOut({
542     requestType: 'vendor',
543     recipient: 'invalid',
544     request: 0x42,
545     value: 0x1234,
546     index: 0x5678
547   }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])));
548   assertRejectsWithTypeError(device.controlTransferIn({
549     requestType: 'vendor',
550     recipient: 'invalid',
551     request: 0x42,
552     value: 0x1234,
553     index: 0x5678
554   }, 0));
555 }, 'control transfers with a invalid recipient type reject');
557 usb_test(async () => {
558   let { device } = await getFakeDevice();
559   await device.open();
560   await device.selectConfiguration(1);
561   await device.claimInterface(0);
562   assertRejectsWithNotFoundError(device.controlTransferOut({
563     requestType: 'vendor',
564     recipient: 'interface',
565     request: 0x42,
566     value: 0x1234,
567     index: 0x0002  // Last byte of index is interface number.
568   }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])));
569   assertRejectsWithNotFoundError(device.controlTransferIn({
570     requestType: 'vendor',
571     recipient: 'interface',
572     request: 0x42,
573     value: 0x1234,
574     index: 0x0002  // Last byte of index is interface number.
575   }, 0));
576 }, 'control transfers to a non-existant interface reject');
578 usb_test(() => {
579   return getFakeDevice().then(({ device }) => {
580     let interfaceRequest = {
581         requestType: 'vendor',
582         recipient: 'interface',
583         request: 0x42,
584         value: 0x1234,
585         index: 0x5600  // Last byte of index is interface number.
586     };
587     let endpointRequest = {
588         requestType: 'vendor',
589         recipient: 'endpoint',
590         request: 0x42,
591         value: 0x1234,
592         index: 0x5681  // Last byte of index is endpoint address.
593     };
594     let data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
595     return device.open()
596       .then(() => device.selectConfiguration(1))
597       .then(() => Promise.all([
598           assertRejectsWithError(
599               device.controlTransferIn(interfaceRequest, 7),
600               'InvalidStateError'),
601           assertRejectsWithError(
602               device.controlTransferIn(endpointRequest, 7),
603               'NotFoundError'),
604           assertRejectsWithError(
605               device.controlTransferOut(interfaceRequest, data),
606               'InvalidStateError'),
607           assertRejectsWithError(
608               device.controlTransferOut(endpointRequest, data),
609               'NotFoundError'),
610       ]))
611       .then(() => device.claimInterface(0))
612       .then(() => Promise.all([
613           device.controlTransferIn(interfaceRequest, 7).then(result => {
614             assert_true(result instanceof USBInTransferResult);
615             assert_equals(result.status, 'ok');
616             assert_equals(result.data.byteLength, 7);
617             assert_equals(result.data.getUint16(0), 0x07);
618             assert_equals(result.data.getUint8(2), 0x42);
619             assert_equals(result.data.getUint16(3), 0x1234);
620             assert_equals(result.data.getUint16(5), 0x5600);
621           }),
622           device.controlTransferIn(endpointRequest, 7).then(result => {
623             assert_true(result instanceof USBInTransferResult);
624             assert_equals(result.status, 'ok');
625             assert_equals(result.data.byteLength, 7);
626             assert_equals(result.data.getUint16(0), 0x07);
627             assert_equals(result.data.getUint8(2), 0x42);
628             assert_equals(result.data.getUint16(3), 0x1234);
629             assert_equals(result.data.getUint16(5), 0x5681);
630           }),
631           device.controlTransferOut(interfaceRequest, data),
632           device.controlTransferOut(endpointRequest, data),
633       ]))
634       .then(() => device.close());
635   });
636 }, 'requests to interfaces and endpoint require an interface claim');
638 usb_test(() => {
639   return getFakeDevice().then(({ device }) => {
640     return device.open()
641       .then(() => device.selectConfiguration(1))
642       .then(() => device.claimInterface(0))
643       .then(() => device.clearHalt('in', 1))
644       .then(() => device.close());
645   });
646 }, 'can clear a halt condition');
648 usb_test(() => {
649   return getFakeDevice().then(({ device, fakeDevice }) => {
650     return device.open()
651       .then(() => device.selectConfiguration(1))
652       .then(() => device.claimInterface(0))
653       .then(() => waitForDisconnect(fakeDevice))
654       .then(() => assertRejectsWithNotFoundError(device.clearHalt('in', 1)));
655   });
656 }, 'clearHalt rejects when called on a disconnected device');
658 usb_test(() => {
659   return getFakeDevice().then(({ device }) => {
660     let data = new DataView(new ArrayBuffer(1024));
661     for (let i = 0; i < 1024; ++i)
662       data.setUint8(i, i & 0xff);
663     const notFoundMessage = 'The specified endpoint is not part of a claimed ' +
664                             'and selected alternate interface.';
665     const rangeError = 'The specified endpoint number is out of range.';
666     return device.open()
667       .then(() => device.selectConfiguration(1))
668       .then(() => device.claimInterface(0))
669       .then(() => Promise.all([
670           assertRejectsWithError(device.transferIn(2, 8),
671                                  'NotFoundError', notFoundMessage), // Unclaimed
672           assertRejectsWithError(device.transferIn(3, 8), 'NotFoundError',
673                                  notFoundMessage), // Non-existent
674           assertRejectsWithError(
675               device.transferIn(16, 8), 'IndexSizeError', rangeError),
676           assertRejectsWithError(device.transferOut(2, data),
677                                  'NotFoundError', notFoundMessage), // Unclaimed
678           assertRejectsWithError(device.transferOut(3, data), 'NotFoundError',
679                                  notFoundMessage), // Non-existent
680           assertRejectsWithError(
681               device.transferOut(16, data), 'IndexSizeError', rangeError),
682       ]));
683   });
684 }, 'transfers to unavailable endpoints are rejected');
686 usb_test(() => {
687   return getFakeDevice().then(({ device }) => {
688     return device.open()
689       .then(() => device.selectConfiguration(1))
690       .then(() => device.claimInterface(0))
691       .then(() => device.transferIn(1, 8))
692       .then(result => {
693         assert_true(result instanceof USBInTransferResult);
694         assert_equals(result.status, 'ok');
695         assert_equals(result.data.byteLength, 8);
696         for (let i = 0; i < 8; ++i)
697           assert_equals(result.data.getUint8(i), i, 'mismatch at byte ' + i);
698         return device.close();
699       });
700   });
701 }, 'can issue IN interrupt transfer');
703 usb_test(() => {
704   return getFakeDevice().then(({ device }) => {
705     return device.open()
706       .then(() => device.selectConfiguration(1))
707       .then(() => device.claimInterface(1))
708       .then(() => device.transferIn(2, 1024))
709       .then(result => {
710         assert_true(result instanceof USBInTransferResult);
711         assert_equals(result.status, 'ok');
712         assert_equals(result.data.byteLength, 1024);
713         for (let i = 0; i < 1024; ++i)
714           assert_equals(result.data.getUint8(i), i & 0xff,
715                         'mismatch at byte ' + i);
716         return device.close();
717       });
718   });
719 }, 'can issue IN bulk transfer');
721 usb_test(() => {
722   return getFakeDevice().then(({ device, fakeDevice }) => {
723     return device.open()
724       .then(() => device.selectConfiguration(1))
725       .then(() => device.claimInterface(1))
726       .then(() => waitForDisconnect(fakeDevice))
727       .then(() => assertRejectsWithNotFoundError(device.transferIn(2, 1024)));
728   });
729 }, 'transferIn rejects if called on a disconnected device');
731 usb_test(() => {
732   return getFakeDevice().then(({ device }) => {
733     return device.open()
734       .then(() => device.selectConfiguration(1))
735       .then(() => device.claimInterface(1))
736       .then(() => {
737         let data = new DataView(new ArrayBuffer(1024));
738         for (let i = 0; i < 1024; ++i)
739           data.setUint8(i, i & 0xff);
740         return device.transferOut(2, data);
741       })
742       .then(result => {
743         assert_true(result instanceof USBOutTransferResult);
744         assert_equals(result.status, 'ok');
745         assert_equals(result.bytesWritten, 1024);
746         return device.close();
747       });
748   });
749 }, 'can issue OUT bulk transfer');
751 usb_test(() => {
752   return getFakeDevice().then(({ device, fakeDevice }) => {
753     return device.open()
754       .then(() => device.selectConfiguration(1))
755       .then(() => device.claimInterface(1))
756       .then(() => {
757         let data = new DataView(new ArrayBuffer(1024));
758         for (let i = 0; i < 1024; ++i)
759           data.setUint8(i, i & 0xff);
760         return waitForDisconnect(fakeDevice)
761           .then(() => assertRejectsWithNotFoundError(device.transferOut(2, data)));
762       });
763   });
764 }, 'transferOut rejects if called on a disconnected device');
766 usb_test(() => {
767   return getFakeDevice().then(({ device }) => {
768     return device.open()
769       .then(() => device.selectConfiguration(2))
770       .then(() => device.claimInterface(0))
771       .then(() => device.selectAlternateInterface(0, 1))
772       .then(() => device.isochronousTransferIn(
773           1, [64, 64, 64, 64, 64, 64, 64, 64]))
774       .then(result => {
775         assert_true(result instanceof USBIsochronousInTransferResult);
776         assert_equals(result.data.byteLength, 64 * 8, 'buffer size');
777         assert_equals(result.packets.length, 8, 'number of packets');
778         let byteOffset = 0;
779         for (let i = 0; i < result.packets.length; ++i) {
780           assert_true(
781               result.packets[i] instanceof USBIsochronousInTransferPacket);
782           assert_equals(result.packets[i].status, 'ok');
783           assert_equals(result.packets[i].data.byteLength, 64);
784           assert_equals(result.packets[i].data.buffer, result.data.buffer);
785           assert_equals(result.packets[i].data.byteOffset, byteOffset);
786           for (let j = 0; j < 64; ++j)
787             assert_equals(result.packets[i].data.getUint8(j), j & 0xff,
788                           'mismatch at byte ' + j + ' of packet ' + i);
789           byteOffset += result.packets[i].data.byteLength;
790         }
791         return device.close();
792       });
793   });
794 }, 'can issue IN isochronous transfer');
796 usb_test(() => {
797   return getFakeDevice().then(({ device, fakeDevice }) => {
798     return device.open()
799       .then(() => device.selectConfiguration(2))
800       .then(() => device.claimInterface(0))
801       .then(() => device.selectAlternateInterface(0, 1))
802       .then(() => waitForDisconnect(fakeDevice))
803       .then(() => assertRejectsWithNotFoundError(device.isochronousTransferIn(
804           1, [64, 64, 64, 64, 64, 64, 64, 64])));
805   });
806 }, 'isochronousTransferIn rejects when called on a disconnected device');
808 usb_test(() => {
809   return getFakeDevice().then(({ device }) => {
810     return device.open()
811       .then(() => device.selectConfiguration(2))
812       .then(() => device.claimInterface(0))
813       .then(() => device.selectAlternateInterface(0, 1))
814       .then(() => {
815         let data = new DataView(new ArrayBuffer(64 * 8));
816         for (let i = 0; i < 8; ++i) {
817           for (let j = 0; j < 64; ++j)
818             data.setUint8(i * j, j & 0xff);
819         }
820         return device.isochronousTransferOut(
821             1, data, [64, 64, 64, 64, 64, 64, 64, 64]);
822       })
823       .then(result => {
824         assert_true(result instanceof USBIsochronousOutTransferResult);
825         assert_equals(result.packets.length, 8, 'number of packets');
826         let byteOffset = 0;
827         for (let i = 0; i < result.packets.length; ++i) {
828           assert_true(
829               result.packets[i] instanceof USBIsochronousOutTransferPacket);
830           assert_equals(result.packets[i].status, 'ok');
831           assert_equals(result.packets[i].bytesWritten, 64);
832         }
833         return device.close();
834       });
835   });
836 }, 'can issue OUT isochronous transfer');
838 usb_test(() => {
839   return getFakeDevice().then(({ device, fakeDevice }) => {
840     return device.open()
841       .then(() => device.selectConfiguration(2))
842       .then(() => device.claimInterface(0))
843       .then(() => device.selectAlternateInterface(0, 1))
844       .then(() => {
845         let data = new DataView(new ArrayBuffer(64 * 8));
846         for (let i = 0; i < 8; ++i) {
847           for (let j = 0; j < 64; ++j)
848             data.setUint8(i * j, j & 0xff);
849         }
850         return waitForDisconnect(fakeDevice)
851           .then(() => assertRejectsWithNotFoundError(device.isochronousTransferOut(
852               1, data, [64, 64, 64, 64, 64, 64, 64, 64])));
853       });
854   });
855 }, 'isochronousTransferOut rejects when called on a disconnected device');
857 usb_test(() => {
858   return getFakeDevice().then(({ device }) => {
859     return device.open().then(() => device.reset()).then(() => device.close());
860   });
861 }, 'can reset the device');
863 usb_test(() => {
864   return getFakeDevice().then(({ device, fakeDevice }) => {
865     return device.open()
866       .then(() => waitForDisconnect(fakeDevice))
867       .then(() => assertRejectsWithNotFoundError(device.reset()));
868   });
869 }, 'resetDevice rejects when called on a disconnected device');