use std::path::PathBuf;
use needletail::parse_fastx_file;
use proptest::collection::vec;
use proptest::strategy::Strategy;
use proptest::test_runner::{Config, RngSeed};
const DNA_ALPHABET: &[char] = &[
'A', 'C', 'G', 'T', 'a', 'c', 'g', 't', 'N', 'n', 'R', 'Y', 'S', 'W', 'K', 'M',
];
const FIXED_RNG_SEED: u64 = 0x5b0a_2510_c0de_5eed;
pub fn deterministic_config() -> Config {
Config {
rng_seed: RngSeed::Fixed(FIXED_RNG_SEED),
..Config::default()
}
}
fn dna_char() -> impl Strategy<Value = char> {
(0..DNA_ALPHABET.len()).prop_map(|i| DNA_ALPHABET[i])
}
fn dna_seq(max_len: usize) -> impl Strategy<Value = String> {
vec(dna_char(), 1..=max_len).prop_map(|chars| chars.into_iter().collect())
}
pub fn small_dna(max_len: usize, n_seqs: usize) -> impl Strategy<Value = Vec<String>> {
debug_assert!(
n_seqs >= 1,
"small_dna: n_seqs must be >= 1 (spoa needs at least one sequence); \
n_seqs == 0 builds an inverted 1..=0 range that silently yields an \
empty strategy"
);
debug_assert!(max_len >= 1, "small_dna: max_len must be >= 1");
vec(dna_seq(max_len), 1..=n_seqs)
}
fn crate_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
pub fn upstream_fastq() -> (Vec<String>, Vec<String>) {
let (seqs, quals, _names) = upstream_fastq_with_names();
(seqs, quals)
}
pub fn upstream_fastq_with_names() -> (Vec<String>, Vec<String>, Vec<String>) {
let path = crate_root().join("third_party/spoa/test/data/sample.fastq.gz");
let mut reader = parse_fastx_file(&path).unwrap_or_else(|e| {
panic!(
"failed to open upstream FASTQ fixture {}: {e}",
path.display()
)
});
let mut seqs = Vec::new();
let mut quals = Vec::new();
let mut names = Vec::new();
while let Some(record) = reader.next() {
let record = record.unwrap_or_else(|e| {
panic!(
"failed to parse a record from upstream FASTQ fixture {}: {e}",
path.display()
)
});
let seq = String::from_utf8(record.seq().into_owned()).unwrap_or_else(|e| {
panic!(
"non-UTF8 sequence bytes in upstream FASTQ fixture {}: {e}",
path.display()
)
});
let qual = record.qual().unwrap_or_else(|| {
panic!(
"record in upstream FASTQ fixture {} is missing qualities",
path.display()
)
});
let qual = String::from_utf8(qual.to_vec()).unwrap_or_else(|e| {
panic!(
"non-UTF8 quality bytes in upstream FASTQ fixture {}: {e}",
path.display()
)
});
let id = record.id();
let name_bytes = id.split(|&b| b == b' ' || b == b'\t').next().unwrap_or(id);
let name = String::from_utf8(name_bytes.to_vec()).unwrap_or_else(|e| {
panic!(
"non-UTF8 record name bytes in upstream FASTQ fixture {}: {e}",
path.display()
)
});
seqs.push(seq);
quals.push(qual);
names.push(name);
}
(seqs, quals, names)
}