Skip to content

Commit f0f892f

Browse files
authored
Create tooling for end-to-end testing (#25)
Create two different tools: - `test-drive`: A rustc_driver that compiles a crate and run a few sanity checks on StableMIR. - `compiletest`: A wrapper to run compiler tests using the `test-drive` tool. I am also adding a script to run a few rustc tests and a nightly workflow. The files diff is not quite working yet so most tests that fail compilation don't succeed yet. For our local tests, so far I created two suites (one with a test each): sanity-checks and fixme suite. The fixme suite is for issues that we find that needs fixing.
1 parent cdc5e70 commit f0f892f

File tree

15 files changed

+736
-0
lines changed

15 files changed

+736
-0
lines changed

.github/scripts/run_own_tests.sh

Lines changed: 41 additions & 0 deletions
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 fix-me"
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

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env bash
2+
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+
9+
set -e
10+
set -u
11+
export RUST_BACKTRACE=1
12+
13+
# Location of a rust repository. Clone one if path doesn't exist.
14+
RUST_REPO="${RUST_REPO:-"/tmp/rustc"}"
15+
16+
# Where we will store the SMIR tools (Optional).
17+
TOOLS_BIN="${TOOLS_BIN:-"/tmp/smir/bin"}"
18+
19+
# Assume we are inside SMIR repository
20+
SMIR_PATH=$(git rev-parse --show-toplevel)
21+
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+
--target-rustcflags="--smir-check" \
92+
--host-rustcflags="--smir-check"
93+
done
94+
}
95+
96+
build_smir_tools
97+
setup_rustc_repo
98+
run_tests

.github/workflows/nightly.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Run compiler tests
2+
3+
on:
4+
schedule:
5+
- cron: "0 6 * * *" # Run daily at 06:00 UTC
6+
workflow_dispatch: # Allow manual dispatching
7+
pull_request:
8+
9+
jobs:
10+
compile-test:
11+
name: Rust Compiler Tests
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v3
16+
17+
- name: Install latest nightly
18+
uses: actions-rs/toolchain@v1
19+
with:
20+
toolchain: nightly
21+
22+
- name: Test local suites
23+
run: ./.github/scripts/run_own_tests.sh
24+
env:
25+
TOOLS_BIN: "/tmp/smir/bin"
26+
27+
- name: Test rustc suites
28+
run: ./.github/scripts/run_rustc_tests.sh
29+
env:
30+
RUST_REPO: "/tmp/rustc"
31+
TOOLS_BIN: "/tmp/smir/bin"
32+
# Don't fail CI for now. See: https://github.com/rust-lang/project-stable-mir/issues/39
33+
continue-on-error: true

Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Cargo workspace for utility tools used to check stable-mir in CI
2+
[workspace]
3+
resolver = "2"
4+
members = [
5+
"tools/compiletest",
6+
"tools/test-drive",
7+
]
8+
9+
exclude = [
10+
"build",
11+
"target",
12+
]

rust-toolchain.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[toolchain]
2+
channel = "nightly"
3+
components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"]
Lines changed: 83 additions & 0 deletions
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+
}
Lines changed: 23 additions & 0 deletions
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/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "compiletest"
3+
description = "Run tests using compiletest-rs"
4+
version = "0.0.0"
5+
edition = "2021"
6+
7+
[dependencies]
8+
ui_test = "0.20.0"
9+
clap = { version = "4.1.3", features = ["derive"] }
10+
11+
[package.metadata.rust-analyzer]
12+
# This crate uses #[feature(rustc_private)].
13+
# See https://github.com/rust-analyzer/rust-analyzer/pull/7891
14+
rustc_private = true

tools/compiletest/build.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use std::env;
2+
use std::path::PathBuf;
3+
4+
pub fn main() {
5+
// Add rustup to the rpath in order to properly link with the correct rustc version.
6+
let rustup_home = env::var("RUSTUP_HOME").unwrap();
7+
let toolchain = env::var("RUSTUP_TOOLCHAIN").unwrap();
8+
let rustc_lib: PathBuf = [&rustup_home, "toolchains", &toolchain, "lib"]
9+
.iter()
10+
.collect();
11+
println!(
12+
"cargo:rustc-link-arg-bin=compiletest=-Wl,-rpath,{}",
13+
rustc_lib.display()
14+
);
15+
println!("cargo:rustc-env=RUSTC_LIB_PATH={}", rustc_lib.display());
16+
}

0 commit comments

Comments
 (0)