Skip to content

Commit

Permalink
Update to quickcheck 1.0
Browse files Browse the repository at this point in the history
New in 1.0 is that integers now generate values in their whole range.
That creates a different situation for the tests taking isize than
before.

Shrink their accepted values for now, and leave as fixmes to investigate and
improve.

In some cases, the tests are slow to execute.
In other cases, the tests fail with large values (probably overflow),
and following that, the case shrinking is extremely slow.
  • Loading branch information
bluss committed Nov 17, 2021
1 parent 0172657 commit d0f7499
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ rawpointer = { version = "0.2" }

[dev-dependencies]
defmac = "0.2"
quickcheck = { version = "0.9", default-features = false }
quickcheck = { version = "1.0", default-features = false }
approx = "0.4"
itertools = { version = "0.10.0", default-features = false, features = ["use_std"] }

Expand Down
4 changes: 2 additions & 2 deletions ndarray-rand/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ keywords = ["multidimensional", "matrix", "rand", "ndarray"]
[dependencies]
ndarray = { version = "0.15", path = ".." }
rand_distr = "0.4.0"
quickcheck = { version = "0.9", default-features = false, optional = true }
quickcheck = { version = "1.0", default-features = false, optional = true }

[dependencies.rand]
version = "0.8.0"
features = ["small_rng"]

[dev-dependencies]
rand_isaac = "0.3.0"
quickcheck = { version = "0.9", default-features = false }
quickcheck = { version = "1.0", default-features = false }

[package.metadata.release]
no-dev-version = true
Expand Down
2 changes: 1 addition & 1 deletion ndarray-rand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ pub enum SamplingStrategy {
// `Arbitrary` enables `quickcheck` to generate random `SamplingStrategy` values for testing.
#[cfg(feature = "quickcheck")]
impl Arbitrary for SamplingStrategy {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
fn arbitrary(g: &mut Gen) -> Self {
if bool::arbitrary(g) {
SamplingStrategy::WithReplacement
} else {
Expand Down
29 changes: 19 additions & 10 deletions ndarray-rand/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ndarray_rand::rand::{distributions::Distribution, thread_rng};
use ndarray::ShapeBuilder;
use ndarray_rand::rand_distr::Uniform;
use ndarray_rand::{RandomExt, SamplingStrategy};
use quickcheck::quickcheck;
use quickcheck::{quickcheck, TestResult};

#[test]
fn test_dim() {
Expand Down Expand Up @@ -51,52 +51,61 @@ fn oversampling_without_replacement_should_panic() {
}

quickcheck! {
fn oversampling_with_replacement_is_fine(m: usize, n: usize) -> bool {
fn oversampling_with_replacement_is_fine(m: u8, n: u8) -> TestResult {
let (m, n) = (m as usize, n as usize);
let a = Array::random((m, n), Uniform::new(0., 2.));
// Higher than the length of both axes
let n_samples = m + n + 1;

// We don't want to deal with sampling from 0-length axes in this test
if m != 0 {
if !sampling_works(&a, SamplingStrategy::WithReplacement, Axis(0), n_samples) {
return false;
return TestResult::failed();
}
} else {
return TestResult::discard();
}

// We don't want to deal with sampling from 0-length axes in this test
if n != 0 {
if !sampling_works(&a, SamplingStrategy::WithReplacement, Axis(1), n_samples) {
return false;
return TestResult::failed();
}
} else {
return TestResult::discard();
}

true
TestResult::passed()
}
}

#[cfg(feature = "quickcheck")]
quickcheck! {
fn sampling_behaves_as_expected(m: usize, n: usize, strategy: SamplingStrategy) -> bool {
fn sampling_behaves_as_expected(m: u8, n: u8, strategy: SamplingStrategy) -> TestResult {
let (m, n) = (m as usize, n as usize);
let a = Array::random((m, n), Uniform::new(0., 2.));
let mut rng = &mut thread_rng();

// We don't want to deal with sampling from 0-length axes in this test
if m != 0 {
let n_row_samples = Uniform::from(1..m+1).sample(&mut rng);
if !sampling_works(&a, strategy.clone(), Axis(0), n_row_samples) {
return false;
return TestResult::failed();
}
} else {
return TestResult::discard();
}

// We don't want to deal with sampling from 0-length axes in this test
if n != 0 {
let n_col_samples = Uniform::from(1..n+1).sample(&mut rng);
if !sampling_works(&a, strategy, Axis(1), n_col_samples) {
return false;
return TestResult::failed();
}
} else {
return TestResult::discard();
}

true
TestResult::passed()
}
}

Expand Down
28 changes: 22 additions & 6 deletions src/dimension/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -920,12 +920,16 @@ mod test {
}

quickcheck! {
fn extended_gcd_solves_eq(a: isize, b: isize) -> bool {
// FIXME: This test can't handle larger values at the moment
fn extended_gcd_solves_eq(a: i16, b: i16) -> bool {
let (a, b) = (a as isize, b as isize);
let (g, (x, y)) = extended_gcd(a, b);
a * x + b * y == g
}

fn extended_gcd_correct_gcd(a: isize, b: isize) -> bool {
// FIXME: This test can't handle larger values at the moment
fn extended_gcd_correct_gcd(a: i16, b: i16) -> bool {
let (a, b) = (a as isize, b as isize);
let (g, _) = extended_gcd(a, b);
g == gcd(a, b)
}
Expand All @@ -941,9 +945,12 @@ mod test {
}

quickcheck! {
// FIXME: This test can't handle larger values at the moment
fn solve_linear_diophantine_eq_solution_existence(
a: isize, b: isize, c: isize
a: i16, b: i16, c: i16
) -> TestResult {
let (a, b, c) = (a as isize, b as isize, c as isize);

if a == 0 || b == 0 {
TestResult::discard()
} else {
Expand All @@ -953,9 +960,12 @@ mod test {
}
}

// FIXME: This test can't handle larger values at the moment
fn solve_linear_diophantine_eq_correct_solution(
a: isize, b: isize, c: isize, t: isize
a: i16, b: i16, c: i8, t: i8
) -> TestResult {
let (a, b, c, t) = (a as isize, b as isize, c as isize, t as isize);

if a == 0 || b == 0 {
TestResult::discard()
} else {
Expand All @@ -972,17 +982,23 @@ mod test {
}

quickcheck! {
// FIXME: This test is extremely slow, even with i16 values, investigate
fn arith_seq_intersect_correct(
first1: isize, len1: isize, step1: isize,
first2: isize, len2: isize, step2: isize
first1: i8, len1: i8, step1: i8,
first2: i8, len2: i8, step2: i8
) -> TestResult {
use std::cmp;

let (len1, len2) = (len1 as isize, len2 as isize);
let (first1, step1) = (first1 as isize, step1 as isize);
let (first2, step2) = (first2 as isize, step2 as isize);

if len1 == 0 || len2 == 0 {
// This case is impossible to reach in `arith_seq_intersect()`
// because the `min*` and `max*` arguments are inclusive.
return TestResult::discard();
}

let len1 = len1.abs();
let len2 = len2.abs();

Expand Down

0 comments on commit d0f7499

Please sign in to comment.