OLD | NEW |
| (Empty) |
1 'use strict'; | |
2 | |
3 function assertRejectsWithError(promise, name, message) { | |
4 return promise.then(() => { | |
5 assert_unreached('expected promise to reject with ' + name); | |
6 }, error => { | |
7 assert_equals(error.name, name); | |
8 if (message !== undefined) | |
9 assert_equals(error.message, message); | |
10 }); | |
11 } | |
12 | |
13 // TODO(reillyg): Remove when jyasskin upstreams this to testharness.js: | |
14 // https://crbug.com/509058. | |
15 function callWithKeyDown(functionCalledOnKeyPress) { | |
16 return new Promise(resolve => { | |
17 function onKeyPress() { | |
18 document.removeEventListener('keypress', onKeyPress, false); | |
19 resolve(functionCalledOnKeyPress()); | |
20 } | |
21 document.addEventListener('keypress', onKeyPress, false); | |
22 | |
23 eventSender.keyDown(' ', []); | |
24 }); | |
25 } | |
26 | |
27 function runGarbageCollection() { | |
28 // Run gc() as a promise. | |
29 return new Promise((resolve, reject) => { | |
30 GCController.collect(); | |
31 setTimeout(resolve, 0); | |
32 }); | |
33 } | |
34 | |
35 function usbMocks(mojo) { | |
36 return define('USB Mocks', [ | |
37 'mojo/public/js/bindings', | |
38 'device/usb/public/interfaces/chooser_service.mojom', | |
39 'device/usb/public/interfaces/device_manager.mojom', | |
40 'device/usb/public/interfaces/device.mojom', | |
41 ], (bindings, chooserService, deviceManager, device) => { | |
42 function assertDeviceInfoEquals(device, info) { | |
43 assert_equals(device.usbVersionMajor, info.usb_version_major); | |
44 assert_equals(device.usbVersionMinor, info.usb_version_minor); | |
45 assert_equals(device.usbVersionSubminor, info.usb_version_subminor); | |
46 assert_equals(device.deviceClass, info.class_code); | |
47 assert_equals(device.deviceSubclass, info.subclass_code); | |
48 assert_equals(device.deviceProtocol, info.protocol_code); | |
49 assert_equals(device.vendorId, info.vendor_id); | |
50 assert_equals(device.productId, info.product_id); | |
51 assert_equals(device.deviceVersionMajor, info.device_version_major); | |
52 assert_equals(device.deviceVersionMinor, info.device_version_minor); | |
53 assert_equals(device.deviceVersionSubminor, | |
54 info.device_version_subminor); | |
55 assert_equals(device.manufacturerName, info.manufacturer_name); | |
56 assert_equals(device.productName, info.product_name); | |
57 assert_equals(device.serialNumber, info.serial_number); | |
58 assert_equals(device.configurations.length, | |
59 info.configurations.length); | |
60 for (var i = 0; i < device.configurations.length; ++i) { | |
61 assertConfigurationInfoEquals(device.configurations[i], | |
62 info.configurations[i]); | |
63 } | |
64 }; | |
65 | |
66 function assertConfigurationInfoEquals(configuration, info) { | |
67 assert_equals(configuration.configurationValue, | |
68 info.configuration_value); | |
69 assert_equals(configuration.configurationName, | |
70 info.configuration_name); | |
71 assert_equals(configuration.interfaces.length, | |
72 info.interfaces.length); | |
73 for (var i = 0; i < configuration.interfaces.length; ++i) { | |
74 assertInterfaceInfoEquals(configuration.interfaces[i], | |
75 info.interfaces[i]); | |
76 } | |
77 }; | |
78 | |
79 function assertInterfaceInfoEquals(iface, info) { | |
80 assert_equals(iface.interfaceNumber, info.interface_number); | |
81 assert_equals(iface.alternates.length, info.alternates.length); | |
82 for (var i = 0; i < iface.alternates.length; ++i) { | |
83 assertAlternateInfoEquals(iface.alternates[i], info.alternates[i]); | |
84 } | |
85 }; | |
86 | |
87 function assertAlternateInfoEquals(alternate, info) { | |
88 assert_equals(alternate.alternateSetting, info.alternate_setting); | |
89 assert_equals(alternate.interfaceClass, info.class_code); | |
90 assert_equals(alternate.interfaceSubclass, info.subclass_code); | |
91 assert_equals(alternate.interfaceProtocol, info.protocol_code); | |
92 assert_equals(alternate.interfaceName, info.interface_name); | |
93 assert_equals(alternate.endpoints.length, info.endpoints.length); | |
94 for (var i = 0; i < alternate.endpoints.length; ++i) { | |
95 assertEndpointInfoEquals(alternate.endpoints[i], info.endpoints[i]); | |
96 } | |
97 } | |
98 | |
99 function assertEndpointInfoEquals(endpoint, info) { | |
100 var direction; | |
101 switch (info.direction) { | |
102 case device.TransferDirection.INBOUND: | |
103 direction = 'in'; | |
104 break; | |
105 case device.TransferDirection.OUTBOUND: | |
106 direction = 'out'; | |
107 break; | |
108 } | |
109 | |
110 var type; | |
111 switch (info.type) { | |
112 case device.EndpointType.BULK: | |
113 type = 'bulk'; | |
114 break; | |
115 case device.EndpointType.INTERRUPT: | |
116 type = 'interrupt'; | |
117 break; | |
118 case device.EndpointType.ISOCHRONOUS: | |
119 type = 'isochronous'; | |
120 break; | |
121 } | |
122 | |
123 assert_equals(endpoint.endpointNumber, info.endpoint_number); | |
124 assert_equals(endpoint.direction, direction); | |
125 assert_equals(endpoint.type, type); | |
126 assert_equals(endpoint.packetSize, info.packet_size); | |
127 } | |
128 | |
129 class MockDevice { | |
130 constructor(info) { | |
131 this.info_ = info; | |
132 this.opened_ = false; | |
133 this.currentConfiguration_ = undefined; | |
134 this.claimedInterfaces_ = new Map(); | |
135 } | |
136 | |
137 getDeviceInfo() { | |
138 return Promise.resolve({ info: this.info_ }); | |
139 } | |
140 | |
141 getConfiguration() { | |
142 if (this.currentConfiguration_ === undefined) { | |
143 return Promise.resolve({ value: 0 }); | |
144 } else { | |
145 return Promise.resolve({ | |
146 value: this.currentConfiguration_.configuration_value }); | |
147 } | |
148 } | |
149 | |
150 open() { | |
151 assert_false(this.opened_); | |
152 this.opened_ = true; | |
153 return Promise.resolve({ error: device.OpenDeviceError.OK }); | |
154 } | |
155 | |
156 close() { | |
157 assert_true(this.opened_); | |
158 this.opened_ = false; | |
159 return Promise.resolve({ error: device.OpenDeviceError.OK }); | |
160 } | |
161 | |
162 setConfiguration(value) { | |
163 assert_true(this.opened_); | |
164 | |
165 let selected_configuration = this.info_.configurations.find( | |
166 configuration => configuration.configuration_value == value); | |
167 if (selected_configuration !== undefined) { | |
168 this.currentConfiguration_ = selected_configuration; | |
169 return Promise.resolve({ success: true }); | |
170 } else { | |
171 return Promise.resolve({ success: false }); | |
172 } | |
173 } | |
174 | |
175 claimInterface(interfaceNumber) { | |
176 assert_true(this.opened_); | |
177 assert_true(this.currentConfiguration_ !== undefined, | |
178 'device configured'); | |
179 | |
180 if (this.claimedInterfaces_.has(interfaceNumber)) | |
181 return Promise.resolve({ success: false }); | |
182 | |
183 if (this.currentConfiguration_.interfaces.some( | |
184 iface => iface.interface_number == interfaceNumber)) { | |
185 this.claimedInterfaces_.set(interfaceNumber, 0); | |
186 return Promise.resolve({ success: true }); | |
187 } else { | |
188 return Promise.resolve({ success: false }); | |
189 } | |
190 } | |
191 | |
192 releaseInterface(interfaceNumber) { | |
193 assert_true(this.opened_); | |
194 assert_true(this.currentConfiguration_ !== undefined, | |
195 'device configured'); | |
196 | |
197 if (this.claimedInterfaces_.has(interfaceNumber)) { | |
198 this.claimedInterfaces_.delete(interfaceNumber); | |
199 return Promise.resolve({ success: true }); | |
200 } else { | |
201 return Promise.resolve({ success: false }); | |
202 } | |
203 } | |
204 | |
205 setInterfaceAlternateSetting(interfaceNumber, alternateSetting) { | |
206 assert_true(this.opened_); | |
207 assert_true(this.currentConfiguration_ !== undefined, | |
208 'device configured'); | |
209 | |
210 if (!this.claimedInterfaces_.has(interfaceNumber)) | |
211 return Promise.resolve({ success: false }); | |
212 | |
213 let iface = this.currentConfiguration_.interfaces.find( | |
214 iface => iface.interface_number == interfaceNumber); | |
215 if (iface === undefined) | |
216 return Promise.resolve({ success: false }); | |
217 | |
218 if (iface.alternates.some( | |
219 x => x.alternate_setting == alternateSetting)) { | |
220 this.claimedInterfaces_.set(interfaceNumber, alternateSetting); | |
221 return Promise.resolve({ success: true }); | |
222 } else { | |
223 return Promise.resolve({ success: false }); | |
224 } | |
225 } | |
226 | |
227 reset() { | |
228 assert_true(this.opened_); | |
229 return Promise.resolve({ success: true }); | |
230 } | |
231 | |
232 clearHalt(endpoint) { | |
233 assert_true(this.opened_); | |
234 assert_true(this.currentConfiguration_ !== undefined, | |
235 'device configured'); | |
236 // TODO(reillyg): Check that endpoint is valid. | |
237 return Promise.resolve({ success: true }); | |
238 } | |
239 | |
240 controlTransferIn(params, length, timeout) { | |
241 assert_true(this.opened_); | |
242 assert_true(this.currentConfiguration_ !== undefined, | |
243 'device configured'); | |
244 return Promise.resolve({ | |
245 status: device.TransferStatus.OK, | |
246 data: [length >> 8, length & 0xff, params.request, params.value >> 8, | |
247 params.value & 0xff, params.index >> 8, params.index & 0xff] | |
248 }); | |
249 } | |
250 | |
251 controlTransferOut(params, data, timeout) { | |
252 assert_true(this.opened_); | |
253 assert_true(this.currentConfiguration_ !== undefined, | |
254 'device configured'); | |
255 return Promise.resolve({ | |
256 status: device.TransferStatus.OK, | |
257 bytesWritten: data.byteLength | |
258 }); | |
259 } | |
260 | |
261 genericTransferIn(endpointNumber, length, timeout) { | |
262 assert_true(this.opened_); | |
263 assert_true(this.currentConfiguration_ !== undefined, | |
264 'device configured'); | |
265 // TODO(reillyg): Check that endpoint is valid. | |
266 let data = new Array(length); | |
267 for (let i = 0; i < length; ++i) | |
268 data[i] = i & 0xff; | |
269 return Promise.resolve({ | |
270 status: device.TransferStatus.OK, | |
271 data: data | |
272 }); | |
273 } | |
274 | |
275 genericTransferOut(endpointNumber, data, timeout) { | |
276 assert_true(this.opened_); | |
277 assert_true(this.currentConfiguration_ !== undefined, | |
278 'device configured'); | |
279 // TODO(reillyg): Check that endpoint is valid. | |
280 return Promise.resolve({ | |
281 status: device.TransferStatus.OK, | |
282 bytesWritten: data.byteLength | |
283 }); | |
284 } | |
285 | |
286 isochronousTransferIn(endpointNumber, packetLengths, timeout) { | |
287 assert_true(this.opened_); | |
288 assert_true(this.currentConfiguration_ !== undefined, | |
289 'device configured'); | |
290 // TODO(reillyg): Check that endpoint is valid. | |
291 let data = new Array(packetLengths.reduce((a, b) => a + b, 0)); | |
292 let dataOffset = 0; | |
293 let packets = new Array(packetLengths.length); | |
294 for (let i = 0; i < packetLengths.length; ++i) { | |
295 for (let j = 0; j < packetLengths[i]; ++j) | |
296 data[dataOffset++] = j & 0xff; | |
297 packets[i] = { | |
298 length: packetLengths[i], | |
299 transferred_length: packetLengths[i], | |
300 status: device.TransferStatus.OK | |
301 }; | |
302 } | |
303 return Promise.resolve({ data: data, packets: packets }); | |
304 } | |
305 | |
306 isochronousTransferOut(endpointNumber, data, packetLengths, timeout) { | |
307 assert_true(this.opened_); | |
308 assert_true(this.currentConfiguration_ !== undefined, | |
309 'device configured'); | |
310 // TODO(reillyg): Check that endpoint is valid. | |
311 let packets = new Array(packetLengths.length); | |
312 for (let i = 0; i < packetLengths.length; ++i) { | |
313 packets[i] = { | |
314 length: packetLengths[i], | |
315 transferred_length: packetLengths[i], | |
316 status: device.TransferStatus.OK | |
317 }; | |
318 } | |
319 return Promise.resolve({ packets: packets }); | |
320 } | |
321 }; | |
322 | |
323 class MockDeviceManager { | |
324 constructor() { | |
325 this.bindingSet = new bindings.BindingSet(deviceManager.DeviceManager); | |
326 | |
327 this.mockDevices_ = new Map(); | |
328 this.deviceCloseHandler_ = null; | |
329 this.client_ = null; | |
330 } | |
331 | |
332 reset() { | |
333 this.mockDevices_.forEach(device => { | |
334 for (var binding of device.bindingArray) | |
335 binding.close(); | |
336 this.client_.onDeviceRemoved(device.info); | |
337 }); | |
338 this.mockDevices_.clear(); | |
339 } | |
340 | |
341 addMockDevice(info) { | |
342 let device = { | |
343 info: info, | |
344 bindingArray: [] | |
345 }; | |
346 this.mockDevices_.set(info.guid, device); | |
347 if (this.client_) | |
348 this.client_.onDeviceAdded(info); | |
349 } | |
350 | |
351 removeMockDevice(info) { | |
352 let device = this.mockDevices_.get(info.guid); | |
353 for (var binding of device.bindingArray) | |
354 binding.close(); | |
355 this.mockDevices_.delete(info.guid); | |
356 if (this.client_) | |
357 this.client_.onDeviceRemoved(info); | |
358 } | |
359 | |
360 setDeviceCloseHandler(handler) { | |
361 this.deviceCloseHandler_ = handler; | |
362 } | |
363 | |
364 getDevices(options) { | |
365 let devices = []; | |
366 this.mockDevices_.forEach(device => { | |
367 devices.push(device.info); | |
368 }); | |
369 return Promise.resolve({ results: devices }); | |
370 } | |
371 | |
372 getDevice(guid, request) { | |
373 let deviceData = this.mockDevices_.get(guid); | |
374 if (deviceData === undefined) { | |
375 request.close(); | |
376 } else { | |
377 var binding = new bindings.Binding( | |
378 device.Device, new MockDevice(deviceData.info), request); | |
379 binding.setConnectionErrorHandler(() => { | |
380 if (this.deviceCloseHandler_) | |
381 this.deviceCloseHandler_(deviceData.info); | |
382 }); | |
383 deviceData.bindingArray.push(binding); | |
384 } | |
385 } | |
386 | |
387 setClient(client) { | |
388 this.client_ = client; | |
389 } | |
390 } | |
391 | |
392 class MockChooserService { | |
393 constructor() { | |
394 this.bindingSet = new bindings.BindingSet( | |
395 chooserService.ChooserService); | |
396 | |
397 this.chosenDevice_ = null; | |
398 this.lastFilters_ = null; | |
399 } | |
400 | |
401 setChosenDevice(deviceInfo) { | |
402 this.chosenDeviceInfo_ = deviceInfo; | |
403 } | |
404 | |
405 getLastFilters() { | |
406 return this.lastFilters_; | |
407 } | |
408 | |
409 getPermission(deviceFilters) { | |
410 this.lastFilters_ = deviceFilters; | |
411 return Promise.resolve({ result: this.chosenDeviceInfo_ }); | |
412 } | |
413 } | |
414 | |
415 let mockDeviceManager = new MockDeviceManager; | |
416 mojo.frameInterfaces.addInterfaceOverrideForTesting( | |
417 deviceManager.DeviceManager.name, | |
418 handle => { | |
419 mockDeviceManager.bindingSet.addBinding(mockDeviceManager, handle); | |
420 }); | |
421 | |
422 let mockChooserService = new MockChooserService; | |
423 mojo.frameInterfaces.addInterfaceOverrideForTesting( | |
424 chooserService.ChooserService.name, | |
425 handle => { | |
426 mockChooserService.bindingSet.addBinding(mockChooserService, handle); | |
427 }); | |
428 | |
429 return fakeUsbDevices().then(fakeDevices => Promise.resolve({ | |
430 DeviceManager: deviceManager.DeviceManager, | |
431 Device: device.Device, | |
432 MockDeviceManager: MockDeviceManager, | |
433 mockDeviceManager: mockDeviceManager, | |
434 mockChooserService: mockChooserService, | |
435 fakeDevices: fakeDevices, | |
436 assertDeviceInfoEquals: assertDeviceInfoEquals, | |
437 assertConfigurationInfoEquals: assertConfigurationInfoEquals, | |
438 })); | |
439 }); | |
440 } | |
441 | |
442 function usb_test(func, name, properties) { | |
443 mojo_test(mojo => usbMocks(mojo).then(usb => { | |
444 let result = Promise.resolve(func(usb)); | |
445 let cleanUp = () => usb.mockDeviceManager.reset(); | |
446 result.then(cleanUp, cleanUp); | |
447 return result; | |
448 }), name, properties); | |
449 } | |
OLD | NEW |