Skip to content

Commit

Permalink
added new integration tests (valide_score_matches_alignment) and iden…
Browse files Browse the repository at this point in the history
…tified a new bug
  • Loading branch information
ostnam committed Mar 12, 2022
1 parent b3377cb commit b27d115
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 6 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ path = "src/lib.rs"
name = "validate"
path = "src/validate.rs"

[[bin]]
name = "validate_score_matches_alignment"
path = "src/validate_score_matches_alignment.rs"

[[bin]]
name = "bench_manual"
path = "src/bench_manual.rs"
Expand Down
88 changes: 88 additions & 0 deletions src/validate_score_matches_alignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use lib::validation_lib::*;
use lib::alignment_lib::{Alignment, Penalties};

use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
use std::thread;

use clap::Parser;

/// Type used for CLI args parsing using clap.
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct ValidateArgs {
#[clap(short, long)]
parallel: bool,

#[clap(long)]
min_length: usize,

#[clap(long)]
max_length: usize,

#[clap(long)]
min_error: i32,

#[clap(long)]
max_error: i32,
}

fn run_validate_sma(args: ValidateArgs) {
for cycle in 0..u32::MAX {
let (computed_score, alignment, pens) = validate_sma(
&AlignmentType::WavefrontNaive,
args.min_length,
args.max_length,
args.min_error,
args.max_error,
);
if computed_score == alignment.score {
println!("Validation successful at cycle {}", cycle)}
else {
println!("Validation failed at cycle {}. The score of: {:?}, should be: {} for the penalties: {:?}.", cycle, alignment, computed_score, pens);
panic!();
}
}
}

fn run_validate_sma_concurrent(args: ValidateArgs) {
let num_threads = num_cpus::get();
let (tx, rx): (Sender<(i32, Alignment, Penalties)>, Receiver<(i32, Alignment, Penalties)>) = mpsc::channel();
let mut threads = Vec::new();

for _ in 0..num_threads {
let new_tx = tx.clone();
threads.push(thread::spawn(move || while let Ok(_) = new_tx.send(validate_sma(
&AlignmentType::WavefrontNaive,
args.min_length,
args.max_length,
args.min_error,
args.max_error,
)) {}
));
}

for cycle in 0..=u64::MAX {
match rx.recv() {
Ok((computed_score, alignment, pens)) => {
if computed_score == alignment.score {
println!("Validation successful at cycle {}", cycle);
} else {
println!("Validation failed at cycle {}. The score of: {:?} should be {} for the penalties: {:?}.", cycle, alignment, computed_score, pens);
panic!();
}
}
Err(_) => panic!(),
}
}
}

fn main() {
let args = ValidateArgs::parse();

if args.parallel {
run_validate_sma_concurrent(args);
} else {
run_validate_sma(args);
}
}
63 changes: 62 additions & 1 deletion src/validation_lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::alignment_lib::*;
use crate::{alignment_lib::*, reference};
use crate::reference::affine_gap_align;
use crate::wavefront_alignment::wavefront_align;
use core::fmt;
Expand Down Expand Up @@ -82,6 +82,33 @@ fn mutate(text: &str, min_error: i32, max_error: i32) -> String {
mutated.into_iter().collect()
}

fn compute_score_from_alignment(alignment: &Alignment, pens: &Penalties) -> i32 {
let mut computed_score: i32 = 0;
let mut current_layer: AlignmentLayer = AlignmentLayer::Matches;
for (c1, c2) in alignment.query_aligned.chars().zip(
alignment.text_aligned.chars()) {
if c1 == '-' {
computed_score += pens.extd_pen + match current_layer {
AlignmentLayer::Deletes => 0,
_ => pens.open_pen,
};
current_layer = AlignmentLayer::Deletes;
} else if c2 == '-' {
computed_score += pens.extd_pen + match current_layer {
AlignmentLayer::Inserts => 0,
_ => pens.open_pen,
};
current_layer = AlignmentLayer::Inserts;
} else {
current_layer = AlignmentLayer::Matches;
if c1 != c2 {
computed_score += pens.mismatch_pen;
}
}
}
computed_score
}

pub enum ValidationResult {
Passed,
Failed(ValidationFailureType),
Expand Down Expand Up @@ -190,3 +217,37 @@ pub fn compare_alignment(
),
}
}
pub fn validate_sma(
a_type: &AlignmentType,
min_length: usize,
max_length: usize,
min_error: i32,
max_error: i32,
) -> (i32, Alignment, Penalties) {
// generate 2 strings
let mut text = random_string(min_length, max_length);
let mut query = mutate(&text, min_error, max_error);
if query.len() > text.len() {
std::mem::swap(&mut query, &mut text);
}

// generate pens
let mut rng = thread_rng();

let pens = Penalties {
mismatch_pen: rng.gen_range(1..100),
open_pen: rng.gen_range(1..100),
extd_pen: rng.gen_range(1..100),
};

// align them using the method
let a_result = match a_type {
AlignmentType::WavefrontNaive => wavefront_align(&query, &text, &pens),
AlignmentType::Reference => reference::affine_gap_align(&query, &text, &pens),
_ => todo!(),
};
match a_result {
AlignResult::Res(a) => (compute_score_from_alignment(&a, &pens), a, pens),
AlignResult::Error(_) => panic!(),
}
}
10 changes: 5 additions & 5 deletions src/wavefront_alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,17 +1088,17 @@ mod tests {

assert_eq!(
wavefront_align(
"AV",
"VM",
"AVD",
"VDM",
&Penalties {
mismatch_pen: 5,
mismatch_pen: 2,
extd_pen: 1,
open_pen: 1,
}
),
AlignResult::Res(Alignment {
query_aligned: "AV-".to_string(),
text_aligned: "-VM".to_string(),
query_aligned: "AVD-".to_string(),
text_aligned: "-VDM".to_string(),
score: 4,
})
);
Expand Down

0 comments on commit b27d115

Please sign in to comment.