otvec/tests/proptest.rs

389 lines
12 KiB
Rust

mod util;
use proptest::prelude::*;
use rayon::prelude::*;
use otvec::Operation;
use util::{print_cond_catch_ctr, test_transform_cond, test_transform_cond_catch, CondCatchCtr};
const ALL_SIZE: usize = 20;
const MIN_RANGE_LEN: usize = 1;
const TEST_SIZE: usize = 9;
const TEST_MIN_RANGE_LEN: usize = 1;
const VEC_SIZE: usize = 100;
fn testvec(len: usize) -> Vec<usize> {
(0..len).collect::<Vec<_>>()
}
fn t_ins_ins(size: usize, a_pos: usize, a_len: usize, b_pos: usize, b_len: usize) {
let input = testvec(size);
let a = Operation::Ins {
pos: a_pos,
val: testvec(a_len),
};
let b = Operation::Ins {
pos: b_pos,
val: testvec(b_len),
};
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
fn t_del_del(size: usize, a_pos: usize, a_len: usize, b_pos: usize, b_len: usize) {
let input = testvec(size);
let a = Operation::Del {
pos: a_pos,
n: a_len,
};
let b = Operation::Del {
pos: b_pos,
n: b_len,
};
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
fn t_ins_del(size: usize, a_pos: usize, a_len: usize, b_pos: usize, b_len: usize) {
let input = testvec(size);
let a = Operation::Ins {
pos: a_pos,
val: testvec(a_len),
};
let b = Operation::Del {
pos: b_pos,
n: b_len,
};
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
fn t_mov_ins(size: usize, a_pos: usize, a_len: usize, a_to: usize, b_pos: usize, b_len: usize) {
let input = testvec(size);
let a = Operation::Mov {
pos: a_pos,
n: a_len,
to: a_to,
};
let b = Operation::Ins {
pos: b_pos,
val: testvec(b_len),
};
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
fn t_mov_del(size: usize, a_pos: usize, a_len: usize, a_to: usize, b_pos: usize, b_len: usize) {
let input = testvec(size);
let a = Operation::Mov {
pos: a_pos,
n: a_len,
to: a_to,
};
let b = Operation::Del {
pos: b_pos,
n: b_len,
};
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
fn t_mov_mov_catch(
size: usize,
a_pos: usize,
a_len: usize,
a_to: usize,
b_pos: usize,
b_len: usize,
b_to: usize,
ctr: Option<&CondCatchCtr>,
) {
let input = testvec(size);
let a = Operation::Mov {
pos: a_pos,
n: a_len,
to: a_to,
};
let b = Operation::Mov {
pos: b_pos,
n: b_len,
to: b_to,
};
test_transform_cond_catch(&a, &b, &input, ctr);
test_transform_cond_catch(&b, &a, &input, ctr);
}
fn t_mov_mov(
size: usize,
a_pos: usize,
a_len: usize,
a_to: usize,
b_pos: usize,
b_len: usize,
b_to: usize,
) {
let input = testvec(size);
let a = Operation::Mov {
pos: a_pos,
n: a_len,
to: a_to,
};
let b = Operation::Mov {
pos: b_pos,
n: b_len,
to: b_to,
};
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
#[test]
fn all_ins_ins() {
(0..ALL_SIZE).into_par_iter().for_each(|a_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - a_pos))
.into_par_iter()
.for_each(|a_len| {
(0..ALL_SIZE).into_par_iter().for_each(|b_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - b_pos))
.into_par_iter()
.for_each(|b_len| {
t_ins_ins(ALL_SIZE, a_pos, a_len, b_pos, b_len);
});
});
});
});
}
#[test]
fn all_del_del() {
(0..ALL_SIZE).into_par_iter().for_each(|a_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - a_pos))
.into_par_iter()
.for_each(|a_len| {
(0..ALL_SIZE).into_par_iter().for_each(|b_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - b_pos))
.into_par_iter()
.for_each(|b_len| {
t_del_del(ALL_SIZE, a_pos, a_len, b_pos, b_len);
});
});
});
});
}
#[test]
fn all_ins_del() {
(0..ALL_SIZE).into_par_iter().for_each(|a_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - a_pos))
.into_par_iter()
.for_each(|a_len| {
(0..ALL_SIZE).into_par_iter().for_each(|b_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - b_pos))
.into_par_iter()
.for_each(|b_len| {
t_ins_del(ALL_SIZE, a_pos, a_len, b_pos, b_len);
});
});
});
});
}
#[test]
fn all_mov_ins() {
(0..ALL_SIZE).into_par_iter().for_each(|a_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - a_pos))
.into_par_iter()
.for_each(|a_len| {
(0..a_pos)
.into_par_iter()
.chain((a_pos + a_len + 1)..=ALL_SIZE)
.for_each(|a_to| {
(0..ALL_SIZE).into_par_iter().for_each(|b_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - b_pos))
.into_par_iter()
.for_each(|b_len| {
t_mov_ins(ALL_SIZE, a_pos, a_len, a_to, b_pos, b_len);
});
});
});
});
});
}
#[test]
fn all_mov_del() {
(0..ALL_SIZE).into_par_iter().for_each(|a_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - a_pos))
.into_par_iter()
.for_each(|a_len| {
(0..a_pos)
.into_par_iter()
.chain((a_pos + a_len + 1)..=ALL_SIZE)
.for_each(|a_to| {
(0..ALL_SIZE).into_par_iter().for_each(|b_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - b_pos))
.into_par_iter()
.for_each(|b_len| {
t_mov_del(ALL_SIZE, a_pos, a_len, a_to, b_pos, b_len);
});
});
});
});
});
}
// For development (non-parallel and panic-catching)
#[test]
fn dev_all_mov_mov() {
let ctr = CondCatchCtr::default();
(0..TEST_SIZE).into_iter().for_each(|a_pos| {
(TEST_MIN_RANGE_LEN..=(TEST_SIZE - a_pos))
.into_iter()
// .rev()
.for_each(|a_len| {
(0..a_pos)
.into_iter()
.chain((a_pos + a_len + 1)..=TEST_SIZE)
.for_each(|a_to| {
(0..TEST_SIZE).into_iter().for_each(|b_pos| {
(TEST_MIN_RANGE_LEN..=(TEST_SIZE - b_pos))
.into_iter()
// .rev()
.for_each(|b_len| {
(0..b_pos)
.into_iter()
.chain((b_pos + b_len + 1)..=TEST_SIZE)
.for_each(|b_to| {
t_mov_mov_catch(
TEST_SIZE,
a_pos,
a_len,
a_to,
b_pos,
b_len,
b_to,
Some(&ctr),
);
});
});
});
});
});
});
print_cond_catch_ctr(&ctr);
}
#[test]
fn all_mov_mov() {
(0..ALL_SIZE).into_par_iter().for_each(|a_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - a_pos))
.into_par_iter()
.for_each(|a_len| {
(0..a_pos)
.into_par_iter()
.chain((a_pos + a_len + 1)..=ALL_SIZE)
.for_each(|a_to| {
(0..ALL_SIZE).into_par_iter().for_each(|b_pos| {
(MIN_RANGE_LEN..=(ALL_SIZE - b_pos))
.into_par_iter()
.for_each(|b_len| {
(0..b_pos)
.into_par_iter()
.chain((b_pos + b_len + 1)..=ALL_SIZE)
.for_each(|b_to| {
t_mov_mov(
ALL_SIZE, a_pos, a_len, a_to, b_pos, b_len, b_to,
);
});
});
});
});
});
});
}
fn test_params() -> impl Strategy<Value = (usize, (usize, usize, usize), (usize, usize, usize))> {
((MIN_RANGE_LEN + 1)..=VEC_SIZE)
.prop_flat_map(|vec_size| (Just(vec_size), mov_params(vec_size), mov_params(vec_size)))
}
/// Parameters for a single test operation
fn mov_params(vec_size: usize) -> impl Strategy<Value = (usize, usize, usize)> {
(0..(vec_size - MIN_RANGE_LEN))
.prop_flat_map(move |pos| (Just(pos), MIN_RANGE_LEN..=(vec_size - pos)))
.prop_flat_map(move |(pos, len)| {
let rb = (pos + len + 1)..(vec_size + 1);
(
Just(pos),
Just(len),
match (pos > 0, rb.end > rb.start) {
(true, true) => Strategy::boxed((0..pos).prop_union(rb)),
(true, false) => Strategy::boxed(0..pos),
(false, true) => Strategy::boxed(rb),
(false, false) => Strategy::boxed(Just(pos)),
},
)
})
}
proptest! {
#[test]
fn transform_ins_ins((vec_len, a, b) in test_params(), a_len in 1usize..VEC_SIZE, b_len in 1usize..VEC_SIZE) {
t_ins_ins(vec_len, a.0, a_len, b.0, b_len)
}
#[test]
fn transform_del_del((vec_len, a, b) in test_params()) {
t_del_del(vec_len, a.0, a.1, b.0, b.1)
}
#[test]
fn transform_ins_del((vec_len, a, b) in test_params(), i_len in 1usize..VEC_SIZE) {
t_ins_del(vec_len, a.0, i_len, b.0, b.1)
}
#[test]
fn transform_mov_ins((vec_len, a, b) in test_params(), i_len in 1usize..VEC_SIZE) {
t_mov_ins(vec_len, a.0, a.1, a.2, b.0, i_len)
}
#[test]
fn transform_mov_del((vec_len, a, b) in test_params()) {
t_mov_del(vec_len, a.0, a.1, a.2, b.0, b.1)
}
#[test]
fn transform_mov_mov((vec_len, a, b) in test_params()) {
t_mov_mov(vec_len, a.0, a.1, a.2, b.0, b.1, b.2);
}
#[test]
fn transform_seq((vec_len, a, b, a2, b2, a3, b3) in test_params().prop_flat_map(|(vec_len, a, b)|
(Just(vec_len), Just(a), Just(b), mov_params(vec_len), mov_params(vec_len), mov_params(vec_len), mov_params(vec_len)))
) {
let input = testvec(vec_len);
let a = Operation::Seq { ops: vec![
Operation::Mov {
pos: a.0,
n: a.1,
to: a.2,
},
Operation::Ins { pos: a2.0, val: testvec(a3.1) },
Operation::Del { pos: a3.0, n: a3.1 },
] };
let b = Operation::Seq { ops: vec![
Operation::Mov {
pos: b.0,
n: b.1,
to: b.2,
},
Operation::Ins { pos: b2.0, val: testvec(b3.1) },
Operation::Del { pos: b3.0, n: b3.1 },
] };
test_transform_cond(&a, &b, &input);
test_transform_cond(&b, &a, &input);
}
}