Skip to content

Commit bc4c998

Browse files
committed
Split compiler tests and local tests
1 parent 96ac2b4 commit bc4c998

File tree

9 files changed

+310
-40
lines changed

9 files changed

+310
-40
lines changed

.github/scripts/run_own_tests.sh

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# Execute our own set of tests using a local `compiletest` tool based on `ui_test`.
3+
set -e
4+
set -u
5+
6+
# Where we will store the SMIR tools (Optional).
7+
TOOLS_BIN="${TOOLS_BIN:-"/tmp/smir/bin"}"
8+
# Assume we are inside SMIR repository
9+
SMIR_PATH=$(git rev-parse --show-toplevel)
10+
export RUST_BACKTRACE=1
11+
12+
# Build stable_mir tools
13+
function build_smir_tools() {
14+
pushd "${SMIR_PATH}"
15+
cargo +nightly build -Z unstable-options --out-dir "${TOOLS_BIN}"
16+
export PATH="${TOOLS_BIN}":"${PATH}"
17+
}
18+
19+
# Run tests
20+
function run_tests() {
21+
SUITES=(
22+
"sanity-checks pass"
23+
"fixme fail"
24+
)
25+
for suite_cfg in "${SUITES[@]}"; do
26+
# Hack to work on older bash like the ones on MacOS.
27+
suite_pair=($suite_cfg)
28+
suite=${suite_pair[0]}
29+
mode=${suite_pair[1]}
30+
echo "#### Running suite: ${suite} mode: ${mode}"
31+
compiletest \
32+
--driver-path="${TOOLS_BIN}/test-drive" \
33+
--mode=${mode} \
34+
--src-base="tests/${suite}" \
35+
--output-dir="target/tests/" \
36+
--no-capture
37+
done
38+
}
39+
40+
build_smir_tools
41+
run_tests

.github/scripts/run_rustc_tests.sh

+85-24
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,96 @@
11
#!/usr/bin/env bash
22

3+
# Run rustc test suites using our test driver using nightly.
4+
# This script leverages the rustc's repo compiletest crate.
5+
#
6+
# The suites configuration should match:
7+
# https://github.com/rust-lang/rust/blob/master/src/bootstrap/test.rs
8+
39
set -e
410
set -u
11+
export RUST_BACKTRACE=1
512

613
# Location of a rust repository. Clone one if path doesn't exist.
7-
RUST_REPO="${RUST_REPO:?Missing path to rust repository. Set RUST_REPO}"
14+
RUST_REPO="${RUST_REPO:-"/tmp/rustc"}"
15+
816
# Where we will store the SMIR tools (Optional).
917
TOOLS_BIN="${TOOLS_BIN:-"/tmp/smir/bin"}"
18+
1019
# Assume we are inside SMIR repository
1120
SMIR_PATH=$(git rev-parse --show-toplevel)
12-
export RUST_BACKTRACE=1
1321

14-
pushd "${SMIR_PATH}"
15-
cargo build -Z unstable-options --out-dir "${TOOLS_BIN}"
16-
export PATH="${TOOLS_BIN}":"${PATH}"
17-
18-
if [[ ! -e "${RUST_REPO}" ]]; then
19-
mkdir -p "$(dirname ${RUST_REPO})"
20-
git clone --depth 1 https://github.com/rust-lang/rust.git "${RUST_REPO}"
21-
fi
22-
23-
pushd "${RUST_REPO}"
24-
SUITES=(
25-
# Match https://github.com/rust-lang/rust/blob/master/src/bootstrap/test.rs for now
26-
"tests/ui/cfg yolo"
27-
)
28-
for suite_cfg in "${SUITES[@]}"; do
29-
# Hack to work on older bash like the ones on MacOS.
30-
suite_pair=($suite_cfg)
31-
suite=${suite_pair[0]}
32-
mode=${suite_pair[1]}
33-
echo "${suite_cfg} pair: $suite_pair mode: $mode"
34-
compiletest --driver-path="${TOOLS_BIN}/test-drive" --mode=${mode} --src-base="${suite}" --output-dir="${RUST_REPO}/build"
35-
done
22+
# Build stable_mir tools
23+
function build_smir_tools() {
24+
pushd "${SMIR_PATH}"
25+
cargo +nightly build -Z unstable-options --out-dir "${TOOLS_BIN}"
26+
export PATH="${TOOLS_BIN}":"${PATH}"
27+
}
28+
29+
# Set up rustc repository
30+
function setup_rustc_repo() {
31+
if [[ ! -e "${RUST_REPO}" ]]; then
32+
mkdir -p "$(dirname ${RUST_REPO})"
33+
git clone -b master https://github.com/rust-lang/rust.git "${RUST_REPO}"
34+
pushd "${RUST_REPO}"
35+
commit="$(rustc +nightly -vV | awk '/^commit-hash/ { print $2 }')"
36+
git checkout ${commit}
37+
git submodule init -- "${RUST_REPO}/library/stdarch"
38+
git submodule update
39+
else
40+
pushd "${RUST_REPO}"
41+
fi
42+
}
43+
44+
function run_tests() {
45+
# Run the following suite configuration for now (test suite + mode)
46+
SUITES=(
47+
"codegen codegen"
48+
"codegen-units codegen-units"
49+
# -- The suites below are failing because of fully qualified paths for standard library
50+
# E.g.:
51+
# - _10 = _eprint(move _11) -> [return: bb6, unwind unreachable];
52+
# + _10 = std::io::_eprint(move _11) -> [return: bb6, unwind unreachable];
53+
#
54+
#"ui ui"
55+
#"mir-opt mir-opt"
56+
#"pretty pretty" -- 2 failing tests
57+
)
58+
59+
SYSROOT=$(rustc +nightly --print sysroot)
60+
PY_PATH=$(type -P python3)
61+
HOST=$(rustc +nightly -vV | awk '/^host/ { print $2 }')
62+
FILE_CHECK="$(which FileCheck-12 || which FileCheck-13 || which FileCheck-14)"
63+
64+
for suite_cfg in "${SUITES[@]}"; do
65+
# Hack to work on older bash like the ones on MacOS.
66+
suite_pair=($suite_cfg)
67+
suite=${suite_pair[0]}
68+
mode=${suite_pair[1]}
69+
70+
echo "#### Running suite: ${suite} mode: ${mode}"
71+
cargo +nightly run -p compiletest -- \
72+
--compile-lib-path="${SYSROOT}/lib" \
73+
--run-lib-path="${SYSROOT}/lib"\
74+
--python="${PY_PATH}" \
75+
--rustc-path="${TOOLS_BIN}/test-drive" \
76+
--mode=${mode} \
77+
--suite="${suite}" \
78+
--src-base="tests/${suite}" \
79+
--build-base="$(pwd)/build/${HOST}/stage1/tests/${suite}" \
80+
--sysroot-base="$SYSROOT" \
81+
--stage-id=stage1-${HOST} \
82+
--cc= \
83+
--cxx= \
84+
--cflags= \
85+
--cxxflags= \
86+
--llvm-components= \
87+
--android-cross-path= \
88+
--target=${HOST} \
89+
--llvm-filecheck="${FILE_CHECK}" \
90+
--channel=nightly
91+
done
92+
}
93+
94+
build_smir_tools
95+
setup_rustc_repo
96+
run_tests

.github/workflows/nightly.yml

+10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ jobs:
1414
- name: Checkout
1515
uses: actions/checkout@v3
1616

17+
- name: Install latest nightly
18+
uses: actions-rs/toolchain@v1
19+
with:
20+
toolchain: nightly
21+
22+
- name: Test
23+
run: ./.github/scripts/run_own_tests.sh
24+
env:
25+
TOOLS_BIN: "/tmp/smir/bin"
26+
1727
- name: Test
1828
run: ./.github/scripts/run_rustc_tests.sh
1929
env:
+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Example derived from <https://doc.rust-lang.org/reference/items/associated-items.html>
2+
#![feature(box_into_inner)]
3+
4+
use std::pin::Pin;
5+
use std::rc::Rc;
6+
use std::sync::Arc;
7+
8+
#[derive(Default, Debug)]
9+
struct Example {
10+
inner: String,
11+
}
12+
13+
type Alias = Example;
14+
trait Trait {
15+
type Output;
16+
}
17+
impl Trait for Example {
18+
type Output = Example;
19+
}
20+
21+
#[allow(unused)]
22+
impl Example {
23+
pub fn by_value(self: Self) {
24+
self.by_ref("by_val");
25+
}
26+
27+
pub fn by_ref(self: &Self, source: &str) {
28+
println!("{source}: {}", self.inner);
29+
}
30+
31+
pub fn by_ref_mut(self: &mut Self) {
32+
self.inner = "by_ref_mut".to_string();
33+
self.by_ref("mut");
34+
}
35+
36+
pub fn by_box(self: Box<Self>) {
37+
self.by_ref("by_box");
38+
Box::into_inner(self).by_value();
39+
}
40+
41+
pub fn by_rc(self: Rc<Self>) {
42+
self.by_ref("by_rc");
43+
}
44+
45+
pub fn by_arc(self: Arc<Self>) {
46+
self.by_ref("by_arc");
47+
}
48+
49+
pub fn by_pin(self: Pin<&Self>) {
50+
self.by_ref("by_pin");
51+
}
52+
53+
pub fn explicit_type(self: Arc<Example>) {
54+
self.by_ref("explicit");
55+
}
56+
57+
pub fn with_lifetime<'a>(self: &'a Self) {
58+
self.by_ref("lifetime");
59+
}
60+
61+
pub fn nested<'a>(self: &mut &'a Arc<Rc<Box<Alias>>>) {
62+
self.by_ref("nested");
63+
}
64+
65+
pub fn via_projection(self: <Example as Trait>::Output) {
66+
self.by_ref("via_projection");
67+
}
68+
69+
pub fn from(name: String) -> Self {
70+
Example { inner: name }
71+
}
72+
}
73+
74+
fn main() {
75+
let example = Example::from("Hello".to_string());
76+
example.by_value();
77+
78+
let boxed = Box::new(Example::default());
79+
boxed.by_box();
80+
81+
Example::default().by_ref_mut();
82+
Example::default().with_lifetime();
83+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//! Just a simple library
2+
3+
pub struct Point {
4+
pub x: i64,
5+
pub y: i64,
6+
}
7+
8+
impl Point {
9+
pub fn distance(&self, other: &Point) -> u64 {
10+
let (x_dist, x_over) = (self.x - other.x).overflowing_pow(2);
11+
let (y_dist, y_over) = (self.y - other.y).overflowing_pow(2);
12+
if y_over | x_over {
13+
panic!("overflow");
14+
}
15+
16+
let dist = (x_dist as u64 + y_dist as u64) >> 1;
17+
dist
18+
}
19+
20+
pub fn distance_root(&self) -> u64 {
21+
self.distance(&Point { x: 0, y: 0 })
22+
}
23+
}

tools/compiletest/src/args.rs

+55-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::ffi::OsString;
12
/// Create our own parser and build the Config from it.
23
use std::fmt::Debug;
34
use std::path::PathBuf;
@@ -16,6 +17,8 @@ pub enum Mode {
1617
Fail,
1718
/// Run the tests, but always pass them as long as all annotations are satisfied and stderr files match.
1819
Yolo,
20+
/// The test passes a full execution of `cargo build`
21+
CargoPass,
1922
}
2023

2124
#[derive(Debug, clap::Parser)]
@@ -26,7 +29,7 @@ pub struct Args {
2629
src_base: PathBuf,
2730

2831
/// The mode according to ui_test modes.
29-
#[arg(long, default_value="yolo")]
32+
#[arg(long, default_value = "yolo")]
3033
mode: Mode,
3134

3235
/// Path for the stable-mir driver.
@@ -39,32 +42,74 @@ pub struct Args {
3942

4043
#[arg(long)]
4144
pub verbose: bool,
45+
46+
/// Run test-driver on verbose mode to print test outputs.
47+
#[arg(long)]
48+
pub no_capture: bool,
4249
}
4350

4451
impl From<Mode> for ui_test::Mode {
4552
/// Use rustc configuration as default but override arguments to fit our use case.
4653
fn from(mode: Mode) -> ui_test::Mode {
4754
match mode {
48-
Mode::Pass => { ui_test::Mode::Pass }
49-
Mode::Run => { ui_test::Mode::Run { exit_code: 0 }}
50-
Mode::Panic => { ui_test::Mode::Panic }
51-
Mode::Fail => { ui_test::Mode::Fail { require_patterns: false, rustfix: RustfixMode::Disabled }}
52-
Mode::Yolo => { ui_test::Mode::Yolo { rustfix: RustfixMode::Disabled }}
55+
Mode::Pass | Mode::CargoPass => ui_test::Mode::Pass,
56+
Mode::Run => ui_test::Mode::Run { exit_code: 0 },
57+
Mode::Panic => ui_test::Mode::Panic,
58+
Mode::Fail => ui_test::Mode::Fail {
59+
require_patterns: false,
60+
rustfix: RustfixMode::Disabled,
61+
},
62+
Mode::Yolo => ui_test::Mode::Yolo {
63+
rustfix: RustfixMode::Disabled,
64+
},
5365
}
5466
}
5567
}
5668

5769
impl From<Args> for Config {
5870
/// Use rustc configuration as default but override arguments to fit our use case.
5971
fn from(args: Args) -> Config {
60-
let mut config = Config::rustc(args.src_base);
61-
config.program = CommandBuilder::rustc();
62-
config.program.program = args.driver_path;
63-
config.program.args.push("--check-smir".into());
72+
let mut config = if matches!(args.mode, Mode::CargoPass) {
73+
cargo_config(&args)
74+
} else {
75+
driver_config(&args)
76+
};
77+
config.filter(r"\[T-DRIVE\].*\n", "");
6478
config.mode = ui_test::Mode::from(args.mode);
6579
config.output_conflict_handling = OutputConflictHandling::Error("Should Fail".to_string());
6680
config.out_dir = args.output_dir;
6781
//config.run_lib_path = PathBuf::from(env!("RUSTC_LIB_PATH"));
6882
config
6983
}
7084
}
85+
86+
fn rustc_flags(args: &Args) -> Vec<OsString> {
87+
let mut flags = vec!["--check-smir".into()];
88+
if args.verbose || args.no_capture {
89+
flags.push("--verbose".into());
90+
}
91+
flags
92+
}
93+
94+
/// Configure cargo tests that will run the test-driver instead of rustc.
95+
fn cargo_config(args: &Args) -> Config {
96+
let mut config = Config::cargo(args.src_base.clone());
97+
config.program.envs.push((
98+
"RUST".into(),
99+
Some(args.driver_path.clone().into_os_string()),
100+
));
101+
config.program.envs.push((
102+
"CARGO_ENCODED_RUSTFLAGS".into(),
103+
Some(rustc_flags(args).join(&OsString::from("\x1f")).into()),
104+
));
105+
config
106+
}
107+
108+
/// Configure tests that will invoke the test-driver directly as rustc.
109+
fn driver_config(args: &Args) -> Config {
110+
let mut config = Config::rustc(args.src_base.clone());
111+
config.program = CommandBuilder::rustc();
112+
config.program.program = args.driver_path.clone();
113+
config.program.args = rustc_flags(args);
114+
config
115+
}

0 commit comments

Comments
 (0)