Skip to content

Commit 177e698

Browse files
authored
Rollup merge of rust-lang#72672 - seritools:remote-test-windows, r=Mark-Simulacrum
Make remote-test-client and remote-test-server compatible with windows `compiletest` and `remote-test-client`: The command line for `remote-test-client` was changed slightly to allow cross-platform compatible paths. The old way of supplying the support libs was by joining their paths with the executable path with `:`. This caused Windows-style paths to be split after the directory letter. Now, the number of support libs is provided as a parameter as well, and the support lib paths are split off from the regular args in the client. `remote-test-server`: - Marked Unix-only parts as such and implemented Windows alternatives - On Windows `LD_LIBRARY_PATH` doesn't exist. Libraries are loaded from `PATH` though, so that's the way around it. - Tiny cleanup: `Command::args`/`envs` instead of manually looping over them - The temp path for Windows has to be set via environment variable, since there isn't a global temp directory that would work on every machine (as a static string)
2 parents 29704a0 + 36d6791 commit 177e698

File tree

3 files changed

+83
-36
lines changed

3 files changed

+83
-36
lines changed

src/tools/compiletest/src/runtest.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -1584,29 +1584,35 @@ impl<'test> TestCx<'test> {
15841584
//
15851585
// into
15861586
//
1587-
// remote-test-client run program:support-lib.so arg1 arg2
1587+
// remote-test-client run program 2 support-lib.so support-lib2.so arg1 arg2
15881588
//
15891589
// The test-client program will upload `program` to the emulator
15901590
// along with all other support libraries listed (in this case
1591-
// `support-lib.so`. It will then execute the program on the
1592-
// emulator with the arguments specified (in the environment we give
1593-
// the process) and then report back the same result.
1591+
// `support-lib.so` and `support-lib2.so`. It will then execute
1592+
// the program on the emulator with the arguments specified
1593+
// (in the environment we give the process) and then report back
1594+
// the same result.
15941595
_ if self.config.remote_test_client.is_some() => {
15951596
let aux_dir = self.aux_output_dir_name();
1596-
let ProcArgs { mut prog, args } = self.make_run_args();
1597+
let ProcArgs { prog, args } = self.make_run_args();
1598+
let mut support_libs = Vec::new();
15971599
if let Ok(entries) = aux_dir.read_dir() {
15981600
for entry in entries {
15991601
let entry = entry.unwrap();
16001602
if !entry.path().is_file() {
16011603
continue;
16021604
}
1603-
prog.push_str(":");
1604-
prog.push_str(entry.path().to_str().unwrap());
1605+
support_libs.push(entry.path());
16051606
}
16061607
}
16071608
let mut test_client =
16081609
Command::new(self.config.remote_test_client.as_ref().unwrap());
1609-
test_client.args(&["run", &prog]).args(args).envs(env.clone());
1610+
test_client
1611+
.args(&["run", &prog])
1612+
.arg(support_libs.len().to_string())
1613+
.args(support_libs)
1614+
.args(args)
1615+
.envs(env.clone());
16101616
self.compose_and_run(
16111617
test_client,
16121618
self.config.run_lib_path.to_str().unwrap(),

src/tools/remote-test-client/src/main.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ fn main() {
4444
args.next().map(|s| s.into()),
4545
),
4646
"push" => push(Path::new(&args.next().unwrap())),
47-
"run" => run(args.next().unwrap(), args.collect()),
47+
"run" => run(
48+
args.next().unwrap(),
49+
args.next().and_then(|count| count.parse().ok()).unwrap(),
50+
args.collect(),
51+
),
4852
"help" | "-h" | "--help" => help(),
4953
cmd => {
5054
println!("unknown command: {}", cmd);
@@ -197,12 +201,14 @@ fn push(path: &Path) {
197201
println!("done pushing {:?}", path);
198202
}
199203

200-
fn run(files: String, args: Vec<String>) {
204+
fn run(exe: String, support_lib_count: usize, all_args: Vec<String>) {
201205
let device_address = env::var(REMOTE_ADDR_ENV).unwrap_or(DEFAULT_ADDR.to_string());
202206
let client = t!(TcpStream::connect(device_address));
203207
let mut client = BufWriter::new(client);
204208
t!(client.write_all(b"run "));
205209

210+
let (support_libs, args) = all_args.split_at(support_lib_count);
211+
206212
// Send over the args
207213
for arg in args {
208214
t!(client.write_all(arg.as_bytes()));
@@ -227,9 +233,7 @@ fn run(files: String, args: Vec<String>) {
227233
t!(client.write_all(&[0]));
228234

229235
// Send over support libraries
230-
let mut files = files.split(':');
231-
let exe = files.next().unwrap();
232-
for file in files.map(Path::new) {
236+
for file in support_libs.iter().map(Path::new) {
233237
send(&file, &mut client);
234238
}
235239
t!(client.write_all(&[0]));

src/tools/remote-test-server/src/main.rs

+60-23
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212
1313
#![deny(warnings)]
1414

15+
#[cfg(not(windows))]
16+
use std::fs::Permissions;
17+
#[cfg(not(windows))]
18+
use std::os::unix::prelude::*;
19+
1520
use std::cmp;
1621
use std::env;
17-
use std::fs::{self, File, Permissions};
22+
use std::fs::{self, File};
1823
use std::io::prelude::*;
1924
use std::io::{self, BufReader};
2025
use std::net::{TcpListener, TcpStream};
21-
use std::os::unix::prelude::*;
2226
use std::path::{Path, PathBuf};
23-
use std::process::{Command, Stdio};
27+
use std::process::{Command, ExitStatus, Stdio};
2428
use std::str;
2529
use std::sync::atomic::{AtomicUsize, Ordering};
2630
use std::sync::{Arc, Mutex};
@@ -72,21 +76,23 @@ fn main() {
7276

7377
let config = Config::parse_args();
7478

75-
let bind_addr = if cfg!(target_os = "android") || config.remote {
79+
let bind_addr = if cfg!(target_os = "android") || cfg!(windows) || config.remote {
7680
"0.0.0.0:12345"
7781
} else {
7882
"10.0.2.15:12345"
7983
};
8084

81-
let (listener, work) = if cfg!(target_os = "android") {
82-
(t!(TcpListener::bind(bind_addr)), "/data/tmp/work")
85+
let listener = t!(TcpListener::bind(bind_addr));
86+
let work: PathBuf = if cfg!(target_os = "android") {
87+
"/data/tmp/work".into()
8388
} else {
84-
(t!(TcpListener::bind(bind_addr)), "/tmp/work")
89+
let mut temp_dir = env::temp_dir();
90+
temp_dir.push("work");
91+
temp_dir
8592
};
8693
println!("listening!");
8794

88-
let work = Path::new(work);
89-
t!(fs::create_dir_all(work));
95+
t!(fs::create_dir_all(&work));
9096

9197
let lock = Arc::new(Mutex::new(()));
9298

@@ -99,10 +105,11 @@ fn main() {
99105
if &buf[..] == b"ping" {
100106
t!(socket.write_all(b"pong"));
101107
} else if &buf[..] == b"push" {
102-
handle_push(socket, work);
108+
handle_push(socket, &work);
103109
} else if &buf[..] == b"run " {
104110
let lock = lock.clone();
105-
thread::spawn(move || handle_run(socket, work, &lock));
111+
let work = work.clone();
112+
thread::spawn(move || handle_run(socket, &work, &lock));
106113
} else {
107114
panic!("unknown command {:?}", buf);
108115
}
@@ -196,17 +203,28 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
196203
let exe = recv(&path, &mut reader);
197204

198205
let mut cmd = Command::new(&exe);
199-
for arg in args {
200-
cmd.arg(arg);
201-
}
202-
for (k, v) in env {
203-
cmd.env(k, v);
204-
}
206+
cmd.args(args);
207+
cmd.envs(env);
205208

206209
// Support libraries were uploaded to `work` earlier, so make sure that's
207210
// in `LD_LIBRARY_PATH`. Also include our own current dir which may have
208211
// had some libs uploaded.
209-
cmd.env("LD_LIBRARY_PATH", format!("{}:{}", work.display(), path.display()));
212+
if cfg!(windows) {
213+
// On windows, libraries are just searched in the executable directory,
214+
// system directories, PWD, and PATH, in that order. PATH is the only one
215+
// we can change for this.
216+
cmd.env(
217+
"PATH",
218+
env::join_paths(
219+
std::iter::once(work.to_owned())
220+
.chain(std::iter::once(path.clone()))
221+
.chain(env::split_paths(&env::var_os("PATH").unwrap())),
222+
)
223+
.unwrap(),
224+
);
225+
} else {
226+
cmd.env("LD_LIBRARY_PATH", format!("{}:{}", work.display(), path.display()));
227+
}
210228

211229
// Spawn the child and ferry over stdout/stderr to the socket in a framed
212230
// fashion (poor man's style)
@@ -223,10 +241,9 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
223241

224242
// Finally send over the exit status.
225243
let status = t!(child.wait());
226-
let (which, code) = match status.code() {
227-
Some(n) => (0, n),
228-
None => (1, status.signal().unwrap()),
229-
};
244+
245+
let (which, code) = get_status_code(&status);
246+
230247
t!(socket.lock().unwrap().write_all(&[
231248
which,
232249
(code >> 24) as u8,
@@ -236,6 +253,19 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
236253
]));
237254
}
238255

256+
#[cfg(not(windows))]
257+
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
258+
match status.code() {
259+
Some(n) => (0, n),
260+
None => (1, status.signal().unwrap()),
261+
}
262+
}
263+
264+
#[cfg(windows)]
265+
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
266+
(0, status.code().unwrap())
267+
}
268+
239269
fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
240270
let mut filename = Vec::new();
241271
t!(io.read_until(0, &mut filename));
@@ -253,10 +283,17 @@ fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
253283
let dst = dir.join(t!(str::from_utf8(&filename[..len])));
254284
let amt = read_u32(io) as u64;
255285
t!(io::copy(&mut io.take(amt), &mut t!(File::create(&dst))));
256-
t!(fs::set_permissions(&dst, Permissions::from_mode(0o755)));
286+
set_permissions(&dst);
257287
dst
258288
}
259289

290+
#[cfg(not(windows))]
291+
fn set_permissions(path: &Path) {
292+
t!(fs::set_permissions(&path, Permissions::from_mode(0o755)));
293+
}
294+
#[cfg(windows)]
295+
fn set_permissions(_path: &Path) {}
296+
260297
fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
261298
let mut b = [0; 1024];
262299
loop {

0 commit comments

Comments
 (0)