Open bionicles opened 2 months ago
(tried without the box, tried Ok(box), etc etc) , edited to add some context but tried not to put too much. Anyway, just pestering about docs / examples, user error, carry on
Strategy::boxed
worked, here is an example impl proptest::Arbitrary
which compiles and works
// In your library's module (e.g., mod.rs)
// suppose you want to enable a new data type in your sql tables, like GIS / coordinates
use chrono::{DateTime, FixedOffset, TimeZone};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use uom::si::angle::degree;
use uom::si::f64::{Angle, Length};
use uom::si::length::meter;
// suppose this is a separate crate and you can't implement our traits on it
// how do you add a new plugin custom datatype easily
mod coordinate_library {
use chrono::{DateTime, FixedOffset};
use uom::si::angle::degree;
use uom::si::f64::{Angle, Length};
use uom::si::length::meter;
#[derive(Debug)]
pub struct SpaceTimeCoordinate {
pub latitude: Angle,
pub longitude: Angle,
pub elevation: Length,
pub datetime: DateTime<FixedOffset>,
}
impl SpaceTimeCoordinate {
pub fn new(lat: f64, lng: f64, elev: f64, dt: DateTime<FixedOffset>) -> Self {
SpaceTimeCoordinate {
latitude: Angle::new::<degree>(lat),
longitude: Angle::new::<degree>(lng),
elevation: Length::new::<meter>(elev),
datetime: dt,
}
}
}
}
// Import the external library type.
use coordinate_library::SpaceTimeCoordinate;
// compile failure due to orphan rules prevents direct implementation
// impl CustomDType for SpaceTimeCoordinate {} // error
#[derive(Debug)]
// Define a newtype wrapper for the external library type.
pub struct Coordinate(pub SpaceTimeCoordinate);
use proptest::prelude::*;
use proptest::test_runner::TestRunner;
// use proptest::strategy::{BoxedStrategy, Just, Strategy}; // redundant with "prelude"
const HOUR: i32 = 3600;
impl Arbitrary for Coordinate {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
let timestamp = any::<i32>().prop_map(|seconds| {
let seconds_i64 = seconds as i64;
let tz = FixedOffset::east_opt(5 * HOUR).unwrap();
println!("seconds={seconds:#?}");
let dt: DateTime<FixedOffset> = tz.timestamp_opt(seconds_i64, 0).unwrap();
dt
});
let latitude = any::<f32>().prop_map(|x| Angle::new::<degree>(x as f64));
let longitude = any::<f32>().prop_map(|x| Angle::new::<degree>(x as f64));
let elevation = any::<f32>().prop_map(|x| Length::new::<meter>(x as f64));
let pipeline = (latitude, longitude, elevation, timestamp).prop_map(
|(latitude, longitude, elevation, datetime)| {
Coordinate(SpaceTimeCoordinate {
latitude,
longitude,
elevation,
datetime,
})
},
);
Strategy::boxed(pipeline)
}
}
const MAX_LOOPS: usize = 12;
fn main() {
let config = Default::default();
let mut runner = TestRunner::new(config);
let strat = Coordinate::arbitrary_with(());
for iteration in 0..MAX_LOOPS {
match strat.new_tree(&mut runner) {
Ok(tree) => {
let value = tree.current();
println!("{iteration:#?} {value:#?}")
}
Err(reason) => {
eprintln!("{reason:#?}")
}
}
}
}
gonna keep this open since it's a docs issue edited to use f32 for more satisfying diversity of timestamps and less huge angles
Hi sorry for the delay -- glad you ended up figuring it out. Will see what we can do to improve the docs/guides
Hey, I admit I'm a noob, but i just wanted to make a simple toy example of proptest but it looks like everything is either macros or derive, functions accepting ranges as arguments, what's the simple straightforward way to create a BoxedStrategy from a prop_map? Should i be using Arbitrary from the arbitrary crate instead of from the proptest crate?
you could improve the docs a ton by putting complete example of how to impl Arbitrary somewhere, even the reference docs for the trait itself do not have a code block example of how to implement that, and it seems pretty specific about how we ought to code this, anyway, thanks for all the fuzz testing, i feel dumb right now