-
Notifications
You must be signed in to change notification settings - Fork 17
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
How to use Arbitrary
generators?
#150
Comments
The Lines 261 to 262 in b1b519e
We'll need to make it show up in docs and that it requires that feature. But you can do that in your Cargo.toml: bolero = { version = "0.9", features = ["arbitrary"] } and then in the harness #[derive(Arbitrary)]
struct MyType {
a: u8,
b: u8,
c: u8,
}
#[test]
fn my_test() {
bolero::check!()
.with_arbitrary::<MyType>()
.for_each(|value| { ... });
} |
Thanks! I got that to work. But: using
compared to this, with the derived
I can file another issue if that helps, but maybe it's expected for some reason? |
Yeah the initial pass on the arbitrary integration is pretty unoptimal...
It does a bunch of allocation and copying between the slices so it could be improved. That being said, 2 exec/s seems extremely low even with those things so there may be other issues. Can you share what your recursive data type looks like and I can take a look to see if I can fix it. |
After some digging it looks like we're running into rust-fuzz/arbitrary#144. The size_hint is taking forever to compute. In #151 I have a change that caches the hint, which speeds things up from 2 to about 4000 iterations per second. In #151, I've also added a depth guard to bolero-generator so we don't blow up the stack on recursive types. That does about 70,000 iterations per second, but looking at the flamegraph we're spending a lot more time inside libfuzzer. This likely means we're bailing a lot on inputs and libfuzzer isn't finding many that satisfy the constraints. I'm still digging in on this to confirm, though. |
Ok so the difference between the two seems to be coming from the way arbitrary does depth guarding and how I implemented it in #151. Arbitrary only guards depth once the byte slice is empty (see rust-fuzz/arbitrary#111) whereas I am guarding it all the time. As a result, the arbitrary-generated trees are much deeper. I think the "always guard" approach is a bit more predictable since it will always limit the tree depth to the configured limit in the harness. With the current approach in arbitrary, I was seeing trees with +150 levels, which may not be desirable for all harnesses. |
In the case of both arbitrary and bolero-generator I am seeing memory grow and eventually hitting a OOM at 2GB. I need to figure out if this is bolero's issue or something to do with libfuzzer/ASAN. |
Thanks for looking into this! Recursive generators are hard.
Where in the harness is this depth configured? IIRC, size-bounding is the best practice for generating recursive structures. I.e., you should generate a random structure up to a particular size, and that size can be bounded by the user or generated itself. I.e., "let list_len = rand(); return list with list_len random elements". Does the " |
I saw that PR #108 that includes
Arbitrary
generator support, but I didn't see corresponding instructions for how to leverage it.In particular, I'd like to use values generated by an
Arbitrary::<Type>
rather than aTypeGenerator::<Type>
. I'm not seeing docs on that. Issue #31 and the comments in PR #108 suggest usingwith_arbitrary...
rather thanwith_type...
but I don't see that function in the docs. I wondered if perhaps you needed to#derive
aTypeGenerator
and could point to anArbitrary
as the source, but I don't see that in the docs either.The text was updated successfully, but these errors were encountered: