Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions tests/integration/helpers/assertions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,63 @@ pub fn assert_bam_sorted(bam: &std::path::Path, order: &str, key_types: Option<&
);
}

/// Asserts two text files exist and are byte-for-byte identical, panicking
/// with `label` and the offending path named on either a read error or a
/// content mismatch.
///
/// This is the shared home for the `assert_eq!(read_to_string(a),
/// read_to_string(b))` idiom that the cutover-parity tests (dedup, group,
/// clip, retag, correct, …) each reimplemented inline. It intentionally does
/// NOT guard for non-empty / data-bearing content: whether an output file
/// must carry data rows is specific to the metric being compared, so any such
/// check belongs with the individual caller that needs it, not in a general
/// text-file comparison.
pub fn assert_text_files_eq(actual: &std::path::Path, expected: &std::path::Path, label: &str) {
let a = std::fs::read_to_string(actual)
.unwrap_or_else(|e| panic!("{label}: reading actual {}: {e}", actual.display()));
let e = std::fs::read_to_string(expected)
.unwrap_or_else(|e| panic!("{label}: reading expected {}: {e}", expected.display()));
assert_eq!(a, e, "{label}: {} differs from {}", actual.display(), expected.display());
}

#[cfg(test)]
mod tests {
use super::*;
use crate::helpers::bam_generator::to_record_buf;
use fgumi_raw_bam::{SamBuilder, flags};

#[test]
fn assert_text_files_eq_passes_on_identical_content() {
let dir = tempfile::tempdir().expect("tempdir");
let a = dir.path().join("a");
let b = dir.path().join("b");
std::fs::write(&a, "col1\tcol2\n1\t2\n").expect("write a");
std::fs::write(&b, "col1\tcol2\n1\t2\n").expect("write b");
assert_text_files_eq(&a, &b, "identical files");
}

#[test]
#[should_panic(expected = "differs from")]
fn assert_text_files_eq_panics_on_divergent_content() {
let dir = tempfile::tempdir().expect("tempdir");
let a = dir.path().join("a");
let b = dir.path().join("b");
std::fs::write(&a, "1\n").expect("write a");
std::fs::write(&b, "2\n").expect("write b");
assert_text_files_eq(&a, &b, "divergent files");
}

#[test]
#[should_panic(expected = "reading actual")]
fn assert_text_files_eq_panics_naming_a_missing_file() {
let dir = tempfile::tempdir().expect("tempdir");
assert_text_files_eq(
&dir.path().join("missing-actual"),
&dir.path().join("missing-expected"),
"missing file",
);
}

/// Locks down the noodles behavior that `assert_rejects_header_matches_input`
/// relies on: SO/GO/SS are accessible via the typed `Other` tag constants on
/// `Map<Header>::other_fields()`. If noodles ever moves these to first-class
Expand Down
9 changes: 5 additions & 4 deletions tests/integration/test_clip_cutover_parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use fgumi_raw_bam::{RawRecord, SamBuilder, flags};
use rstest::rstest;
use tempfile::TempDir;

use crate::helpers::assertions::assert_text_files_eq;
use crate::helpers::bam_generator::{create_minimal_header, create_test_reference, write_bam};
use crate::helpers::read_bam_output;

Expand Down Expand Up @@ -491,10 +492,10 @@ fn cutover_matches_baseline(#[case] with_metrics: bool) {
baseline.display(),
);
if with_metrics {
assert_eq!(
std::fs::read_to_string(&current_tsv).expect("current tsv"),
std::fs::read_to_string(&baseline_tsv).expect("baseline tsv"),
"chain --metrics TSV diverges from the serial baseline binary"
assert_text_files_eq(
&current_tsv,
&baseline_tsv,
"chain --metrics TSV diverges from the serial baseline binary",
);
}
} else {
Expand Down
15 changes: 8 additions & 7 deletions tests/integration/test_correct_cutover_parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use std::process::Command;
use rstest::rstest;
use tempfile::TempDir;

use crate::helpers::assertions::assert_text_files_eq;
use crate::helpers::bam_generator::create_umi_family;
use crate::helpers::read_bam_output;
use crate::test_correct_command::create_umi_bam;
Expand Down Expand Up @@ -284,10 +285,10 @@ fn cutover_matches_baseline(#[case] with_metrics: bool) {
baseline.display(),
);
if with_metrics {
assert_eq!(
std::fs::read_to_string(&current_tsv).expect("current tsv"),
std::fs::read_to_string(&baseline_tsv).expect("baseline tsv"),
"chain --metrics TSV diverges from the serial baseline binary"
assert_text_files_eq(
&current_tsv,
&baseline_tsv,
"chain --metrics TSV diverges from the serial baseline binary",
);
}
} else {
Expand Down Expand Up @@ -406,9 +407,9 @@ fn cutover_min_corrected_failure_writes_metrics() {
baseline_tsv.exists(),
"the baseline's legacy path must also leave a --metrics TSV behind on the failure"
);
assert_eq!(
std::fs::read_to_string(&current_tsv).expect("current tsv"),
std::fs::read_to_string(&baseline_tsv).expect("baseline tsv"),
assert_text_files_eq(
&current_tsv,
&baseline_tsv,
"chain --metrics TSV on a --min-corrected failure diverges from the serial baseline",
);
assert_eq!(
Expand Down
23 changes: 14 additions & 9 deletions tests/integration/test_dedup_cutover_parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use tempfile::TempDir;
use fgumi_lib::sam::SamTag;
use fgumi_raw_bam::{RawRecord, SamBuilder, flags};

use crate::helpers::assertions::assert_text_files_eq;
use crate::helpers::bam_generator::{create_minimal_header, write_bam};
use crate::helpers::read_bam_output;

Expand Down Expand Up @@ -578,16 +579,20 @@ fn cutover_matches_baseline_by_strategy(#[case] strategy: &str) {
baseline binary ({}) after stripping @PG — a real cutover parity bug",
baseline.display(),
);
assert_eq!(
std::fs::read_to_string(&current_metrics).expect("current metrics"),
std::fs::read_to_string(&baseline_metrics).expect("baseline metrics"),
"chain --metrics TSV (--strategy {strategy}) diverges from the legacy baseline"
assert_text_files_eq(
&current_metrics,
&baseline_metrics,
&format!(
"chain --metrics TSV (--strategy {strategy}) diverges from the legacy baseline"
),
);
assert_eq!(
std::fs::read_to_string(&current_hist).expect("current histogram"),
std::fs::read_to_string(&baseline_hist).expect("baseline histogram"),
"chain --family-size-histogram TSV (--strategy {strategy}) diverges from the legacy \
baseline"
assert_text_files_eq(
&current_hist,
&baseline_hist,
&format!(
"chain --family-size-histogram TSV (--strategy {strategy}) diverges from the \
legacy baseline"
),
);
} else {
eprintln!(
Expand Down
13 changes: 8 additions & 5 deletions tests/integration/test_group_cutover_parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use tempfile::TempDir;
use fgumi_lib::sam::SamTag;
use fgumi_raw_bam::{RawRecord, SamBuilder, flags};

use crate::helpers::assertions::assert_text_files_eq;
use crate::helpers::bam_generator::{create_minimal_header, write_bam};
use crate::helpers::read_bam_output;

Expand Down Expand Up @@ -534,11 +535,13 @@ fn cutover_matches_baseline_by_strategy(#[case] strategy: &str) {
("grouping_metrics", cur_grp, base_grp),
("position_group_sizes", cur_pos, base_pos),
] {
assert_eq!(
std::fs::read_to_string(&cur).unwrap_or_else(|e| panic!("current {label}: {e}")),
std::fs::read_to_string(&base).unwrap_or_else(|e| panic!("baseline {label}: {e}")),
"chain --metrics {label} TSV (--strategy {strategy}) diverges from the legacy \
baseline"
assert_text_files_eq(
&cur,
&base,
&format!(
"chain --metrics {label} TSV (--strategy {strategy}) diverges from the legacy \
baseline"
),
);
}
} else {
Expand Down
9 changes: 5 additions & 4 deletions tests/integration/test_retag_cutover_parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use fgumi_raw_bam::{RawRecord, SamBuilder, flags};
use rstest::rstest;
use tempfile::TempDir;

use crate::helpers::assertions::assert_text_files_eq;
use crate::helpers::bam_generator::{create_minimal_header, write_bam};
use crate::helpers::cutover::{baseline_bin, decompressed_records_without_pg};
use crate::helpers::read_bam_output;
Expand Down Expand Up @@ -206,10 +207,10 @@ fn cutover_matches_baseline(#[case] ops: &[&str], #[case] with_metrics: bool) {
baseline.display(),
);
if with_metrics {
assert_eq!(
std::fs::read_to_string(&current_tsv).expect("current tsv"),
std::fs::read_to_string(&baseline_tsv).expect("baseline tsv"),
"chain --metrics TSV diverges from the serial baseline binary"
assert_text_files_eq(
&current_tsv,
&baseline_tsv,
"chain --metrics TSV diverges from the serial baseline binary",
);
}
} else {
Expand Down
Loading