mod support;
use proptest::prelude::*;
use support::generators::{deterministic_config, small_dna};
use support::oracle::{run_oracle, AlignType, OracleCase};
use support::runner::run_spoars;
#[test]
fn linear_nw_identical_sequences_align_on_the_diagonal() {
let seqs = vec!["ACGT".to_string(), "ACGT".to_string()];
let case = OracleCase::linear(AlignType::Nw, &seqs);
let (aligns, cons) = run_spoars(&case);
assert_eq!(aligns.len(), 2);
assert_eq!(aligns[0], Vec::<(i32, i32)>::new());
assert_eq!(aligns[1], vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
assert_eq!(cons, "ACGT");
}
#[test]
fn linear_nw_single_sequence_is_added_verbatim() {
let seqs = vec!["ACGTACGT".to_string()];
let case = OracleCase::linear(AlignType::Nw, &seqs);
let (aligns, cons) = run_spoars(&case);
assert_eq!(aligns, vec![Vec::<(i32, i32)>::new()]);
assert_eq!(cons, "ACGTACGT");
}
#[test]
fn linear_nw_one_mismatch_stays_on_the_diagonal() {
let seqs = vec!["ACGT".to_string(), "ACTT".to_string()];
let case = OracleCase::linear(AlignType::Nw, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
assert_eq!(aligns[1], vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
assert_eq!(&aligns, &exp.alignments);
assert_eq!(cons, exp.consensus);
}
#[test]
fn affine_nw_insertion_run_walks_the_e_matrix() {
let seqs = vec!["AAGG".to_string(), "AACCGG".to_string()];
let case = OracleCase::affine(AlignType::Nw, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
assert_eq!(
aligns[1],
vec![(0, 0), (1, 1), (-1, 2), (-1, 3), (2, 4), (3, 5)]
);
assert_eq!(&aligns, &exp.alignments);
assert_eq!(cons, exp.consensus);
}
#[test]
fn affine_nw_deletion_run_walks_the_f_matrix() {
let seqs = vec!["AACCGG".to_string(), "AAGG".to_string()];
let case = OracleCase::affine(AlignType::Nw, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
assert_eq!(
aligns[1],
vec![(0, 0), (1, 1), (2, -1), (3, -1), (4, 2), (5, 3)]
);
assert_eq!(&aligns, &exp.alignments);
assert_eq!(cons, exp.consensus);
}
#[test]
fn convex_nw_long_deletion_run_uses_the_second_gap_function() {
let seqs = vec!["AACCCGG".to_string(), "AAGG".to_string()];
let case = OracleCase::convex(AlignType::Nw, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
assert_eq!(
aligns[1],
vec![(0, 0), (1, 1), (2, -1), (3, -1), (4, -1), (5, 2), (6, 3)]
);
assert_eq!(&aligns, &exp.alignments);
assert_eq!(cons, exp.consensus);
}
#[test]
fn convex_nw_long_insertion_run_uses_the_second_gap_function() {
let seqs = vec!["AAGG".to_string(), "AACCCGG".to_string()];
let case = OracleCase::convex(AlignType::Nw, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
assert_eq!(
aligns[1],
vec![(0, 0), (1, 1), (-1, 2), (-1, 3), (-1, 4), (2, 5), (3, 6)]
);
assert_eq!(&aligns, &exp.alignments);
assert_eq!(cons, exp.consensus);
}
#[test]
fn convex_nw_very_long_deletion_run_walks_the_o_matrix() {
let seqs = vec!["AACCCCCGG".to_string(), "AAGG".to_string()];
let case = OracleCase::convex(AlignType::Nw, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
assert_eq!(
aligns[1],
vec![
(0, 0),
(1, 1),
(2, -1),
(3, -1),
(4, -1),
(5, -1),
(6, -1),
(7, 2),
(8, 3)
]
);
assert_eq!(&aligns, &exp.alignments);
assert_eq!(cons, exp.consensus);
}
proptest! {
#![proptest_config(ProptestConfig { cases: 48, ..deterministic_config() })]
#[test]
fn linear_alignment_matches_oracle(seqs in small_dna(40, 6)) {
for ty in [AlignType::Sw, AlignType::Nw, AlignType::Ov] {
let case = OracleCase::linear(ty, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
prop_assert_eq!(
&aligns, &exp.alignments,
"alignment mismatch ty={:?} seqs={:?}", ty, seqs
);
prop_assert_eq!(
&cons, &exp.consensus,
"consensus mismatch ty={:?} seqs={:?}", ty, seqs
);
}
}
#[test]
fn affine_alignment_matches_oracle(seqs in small_dna(40, 6)) {
for ty in [AlignType::Sw, AlignType::Nw, AlignType::Ov] {
let case = OracleCase::affine(ty, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
prop_assert_eq!(
&aligns, &exp.alignments,
"alignment mismatch ty={:?} seqs={:?}", ty, seqs
);
prop_assert_eq!(
&cons, &exp.consensus,
"consensus mismatch ty={:?} seqs={:?}", ty, seqs
);
}
}
#[test]
fn convex_alignment_matches_oracle(seqs in small_dna(40, 6)) {
for ty in [AlignType::Sw, AlignType::Nw, AlignType::Ov] {
let case = OracleCase::convex(ty, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
prop_assert_eq!(
&aligns, &exp.alignments,
"alignment mismatch ty={:?} seqs={:?}", ty, seqs
);
prop_assert_eq!(
&cons, &exp.consensus,
"consensus mismatch ty={:?} seqs={:?}", ty, seqs
);
}
}
}
proptest! {
#![proptest_config(ProptestConfig { cases: 32, ..deterministic_config() })]
#[test]
fn all_gap_modes_match_oracle(seqs in small_dna(40, 6)) {
type CaseBuilder = fn(AlignType, &[String]) -> OracleCase;
let builders: [(&str, CaseBuilder); 3] = [
("linear", OracleCase::linear),
("affine", OracleCase::affine),
("convex", OracleCase::convex),
];
for (mode, build) in builders {
for ty in [AlignType::Sw, AlignType::Nw, AlignType::Ov] {
let case = build(ty, &seqs);
let exp = &run_oracle(std::slice::from_ref(&case))[0];
let (aligns, cons) = run_spoars(&case);
prop_assert_eq!(
&aligns, &exp.alignments,
"alignment mismatch mode={} ty={:?} seqs={:?}", mode, ty, seqs
);
prop_assert_eq!(
&cons, &exp.consensus,
"consensus mismatch mode={} ty={:?} seqs={:?}", mode, ty, seqs
);
}
}
}
}