Skip to content

Commit 68332d8

Browse files
authored
Unrolled build for rust-lang#127510
Rollup merge of rust-lang#127510 - tgross35:test-float-parse-update, r=Mark-Simulacrum Rewrite `test-float-parse` in Rust Migrate from the currently broken Rust + Python `test-float-parse` to a Rust implementation. This newer version should be significantly faster (tests execute in parallel with threads, rather than series across multiple processes, which also eliminates the "...the worker processes are leaked and stick around forever" message), and should be significantly easier to extend to the new float types. Since this is faster and hopefully more stable, we should be able to launch it with `x` and run the faster tests in CI.
2 parents ae7b1c1 + d123878 commit 68332d8

36 files changed

+2509
-555
lines changed

Cargo.lock

+75
Original file line numberDiff line numberDiff line change
@@ -2598,12 +2598,76 @@ dependencies = [
25982598
"windows-sys 0.48.0",
25992599
]
26002600

2601+
[[package]]
2602+
name = "num"
2603+
version = "0.4.3"
2604+
source = "registry+https://github.com/rust-lang/crates.io-index"
2605+
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
2606+
dependencies = [
2607+
"num-bigint",
2608+
"num-complex",
2609+
"num-integer",
2610+
"num-iter",
2611+
"num-rational",
2612+
"num-traits",
2613+
]
2614+
2615+
[[package]]
2616+
name = "num-bigint"
2617+
version = "0.4.6"
2618+
source = "registry+https://github.com/rust-lang/crates.io-index"
2619+
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
2620+
dependencies = [
2621+
"num-integer",
2622+
"num-traits",
2623+
]
2624+
2625+
[[package]]
2626+
name = "num-complex"
2627+
version = "0.4.6"
2628+
source = "registry+https://github.com/rust-lang/crates.io-index"
2629+
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
2630+
dependencies = [
2631+
"num-traits",
2632+
]
2633+
26012634
[[package]]
26022635
name = "num-conv"
26032636
version = "0.1.0"
26042637
source = "registry+https://github.com/rust-lang/crates.io-index"
26052638
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
26062639

2640+
[[package]]
2641+
name = "num-integer"
2642+
version = "0.1.46"
2643+
source = "registry+https://github.com/rust-lang/crates.io-index"
2644+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
2645+
dependencies = [
2646+
"num-traits",
2647+
]
2648+
2649+
[[package]]
2650+
name = "num-iter"
2651+
version = "0.1.45"
2652+
source = "registry+https://github.com/rust-lang/crates.io-index"
2653+
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
2654+
dependencies = [
2655+
"autocfg",
2656+
"num-integer",
2657+
"num-traits",
2658+
]
2659+
2660+
[[package]]
2661+
name = "num-rational"
2662+
version = "0.4.2"
2663+
source = "registry+https://github.com/rust-lang/crates.io-index"
2664+
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
2665+
dependencies = [
2666+
"num-bigint",
2667+
"num-integer",
2668+
"num-traits",
2669+
]
2670+
26072671
[[package]]
26082672
name = "num-traits"
26092673
version = "0.2.19"
@@ -5630,6 +5694,17 @@ dependencies = [
56305694
"std",
56315695
]
56325696

5697+
[[package]]
5698+
name = "test-float-parse"
5699+
version = "0.1.0"
5700+
dependencies = [
5701+
"indicatif",
5702+
"num",
5703+
"rand",
5704+
"rand_chacha",
5705+
"rayon",
5706+
]
5707+
56335708
[[package]]
56345709
name = "textwrap"
56355710
version = "0.16.1"

Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ members = [
44
"compiler/rustc",
55
"library/std",
66
"library/sysroot",
7+
"src/etc/test-float-parse",
78
"src/rustdoc-json-types",
89
"src/tools/build_helper",
910
"src/tools/cargotest",
@@ -109,6 +110,18 @@ strip = true
109110
debug = 0
110111
strip = true
111112

113+
# Bigint libraries are slow without optimization, speed up testing
114+
[profile.dev.package.test-float-parse]
115+
opt-level = 3
116+
117+
# Speed up the binary as much as possible
118+
[profile.release.package.test-float-parse]
119+
opt-level = 3
120+
codegen-units = 1
121+
# FIXME: LTO cannot be enabled for binaries in a workspace
122+
# <https://github.com/rust-lang/cargo/issues/9330>
123+
# lto = true
124+
112125
[patch.crates-io]
113126
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
114127
# here

src/bootstrap/mk/Makefile.in

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ check-aux:
5151
$(Q)$(BOOTSTRAP) test --stage 2 \
5252
src/tools/cargo \
5353
src/tools/cargotest \
54+
src/etc/test-float-parse \
5455
$(BOOTSTRAP_ARGS)
5556
# Run standard library tests in Miri.
5657
$(Q)BOOTSTRAP_SKIP_TARGET_SANITY=1 \

src/bootstrap/src/core/build_steps/check.rs

+1
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ tool_check_step!(CargoMiri, "src/tools/miri/cargo-miri", SourceType::InTree);
466466
tool_check_step!(Rls, "src/tools/rls", SourceType::InTree);
467467
tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree);
468468
tool_check_step!(MiroptTestTools, "src/tools/miropt-test-tools", SourceType::InTree);
469+
tool_check_step!(TestFloatParse, "src/etc/test-float-parse", SourceType::InTree);
469470

470471
tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree, false);
471472

src/bootstrap/src/core/build_steps/clippy.rs

+1
Original file line numberDiff line numberDiff line change
@@ -326,4 +326,5 @@ lint_any!(
326326
Rustfmt, "src/tools/rustfmt", "rustfmt";
327327
RustInstaller, "src/tools/rust-installer", "rust-installer";
328328
Tidy, "src/tools/tidy", "tidy";
329+
TestFloatParse, "src/etc/test-float-parse", "test-float-parse";
329330
);

src/bootstrap/src/core/build_steps/test.rs

+77
Original file line numberDiff line numberDiff line change
@@ -3505,3 +3505,80 @@ impl Step for CodegenGCC {
35053505
cargo.into_cmd().run(builder);
35063506
}
35073507
}
3508+
3509+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3510+
pub struct TestFloatParse {
3511+
path: PathBuf,
3512+
host: TargetSelection,
3513+
}
3514+
3515+
impl Step for TestFloatParse {
3516+
type Output = ();
3517+
const ONLY_HOSTS: bool = true;
3518+
const DEFAULT: bool = true;
3519+
3520+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3521+
run.path("src/etc/test-float-parse")
3522+
}
3523+
3524+
fn make_run(run: RunConfig<'_>) {
3525+
for path in run.paths {
3526+
let path = path.assert_single_path().path.clone();
3527+
run.builder.ensure(Self { path, host: run.target });
3528+
}
3529+
}
3530+
3531+
fn run(self, builder: &Builder<'_>) {
3532+
let bootstrap_host = builder.config.build;
3533+
let compiler = builder.compiler(0, bootstrap_host);
3534+
let path = self.path.to_str().unwrap();
3535+
let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap();
3536+
3537+
builder.ensure(compile::Std::new(compiler, self.host));
3538+
3539+
// Run any unit tests in the crate
3540+
let cargo_test = tool::prepare_tool_cargo(
3541+
builder,
3542+
compiler,
3543+
Mode::ToolStd,
3544+
bootstrap_host,
3545+
"test",
3546+
path,
3547+
SourceType::InTree,
3548+
&[],
3549+
);
3550+
3551+
run_cargo_test(
3552+
cargo_test,
3553+
&[],
3554+
&[],
3555+
crate_name,
3556+
crate_name,
3557+
compiler,
3558+
bootstrap_host,
3559+
builder,
3560+
);
3561+
3562+
// Run the actual parse tests.
3563+
let mut cargo_run = tool::prepare_tool_cargo(
3564+
builder,
3565+
compiler,
3566+
Mode::ToolStd,
3567+
bootstrap_host,
3568+
"run",
3569+
path,
3570+
SourceType::InTree,
3571+
&[],
3572+
);
3573+
3574+
cargo_run.arg("--");
3575+
if builder.config.args().is_empty() {
3576+
// By default, exclude tests that take longer than ~1m.
3577+
cargo_run.arg("--skip-huge");
3578+
} else {
3579+
cargo_run.args(builder.config.args());
3580+
}
3581+
3582+
cargo_run.into_cmd().run(builder);
3583+
}
3584+
}

src/bootstrap/src/core/builder.rs

+3
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,7 @@ impl<'a> Builder<'a> {
826826
clippy::Rustdoc,
827827
clippy::Rustfmt,
828828
clippy::RustInstaller,
829+
clippy::TestFloatParse,
829830
clippy::Tidy,
830831
),
831832
Kind::Check | Kind::Fix => describe!(
@@ -840,6 +841,7 @@ impl<'a> Builder<'a> {
840841
check::Rls,
841842
check::Rustfmt,
842843
check::RustAnalyzer,
844+
check::TestFloatParse,
843845
check::Bootstrap,
844846
),
845847
Kind::Test => describe!(
@@ -901,6 +903,7 @@ impl<'a> Builder<'a> {
901903
test::RustdocJson,
902904
test::HtmlCheck,
903905
test::RustInstaller,
906+
test::TestFloatParse,
904907
// Run bootstrap close to the end as it's unlikely to fail
905908
test::Bootstrap,
906909
// Run run-make last, since these won't pass without make on Windows

src/etc/test-float-parse/Cargo.toml

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ version = "0.1.0"
44
edition = "2021"
55
publish = false
66

7-
[workspace]
8-
resolver = "1"
9-
107
[dependencies]
11-
rand = "0.8"
8+
indicatif = { version = "0.17.8", default-features = false }
9+
num = "0.4.3"
10+
rand = "0.8.5"
11+
rand_chacha = "0.3"
12+
rayon = "1"
1213

1314
[lib]
1415
name = "test_float_parse"

src/etc/test-float-parse/README.md

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Float Parsing Tests
2+
3+
These are tests designed to test decimal to float conversions (`dec2flt`) used
4+
by the standard library.
5+
6+
It consistes of a collection of test generators that each generate a set of
7+
patterns intended to test a specific property. In addition, there are exhaustive
8+
tests (for <= `f32`) and fuzzers (for anything that can't be run exhaustively).
9+
10+
The generators work as follows:
11+
12+
- Each generator is a struct that lives somewhere in the `gen` module. Usually
13+
it is generic over a float type.
14+
- These generators must implement `Iterator`, which should return a context type
15+
that can be used to construct a test string (but usually not the string
16+
itself).
17+
- They must also implement the `Generator` trait, which provides a method to
18+
write test context to a string as a test case, as well as some extra metadata.
19+
20+
The split between context generation and string construction is so that we can
21+
reuse string allocations.
22+
- Each generator gets registered once for each float type. Each of these
23+
generators then get their iterator called, and each test case checked against
24+
the float type's parse implementation.
25+
26+
Some generators produce decimal strings, others create bit patterns that need to
27+
be bitcasted to the float type, which then uses its `Display` implementation to
28+
write to a string. For these, float to decimal (`flt2dec`) conversions also get
29+
tested, if unintentionally.
30+
31+
For each test case, the following is done:
32+
33+
- The test string is parsed to the float type using the standard library's
34+
implementation.
35+
- The test string is parsed separately to a `BigRational`, which acts as a
36+
representation with infinite precision.
37+
- The rational value then gets checked that it is within the float's
38+
representable values (absolute value greater than the smallest number to round
39+
to zero, but less less than the first value to round to infinity). If these
40+
limits are exceeded, check that the parsed float reflects that.
41+
- For real nonzero numbers, the parsed float is converted into a rational using
42+
`significand * 2^exponent`. It is then checked against the actual rational
43+
value, and verified to be within half a bit's precision of the parsed value.
44+
Also it is checked that ties round to even.
45+
46+
This is all highly parallelized with `rayon`; test generators can run in
47+
parallel, and their tests get chunked and run in parallel.
48+
49+
There is a simple command line that allows filtering which tests are run,
50+
setting the number of iterations for fuzzing tests, limiting failures, setting
51+
timeouts, etc. See `main.rs` or run with `--help` for options.
52+
53+
Note that when running via `./x`, only tests that take less than a few minutes
54+
are run by default. Navigate to the crate (or pass `-C` to Cargo) and run it
55+
directly to run all tests or pass specific arguments.

0 commit comments

Comments
 (0)