Skip to content

Commit

Permalink
Merge pull request #36 from Garvys/task/prop_test
Browse files Browse the repository at this point in the history
Add Property Testing
  • Loading branch information
Alexandre Caulier committed Sep 8, 2019
2 parents e722d5e + 24bb1e8 commit ff97246
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 1 deletion.
3 changes: 2 additions & 1 deletion rustfst/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ serde_derive = '1.0'
serde_json = '1.0'
tempfile = '3.0'
path_abs = '0.5'
pretty_assertions = "0.6.1"
pretty_assertions = "0.6.1"
proptest = "0.9.4"
16 changes: 16 additions & 0 deletions rustfst/src/algorithms/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,24 @@ impl<'a, F: 'a + ExpandedFst> Visitor<'a, F> for ConnectVisitor<'a, F> {
mod tests {
use crate::test_data::vector_fst::get_vector_fsts_for_tests;

use crate::proptest_fst::proptest_fst;

use crate::fst_properties::FstProperties;

use proptest::prelude::*;

use super::*;

proptest! {
#[test]
fn test_connect_proptest(mut fst in proptest_fst()) {
connect(&mut fst).unwrap();
prop_assume!(fst.properties().unwrap().intersects(
FstProperties::ACCESSIBLE | FstProperties::COACCESSIBLE
));
}
}

#[test]
fn test_connect_generic() -> Fallible<()> {
for data in get_vector_fsts_for_tests() {
Expand Down
21 changes: 21 additions & 0 deletions rustfst/src/algorithms/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,31 @@ mod tests {
use failure::Fallible;

use crate::fst_traits::PathsIterator;
use crate::proptest_fst::proptest_fst;
use crate::test_data::vector_fst::get_vector_fsts_for_tests;

use crate::fst_properties::FstProperties;

use super::*;

use proptest::prelude::*;

proptest! {
#[test]
fn test_project_input_proptest(mut fst in proptest_fst()) {
project(&mut fst, ProjectType::ProjectInput);
prop_assume!(fst.properties().unwrap().intersects(FstProperties::ACCEPTOR));
}
}

proptest! {
#[test]
fn test_project_output_proptest(mut fst in proptest_fst()) {
project(&mut fst, ProjectType::ProjectOutput);
prop_assume!(fst.properties().unwrap().intersects(FstProperties::ACCEPTOR));
}
}

#[test]
fn test_projection_input_generic() -> Fallible<()> {
for data in get_vector_fsts_for_tests() {
Expand Down
2 changes: 2 additions & 0 deletions rustfst/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,5 @@ pub mod prelude {
pub use crate::fst_traits::*;
pub use crate::semirings::*;
}

mod proptest_fst;
89 changes: 89 additions & 0 deletions rustfst/src/proptest_fst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#![cfg(test)]

use proptest::prelude::*;

use crate::fst_impls::VectorFst;
use crate::fst_traits::MutableFst;
use crate::semirings::{Semiring, TropicalWeight};
use crate::Arc;

static MAX_NUM_STATES: usize = 100;
static MAX_ILABEL: usize = 100;
static MAX_OLABEL: usize = 100;
static MAX_NUM_ARCS: usize = 500;

fn proptest_weight() -> impl Strategy<Value = Option<TropicalWeight>> {
prop_oneof![
Just(None),
(2..10).prop_map(|e| Some(TropicalWeight::new(e as f32)))
]
}

fn proptest_arcs(nstates: usize) -> impl Strategy<Value = Vec<(usize, Arc<TropicalWeight>)>> {
proptest::collection::vec(
(
0..nstates,
0..MAX_ILABEL,
0..MAX_OLABEL,
proptest_weight(),
0..nstates,
),
// Number of arcs
0..MAX_NUM_ARCS,
)
.prop_map(|v| {
v.into_iter()
.map(|(state, ilabel, olabel, weight, nextstate)| {
(
state,
Arc {
ilabel,
olabel,
weight: weight.unwrap_or_else(TropicalWeight::one),
nextstate,
},
)
})
.collect()
})
}

pub(crate) fn proptest_fst() -> impl Strategy<Value = VectorFst<TropicalWeight>> {
let nstates_strategy = 1..MAX_NUM_STATES;
nstates_strategy
.prop_flat_map(|nstates| {
(
// Number of states.
Just(nstates),
// Start state.
(0..nstates),
// List of states : Vec<State, Arc>.
proptest_arcs(nstates),
// List of final weight.
proptest::collection::vec(proptest_weight(), nstates..=nstates),
)
})
.prop_map(|(nstates, start_state, arcs, final_weights)| {
let mut fst = VectorFst::new();

// Create all states.
fst.add_states(nstates);

// Set start state.
fst.set_start(start_state).unwrap();

// Add arcs.
for (state, arc) in arcs.into_iter() {
unsafe { fst.add_arc_unchecked(state, arc) };
}

// Set final weights.
for (idx, final_weight) in final_weights.into_iter().enumerate() {
if let Some(_final_weight) = final_weight {
unsafe { fst.set_final_unchecked(idx, _final_weight) };
}
}

fst
})
}

0 comments on commit ff97246

Please sign in to comment.