#![allow(
clippy::allow_attributes,
reason = "`alloc::format` only warns on some feature combinations"
)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
extern crate std;
use {
crate::{NonNegative, Zero as _},
core::cmp::Ordering,
quickcheck::TestResult,
quickcheck_macros::quickcheck,
};
#[cfg(not(feature = "serde"))]
use serde_json as _;
#[cfg(feature = "quickcheck")]
use {
crate::Positive,
quickcheck::{Arbitrary, Gen},
};
#[cfg(not(feature = "std"))]
#[allow(unused_imports, reason = "complicated namespace resolution")]
use alloc::{format, vec::Vec};
#[cfg(debug_assertions)]
use std::panic::catch_unwind;
const _CHECK_ZERO_IMPL_FOR_NON_NEGATIVE: NonNegative<u8> = NonNegative::ZERO;
#[quickcheck]
#[cfg(all(debug_assertions, feature = "quickcheck"))]
fn all_positive(tuple: (f64, f64, f64, f64)) -> TestResult {
let array: [f64; 4] = tuple.into();
let ground_truth = array.iter().all(|f| *f > 0_f64);
match catch_unwind(|| Positive::all(&array)) {
Ok(..) => {
if ground_truth {
TestResult::passed()
} else {
TestResult::error("not all positive but passed")
}
}
Err(e) => {
if ground_truth {
TestResult::error(format!("all positive but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(feature = "quickcheck")]
fn positive_f64_doesnt_panic_arbitrary(size: usize) -> TestResult {
let mut g = Gen::new(size);
let dropped: Positive<f64> = Arbitrary::arbitrary(&mut g);
_ = dropped;
TestResult::passed()
}
#[quickcheck]
#[cfg(feature = "quickcheck")]
fn positive_f64_doesnt_panic_shrink(size: usize) -> TestResult {
let mut g = Gen::new(size);
let init: Positive<f64> = Arbitrary::arbitrary(&mut g);
for _ in init.shrink() {}
TestResult::passed()
}
#[quickcheck]
#[cfg(debug_assertions)]
fn sorted_vec_non_strict(v: Vec<u8>) -> TestResult {
type Sorted = crate::Sorted<Vec<u8>, true>;
let actually_sorted = v.is_sorted();
match catch_unwind(|| Sorted::new(v)) {
Ok(ok) => {
if actually_sorted {
if ok.is_sorted() {
for _ in ok {}
TestResult::passed()
} else {
TestResult::error("sigma type not sorted")
}
} else {
TestResult::error("not sorted but passed")
}
}
Err(e) => {
if actually_sorted {
TestResult::error(format!("sorted but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn sorted_vec_strict(v: Vec<u8>) -> TestResult {
type Sorted = crate::Sorted<Vec<u8>, false>;
let actually_sorted = v.is_sorted_by(|a, b| matches!(a.cmp(b), Ordering::Less));
match catch_unwind(|| Sorted::new(v)) {
Ok(ok) => {
if actually_sorted {
if ok.is_sorted() {
for _ in ok {}
TestResult::passed()
} else {
TestResult::error("sigma type not sorted")
}
} else {
TestResult::error("not sorted but passed")
}
}
Err(e) => {
if actually_sorted {
TestResult::error(format!("sorted but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn unit_closed(f: f32) -> TestResult {
type OnUnit = crate::OnUnit<f32, true, true>;
let actually_on_unit = ((0.)..=1.).contains(&f);
match catch_unwind(|| OnUnit::new(f)) {
Ok(..) => {
if actually_on_unit {
TestResult::passed()
} else {
TestResult::error("not on unit but passed")
}
}
Err(e) => {
if actually_on_unit {
TestResult::error(format!("on unit but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn unit_open(f: f32) -> TestResult {
type OnUnit = crate::OnUnit<f32, false, false>;
let actually_on_unit = (f > 0_f32) && (f < 1_f32);
match catch_unwind(|| OnUnit::new(f)) {
Ok(..) => {
if actually_on_unit {
TestResult::passed()
} else {
TestResult::error("not on unit but passed")
}
}
Err(e) => {
if actually_on_unit {
TestResult::error(format!("on unit but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
fn try_sorted_vec_strict(v: Vec<u8>) -> TestResult {
type Sorted = crate::Sorted<Vec<u8>, false>;
let actually_sorted = v.is_sorted_by(|a, b| matches!(a.cmp(b), Ordering::Less));
Sorted::try_new(v).map_or_else(
|e| {
if actually_sorted {
TestResult::error(format!("sorted but failed: {e:#?}"))
} else {
TestResult::passed()
}
},
|some| {
if actually_sorted {
if some.is_sorted() {
for _ in some {}
TestResult::passed()
} else {
TestResult::error("sigma type not sorted")
}
} else {
TestResult::error("not sorted but passed")
}
},
)
}
#[quickcheck]
#[cfg(debug_assertions)]
fn i64_non_negative(i: i64) -> TestResult {
type NonNegative = crate::NonNegative<i64>;
let actually_non_negative = i >= 0;
match catch_unwind(|| NonNegative::new(i)) {
Ok(..) => {
if actually_non_negative {
TestResult::passed()
} else {
TestResult::error("negative but passed")
}
}
Err(e) => {
if actually_non_negative {
TestResult::error(format!("non-negative but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn i64_positive(i: i64) -> TestResult {
type Positive = crate::Positive<i64>;
let actually_positive = i > 0;
match catch_unwind(|| Positive::new(i)) {
Ok(..) => {
if actually_positive {
TestResult::passed()
} else {
TestResult::error("non-positive but passed")
}
}
Err(e) => {
if actually_positive {
TestResult::error(format!("positive but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn i64_positive_wrap(i: i64) -> TestResult {
type Positive = crate::Positive<i64>;
let actually_positive = i > 0;
match catch_unwind(|| Positive::wrap(&i)) {
Ok(..) => {
if actually_positive {
TestResult::passed()
} else {
TestResult::error("non-positive but passed")
}
}
Err(e) => {
if actually_positive {
TestResult::error(format!("positive but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn i64_positive_wrap_mut(i: i64) -> TestResult {
type Positive = crate::Positive<i64>;
let actually_positive = i > 0;
match catch_unwind(|| {
let mut j = i;
*Positive::wrap_mut(&mut j)
}) {
Ok(..) => {
if actually_positive {
TestResult::passed()
} else {
TestResult::error("non-positive but passed")
}
}
Err(e) => {
if actually_positive {
TestResult::error(format!("positive but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn positive_also_non_negative(i: i64) {
type Positive = crate::Positive<i64>;
type NonNegative = crate::NonNegative<i64>;
let Ok(positive) = Positive::try_new(i) else {
return;
};
let _: NonNegative = positive.also();
}
#[quickcheck]
#[cfg(debug_assertions)]
fn positive_also_ref_non_negative(i: i64) {
type Positive = crate::Positive<i64>;
type NonNegative = crate::NonNegative<i64>;
let Ok(positive) = Positive::try_new(i) else {
return;
};
let _: &NonNegative = positive.also_ref();
}
#[quickcheck]
#[cfg(debug_assertions)]
fn non_negative_try_also_positive(i: i64) -> TestResult {
type NonNegative = crate::NonNegative<i64>;
type Positive = crate::Positive<i64>;
let Ok(non_negative) = NonNegative::try_new(i) else {
return TestResult::discard();
};
let maybe_also: Result<Positive, _> = non_negative.try_also();
match maybe_also {
Ok(..) => {
if i == 0 {
TestResult::error("Zero but passed")
} else {
TestResult::passed()
}
}
Err(..) => {
if i == 0 {
TestResult::passed()
} else {
TestResult::error("Positive but failed")
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn non_negative_try_also_ref_positive(i: i64) -> TestResult {
type NonNegative = crate::NonNegative<i64>;
type Positive = crate::Positive<i64>;
let Ok(non_negative) = NonNegative::try_new(i) else {
return TestResult::discard();
};
let maybe_also: Result<&Positive, _> = non_negative.try_also_ref();
match maybe_also {
Ok(..) => {
if i == 0 {
TestResult::error("Zero but passed")
} else {
TestResult::passed()
}
}
Err(e) => {
if i == 0 {
TestResult::passed()
} else {
TestResult::error(format!("Positive but failed: {e}"))
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
#[cfg(feature = "serde")]
fn serde_roundtrip_positive_i64(i: i64) -> TestResult {
type Positive = crate::Positive<i64>;
let Ok(positive) = catch_unwind(|| Positive::new(i)) else {
return TestResult::discard();
};
let json = match serde_json::to_string(&positive) {
Ok(ok) => ok,
Err(e) => return TestResult::error(format!("Couldn't serialize {positive:#?}: {e}")),
};
let rust: Positive = match serde_json::from_str(&json) {
Ok(ok) => ok,
Err(e) => return TestResult::error(format!("Couldn't deserialize {json:#?}: {e}")),
};
if positive == rust {
TestResult::passed()
} else {
TestResult::error(format!(
"{positive:#?} -> {json:#?} -> {rust:#?} =/= {positive:#?}"
))
}
}
#[quickcheck]
#[cfg(feature = "serde")]
fn serde_fallible_positive_i64(i: i64) -> TestResult {
type Positive = crate::Positive<i64>;
let actually_positive = i > 0;
let json = match serde_json::to_string(&i) {
Ok(ok) => ok,
Err(e) => return TestResult::error(format!("Couldn't serialize {i:#?}: {e}")),
};
let rust: Positive = match serde_json::from_str(&json) {
Ok(ok) => {
if actually_positive {
ok
} else {
return TestResult::error(format!(
"Not positive, but deserialization succeeded: {i}"
));
}
}
Err(e) => {
return if actually_positive {
TestResult::error(format!("Couldn't deserialize {json:#?}: {e}"))
} else {
TestResult::passed()
};
}
};
if i == *rust.as_ref() {
TestResult::passed()
} else {
TestResult::error(format!("{i:#?} -> {json:#?} -> {rust:#?} =/= {i:#?}"))
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn i64_negative(i: i64) -> TestResult {
type Negative = crate::Negative<i64>;
let actually_negative = i < 0;
match catch_unwind(|| Negative::new(i)) {
Ok(..) => {
if actually_negative {
TestResult::passed()
} else {
TestResult::error("non-negative but passed")
}
}
Err(e) => {
if actually_negative {
TestResult::error(format!("negative but failed: {e:#?}"))
} else {
TestResult::passed()
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn negative_also_non_positive(i: i64) {
type Negative = crate::Negative<i64>;
type NonPositive = crate::NonPositive<i64>;
let Ok(negative) = Negative::try_new(i) else {
return;
};
let _: NonPositive = negative.also();
}
#[quickcheck]
#[cfg(debug_assertions)]
fn negative_also_ref_non_positive(i: i64) {
type Negative = crate::Negative<i64>;
type NonPositive = crate::NonPositive<i64>;
let Ok(negative) = Negative::try_new(i) else {
return;
};
let _: &NonPositive = negative.also_ref();
}
#[quickcheck]
#[cfg(debug_assertions)]
fn non_positive_try_also_negative(i: i64) -> TestResult {
type NonPositive = crate::NonPositive<i64>;
type Negative = crate::Negative<i64>;
let Ok(non_positive) = NonPositive::try_new(i) else {
return TestResult::discard();
};
let maybe_also: Result<Negative, _> = non_positive.try_also();
match maybe_also {
Ok(..) => {
if i == 0 {
TestResult::error("Zero but passed")
} else {
TestResult::passed()
}
}
Err(..) => {
if i == 0 {
TestResult::passed()
} else {
TestResult::error("Negative but failed")
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
fn non_positive_try_also_ref_negative(i: i64) -> TestResult {
type NonPositive = crate::NonPositive<i64>;
type Negative = crate::Negative<i64>;
let Ok(non_positive) = NonPositive::try_new(i) else {
return TestResult::discard();
};
let maybe_also: Result<&Negative, _> = non_positive.try_also_ref();
match maybe_also {
Ok(..) => {
if i == 0 {
TestResult::error("Zero but passed")
} else {
TestResult::passed()
}
}
Err(e) => {
if i == 0 {
TestResult::passed()
} else {
TestResult::error(format!("Negative but failed: {e}"))
}
}
}
}
#[quickcheck]
#[cfg(debug_assertions)]
#[cfg(feature = "serde")]
fn serde_roundtrip_negative_i64(i: i64) -> TestResult {
type Negative = crate::Negative<i64>;
let Ok(negative) = catch_unwind(|| Negative::new(i)) else {
return TestResult::discard();
};
let json = match serde_json::to_string(&negative) {
Ok(ok) => ok,
Err(e) => return TestResult::error(format!("Couldn't serialize {negative:#?}: {e}")),
};
let rust: Negative = match serde_json::from_str(&json) {
Ok(ok) => ok,
Err(e) => return TestResult::error(format!("Couldn't deserialize {json:#?}: {e}")),
};
if negative == rust {
TestResult::passed()
} else {
TestResult::error(format!(
"{negative:#?} -> {json:#?} -> {rust:#?} =/= {negative:#?}"
))
}
}
#[quickcheck]
#[cfg(feature = "serde")]
fn serde_fallible_negative_i64(i: i64) -> TestResult {
type Negative = crate::Negative<i64>;
let actually_negative = i < 0;
let json = match serde_json::to_string(&i) {
Ok(ok) => ok,
Err(e) => return TestResult::error(format!("Couldn't serialize {i:#?}: {e}")),
};
let rust: Negative = match serde_json::from_str(&json) {
Ok(ok) => {
if actually_negative {
ok
} else {
return TestResult::error(format!(
"Not negative, but deserialization succeeded: {i}"
));
}
}
Err(e) => {
return if actually_negative {
TestResult::error(format!("Couldn't deserialize {json:#?}: {e}"))
} else {
TestResult::passed()
};
}
};
if i == *rust.as_ref() {
TestResult::passed()
} else {
TestResult::error(format!("{i:#?} -> {json:#?} -> {rust:#?} =/= {i:#?}"))
}
}