#![allow(dead_code)]
use std::fmt::Display;
pub use assert_cmd::prelude::*; pub use assert_cmd::Command;
pub use assert_fs::fixture::ChildPath;
pub use assert_fs::prelude::*;
pub use assert_fs::TempDir;
#[allow(unused_imports)]
pub use predicates::prelude::*; #[allow(unused_imports)]
use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
use regex::RegexBuilder;
pub const FILE_10_RDH: &str = "../tests/test-data/10_rdh.raw";
pub const FILE_ERR_NOT_HBF: &str = "../tests/test-data/err_not_hbf.raw";
pub const FILE_THRS_CDW_LINKS: &str = "../tests/test-data/thrs_cdw_links.raw";
pub const FILE_READOUT_SUPERPAGE_1: &str = "../tests/test-data/readout.superpage.1.raw";
pub const FILE_1_HBF_BAD_CDP_STRUCTURE: &str = "../tests/test-data/1_hbf_bad_cdp_structure.raw";
pub const FILE_1_HBF_BAD_DW_DDW0: &str = "../tests/test-data/1_hbf_bad_dw_ddw0.raw";
pub const FILE_1_HBF_BAD_IHW_TDH: &str = "../tests/test-data/1_hbf_bad_ihw_tdh.raw";
pub const FILE_1_HBF_BAD_ITS_PAYLOAD: &str = "../tests/test-data/1_hbf_bad_its_payload.raw";
pub const FILE_1_HBF_BAD_TDT: &str = "../tests/test-data/1_hbf_bad_tdt.raw";
pub const FILE_TDH_NO_DATA: &str = "../tests/test-data/tdh_no_data.raw";
pub const FILE_TDH_NO_DATA_IHW: &str = "../tests/test-data/tdh_no_data_ihw.raw";
pub const FILE_RAWTF_EPN180_L6_1: &str = "../tests/test-data/rawtf_epn180_l6_1.raw";
pub const FILE_RAWTF_FEE_24612_4RDHS: &str = "../tests/test-data/o2_rawtf_fee24612_4rdh.raw";
pub const FILE_INVALID_LANE_ORDER_1HBF: &str = "../tests/test-data/invalid_lane_order_1hbf.raw";
pub const FILE_CI_OLS_DATA_1HBF: &str = "../tests/test-data/ci_ols_data_1hbf.raw"; pub const FILE_2_RDH_DET_FIELD_V1_21_0: &str = "../tests/test-data/2_rdh_det_field_v1.21.0.raw"; pub const FILE_2_HBF_2ND_BAD_FRAME: &str = "../tests/test-data/2_hbf_2nd_bad_frame.raw"; pub const FILE_12_LINKS_2HBF: &str = "../tests/test-data/12_links_2hbf.raw";
pub const ANSI_ESCAPE_REGEX: &str = r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]";
pub const WARN_PREFIX: &str = concat!("WARN ", r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]");
pub const ERROR_PREFIX: &str = concat!("ERROR ", r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]");
pub fn prefix_and_then<S>(prefix: &'static str, suffix: S) -> String
where
S: AsRef<str> + Display,
{
format!("{prefix}{suffix}")
}
pub const VIEW_RDH_REGEX_SANITY: &str = ":.*(7|6).*64.*(0|2)";
pub fn make_tmp_dir_w_fpath() -> (TempDir, ChildPath) {
let tmp_d = TempDir::new().unwrap();
let tmp_fpath = tmp_d.child("tmp.raw");
(tmp_d, tmp_fpath)
}
pub fn make_tmp_dir_w_named_file(fname: &str) -> (TempDir, ChildPath) {
let tmp_d = TempDir::new().unwrap();
let tmp_fpath = tmp_d.child(fname);
(tmp_d, tmp_fpath)
}
pub fn read_stats_from_file(
stats_fpath: &ChildPath,
format: &str,
) -> Result<fastpasta::stats::stats_collector::StatsCollector, Box<dyn std::error::Error>> {
let stats_file = std::fs::read_to_string(stats_fpath)?;
let stats = match format.to_uppercase().as_str() {
"JSON" => serde_json::from_str(&stats_file)?,
"TOML" => toml::from_str(&stats_file)?,
_ => panic!("Invalid format: {format}"),
};
Ok(stats)
}
pub fn match_on_out<S>(
case_sensitive: bool,
byte_output: &[u8],
re: S,
expect_match: usize,
) -> Result<(), Box<dyn std::error::Error>>
where
S: AsRef<str> + ToOwned + Display + Into<String>,
{
let str_res = std::str::from_utf8(byte_output).expect("invalid utf-8 sequence");
let regex_pattern = if case_sensitive {
re.to_string()
} else {
format!("(?i){re}")
};
let re = fancy_regex::Regex::new(®ex_pattern).unwrap();
let match_count = re.find_iter(str_res).count();
assert_eq!(
match_count, expect_match,
"regex: {re} - expected match count: {expect_match}, got {match_count}\nFailed to match on:\n{str_res}"
);
Ok(())
}
pub fn assert_no_errors_or_warn(
stderr_byte_output: &[u8],
) -> Result<(), Box<dyn std::error::Error>> {
match_on_out(true, stderr_byte_output, ERROR_PREFIX, 0)?;
match_on_out(true, stderr_byte_output, WARN_PREFIX, 0)?;
match_on_out(false, stderr_byte_output, "thread.*panicked", 0)?;
Ok(())
}
pub fn create_custom_checks_toml(
toml_content: &str,
toml_path: &std::path::PathBuf,
) -> Result<(), Box<dyn std::error::Error>> {
let mut custom_checks_file = std::fs::File::create(toml_path)?;
std::io::Write::write_all(&mut custom_checks_file, toml_content.as_bytes())?;
custom_checks_file.sync_all()?;
Ok(())
}
fn match_count_suffix(
haystack: &str,
pre_re: &str,
expect_cnt: u64,
) -> Result<(), Box<dyn std::error::Error>> {
let re = RegexBuilder::new(&format!("{pre_re}{expect_cnt}"))
.case_insensitive(true)
.build()
.unwrap();
assert!(
re.is_match(haystack),
"regex: {re}\nFailed to match on:\n{haystack}"
);
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn assert_alpide_stats_report(
byte_output: &[u8],
chip_trailers_seen: u64,
busy_violations: u64,
data_overrun: u64,
transmission_in_fatal: u64,
flushed_incomplete: u64,
strobe_extended: u64,
busy_transitions: u64,
) -> Result<(), Box<dyn std::error::Error>> {
let str_res = std::str::from_utf8(byte_output).expect("invalid utf-8 sequence");
match_count_suffix(str_res, "chip.*trailers.*seen.*", chip_trailers_seen)?;
match_count_suffix(str_res, "busy.*violations.*", busy_violations)?;
match_count_suffix(str_res, "data.*overrun.*", data_overrun)?;
match_count_suffix(str_res, "transmission.*in.*fatal.*", transmission_in_fatal)?;
match_count_suffix(str_res, "flushed.*incomplete.*", flushed_incomplete)?;
match_count_suffix(str_res, "strobe.*extended.*", strobe_extended)?;
match_count_suffix(str_res, "busy.*transitions.*", busy_transitions)?;
Ok(())
}