-
Notifications
You must be signed in to change notification settings - Fork 150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Q: Idiomatic way to specify the length of an arbitrary vector #297
Comments
In the past, I used something like the following in such situations: let mut g = Gen::new(g.size() / n);
let v: Vec<_> = std::iter::from_fn(|| Some(Arbitrary::arbitrary(&mut g))).take(n).collect() Obviously not the most pretty thing to write. And you must take care not to forget wrapping If/when #292 gets merged, you can also use the following pattern: let mut v = vec![Default::default(); N]; // or use `Vec::new` and `Vec::resize`
Gen::new(g.size() / N).fill_slice(v.as_mut()); One day, #282 may also provide an option if your target size is known at compile time: let buf: [_; N] = Arbitrary::arbitrary(g);
let v: Vec<_> = buf.into(); |
Stupid me just realized that you can just do: let mut v = Vec::new();
let mut g = Gen::new(g.size() / n);
v.resize_with(n, || Arbitrary::arbitrary(&mut g)); |
@neithernut ty! So you are suggesting to create a new generator in the |
It depends. With recursive structures, you usually want to either create a new generator with a reduced size in order to ensure the recursion is bounded. In such cases, you also want to specialcase the generator having a size of
Whether or not you create a new generator doesn't affect shrinking at all. Shrinking in itself is both independent from the generator and deterministic (unless you do very weird things in your shrinker). |
Ok. Is not very clear why should I shrink if I lose reproducibility? Is not goal of shrinking to have a minimal failing case? If I do not have reproducibility maybe the shrinked case is not failing anymore. Just asking for future reference, right now I will implement from random following your above example, and use the default shrink function. Ty again |
You loose reproducibility in the generation when creating a new Shrinking should always be deterministic and only operate on the value itself. For example, you should never use Sorry if I wasn't clear enough on that front.
Note that the default shrink function supplied by the The initial post by @rrybarczyk talks about a |
Thank you so much @neithernut! |
Is there documentation on the idiomatic way to specify the length of an arbitrary vector?
My specific example is this:
I have a struct with fields containing various data types (like max 64-bytes, max 255-bytes, exactly 32-bytes, etc.) that I need to implement
Arbitrary
for. As an example, I will use one field in theFoo
struct that represents a vector of 255 bytes.Where
To test this struct, I have created a new struct and implemented
Arbitrary
, which calls a functionfrom_random
which is implemented forFoo
.from_random
is needed becauseArbitrary
needs to be implemented in another crate.Currently, I am passing in the generator to the
from_random
function and generating the 255 byte vectors as:Here I am truncating the vector to avoid a panic caused by a vector that is too big. Was thinking that the best approach may be having the
try_into
return the right error when called with a value that is too big, but I am not sure if this is possible asArbitrary
needs to returnSelf
?Additionally, when
from_random
is implemented for fixed size primitives (egU256
) shouldresize(255, 0)
be used instead oftruncate
?Alternatively, I can implement
from_random
as:Which, if either,
from_random
implementation is the idiomatic way to generate a vector of a specific size?The text was updated successfully, but these errors were encountered: