use std::path::{Path, PathBuf};
use vareffect::{FastaReader, TranscriptStore, VarEffect};
fn open_var_effect() -> VarEffect {
let path = std::env::var("FASTA_PATH").expect(
"FASTA_PATH env var must point to a GRCh38 genome binary (.bin) \
with its .bin.idx sidecar. Run `vareffect-cli setup` first, then \
set FASTA_PATH=data/vareffect/GRCh38.bin.",
);
let path_buf = PathBuf::from(path);
let fasta =
FastaReader::open(Path::new(&path_buf)).expect("opening the reference genome binary");
let transcripts = TranscriptStore::from_transcripts(Vec::new());
VarEffect::new(transcripts, fasta)
}
#[test]
#[ignore]
fn snv_passthrough() {
let ve = open_var_effect();
let result = ve
.left_align_indel("chr17", 7_676_154, "C", "T")
.expect("left_align_indel should not error on SNV");
assert_eq!(result, None, "SNV should pass through unchanged");
}
#[test]
#[ignore]
fn mnv_passthrough() {
let ve = open_var_effect();
let result = ve
.left_align_indel("chr17", 7_676_154, "CC", "TG")
.expect("left_align_indel should not error on MNV");
assert_eq!(result, None, "MNV should pass through unchanged");
}
#[test]
#[ignore]
fn already_leftmost_deletion() {
let ve = open_var_effect();
let result = ve
.left_align_indel("chr7", 117_559_590, "ATCT", "A")
.expect("left_align_indel should not error");
assert_eq!(result, None, "non-repeat deletion should be unchanged");
}
#[test]
#[ignore]
fn homopolymer_deletion_shifts_left() {
let ve = open_var_effect();
let canonical = Some((43_057_062, "TG".to_string(), "T".to_string()));
let from_inner = ve
.left_align_indel("chr17", 43_057_063, "GG", "G")
.expect("left_align_indel should not error");
let from_outer = ve
.left_align_indel("chr17", 43_057_064, "GG", "G")
.expect("left_align_indel should not error");
assert_eq!(
from_inner, canonical,
"inner deletion must left-align to TG>T"
);
assert_eq!(
from_outer, canonical,
"outer deletion must left-align to TG>T"
);
}
#[test]
#[ignore]
fn homopolymer_insertion_shifts_left() {
let ve = open_var_effect();
let canonical = Some((43_057_062, "T".to_string(), "TG".to_string()));
let from_inner = ve
.left_align_indel("chr17", 43_057_063, "G", "GG")
.expect("left_align_indel should not error");
let from_outer = ve
.left_align_indel("chr17", 43_057_065, "G", "GG")
.expect("left_align_indel should not error");
assert_eq!(
from_inner, canonical,
"inner insertion must left-align to T>TG"
);
assert_eq!(
from_outer, canonical,
"outer insertion must left-align to T>TG"
);
}
#[test]
#[ignore]
fn complex_becomes_deletion_after_shift() {
let ve = open_var_effect();
let result = ve.left_align_indel("chr17", 7_676_154, "CCC", "CC");
assert!(result.is_ok(), "should not error on complex-becomes-indel");
}
#[test]
#[ignore]
fn idempotent() {
let ve = open_var_effect();
let (pos, ref_a, alt_a) = ve
.left_align_indel("chr17", 43_057_064, "GG", "G")
.expect("first pass should not error")
.expect("a right-shifted homopolymer deletion must left-align");
let second = ve
.left_align_indel("chr17", pos, &ref_a, &alt_a)
.expect("second pass should not error");
assert_eq!(
second, None,
"already-normalized variant should return None on second pass"
);
}
#[test]
#[ignore]
fn position_one_boundary() {
let ve = open_var_effect();
let result = ve.left_align_indel("chr1", 1, "NN", "N");
assert!(
result.is_ok(),
"position 1 should not cause underflow: {:?}",
result
);
}
#[test]
#[ignore]
fn vcf_anchor_preserved() {
let ve = open_var_effect();
let result = ve
.left_align_indel("chr13", 32_340_301, "GA", "G")
.expect("should not error");
if let Some((_, ref ref_a, ref alt_a)) = result {
assert!(
!ref_a.is_empty() && !alt_a.is_empty(),
"both alleles must have at least one base (VCF anchor): ref={ref_a}, alt={alt_a}"
);
let shorter = ref_a.len().min(alt_a.len());
assert!(shorter >= 1, "shorter allele must be >= 1 base");
}
}
#[test]
#[ignore]
fn brca1_5266dup_left_aligns_to_insertion_not_snv() {
let ve = open_var_effect();
let result = ve
.left_align_indel("chr17", 43_057_063, "G", "GG")
.expect("left_align_indel should not error");
assert_eq!(
result,
Some((43_057_062, "T".to_string(), "TG".to_string())),
"duplication must remain an insertion (T>TG), not collapse to a SNV (T>G)"
);
}