Skip to content

Commit 2554087

Browse files
authored
Merge pull request #2401 from sporksmith/miri
Run tests under Miri in CI
2 parents 6944c55 + 2b8750b commit 2554087

File tree

9 files changed

+115
-19
lines changed

9 files changed

+115
-19
lines changed

.github/workflows/sanitizers.yml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Syntax reference:
2+
# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions
3+
4+
name: Rust Sanitizers
5+
permissions: read-all
6+
7+
on:
8+
push:
9+
branches: [main]
10+
pull_request:
11+
types: [opened, synchronize]
12+
13+
14+
jobs:
15+
miri:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- uses: actions/checkout@v3
20+
with:
21+
persist-credentials: false
22+
# Run on PR head instead of merge result. Running on the merge
23+
# result can give confusing results, and we require PR to be up to
24+
# date with target branch before merging, anyway.
25+
# See https://github.com/shadow/shadow/issues/2166
26+
ref: ${{ github.event.pull_request.head.sha }}
27+
28+
# From https://github.com/rust-lang/miri#running-miri-on-ci
29+
- name: Install miri
30+
run: |
31+
rustup toolchain install nightly --component miri
32+
rustup override set nightly
33+
cargo miri setup
34+
35+
- name: Test
36+
run: |
37+
cd src
38+
# Disable isolation for some tests that use the current time (Instant::now).
39+
#
40+
# Disable leak-checking for now. Some tests intentionally panic, causing leaks.
41+
export MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks"
42+
43+
cargo miri test --workspace

src/lib/syscall-logger/src/lib.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,44 @@
11
use proc_macro::*;
22
use quote::ToTokens;
33

4-
/// This macro wraps a syscall handler function by renaming the original function and making a new
4+
// FIXME: These doctests are effectively disabled via `compile_fail`.
5+
// For them to work, this crate would need to depend on shadow_rs. We can't do that though,
6+
// since shadow_rs depends on this crate. This could perhaps be fixed by moving the parts
7+
// of shadow_rs neede by this crate out to a separate crate to break the cycle.
8+
/// This macro wraps a syscall handler by renaming the original function and making a new
59
/// function with the original name that calls the original function. When the syscall handler
610
/// function is called, it will log the syscall if syscall logging is enabled in Shadow.
711
///
812
/// For example,
913
///
10-
/// ```
11-
/// #[log_syscall(/* rv */ libc::c_int, /* fd */ libc::c_int)]
12-
/// pub fn close(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {}
14+
/// ```compile_fail
15+
/// # use syscall_logger::log_syscall;
16+
/// # use shadow_rs::host::context::ThreadContext;
17+
/// # use shadow_rs::host::syscall_types::{SysCallArgs, SyscallResult};
18+
/// struct MyHandler {}
19+
///
20+
/// impl MyHandler {
21+
/// #[log_syscall(/* rv */ libc::c_int, /* fd */ libc::c_int)]
22+
/// pub fn close(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {}
23+
/// }
1324
/// ```
1425
///
1526
/// will become,
1627
///
17-
/// ```
18-
/// pub fn close(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
19-
/// ...
20-
/// let rv = close_original(ctx, args);
21-
/// ...
22-
/// rv
23-
/// }
24-
/// fn close_original(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
28+
/// ```compile_fail
29+
/// # use shadow_rs::host::context::ThreadContext;
30+
/// # use shadow_rs::host::syscall_types::{SysCallArgs, SyscallResult};
31+
/// struct MyHandler {}
32+
///
33+
/// impl MyHandler {
34+
/// pub fn close(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
35+
/// // ...
36+
/// let rv = close_original(ctx, args);
37+
/// // ...
38+
/// rv
39+
/// }
40+
/// fn close_original(ctx: &mut ThreadContext, args: &SysCallArgs) -> SyscallResult {
41+
/// }
2542
/// }
2643
/// ```
2744
#[proc_macro_attribute]

src/main/core/support/configuration.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,8 @@ mod tests {
10891089
use super::*;
10901090

10911091
#[test]
1092+
// can't call foreign function: process_parseArgStr
1093+
#[cfg_attr(miri, ignore)]
10921094
fn test_parse_args() {
10931095
let arg_str = r#"the quick brown fox "jumped over" the "\"lazy\" dog""#;
10941096
let expected_args = &[
@@ -1108,6 +1110,8 @@ mod tests {
11081110
}
11091111

11101112
#[test]
1113+
// can't call foreign function: process_parseArgStr
1114+
#[cfg_attr(miri, ignore)]
11111115
fn test_parse_args_empty() {
11121116
let arg_str = "";
11131117
let expected_args: &[&str] = &[];
@@ -1119,6 +1123,8 @@ mod tests {
11191123
}
11201124

11211125
#[test]
1126+
// can't call foreign function: process_parseArgStr
1127+
#[cfg_attr(miri, ignore)]
11221128
fn test_parse_args_error() {
11231129
let arg_str = r#"hello "world"#;
11241130

@@ -1129,6 +1135,8 @@ mod tests {
11291135
}
11301136

11311137
#[test]
1138+
// can't call foreign function: process_parseArgStr
1139+
#[cfg_attr(miri, ignore)]
11321140
fn test_nullable_option() {
11331141
// format the yaml with an optional general option
11341142
let yaml_fmt_fn = |option| {

src/main/host/descriptor/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,8 @@ mod tests {
996996
use crate::host::syscall_types::{Blocked, Failed, SyscallError};
997997

998998
#[test]
999+
// can't call foreign function: syscallcondition_new
1000+
#[cfg_attr(miri, ignore)]
9991001
fn test_syscallresult_roundtrip() {
10001002
for val in vec![
10011003
Ok(1.into()),
@@ -1032,6 +1034,8 @@ mod tests {
10321034
}
10331035

10341036
#[test]
1037+
// can't call foreign function: syscallcondition_new
1038+
#[cfg_attr(miri, ignore)]
10351039
fn test_syscallreturn_roundtrip() {
10361040
let condition = SysCallCondition::new(Trigger::from(c::Trigger {
10371041
type_: 1,

src/main/host/syscall/format.rs

+2
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ mod test {
614614
use std::process::Command;
615615

616616
#[test]
617+
// can't call foreign function: gnu_get_libc_version
618+
#[cfg_attr(miri, ignore)]
617619
fn test_no_args() {
618620
let args = SysCallArgs {
619621
number: 100,

src/main/utility/childpid_watcher.rs

+8
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ mod tests {
359359
}
360360

361361
#[test]
362+
// can't call foreign function: pipe
363+
#[cfg_attr(miri, ignore)]
362364
fn register_before_exit() {
363365
let notifier = nix::sys::eventfd::eventfd(0, nix::sys::eventfd::EfdFlags::empty()).unwrap();
364366

@@ -412,6 +414,8 @@ mod tests {
412414
}
413415

414416
#[test]
417+
// can't call foreign function: pipe
418+
#[cfg_attr(miri, ignore)]
415419
fn register_after_exit() {
416420
let (read_fd, write_fd) = nix::unistd::pipe().unwrap();
417421
let child = match unsafe { nix::unistd::fork() }.unwrap() {
@@ -463,6 +467,8 @@ mod tests {
463467
}
464468

465469
#[test]
470+
// can't call foreign function: pipe
471+
#[cfg_attr(miri, ignore)]
466472
fn register_multiple() {
467473
let cb1_ran = Arc::new((Mutex::new(false), Condvar::new()));
468474
let cb2_ran = Arc::new((Mutex::new(false), Condvar::new()));
@@ -502,6 +508,8 @@ mod tests {
502508
}
503509

504510
#[test]
511+
// can't call foreign function: pipe
512+
#[cfg_attr(miri, ignore)]
505513
fn unregister_one() {
506514
let cb1_ran = Arc::new((Mutex::new(false), Condvar::new()));
507515
let cb2_ran = Arc::new((Mutex::new(false), Condvar::new()));

src/main/utility/interval_map.rs

+4
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ mod tests {
346346
}
347347

348348
#[test]
349+
// Too slow for miri
350+
#[cfg_attr(miri, ignore)]
349351
fn test_insert_random() {
350352
use rand::Rng;
351353
use rand_core::SeedableRng;
@@ -576,6 +578,8 @@ mod tests {
576578
}
577579

578580
#[test]
581+
// Too slow for miri
582+
#[cfg_attr(miri, ignore)]
579583
fn test_clear_random() {
580584
use rand::Rng;
581585
use rand_core::SeedableRng;

src/main/utility/proc_maps.rs

+3
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,9 @@ mod tests {
515515
}
516516

517517
#[test]
518+
// Hangs in miri. Not sure why, but also not surpring in general that this
519+
// test would be incompatible.
520+
#[cfg_attr(miri, ignore)]
518521
fn test_mappings_for_pid() {
519522
// Difficult to write a precise test here; just try to read our own mappings and validate
520523
// that it parses and is non-empty.

src/test/test_utils.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ where
247247
/// Similar to the `vec!` macro, `set!` will create a `HashSet` with the given elements.
248248
///
249249
/// ```
250+
/// # use test_utils::*;
250251
/// let s = set![1, 2, 3, 1];
251252
/// assert_eq!(s.len(), 3);
252253
/// ```
@@ -357,15 +358,21 @@ pub fn nop_sig_handler() -> nix::sys::signal::SigHandler {
357358
/// Example:
358359
///
359360
/// ```
360-
/// let x = 2;
361-
/// let y = 3;
362-
/// ensure_ord!(x, >, y);
363-
/// ```
361+
/// # use test_utils::*;
362+
/// # use anyhow::anyhow;
363+
/// fn fn1() -> Result<(), anyhow::Error> {
364+
/// let x = 2;
365+
/// let y = 3;
366+
/// ensure_ord!(x, >, y);
367+
/// Ok(())
368+
/// }
364369
///
365-
/// Will evaluate to the same error as:
370+
/// fn fn2() -> Result<(), anyhow::Error> {
371+
/// return Err(anyhow!("!(2 > 3)"));
372+
/// }
366373
///
367-
/// ```
368-
/// anyhow!("!(3 > 2)");
374+
/// assert_eq!(format!("{}", fn1().unwrap_err()),
375+
/// format!("{}", fn2().unwrap_err()));
369376
/// ```
370377
#[macro_export]
371378
macro_rules! ensure_ord {

0 commit comments

Comments
 (0)