Skip to content

Commit ca3a1ee

Browse files
committed
Add test case for prompt enumeration
1 parent e901d76 commit ca3a1ee

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

tests/test_class_host/tests.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rand::prelude::*;
33
use rusb::{request_type, Direction, Recipient, RequestType, TransferType};
44
use std::cmp::max;
55
use std::fmt::Write;
6+
use std::thread;
67
use std::time::{Duration, Instant};
78
use usb_device::test_class;
89

@@ -367,6 +368,62 @@ fn bench_bulk_read(context, out) {
367368
});
368369
}
369370

371+
fn enumerates_promptly(context, out) {
372+
// Time measured between issuance of the hard reset command, to the device
373+
// successfully enumerating. This approach might need to be improved on,
374+
// since the time might depend on USB host implementation details,
375+
// bootloaders in the device, etc.
376+
const MAX_TIME: Duration = Duration::from_secs(2);
377+
378+
let dev = match context.device_for_test() {
379+
Ok(dev) => dev,
380+
Err(err) => {
381+
assert!(false, "Failed to prepare for test: {}", err);
382+
return;
383+
}
384+
};
385+
386+
// Ensure we've got a device by doing a dummy read
387+
let mut response = [0u8; 8];
388+
dev.read_control(
389+
request_type(Direction::In, RequestType::Vendor, Recipient::Device),
390+
test_class::REQ_READ_BUFFER, 0, 0, &mut response, TIMEOUT)
391+
.expect("control read");
392+
393+
// Since the write_control() may have a timeout, measure from the point when
394+
// the request is sent
395+
let reset_started = Instant::now();
396+
397+
// This is expected to fail since the device immediately restarts
398+
let res = dev.write_control(
399+
request_type(Direction::Out, RequestType::Vendor, Recipient::Device),
400+
test_class::REQ_HARD_RESET, 0, 0, &[], TIMEOUT);
401+
402+
if res.is_ok() {
403+
panic!("Hard reset request succeeded, implies the device didn't reset");
404+
}
405+
406+
loop {
407+
thread::sleep(Duration::from_millis(100));
408+
409+
if reset_started.elapsed() > MAX_TIME {
410+
eprintln!(" Didn't enumerate in {:?}", MAX_TIME);
411+
// Note this hoses the rest of the test suite, since the loop in
412+
// main.rs expects tests to leave the test interface claimed.
413+
panic!("Enumeration timed out");
414+
}
415+
if context.reopen_device(None).is_ok() {
416+
let enumeration_duration = reset_started.elapsed();
417+
418+
if let Ok(_) = context.device_for_test() {
419+
writeln!(out, " enumerated in {:?}", enumeration_duration).expect("write failed");
420+
}
421+
422+
break;
423+
}
424+
}
425+
}
426+
370427
} // end tests! {
371428

372429
fn run_bench(dev: &DeviceHandles, out: &mut String, f: impl Fn(&mut [u8])) {

0 commit comments

Comments
 (0)