blob: accb39654d15ac35cdf549948652d661152303bf [file] [log] [blame]
#![cfg_attr(f16_enabled, feature(f16))]
#![cfg_attr(f128_enabled, feature(f128))]
#![allow(clippy::unusual_byte_groupings)] // sometimes we group by sign_exp_sig
pub mod domain;
mod f8_impl;
pub mod generate;
#[cfg(feature = "build-mpfr")]
pub mod mpfloat;
mod num;
pub mod op;
mod precision;
mod run_cfg;
mod test_traits;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::sync::LazyLock;
use std::time::SystemTime;
pub use f8_impl::{f8, hf8};
pub use libm::support::{Float, Int, IntTy, MinInt};
pub use num::{FloatExt, linear_ints, logspace};
pub use op::{
BaseName, FloatTy, Identifier, MathOp, OpCFn, OpCRet, OpFTy, OpRustArgs, OpRustFn, OpRustRet,
Ty,
};
pub use precision::{MaybeOverride, SpecialCase, default_ulp};
use run_cfg::extensive_max_iterations;
pub use run_cfg::{
CheckBasis, CheckCtx, EXTENSIVE_ENV, GeneratorKind, bigint_fuzz_iteration_count,
skip_extensive_test,
};
pub use test_traits::{CheckOutput, Hex, TupleCall};
/// Result type for tests is usually from `anyhow`. Most times there is no success value to
/// propagate.
pub type TestResult<T = (), E = anyhow::Error> = Result<T, E>;
/// True if `EMULATED` is set and nonempty. Used to determine how many iterations to run.
pub const fn emulated() -> bool {
match option_env!("EMULATED") {
Some(s) if s.is_empty() => false,
None => false,
Some(_) => true,
}
}
/// True if `CI` is set and nonempty.
pub const fn ci() -> bool {
match option_env!("CI") {
Some(s) if s.is_empty() => false,
None => false,
Some(_) => true,
}
}
/// Print to stderr and additionally log it to `target/test-log.txt`. This is useful for saving
/// output that would otherwise be consumed by the test harness.
pub fn test_log(s: &str) {
// Handle to a file opened in append mode, unless a suitable path can't be determined.
static OUTFILE: LazyLock<Option<File>> = LazyLock::new(|| {
// If the target directory is overridden, use that environment variable. Otherwise, save
// at the default path `{workspace_root}/target`.
let target_dir = match env::var("CARGO_TARGET_DIR") {
Ok(s) => PathBuf::from(s),
Err(_) => {
let Ok(x) = env::var("CARGO_MANIFEST_DIR") else {
return None;
};
PathBuf::from(x).join("../target")
}
};
let outfile = target_dir.join("test-log.txt");
let mut f = File::options()
.create(true)
.append(true)
.open(outfile)
.expect("failed to open logfile");
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap();
writeln!(f, "\n\nTest run at {}", now.as_secs()).unwrap();
writeln!(f, "arch: {}", env::consts::ARCH).unwrap();
writeln!(f, "os: {}", env::consts::OS).unwrap();
writeln!(f, "bits: {}", usize::BITS).unwrap();
writeln!(f, "emulated: {}", emulated()).unwrap();
writeln!(f, "ci: {}", ci()).unwrap();
writeln!(f, "cargo features: {}", env!("CFG_CARGO_FEATURES")).unwrap();
writeln!(f, "opt level: {}", env!("CFG_OPT_LEVEL")).unwrap();
writeln!(f, "target features: {}", env!("CFG_TARGET_FEATURES")).unwrap();
writeln!(f, "extensive iterations {}", extensive_max_iterations()).unwrap();
Some(f)
});
eprintln!("{s}");
if let Some(mut f) = OUTFILE.as_ref() {
writeln!(f, "{s}").unwrap();
}
}