Skip to content

Commit c141add

Browse files
authored
Unrolled build for #147952
Rollup merge of #147952 - ferrocene:pvdrz/remote-test-client-timeout, r=Enselic Add a timeout to the `remote-test-client` connection Currently, the `remote-test-client` doesn't have a timeout when connecting to the `remote-test-server`. This means that running tests using it can hang indefinitely which causes issues when running tests on CI, for example. This PR now sets a default timeout of 5 minutes, meaning that if, for example, `TEST_DEVICE_ADDR=<IP:PORT> ./x test --target riscv64gc-unknown-linux-gnu tests/ui` is run and the `remote-test-server` is not reachable by the client, the client will panic after the timeout is reached. Additionally, the `TEST_DEVICE_CONNECT_TIMEOUT` env variable can be used to set up the timeout to any value (in seconds). This PR also wires up a test step for `remote-test-client`, which didn't previously have tool tests run in CI. Edit: ~~blocked by #149071~~
2 parents 9050733 + 6bd5de7 commit c141add

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

src/doc/rustc-dev-guide/src/tests/running.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ Tests are built on the machine running `x` not on the remote machine.
321321
Tests which fail to build unexpectedly (or `ui` tests producing incorrect build
322322
output) may fail without ever running on the remote machine.
323323

324+
There is a default timeout of 30 minutes in case the `remote-test-server`
325+
cannot be reached by the `x` command. This timeout can be modified by using the
326+
`TEST_DEVICE_CONNECT_TIMEOUT_SECONDS` environment variable.
327+
324328
## Testing on emulators
325329

326330
Some platforms are tested via an emulator for architectures that aren't readily available.

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ use std::io::{self, BufWriter};
1111
use std::net::TcpStream;
1212
use std::path::{Path, PathBuf};
1313
use std::process::{Command, Stdio};
14-
use std::time::Duration;
14+
use std::time::{Duration, Instant};
1515
use std::{env, thread};
1616

1717
const REMOTE_ADDR_ENV: &str = "TEST_DEVICE_ADDR";
1818
const DEFAULT_ADDR: &str = "127.0.0.1:12345";
1919

20+
const CONNECT_TIMEOUT_ENV: &str = "TEST_DEVICE_CONNECT_TIMEOUT_SECONDS";
21+
/// The default timeout is high to not break slow CI or slow device starts.
22+
const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_mins(30);
23+
2024
macro_rules! t {
2125
($e:expr) => {
2226
match $e {
@@ -56,6 +60,17 @@ fn main() {
5660
}
5761
}
5862

63+
fn connect_timeout() -> Duration {
64+
match env::var(CONNECT_TIMEOUT_ENV).ok() {
65+
Some(timeout) => timeout.parse().map(Duration::from_secs).unwrap_or_else(|e| {
66+
panic!(
67+
"error: parsing `{CONNECT_TIMEOUT_ENV}` value \"{timeout}\" as seconds failed: {e}"
68+
)
69+
}),
70+
None => DEFAULT_CONNECT_TIMEOUT,
71+
}
72+
}
73+
5974
fn spawn_emulator(target: &str, server: &Path, tmpdir: &Path, rootfs: Option<PathBuf>) {
6075
let device_address = env::var(REMOTE_ADDR_ENV).unwrap_or(DEFAULT_ADDR.to_string());
6176

@@ -69,20 +84,28 @@ fn spawn_emulator(target: &str, server: &Path, tmpdir: &Path, rootfs: Option<Pat
6984
}
7085

7186
// Wait for the emulator to come online
72-
loop {
87+
let timeout = connect_timeout();
88+
let mut successful_read = false;
89+
let start_time = Instant::now();
90+
while start_time.elapsed() < timeout {
7391
let dur = Duration::from_millis(2000);
7492
if let Ok(mut client) = TcpStream::connect(&device_address) {
7593
t!(client.set_read_timeout(Some(dur)));
7694
t!(client.set_write_timeout(Some(dur)));
7795
if client.write_all(b"ping").is_ok() {
7896
let mut b = [0; 4];
7997
if client.read_exact(&mut b).is_ok() {
98+
successful_read = true;
8099
break;
81100
}
82101
}
83102
}
84103
thread::sleep(dur);
85104
}
105+
106+
if !successful_read {
107+
panic!("Gave up trying to connect to test device at {device_address} after {timeout:?}");
108+
}
86109
}
87110

88111
fn start_android_emulator(server: &Path) {

src/tools/remote-test-client/tests/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,18 @@ fn test_help() {
88
let stdout = String::from_utf8(output.stdout.clone()).unwrap();
99
assert!(stdout.trim().starts_with("Usage:"));
1010
}
11+
12+
#[test]
13+
fn test_timeout() {
14+
let mut cmd = assert_cmd::cargo::cargo_bin_cmd!();
15+
cmd.env("TEST_DEVICE_CONNECT_TIMEOUT_SECONDS", "1");
16+
cmd.env("TEST_DEVICE_ADDR", "127.69.69.69:6969");
17+
cmd.args(["spawn-emulator", "dummy-target", "dummy-server", "dummy-tmpdir"]);
18+
19+
let assert = cmd.assert().failure();
20+
let output = assert.get_output();
21+
22+
let stderr = String::from_utf8(output.stderr.clone()).unwrap();
23+
let pass_msg = "Gave up trying to connect to test device";
24+
assert!(stderr.contains(pass_msg), "Could not find `{pass_msg}` in `{stderr}`");
25+
}

0 commit comments

Comments
 (0)