use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use brink_compiler::{AnalysisOptions, Dialect, TypePolicy};
#[derive(Clone, Copy, Debug)]
enum FixturePolicy {
Default,
BrinkGradual,
BrinkStrict,
}
impl FixturePolicy {
const fn name(self) -> &'static str {
match self {
FixturePolicy::Default => "Default",
FixturePolicy::BrinkGradual => "BrinkGradual",
FixturePolicy::BrinkStrict => "BrinkStrict",
}
}
}
const FIXTURES: &[(&str, FixturePolicy)] = &[
("hanoi-10", FixturePolicy::Default),
("crucible-8", FixturePolicy::Default),
("loop-append-10k", FixturePolicy::BrinkGradual),
("loop-append-field-10k", FixturePolicy::BrinkGradual),
("share-then-mutate-5k", FixturePolicy::BrinkGradual),
("fn-creation-density-10k", FixturePolicy::BrinkGradual),
("fn-bind-chain-shallow", FixturePolicy::BrinkGradual),
("fn-bind-chain-deep", FixturePolicy::BrinkGradual),
("dynamic-dispatch-10k", FixturePolicy::BrinkGradual),
("direct-call-10k", FixturePolicy::BrinkGradual),
("save-state-small", FixturePolicy::BrinkGradual),
("save-state-medium", FixturePolicy::BrinkGradual),
("save-state-large", FixturePolicy::BrinkGradual),
("snapshot-retention-g10-m10", FixturePolicy::BrinkGradual),
("snapshot-retention-g10-m100", FixturePolicy::BrinkGradual),
("snapshot-retention-g100-m10", FixturePolicy::BrinkGradual),
("snapshot-retention-g100-m100", FixturePolicy::BrinkGradual),
("struct-field-access-10k", FixturePolicy::BrinkGradual),
("struct-field-access-10k", FixturePolicy::BrinkStrict),
];
fn benchmarks_stories_dir() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../benchmarks/stories")
}
#[test]
fn every_benchmark_fixture_compiles_under_its_bench_scenarios_policy() {
let mut failures = Vec::new();
for (dir, policy) in FIXTURES {
let path = benchmarks_stories_dir().join(dir).join("story.ink");
let result = match policy {
FixturePolicy::Default => brink_compiler::compile_path(&path),
FixturePolicy::BrinkGradual => brink_compiler::compile_path_with_options(
&path,
AnalysisOptions {
dialect: Dialect::Brink,
types: Some(TypePolicy::Gradual),
..AnalysisOptions::default()
},
),
FixturePolicy::BrinkStrict => brink_compiler::compile_path_with_options(
&path,
AnalysisOptions {
dialect: Dialect::Brink,
types: Some(TypePolicy::Strict),
..AnalysisOptions::default()
},
),
};
if let Err(err) = result {
failures.push(format!(
"benchmarks/stories/{dir}/story.ink failed to compile under \
its bench scenario's {policy_name} policy — this is the \
#2138 class (issue #2777): a fixture broke and nothing on \
the normal PR gate noticed. Compile error: {err:?}",
policy_name = policy.name(),
));
}
}
assert!(
failures.is_empty(),
"{} benchmark fixture(s) failed to compile:\n{}",
failures.len(),
failures.join("\n")
);
}
#[test]
fn all_benchmarks_stories_fixtures_are_covered() {
let on_disk: BTreeSet<String> = std::fs::read_dir(benchmarks_stories_dir())
.expect("benchmarks/stories/ should exist")
.filter_map(|entry| {
let entry = entry.expect("dir entry should be readable");
let file_type = entry.file_type().expect("file type should be readable");
file_type
.is_dir()
.then(|| entry.file_name().to_string_lossy().into_owned())
})
.collect();
let covered: BTreeSet<String> = FIXTURES.iter().map(|(dir, _)| (*dir).to_owned()).collect();
assert!(
on_disk == covered,
"benchmarks/stories/ directories and FIXTURES in \
benchmark_fixtures_compile.rs have drifted apart — on disk but \
not covered: {:?}; covered but not on disk: {:?}. Add/remove the \
matching FIXTURES entry (see this file's module doc, issue \
#2777).",
on_disk.difference(&covered).collect::<Vec<_>>(),
covered.difference(&on_disk).collect::<Vec<_>>()
);
}