760 lines
24 KiB
Rust
760 lines
24 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// Currently the mozdevice API is not safe for multiple requests at the same
|
|
// time. It is recommended to run each of the unit tests on its own. Also adb
|
|
// specific tests cannot be run in CI yet. To check those locally, also run
|
|
// the ignored tests.
|
|
//
|
|
// Use the following command to accomplish that:
|
|
//
|
|
// $ cargo test -- --ignored --test-threads=1
|
|
|
|
use crate::*;
|
|
|
|
use std::collections::BTreeSet;
|
|
use std::panic;
|
|
use std::path::PathBuf;
|
|
use tempfile::{tempdir, TempDir};
|
|
|
|
#[test]
|
|
fn read_length_from_valid_string() {
|
|
fn test(message: &str) -> Result<usize> {
|
|
read_length(&mut io::BufReader::new(message.as_bytes()))
|
|
}
|
|
|
|
assert_eq!(test("0000").unwrap(), 0);
|
|
assert_eq!(test("0001").unwrap(), 1);
|
|
assert_eq!(test("000F").unwrap(), 15);
|
|
assert_eq!(test("00FF").unwrap(), 255);
|
|
assert_eq!(test("0FFF").unwrap(), 4095);
|
|
assert_eq!(test("FFFF").unwrap(), 65535);
|
|
|
|
assert_eq!(test("FFFF0").unwrap(), 65535);
|
|
}
|
|
|
|
#[test]
|
|
fn read_length_from_invalid_string() {
|
|
fn test(message: &str) -> Result<usize> {
|
|
read_length(&mut io::BufReader::new(message.as_bytes()))
|
|
}
|
|
|
|
test("").expect_err("empty string");
|
|
test("G").expect_err("invalid hex character");
|
|
test("-1").expect_err("negative number");
|
|
test("000").expect_err("shorter than 4 bytes");
|
|
}
|
|
|
|
#[test]
|
|
fn encode_message_with_valid_string() {
|
|
assert_eq!(encode_message("").unwrap(), "0000".to_string());
|
|
assert_eq!(encode_message("a").unwrap(), "0001a".to_string());
|
|
assert_eq!(
|
|
encode_message(&"a".repeat(15)).unwrap(),
|
|
format!("000F{}", "a".repeat(15))
|
|
);
|
|
assert_eq!(
|
|
encode_message(&"a".repeat(255)).unwrap(),
|
|
format!("00FF{}", "a".repeat(255))
|
|
);
|
|
assert_eq!(
|
|
encode_message(&"a".repeat(4095)).unwrap(),
|
|
format!("0FFF{}", "a".repeat(4095))
|
|
);
|
|
assert_eq!(
|
|
encode_message(&"a".repeat(65535)).unwrap(),
|
|
format!("FFFF{}", "a".repeat(65535))
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn encode_message_with_invalid_string() {
|
|
encode_message(&"a".repeat(65536)).expect_err("string lengths exceeds 4 bytes");
|
|
}
|
|
|
|
fn run_device_test<F>(test: F)
|
|
where
|
|
F: FnOnce(&Device, &TempDir, &UnixPath) + panic::UnwindSafe,
|
|
{
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
let device = host
|
|
.device_or_default::<String>(None, AndroidStorageInput::Auto)
|
|
.expect("device_or_default");
|
|
|
|
let tmp_dir = tempdir().expect("create temp dir");
|
|
let response = device
|
|
.execute_host_shell_command("echo $EXTERNAL_STORAGE")
|
|
.unwrap();
|
|
let mut test_root = UnixPathBuf::from(response.trim_end_matches('\n'));
|
|
test_root.push("mozdevice");
|
|
|
|
let _ = device.remove(&test_root);
|
|
|
|
let result = panic::catch_unwind(|| test(&device, &tmp_dir, &test_root));
|
|
|
|
let _ = device.kill_forward_all_ports();
|
|
// let _ = device.kill_reverse_all_ports();
|
|
|
|
assert!(result.is_ok())
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_features() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let set = host.features::<BTreeSet<_>>().expect("to query features");
|
|
assert!(set.contains("cmd"));
|
|
assert!(set.contains("shell_v2"));
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_devices() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let set: BTreeSet<_> = host.devices().expect("to query devices");
|
|
assert_eq!(1, set.len());
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let devices: Vec<_> = host.devices().expect("to query devices");
|
|
let expected_device = devices.first().expect("found a device");
|
|
|
|
let device = host
|
|
.device_or_default::<String>(Some(&expected_device.serial), AndroidStorageInput::App)
|
|
.expect("connected device with serial");
|
|
assert_eq!(device.run_as_package, None);
|
|
assert_eq!(device.serial, expected_device.serial);
|
|
assert!(device.tempfile.starts_with("/data/local/tmp"));
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default_invalid_serial() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
host.device_or_default::<String>(Some(&"foobar".to_owned()), AndroidStorageInput::Auto)
|
|
.expect_err("invalid serial");
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default_no_serial() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let devices: Vec<_> = host.devices().expect("to query devices");
|
|
let expected_device = devices.first().expect("found a device");
|
|
|
|
let device = host
|
|
.device_or_default::<String>(None, AndroidStorageInput::Auto)
|
|
.expect("connected device with serial");
|
|
assert_eq!(device.serial, expected_device.serial);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default_storage_as_app() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let device = host
|
|
.device_or_default::<String>(None, AndroidStorageInput::App)
|
|
.expect("connected device");
|
|
assert_eq!(device.storage, AndroidStorage::App);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default_storage_as_auto() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let device = host
|
|
.device_or_default::<String>(None, AndroidStorageInput::Auto)
|
|
.expect("connected device");
|
|
assert_eq!(device.storage, AndroidStorage::Sdcard);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default_storage_as_internal() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let device = host
|
|
.device_or_default::<String>(None, AndroidStorageInput::Internal)
|
|
.expect("connected device");
|
|
assert_eq!(device.storage, AndroidStorage::Internal);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn host_device_or_default_storage_as_sdcard() {
|
|
let host = Host {
|
|
..Default::default()
|
|
};
|
|
|
|
let device = host
|
|
.device_or_default::<String>(None, AndroidStorageInput::Sdcard)
|
|
.expect("connected device");
|
|
assert_eq!(device.storage, AndroidStorage::Sdcard);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_shell_command() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
assert_eq!(
|
|
"Linux\n",
|
|
device
|
|
.execute_host_shell_command("uname")
|
|
.expect("to have shell output")
|
|
);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_forward_port_hardcoded() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
assert_eq!(
|
|
3035,
|
|
device
|
|
.forward_port(3035, 3036)
|
|
.expect("forwarded local port")
|
|
);
|
|
// TODO: check with forward --list
|
|
});
|
|
}
|
|
|
|
// #[test]
|
|
// #[ignore]
|
|
// TODO: "adb server response to `forward tcp:0 ...` was not a u16: \"000559464\"")
|
|
// fn device_forward_port_system_allocated() {
|
|
// run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
// let local_port = device.forward_port(0, 3037).expect("local_port");
|
|
// assert_ne!(local_port, 0);
|
|
// // TODO: check with forward --list
|
|
// });
|
|
// }
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_forward_port_no_forwarded_port() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
device
|
|
.kill_forward_port(3038)
|
|
.expect_err("adb error: listener 'tcp:3038' ");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_forward_port_twice() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
let local_port = device
|
|
.forward_port(3039, 3040)
|
|
.expect("forwarded local port");
|
|
assert_eq!(local_port, 3039);
|
|
// TODO: check with forward --list
|
|
device
|
|
.kill_forward_port(local_port)
|
|
.expect("to remove forwarded port");
|
|
device
|
|
.kill_forward_port(local_port)
|
|
.expect_err("adb error: listener 'tcp:3039' ");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_forward_all_ports_no_forwarded_port() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
device
|
|
.kill_forward_all_ports()
|
|
.expect("to not fail for no forwarded ports");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_forward_all_ports_twice() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
let local_port1 = device
|
|
.forward_port(3039, 3040)
|
|
.expect("forwarded local port");
|
|
assert_eq!(local_port1, 3039);
|
|
let local_port2 = device
|
|
.forward_port(3041, 3042)
|
|
.expect("forwarded local port");
|
|
assert_eq!(local_port2, 3041);
|
|
// TODO: check with forward --list
|
|
device
|
|
.kill_forward_all_ports()
|
|
.expect("to remove all forwarded ports");
|
|
device
|
|
.kill_forward_all_ports()
|
|
.expect("to not fail for no forwarded ports");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_reverse_port_hardcoded() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
assert_eq!(4035, device.reverse_port(4035, 4036).expect("remote_port"));
|
|
// TODO: check with reverse --list
|
|
});
|
|
}
|
|
|
|
// #[test]
|
|
// #[ignore]
|
|
// TODO: No adb response: ParseInt(ParseIntError { kind: Empty })
|
|
// fn device_reverse_port_system_allocated() {
|
|
// run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
// let reverse_port = device.reverse_port(0, 4037).expect("remote port");
|
|
// assert_ne!(reverse_port, 0);
|
|
// // TODO: check with reverse --list
|
|
// });
|
|
// }
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_reverse_port_no_reverse_port() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
device
|
|
.kill_reverse_port(4038)
|
|
.expect_err("listener 'tcp:4038' not found");
|
|
});
|
|
}
|
|
|
|
// #[test]
|
|
// #[ignore]
|
|
// TODO: "adb error: adb server response did not contain expected hexstring length: \"\""
|
|
// fn device_kill_reverse_port_twice() {
|
|
// run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
// let remote_port = device
|
|
// .reverse_port(4039, 4040)
|
|
// .expect("reversed local port");
|
|
// assert_eq!(remote_port, 4039);
|
|
// // TODO: check with reverse --list
|
|
// device
|
|
// .kill_reverse_port(remote_port)
|
|
// .expect("to remove reverse port");
|
|
// device
|
|
// .kill_reverse_port(remote_port)
|
|
// .expect_err("listener 'tcp:4039' not found");
|
|
// });
|
|
// }
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_reverse_all_ports_no_reversed_port() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
device
|
|
.kill_reverse_all_ports()
|
|
.expect("to not fail for no reversed ports");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_kill_reverse_all_ports_twice() {
|
|
run_device_test(|device: &Device, _: &TempDir, _: &UnixPath| {
|
|
let local_port1 = device
|
|
.forward_port(4039, 4040)
|
|
.expect("forwarded local port");
|
|
assert_eq!(local_port1, 4039);
|
|
let local_port2 = device
|
|
.forward_port(4041, 4042)
|
|
.expect("forwarded local port");
|
|
assert_eq!(local_port2, 4041);
|
|
// TODO: check with reverse --list
|
|
device
|
|
.kill_reverse_all_ports()
|
|
.expect("to remove all reversed ports");
|
|
device
|
|
.kill_reverse_all_ports()
|
|
.expect("to not fail for no reversed ports");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_push_pull_text_file() {
|
|
run_device_test(
|
|
|device: &Device, _: &TempDir, remote_root_path: &UnixPath| {
|
|
let content = "test";
|
|
let remote_path = remote_root_path.join("foo.txt");
|
|
|
|
device
|
|
.push(
|
|
&mut io::BufReader::new(content.as_bytes()),
|
|
&remote_path,
|
|
0o777,
|
|
)
|
|
.expect("file has been pushed");
|
|
|
|
let file_content = device
|
|
.execute_host_shell_command(&format!("cat {}", remote_path.display()))
|
|
.expect("host shell command for 'cat' to succeed");
|
|
|
|
assert_eq!(file_content, content);
|
|
|
|
// And as second step pull it off the device.
|
|
let mut buffer = Vec::new();
|
|
device
|
|
.pull(&remote_path, &mut buffer)
|
|
.expect("file has been pulled");
|
|
assert_eq!(buffer, content.as_bytes());
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_push_pull_large_binary_file() {
|
|
run_device_test(
|
|
|device: &Device, _: &TempDir, remote_root_path: &UnixPath| {
|
|
let remote_path = remote_root_path.join("foo.binary");
|
|
|
|
let mut content = Vec::new();
|
|
|
|
// Needs to be larger than 64kB to test multiple chunks.
|
|
for i in 0..100000u32 {
|
|
content.push('0' as u8 + (i % 10) as u8);
|
|
}
|
|
|
|
device
|
|
.push(
|
|
&mut std::io::Cursor::new(content.clone()),
|
|
&remote_path,
|
|
0o777,
|
|
)
|
|
.expect("large file has been pushed");
|
|
|
|
let output = device
|
|
.execute_host_shell_command(&format!("ls -l {}", remote_path.display()))
|
|
.expect("host shell command for 'ls' to succeed");
|
|
|
|
assert!(output.contains(remote_path.to_str().unwrap()));
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
device
|
|
.pull(&remote_path, &mut buffer)
|
|
.expect("large binary file has been pulled");
|
|
assert_eq!(buffer, content);
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_push_permission() {
|
|
run_device_test(
|
|
|device: &Device, _: &TempDir, remote_root_path: &UnixPath| {
|
|
fn adjust_mode(mode: u32) -> u32 {
|
|
// Adjust the mode by copying the user permissions to
|
|
// group and other as indicated in
|
|
// [send_impl](https://android.googlesource.com/platform/system/core/+/master/adb/daemon/file_sync_service.cpp#516).
|
|
// This ensures that group and other can both access a
|
|
// file if the user can access it.
|
|
let mut m = mode & 0o777;
|
|
m |= (m >> 3) & 0o070;
|
|
m |= (m >> 3) & 0o007;
|
|
m
|
|
}
|
|
|
|
fn get_permissions(mode: u32) -> String {
|
|
// Convert the mode integer into the string representation
|
|
// of the mode returned by `ls`. This assumes the object is
|
|
// a file and not a directory.
|
|
let mut perms = vec!["-", "r", "w", "x", "r", "w", "x", "r", "w", "x"];
|
|
let mut bit_pos = 0;
|
|
while bit_pos < 9 {
|
|
if (1 << bit_pos) & mode == 0 {
|
|
perms[9 - bit_pos] = "-"
|
|
}
|
|
bit_pos += 1;
|
|
}
|
|
perms.concat()
|
|
}
|
|
let content = "test";
|
|
let remote_path = remote_root_path.join("foo.bar");
|
|
|
|
// First push the file to the device
|
|
let modes = vec![0o421, 0o644, 0o666, 0o777];
|
|
for mode in modes {
|
|
let adjusted_mode = adjust_mode(mode);
|
|
let adjusted_perms = get_permissions(adjusted_mode);
|
|
device
|
|
.push(
|
|
&mut io::BufReader::new(content.as_bytes()),
|
|
&remote_path,
|
|
mode,
|
|
)
|
|
.expect("file has been pushed");
|
|
|
|
let output = device
|
|
.execute_host_shell_command(&format!("ls -l {}", remote_path.display()))
|
|
.expect("host shell command for 'ls' to succeed");
|
|
|
|
assert!(output.contains(remote_path.to_str().unwrap()));
|
|
assert!(output.starts_with(&adjusted_perms));
|
|
}
|
|
|
|
let output = device
|
|
.execute_host_shell_command(&format!("ls -ld {}", remote_root_path.display()))
|
|
.expect("host shell command for 'ls parent' to succeed");
|
|
|
|
assert!(output.contains(remote_root_path.to_str().unwrap()));
|
|
assert!(output.starts_with("drwxrwxrwx"));
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_pull_fails_for_missing_file() {
|
|
run_device_test(
|
|
|device: &Device, _: &TempDir, remote_root_path: &UnixPath| {
|
|
let mut buffer = Vec::new();
|
|
|
|
device
|
|
.pull(&remote_root_path.join("missing"), &mut buffer)
|
|
.expect_err("missing file should not be pulled");
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_push_and_list_dir() {
|
|
run_device_test(
|
|
|device: &Device, tmp_dir: &TempDir, remote_root_path: &UnixPath| {
|
|
let files = ["foo1.bar", "foo2.bar", "bar/foo3.bar", "bar/more/foo3.bar"];
|
|
|
|
for file in files.iter() {
|
|
let path = tmp_dir.path().join(Path::new(file));
|
|
let _ = std::fs::create_dir_all(path.parent().unwrap());
|
|
|
|
let f = File::create(path).expect("to create file");
|
|
let mut f = io::BufWriter::new(f);
|
|
f.write_all(file.as_bytes()).expect("to write data");
|
|
}
|
|
|
|
device
|
|
.push_dir(tmp_dir.path(), &remote_root_path, 0o777)
|
|
.expect("to push_dir");
|
|
|
|
for file in files.iter() {
|
|
let path = append_components(remote_root_path, Path::new(file)).unwrap();
|
|
let output = device
|
|
.execute_host_shell_command(&format!("ls {}", path.display()))
|
|
.expect("host shell command for 'ls' to succeed");
|
|
|
|
assert!(output.contains(path.to_str().unwrap()));
|
|
}
|
|
|
|
let mut listings = device.list_dir(&remote_root_path).expect("to list_dir");
|
|
listings.sort();
|
|
assert_eq!(
|
|
listings,
|
|
vec![
|
|
RemoteDirEntry {
|
|
depth: 0,
|
|
name: "foo1.bar".to_string(),
|
|
metadata: RemoteMetadata::RemoteFile(RemoteFileMetadata {
|
|
mode: 0b110110000,
|
|
size: 8
|
|
})
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 0,
|
|
name: "foo2.bar".to_string(),
|
|
metadata: RemoteMetadata::RemoteFile(RemoteFileMetadata {
|
|
mode: 0b110110000,
|
|
size: 8
|
|
})
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 0,
|
|
name: "bar".to_string(),
|
|
metadata: RemoteMetadata::RemoteDir
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 1,
|
|
name: "bar/foo3.bar".to_string(),
|
|
metadata: RemoteMetadata::RemoteFile(RemoteFileMetadata {
|
|
mode: 0b110110000,
|
|
size: 12
|
|
})
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 1,
|
|
name: "bar/more".to_string(),
|
|
metadata: RemoteMetadata::RemoteDir
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 2,
|
|
name: "bar/more/foo3.bar".to_string(),
|
|
metadata: RemoteMetadata::RemoteFile(RemoteFileMetadata {
|
|
mode: 0b110110000,
|
|
size: 17
|
|
})
|
|
}
|
|
]
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_push_and_pull_dir() {
|
|
run_device_test(
|
|
|device: &Device, tmp_dir: &TempDir, remote_root_path: &UnixPath| {
|
|
let files = ["foo1.bar", "foo2.bar", "bar/foo3.bar", "bar/more/foo3.bar"];
|
|
|
|
let src_dir = tmp_dir.path().join(Path::new("src"));
|
|
let dest_dir = tmp_dir.path().join(Path::new("src"));
|
|
|
|
for file in files.iter() {
|
|
let path = src_dir.join(Path::new(file));
|
|
let _ = std::fs::create_dir_all(path.parent().unwrap());
|
|
|
|
let f = File::create(path).expect("to create file");
|
|
let mut f = io::BufWriter::new(f);
|
|
f.write_all(file.as_bytes()).expect("to write data");
|
|
}
|
|
|
|
device
|
|
.push_dir(&src_dir, &remote_root_path, 0o777)
|
|
.expect("to push_dir");
|
|
|
|
device
|
|
.pull_dir(remote_root_path, &dest_dir)
|
|
.expect("to pull_dir");
|
|
|
|
for file in files.iter() {
|
|
let path = dest_dir.join(Path::new(file));
|
|
let mut f = File::open(path).expect("to open file");
|
|
let mut buf = String::new();
|
|
f.read_to_string(&mut buf).expect("to read content");
|
|
assert_eq!(buf, *file);
|
|
}
|
|
},
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn device_push_and_list_dir_flat() {
|
|
run_device_test(
|
|
|device: &Device, tmp_dir: &TempDir, remote_root_path: &UnixPath| {
|
|
let content = "test";
|
|
|
|
let files = [
|
|
PathBuf::from("foo1.bar"),
|
|
PathBuf::from("foo2.bar"),
|
|
PathBuf::from("bar").join("foo3.bar"),
|
|
];
|
|
|
|
for file in files.iter() {
|
|
let path = tmp_dir.path().join(&file);
|
|
let _ = std::fs::create_dir_all(path.parent().unwrap());
|
|
|
|
let f = File::create(path).expect("to create file");
|
|
let mut f = io::BufWriter::new(f);
|
|
f.write_all(content.as_bytes()).expect("to write data");
|
|
}
|
|
|
|
device
|
|
.push_dir(tmp_dir.path(), &remote_root_path, 0o777)
|
|
.expect("to push_dir");
|
|
|
|
for file in files.iter() {
|
|
let path = append_components(remote_root_path, file).unwrap();
|
|
let output = device
|
|
.execute_host_shell_command(&format!("ls {}", path.display()))
|
|
.expect("host shell command for 'ls' to succeed");
|
|
|
|
assert!(output.contains(path.to_str().unwrap()));
|
|
}
|
|
|
|
let mut listings = device
|
|
.list_dir_flat(&remote_root_path, 7, "prefix".to_string())
|
|
.expect("to list_dir_flat");
|
|
listings.sort();
|
|
assert_eq!(
|
|
listings,
|
|
vec![
|
|
RemoteDirEntry {
|
|
depth: 7,
|
|
metadata: RemoteMetadata::RemoteFile(RemoteFileMetadata {
|
|
mode: 0b110110000,
|
|
size: 4
|
|
}),
|
|
name: "prefix/foo1.bar".to_string(),
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 7,
|
|
metadata: RemoteMetadata::RemoteFile(RemoteFileMetadata {
|
|
mode: 0b110110000,
|
|
size: 4
|
|
}),
|
|
name: "prefix/foo2.bar".to_string(),
|
|
},
|
|
RemoteDirEntry {
|
|
depth: 7,
|
|
metadata: RemoteMetadata::RemoteDir,
|
|
name: "prefix/bar".to_string(),
|
|
},
|
|
]
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn format_own_device_error_types() {
|
|
assert_eq!(
|
|
format!("{}", DeviceError::InvalidStorage),
|
|
"Invalid storage".to_string()
|
|
);
|
|
assert_eq!(
|
|
format!("{}", DeviceError::MissingPackage),
|
|
"Missing package".to_string()
|
|
);
|
|
assert_eq!(
|
|
format!("{}", DeviceError::MultipleDevices),
|
|
"Multiple Android devices online".to_string()
|
|
);
|
|
|
|
assert_eq!(
|
|
format!("{}", DeviceError::Adb("foo".to_string())),
|
|
"foo".to_string()
|
|
);
|
|
}
|