Skip to content

Commit 8904ff1

Browse files
authored
Rollup merge of #146762 - madsmtm:test-apple-sim, r=jieyouxu
Fix and provide instructions for running test suite on Apple simulators The following now works: ```sh ./x test --host='' --target aarch64-apple-ios-sim --skip tests/debuginfo ./x test --host='' --target aarch64-apple-tvos-sim --skip tests/debuginfo ./x test --host='' --target aarch64-apple-watchos-sim --skip tests/debuginfo ./x test --host='' --target aarch64-apple-visionos-sim --skip tests/debuginfo ``` I have documented the setup I used [in the `rustc-dev-guide`](https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators), it's fairly standard use of `remote-test-server` (with a small fix to library load paths which I've made in the first commit). I first tried the somewhat simpler `target.aarch64-apple-ios-sim.runner = "xcrun simctl spawn $UDID"`, but that doesn't work as required libraries etc. also need to be copied to the device. The debuginfo tests fail, I think because the debug info in `.dSYM` isn't available. I am yet unsure exactly how to fix this, either we need to copy that directory to the target as well, or we need to configure `lldb` somehow to read it from the host. I decided to not add this to our CI, since I suspect we wouldn't gain much from it? Running on the simulator still uses the host Darwin kernel, it's basically just configured to run in another mode with more restricted permissions and different system libraries. r? jieyouxu CC ``@simlay,`` you're a lot more familiar with `xcrun simctl` than I.
2 parents 5f8062b + 37be934 commit 8904ff1

33 files changed

+245
-77
lines changed

library/std/src/os/unix/process.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,10 @@ pub trait ChildExt: Sealed {
406406
/// use libc::SIGTERM;
407407
///
408408
/// fn main() -> io::Result<()> {
409+
/// # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
409410
/// let child = Command::new("cat").stdin(Stdio::piped()).spawn()?;
410411
/// child.send_signal(SIGTERM)?;
412+
/// # }
411413
/// Ok(())
412414
/// }
413415
/// ```

library/std/src/process.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ impl fmt::Debug for ChildStderr {
532532
/// to be changed (for example, by adding arguments) prior to spawning:
533533
///
534534
/// ```
535+
/// # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
535536
/// use std::process::Command;
536537
///
537538
/// let output = if cfg!(target_os = "windows") {
@@ -548,6 +549,7 @@ impl fmt::Debug for ChildStderr {
548549
/// };
549550
///
550551
/// let hello = output.stdout;
552+
/// # }
551553
/// ```
552554
///
553555
/// `Command` can be reused to spawn multiple processes. The builder methods
@@ -1348,7 +1350,7 @@ impl Output {
13481350
///
13491351
/// ```
13501352
/// #![feature(exit_status_error)]
1351-
/// # #[cfg(all(unix, not(target_os = "android")))] {
1353+
/// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
13521354
/// use std::process::Command;
13531355
/// assert!(Command::new("false").output().unwrap().exit_ok().is_err());
13541356
/// # }
@@ -1695,7 +1697,7 @@ impl From<io::Stdout> for Stdio {
16951697
/// # Ok(())
16961698
/// # }
16971699
/// #
1698-
/// # if cfg!(all(unix, not(target_os = "android"))) {
1700+
/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
16991701
/// # test().unwrap();
17001702
/// # }
17011703
/// ```
@@ -1724,7 +1726,7 @@ impl From<io::Stderr> for Stdio {
17241726
/// # Ok(())
17251727
/// # }
17261728
/// #
1727-
/// # if cfg!(all(unix, not(target_os = "android"))) {
1729+
/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
17281730
/// # test().unwrap();
17291731
/// # }
17301732
/// ```
@@ -1800,7 +1802,7 @@ impl ExitStatus {
18001802
///
18011803
/// ```
18021804
/// #![feature(exit_status_error)]
1803-
/// # if cfg!(unix) {
1805+
/// # if cfg!(all(unix, not(all(target_vendor = "apple", not(target_os = "macos"))))) {
18041806
/// use std::process::Command;
18051807
///
18061808
/// let status = Command::new("ls")
@@ -1907,7 +1909,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
19071909
///
19081910
/// ```
19091911
/// #![feature(exit_status_error)]
1910-
/// # if cfg!(all(unix, not(target_os = "android"))) {
1912+
/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
19111913
/// use std::process::{Command, ExitStatusError};
19121914
///
19131915
/// fn run(cmd: &str) -> Result<(), ExitStatusError> {
@@ -1950,7 +1952,7 @@ impl ExitStatusError {
19501952
///
19511953
/// ```
19521954
/// #![feature(exit_status_error)]
1953-
/// # #[cfg(all(unix, not(target_os = "android")))] {
1955+
/// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
19541956
/// use std::process::Command;
19551957
///
19561958
/// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err();
@@ -1975,7 +1977,7 @@ impl ExitStatusError {
19751977
/// ```
19761978
/// #![feature(exit_status_error)]
19771979
///
1978-
/// # if cfg!(all(unix, not(target_os = "android"))) {
1980+
/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
19791981
/// use std::num::NonZero;
19801982
/// use std::process::Command;
19811983
///

library/std/src/process/tests.rs

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ use crate::mem::MaybeUninit;
55
use crate::str;
66

77
fn known_command() -> Command {
8-
if cfg!(windows) { Command::new("help") } else { Command::new("echo") }
8+
if cfg!(windows) {
9+
Command::new("help")
10+
} else if cfg!(all(target_vendor = "apple", not(target_os = "macos"))) {
11+
// iOS/tvOS/watchOS/visionOS have a very limited set of commandline
12+
// binaries available.
13+
Command::new("log")
14+
} else {
15+
Command::new("echo")
16+
}
917
}
1018

1119
#[cfg(target_os = "android")]
@@ -19,7 +27,10 @@ fn shell_cmd() -> Command {
1927
}
2028

2129
#[test]
22-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
30+
#[cfg_attr(
31+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
32+
ignore = "no shell available"
33+
)]
2334
fn smoke() {
2435
let p = if cfg!(target_os = "windows") {
2536
Command::new("cmd").args(&["/C", "exit 0"]).spawn()
@@ -41,7 +52,10 @@ fn smoke_failure() {
4152
}
4253

4354
#[test]
44-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
55+
#[cfg_attr(
56+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
57+
ignore = "no shell available"
58+
)]
4559
fn exit_reported_right() {
4660
let p = if cfg!(target_os = "windows") {
4761
Command::new("cmd").args(&["/C", "exit 1"]).spawn()
@@ -56,7 +70,10 @@ fn exit_reported_right() {
5670

5771
#[test]
5872
#[cfg(unix)]
59-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
73+
#[cfg_attr(
74+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
75+
ignore = "no shell available"
76+
)]
6077
fn signal_reported_right() {
6178
use crate::os::unix::process::ExitStatusExt;
6279

@@ -80,7 +97,10 @@ pub fn run_output(mut cmd: Command) -> String {
8097
}
8198

8299
#[test]
83-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
100+
#[cfg_attr(
101+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
102+
ignore = "no shell available"
103+
)]
84104
fn stdout_works() {
85105
if cfg!(target_os = "windows") {
86106
let mut cmd = Command::new("cmd");
@@ -94,7 +114,11 @@ fn stdout_works() {
94114
}
95115

96116
#[test]
97-
#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
117+
#[cfg_attr(windows, ignore)]
118+
#[cfg_attr(
119+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
120+
ignore = "no shell available"
121+
)]
98122
fn set_current_dir_works() {
99123
// On many Unix platforms this will use the posix_spawn path.
100124
let mut cmd = shell_cmd();
@@ -116,7 +140,11 @@ fn set_current_dir_works() {
116140
}
117141

118142
#[test]
119-
#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
143+
#[cfg_attr(windows, ignore)]
144+
#[cfg_attr(
145+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
146+
ignore = "no shell available"
147+
)]
120148
fn stdin_works() {
121149
let mut p = shell_cmd()
122150
.arg("-c")
@@ -134,7 +162,10 @@ fn stdin_works() {
134162
}
135163

136164
#[test]
137-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
165+
#[cfg_attr(
166+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
167+
ignore = "no shell available"
168+
)]
138169
fn child_stdout_read_buf() {
139170
let mut cmd = if cfg!(target_os = "windows") {
140171
let mut cmd = Command::new("cmd");
@@ -165,7 +196,10 @@ fn child_stdout_read_buf() {
165196
}
166197

167198
#[test]
168-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
199+
#[cfg_attr(
200+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
201+
ignore = "no shell available"
202+
)]
169203
fn test_process_status() {
170204
let mut status = if cfg!(target_os = "windows") {
171205
Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap()
@@ -191,7 +225,10 @@ fn test_process_output_fail_to_start() {
191225
}
192226

193227
#[test]
194-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
228+
#[cfg_attr(
229+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
230+
ignore = "no shell available"
231+
)]
195232
fn test_process_output_output() {
196233
let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
197234
Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
@@ -206,7 +243,10 @@ fn test_process_output_output() {
206243
}
207244

208245
#[test]
209-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
246+
#[cfg_attr(
247+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
248+
ignore = "no shell available"
249+
)]
210250
fn test_process_output_error() {
211251
let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
212252
Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
@@ -221,7 +261,10 @@ fn test_process_output_error() {
221261
}
222262

223263
#[test]
224-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
264+
#[cfg_attr(
265+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
266+
ignore = "no shell available"
267+
)]
225268
fn test_finish_once() {
226269
let mut prog = if cfg!(target_os = "windows") {
227270
Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -232,7 +275,10 @@ fn test_finish_once() {
232275
}
233276

234277
#[test]
235-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
278+
#[cfg_attr(
279+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
280+
ignore = "no shell available"
281+
)]
236282
fn test_finish_twice() {
237283
let mut prog = if cfg!(target_os = "windows") {
238284
Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -244,7 +290,10 @@ fn test_finish_twice() {
244290
}
245291

246292
#[test]
247-
#[cfg_attr(any(target_os = "vxworks"), ignore)]
293+
#[cfg_attr(
294+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
295+
ignore = "no shell available"
296+
)]
248297
fn test_wait_with_output_once() {
249298
let prog = if cfg!(target_os = "windows") {
250299
Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap()
@@ -279,7 +328,10 @@ pub fn env_cmd() -> Command {
279328
}
280329

281330
#[test]
282-
#[cfg_attr(target_os = "vxworks", ignore)]
331+
#[cfg_attr(
332+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
333+
ignore = "no shell available"
334+
)]
283335
fn test_override_env() {
284336
use crate::env;
285337

@@ -302,7 +354,10 @@ fn test_override_env() {
302354
}
303355

304356
#[test]
305-
#[cfg_attr(target_os = "vxworks", ignore)]
357+
#[cfg_attr(
358+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
359+
ignore = "no shell available"
360+
)]
306361
fn test_add_to_env() {
307362
let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
308363
let output = String::from_utf8_lossy(&result.stdout).to_string();
@@ -314,7 +369,10 @@ fn test_add_to_env() {
314369
}
315370

316371
#[test]
317-
#[cfg_attr(target_os = "vxworks", ignore)]
372+
#[cfg_attr(
373+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
374+
ignore = "no shell available"
375+
)]
318376
fn test_capture_env_at_spawn() {
319377
use crate::env;
320378

@@ -378,7 +436,10 @@ fn test_interior_nul_in_current_dir_is_error() {
378436

379437
// Regression tests for #30862.
380438
#[test]
381-
#[cfg_attr(target_os = "vxworks", ignore)]
439+
#[cfg_attr(
440+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
441+
ignore = "no `env` cmd available"
442+
)]
382443
fn test_interior_nul_in_env_key_is_error() {
383444
match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
384445
Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
@@ -387,7 +448,10 @@ fn test_interior_nul_in_env_key_is_error() {
387448
}
388449

389450
#[test]
390-
#[cfg_attr(target_os = "vxworks", ignore)]
451+
#[cfg_attr(
452+
any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
453+
ignore = "no `env` cmd available"
454+
)]
391455
fn test_interior_nul_in_env_value_is_error() {
392456
match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
393457
Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),

library/std/src/sys/process/unix/unix/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ fn exitstatus_display_tests() {
5151

5252
#[test]
5353
#[cfg_attr(target_os = "emscripten", ignore)]
54+
#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
5455
fn test_command_fork_no_unwind() {
5556
let got = catch_unwind(|| {
5657
let mut c = Command::new("echo");

library/std/tests/process_spawning.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod common;
77
#[test]
88
// Process spawning not supported by Miri, Emscripten and wasi
99
#[cfg_attr(any(miri, target_os = "emscripten", target_os = "wasi"), ignore)]
10+
#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
1011
fn issue_15149() {
1112
// If we're the parent, copy our own binary to a new directory.
1213
let my_path = env::current_exe().unwrap();

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,34 @@ results. The Docker image is set up to launch `remote-test-server` and the
339339
build tools use `remote-test-client` to communicate with the server to
340340
coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
341341

342-
> **TODO**
343-
>
344-
> - Is there any support for using an iOS emulator?
342+
To run on the iOS/tvOS/watchOS/visionOS simulator, we can similarly treat it as
343+
a "remote" machine. A curious detail here is that the network is shared between
344+
the simulator instance and the host macOS, so we can use the local loopback
345+
address `127.0.0.1`. Something like the following should work:
346+
347+
```sh
348+
# Build the test server for the iOS simulator:
349+
./x build src/tools/remote-test-server --target aarch64-apple-ios-sim
350+
351+
# If you already have a simulator instance open, copy the device UUID from:
352+
xcrun simctl list devices booted
353+
UDID=01234567-89AB-CDEF-0123-456789ABCDEF
354+
355+
# Alternatively, create and boot a new simulator instance:
356+
xcrun simctl list runtimes
357+
xcrun simctl list devicetypes
358+
UDID=$(xcrun simctl create $CHOSEN_DEVICE_TYPE $CHOSEN_RUNTIME)
359+
xcrun simctl boot $UDID
360+
# See https://nshipster.com/simctl/ for details.
361+
362+
# Spawn the runner on port 12345:
363+
xcrun simctl spawn $UDID ./build/host/stage2-tools/aarch64-apple-ios-sim/release/remote-test-server -v --bind 127.0.0.1:12345
364+
365+
# In a new terminal, run tests via the runner:
366+
export TEST_DEVICE_ADDR="127.0.0.1:12345"
367+
./x test --host='' --target aarch64-apple-ios-sim --skip tests/debuginfo
368+
# FIXME(madsmtm): Allow debuginfo tests to work (maybe needs `.dSYM` folder to be copied to the target?).
369+
```
345370

346371
[armhf-gnu]: https://github.com/rust-lang/rust/tree/master/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
347372
[QEMU]: https://www.qemu.org/

0 commit comments

Comments
 (0)