Skip to content

Commit 0dd7967

Browse files
committed
Add back a full integration test for -Zbuild-std
Only run these tests on one CI builder (not all platforms) though. This is extremely resource intensive since it rebuilds libstd. Currently this does not share a build directly like before because the number of tests are supposed to be small, but if necessary we can add that in later too.
1 parent 9115b2c commit 0dd7967

File tree

6 files changed

+229
-89
lines changed

6 files changed

+229
-89
lines changed

azure-pipelines.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
x86_64-msvc:
4444
TOOLCHAIN: stable-x86_64-pc-windows-msvc
4545
OTHER_TARGET: i686-pc-windows-msvc
46+
4647
- job: rustfmt
4748
pool:
4849
vmImage: ubuntu-16.04
@@ -73,6 +74,20 @@ jobs:
7374
variables:
7475
TOOLCHAIN: stable
7576

77+
- job: build_std
78+
pool:
79+
vmImage: ubuntu-16.04
80+
steps:
81+
- template: ci/azure-install-rust.yml
82+
- bash: rustup component add rust-src
83+
displayName: "Install rust-src"
84+
- bash: cargo build
85+
- bash: cargo test --test build-std
86+
displayName: "tests"
87+
variables:
88+
TOOLCHAIN: nightly
89+
CARGO_RUN_BUILD_STD_TESTS: 1
90+
7691
- job: docs
7792
pool:
7893
vmImage: ubuntu-16.04
@@ -90,4 +105,3 @@ jobs:
90105
displayName: "Build mdbook documentation"
91106
variables:
92107
TOOLCHAIN: stable
93-

crates/cargo-test-macro/src/lib.rs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate proc_macro;
33
use proc_macro::*;
44

55
#[proc_macro_attribute]
6-
pub fn cargo_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
6+
pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
77
let span = Span::call_site();
88
let mut ret = TokenStream::new();
99
ret.extend(Some(TokenTree::from(Punct::new('#', Spacing::Alone))));
@@ -13,6 +13,8 @@ pub fn cargo_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
1313
test.into(),
1414
))));
1515

16+
let build_std = contains_ident(&attr, "build_std");
17+
1618
for token in item {
1719
let group = match token {
1820
TokenTree::Group(g) => {
@@ -29,22 +31,20 @@ pub fn cargo_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
2931
}
3032
};
3133

32-
let mut new_body = vec![
33-
TokenTree::from(Ident::new("let", span)),
34-
TokenTree::from(Ident::new("_test_guard", span)),
35-
TokenTree::from(Punct::new('=', Spacing::Alone)),
36-
TokenTree::from(Ident::new("cargo_test_support", span)),
37-
TokenTree::from(Punct::new(':', Spacing::Joint)),
38-
TokenTree::from(Punct::new(':', Spacing::Alone)),
39-
TokenTree::from(Ident::new("paths", span)),
40-
TokenTree::from(Punct::new(':', Spacing::Joint)),
41-
TokenTree::from(Punct::new(':', Spacing::Alone)),
42-
TokenTree::from(Ident::new("init_root", span)),
43-
TokenTree::from(Group::new(Delimiter::Parenthesis, TokenStream::new())),
44-
TokenTree::from(Punct::new(';', Spacing::Alone)),
45-
]
46-
.into_iter()
47-
.collect::<TokenStream>();
34+
let mut new_body =
35+
to_token_stream("let _test_guard = cargo_test_support::paths::init_root();");
36+
37+
// If this is a `build_std` test (aka `tests/build-std/*.rs`) then they
38+
// only run on nightly and they only run when specifically instructed to
39+
// on CI.
40+
if build_std {
41+
let ts = to_token_stream("if !cargo_test_support::is_nightly() { return }");
42+
new_body.extend(ts);
43+
let ts = to_token_stream(
44+
"if std::env::var(\"CARGO_RUN_BUILD_STD_TESTS\").is_err() { return }",
45+
);
46+
new_body.extend(ts);
47+
}
4848
new_body.extend(group.stream());
4949
ret.extend(Some(TokenTree::from(Group::new(
5050
group.delimiter(),
@@ -54,3 +54,14 @@ pub fn cargo_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
5454

5555
return ret;
5656
}
57+
58+
fn contains_ident(t: &TokenStream, ident: &str) -> bool {
59+
t.clone().into_iter().any(|t| match t {
60+
TokenTree::Ident(i) => i.to_string() == ident,
61+
_ => false,
62+
})
63+
}
64+
65+
fn to_token_stream(code: &str) -> TokenStream {
66+
code.parse().unwrap()
67+
}

crates/cargo-test-support/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ version = "0.1.0"
44
authors = ["Alex Crichton <alex@alexcrichton.com>"]
55
edition = "2018"
66

7+
[lib]
8+
doctest = false
9+
710
[dependencies]
811
cargo = { path = "../.." }
12+
cargo-test-macro = { path = "../cargo-test-macro" }
913
filetime = "0.2"
1014
flate2 = "1.0"
1115
git2 = "0.10"

crates/cargo-test-support/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ macro_rules! t {
135135
};
136136
}
137137

138+
pub use cargo_test_macro::cargo_test;
139+
138140
pub mod cross_compile;
139141
pub mod git;
140142
pub mod paths;

tests/build-std/main.rs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
//! A test suite for `-Zbuild-std` which is much more expensive than the
2+
//! standard test suite.
3+
//!
4+
//! This test suite attempts to perform a full integration test where we
5+
//! actually compile the standard library from source (like the real one) and
6+
//! the various tests associated with that.
7+
//!
8+
//! YOU SHOULD IDEALLY NOT WRITE TESTS HERE.
9+
//!
10+
//! If possible, use `tests/testsuite/standard_lib.rs` instead. That uses a
11+
//! 'mock' sysroot which is much faster to compile. The tests here are
12+
//! extremely intensive and are only intended to run on CI and are theoretically
13+
//! not catching any regressions that `tests/testsuite/standard_lib.rs` isn't
14+
//! already catching.
15+
//!
16+
//! All tests here should use `#[cargo_test(build_std)]` to indicate that
17+
//! boilerplate should be generated to require the nightly toolchain and the
18+
//! `CARGO_RUN_BUILD_STD_TESTS` env var to be set to actually run these tests.
19+
//! Otherwise the tests are skipped.
20+
21+
use cargo_test_support::*;
22+
23+
fn enable_build_std(e: &mut Execs, arg: Option<&str>) {
24+
e.env_remove("CARGO_HOME");
25+
e.env_remove("HOME");
26+
e.arg("-Zno-index-update");
27+
28+
// And finally actually enable `build-std` for now
29+
let arg = match arg {
30+
Some(s) => format!("-Zbuild-std={}", s),
31+
None => "-Zbuild-std".to_string(),
32+
};
33+
e.arg(arg);
34+
e.masquerade_as_nightly_cargo();
35+
}
36+
37+
// Helper methods used in the tests below
38+
trait BuildStd: Sized {
39+
fn build_std(&mut self) -> &mut Self;
40+
fn build_std_arg(&mut self, arg: &str) -> &mut Self;
41+
fn target_host(&mut self) -> &mut Self;
42+
}
43+
44+
impl BuildStd for Execs {
45+
fn build_std(&mut self) -> &mut Self {
46+
enable_build_std(self, None);
47+
self
48+
}
49+
50+
fn build_std_arg(&mut self, arg: &str) -> &mut Self {
51+
enable_build_std(self, Some(arg));
52+
self
53+
}
54+
55+
fn target_host(&mut self) -> &mut Self {
56+
self.arg("--target").arg(rustc_host());
57+
self
58+
}
59+
}
60+
61+
#[cargo_test(build_std)]
62+
fn basic() {
63+
let p = project()
64+
.file(
65+
"src/main.rs",
66+
"
67+
fn main() {
68+
foo::f();
69+
}
70+
71+
#[test]
72+
fn smoke_bin_unit() {
73+
foo::f();
74+
}
75+
",
76+
)
77+
.file(
78+
"src/lib.rs",
79+
"
80+
extern crate alloc;
81+
extern crate proc_macro;
82+
83+
/// ```
84+
/// foo::f();
85+
/// ```
86+
pub fn f() {
87+
}
88+
89+
#[test]
90+
fn smoke_lib_unit() {
91+
f();
92+
}
93+
",
94+
)
95+
.file(
96+
"tests/smoke.rs",
97+
"
98+
#[test]
99+
fn smoke_integration() {
100+
foo::f();
101+
}
102+
",
103+
)
104+
.build();
105+
106+
p.cargo("check").build_std().target_host().run();
107+
p.cargo("build").build_std().target_host().run();
108+
p.cargo("run").build_std().target_host().run();
109+
p.cargo("test").build_std().target_host().run();
110+
}
111+
112+
#[cargo_test(build_std)]
113+
fn cross_custom() {
114+
let p = project()
115+
.file("src/lib.rs", "#![no_std] pub fn f() {}")
116+
.file(
117+
"custom-target.json",
118+
r#"
119+
{
120+
"llvm-target": "x86_64-unknown-none-gnu",
121+
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
122+
"arch": "x86_64",
123+
"target-endian": "little",
124+
"target-pointer-width": "64",
125+
"target-c-int-width": "32",
126+
"os": "none",
127+
"linker-flavor": "ld.lld"
128+
}
129+
"#,
130+
)
131+
.build();
132+
133+
p.cargo("build --target custom-target.json -v")
134+
.build_std_arg("core")
135+
.run();
136+
}
137+
138+
#[cargo_test(build_std)]
139+
fn custom_test_framework() {
140+
let p = project()
141+
.file(
142+
"src/lib.rs",
143+
r#"
144+
#![no_std]
145+
#![cfg_attr(test, no_main)]
146+
#![feature(custom_test_frameworks)]
147+
#![test_runner(crate::test_runner)]
148+
149+
pub fn test_runner(_tests: &[&dyn Fn()]) {}
150+
151+
#[panic_handler]
152+
fn panic(_info: &core::panic::PanicInfo) -> ! {
153+
loop {}
154+
}
155+
"#,
156+
)
157+
.file(
158+
"target.json",
159+
r#"
160+
{
161+
"llvm-target": "x86_64-unknown-none-gnu",
162+
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
163+
"arch": "x86_64",
164+
"target-endian": "little",
165+
"target-pointer-width": "64",
166+
"target-c-int-width": "32",
167+
"os": "none",
168+
"linker-flavor": "ld.lld",
169+
"linker": "rust-lld",
170+
"executables": true,
171+
"panic-strategy": "abort"
172+
}
173+
"#,
174+
)
175+
.build();
176+
177+
p.cargo("test --target target.json --no-run -v")
178+
.build_std_arg("core")
179+
.run();
180+
}

tests/testsuite/standard_lib.rs

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -442,74 +442,3 @@ fn doctest() {
442442

443443
p.cargo("test --doc -v").build_std().target_host().run();
444444
}
445-
446-
// FIXME: set up a dedicated builder to run a full integration test?
447-
// #[cargo_test]
448-
// fn cross_custom() {
449-
// if !setup() {
450-
// return;
451-
// }
452-
// let p = project()
453-
// .file("src/lib.rs", "#![no_std] pub fn f() {}")
454-
// .file(
455-
// "custom-target.json",
456-
// r#"
457-
// {
458-
// "llvm-target": "x86_64-unknown-none-gnu",
459-
// "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
460-
// "arch": "x86_64",
461-
// "target-endian": "little",
462-
// "target-pointer-width": "64",
463-
// "target-c-int-width": "32",
464-
// "os": "none",
465-
// "linker-flavor": "ld.lld"
466-
// }
467-
// "#,
468-
// )
469-
// .build();
470-
//
471-
// p.cargo("build --target custom-target.json -v")
472-
// .build_std()
473-
// .run();
474-
// }
475-
//
476-
// fn custom_test_framework() {
477-
// let p = project()
478-
// .file(
479-
// "src/lib.rs",
480-
// r#"
481-
// #![no_std]
482-
// #![cfg_attr(test, no_main)]
483-
// #![feature(custom_test_frameworks)]
484-
// #![test_runner(crate::test_runner)]
485-
//
486-
// pub fn test_runner(_tests: &[&dyn Fn()]) {}
487-
//
488-
// #[panic_handler]
489-
// fn panic(_info: &core::panic::PanicInfo) -> ! {
490-
// loop {}
491-
// }
492-
// "#,
493-
// )
494-
// .file(
495-
// "target.json",
496-
// r#"
497-
// {
498-
// "llvm-target": "x86_64-unknown-none-gnu",
499-
// "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
500-
// "arch": "x86_64",
501-
// "target-endian": "little",
502-
// "target-pointer-width": "64",
503-
// "target-c-int-width": "32",
504-
// "os": "none",
505-
// "linker-flavor": "ld.lld",
506-
// "linker": "rust-lld",
507-
// "executables": true,
508-
// "panic-strategy": "abort"
509-
// }
510-
// "#,
511-
// )
512-
// .build();
513-
//
514-
// cargo_build_std(&p, "test --target target.json --no-run -v", "core").run();
515-
// }

0 commit comments

Comments
 (0)