caio.co/de/cantine

Switch to quickcheck

I expected to have my property tests to start failing on
3049519e6, left a `todo!()` note for it but the failure never
happened and it sneaked past me until now.

The culprit was a bad test: `no_crash_with_properly_sized_junk`
relies on the framework providing a properly sized input and the
decoder (correctly) discards things with wrong size - when the
payload length changed to 34 I expected this to crash, but
naturally it didn't.

A proper fix would have been to adjust `uniform32` to `uniform34`
and assert the length against a constant, but `proptest` doesn't
ship with support for larger arrays and I'm not keen on copy
pasting a bunch of code just for creating my own strategy.

Instead, I switch to `quickcheck` that I'm already familiar with
and allows for quick input discard in my case.

Now the test actually fails :-)
Id
49b5f6d25f9ba014da002ef00ca20885260e875d
Author
Caio
Commit time
2020-01-12T08:27:25+01:00

Modified cantine/Cargo.toml

@@ -31,4 +31,4
uuid = { version = "0.8", features = ["serde", "v4"] }
tempfile = "3.1"
once_cell = "1.2"
-proptest = "0.9"
+quickcheck = "0.9"

Modified cantine/src/model.rs

@@ -281,8 +281,8
#[cfg(test)]
mod tests {
use super::*;
- use proptest::prelude::*;

+ use quickcheck::{quickcheck, TestResult};
use serde_json;

#[test]
@@ -307,18 +307,29
}
}

- proptest! {
- #[test]
- #[allow(unused_must_use)]
- fn no_crash_json_any_input_size(input in "\\PC*") {
- serde_json::from_str::<SearchCursor>(input.as_str());
+ fn search_cursor_from_bytes(input: Vec<u8>) -> TestResult {
+ if input.len() != SearchCursor::SIZE {
+ TestResult::discard()
+ } else {
+ SearchCursor::from_bytes(input.as_slice().try_into().unwrap());
+ TestResult::passed()
}
+ }

- #[test]
- #[allow(unused_must_use)]
- fn no_crash_with_properly_sized_junk(buf in prop::array::uniform32(0u8..)) {
+ #[allow(unused_must_use)]
+ fn search_cursor_from_base64(input: Vec<u8>) -> TestResult {
+ if input.len() != ENCODED_SEARCH_CURSOR_LEN {
+ TestResult::discard()
+ } else {
let visitor = SearchCursorVisitor;
- visitor.visit_bytes::<serde_json::Error>(&buf);
+ visitor.visit_bytes::<serde_json::Error>(input.as_slice().try_into().unwrap());
+ TestResult::passed()
}
+ }
+
+ #[test]
+ fn search_cursor_deserialization_does_not_crash() {
+ quickcheck(search_cursor_from_bytes as fn(Vec<u8>) -> TestResult);
+ quickcheck(search_cursor_from_base64 as fn(Vec<u8>) -> TestResult);
}
}