extern crate quickcheck;
extern crate suffix;
use quickcheck::{QuickCheck, TestResult, Testable};
use suffix::SuffixTable;
fn sais(text: &str) -> SuffixTable {
SuffixTable::new(text)
}
fn naive(text: &str) -> SuffixTable {
SuffixTable::new_naive(text)
}
fn qc<T: Testable>(f: T) {
QuickCheck::new().tests(1000).max_tests(10000).quickcheck(f);
}
#[test]
fn basic1() {
assert_eq!(naive("apple"), sais("apple"));
}
#[test]
fn basic2() {
assert_eq!(naive("banana"), sais("banana"));
}
#[test]
fn basic3() {
assert_eq!(naive("mississippi"), sais("mississippi"));
}
#[test]
fn basic4() {
assert_eq!(naive("tgtgtgtgcaccg"), sais("tgtgtgtgcaccg"));
}
#[test]
fn empty_is_ok() {
assert_eq!(naive(""), sais(""));
}
#[test]
fn one_is_ok() {
assert_eq!(naive("a"), sais("a"));
}
#[test]
fn two_diff_is_ok() {
assert_eq!(naive("ab"), sais("ab"));
}
#[test]
fn two_same_is_ok() {
assert_eq!(naive("aa"), sais("aa"));
}
#[test]
fn nul_is_ok() {
assert_eq!(naive("\x00"), sais("\x00"));
}
#[test]
fn snowman_is_ok() {
assert_eq!(naive("☃abc☃"), sais("☃abc☃"));
}
#[test]
fn prop_naive_equals_sais() {
fn prop(s: String) -> TestResult {
if s.is_empty() {
return TestResult::discard();
}
let expected = naive(&*s);
let got = sais(&*s);
TestResult::from_bool(expected == got)
}
qc(prop as fn(String) -> TestResult);
}
#[test]
fn prop_matches_naive() {
fn prop(s: String) -> bool {
let expected_table = SuffixTable::new_naive(&*s);
let expected = expected_table.table();
let got_table = SuffixTable::new(&*s);
let got = got_table.table();
expected == got
}
qc(prop as fn(String) -> bool);
}
#[test]
fn empty_find_empty() {
let sa = sais("");
assert_eq!(sa.positions(""), &[]);
assert!(!sa.contains(""));
}
#[test]
fn empty_find_one() {
let sa = sais("");
assert_eq!(sa.positions("a"), &[]);
assert!(!sa.contains("a"));
}
#[test]
fn empty_find_two() {
let sa = sais("");
assert_eq!(sa.positions("ab"), &[]);
assert!(!sa.contains("ab"));
}
#[test]
fn one_find_empty() {
let sa = sais("a");
assert_eq!(sa.positions(""), &[]);
assert!(!sa.contains(""));
}
#[test]
fn one_find_one_notexists() {
let sa = sais("a");
assert_eq!(sa.positions("b"), &[]);
assert!(!sa.contains("b"));
}
#[test]
fn one_find_one_exists() {
let sa = sais("a");
assert_eq!(sa.positions("a"), &[0]);
assert!(sa.contains("a"));
}
#[test]
fn two_find_one_exists() {
let sa = sais("ab");
assert_eq!(sa.positions("b"), &[1]);
assert!(sa.contains("b"));
}
#[test]
fn two_find_two_exists() {
let sa = sais("aa");
assert_eq!(vec![1, 0], sa.positions("a"));
assert!(sa.contains("a"));
}
#[test]
fn many_exists() {
let sa = sais("zzzzzaazzzzz");
assert_eq!(vec![5, 6], sa.positions("a"));
assert!(sa.contains("a"));
}
#[test]
fn many_exists_long() {
let sa = sais("zzzzabczzzzzabczzzzzz");
assert_eq!(sa.positions("abc"), &[4, 12]);
assert!(sa.contains("abc"));
}
#[test]
fn parts() {
let sa = sais("poëzie");
let sa2 = sa.clone();
let (data, table) = sa2.into_parts();
let sa3 = SuffixTable::from_parts(data, table);
assert_eq!(sa, sa3);
}
#[test]
fn query_longer() {
let sa = sais("az");
assert_eq!(sa.positions("mnomnomnomnomnomnomno"), &[]);
assert!(!sa.contains("mnomnomnomnomnomnomno"));
}
#[test]
fn query_longer_less() {
let sa = sais("zz");
assert_eq!(sa.positions("mnomnomnomnomnomnomno"), &[]);
assert!(!sa.contains("mnomnomnomnomnomnomno"));
}
#[test]
fn query_longer_greater() {
let sa = sais("aa");
assert_eq!(sa.positions("mnomnomnomnomnomnomno"), &[]);
assert!(!sa.contains("mnomnomnomnomnomnomno"));
}
#[test]
fn query_spaces() {
let sa = sais("The quick brown fox was very quick.");
assert_eq!(sa.positions("quick"), &[4, 29]);
}
#[test]
fn unicode_snowman() {
let sa = sais("☃abc☃");
assert!(sa.contains("☃"));
assert_eq!(sa.positions("☃"), &[6, 0]);
}
#[test]
fn prop_length() {
fn prop(s: String) -> bool {
s.len() == sais(&s).len()
}
qc(prop as fn(String) -> bool);
}
#[test]
fn prop_contains() {
fn prop(s: String, c: u8) -> bool {
let c = (c as char).to_string();
s.contains(&c) == sais(&s).contains(&c)
}
qc(prop as fn(String, u8) -> bool);
}
#[test]
fn prop_positions() {
fn prop(s: String, c: u8) -> bool {
let c = (c as char).to_string();
let expected: Vec<_> =
s.match_indices(&c).map(|(s, _)| s as u32).collect();
let mut got = sais(&s).positions(&c).to_vec();
got.sort();
expected == got
}
qc(prop as fn(String, u8) -> bool);
}