-
Notifications
You must be signed in to change notification settings - Fork 7
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
Listing the differences between venial and syn using a fuzzer #3
Comments
Oh, wow, that is exactly what I needed, thanks! Having someone fuzz your library and pull failing examples out of nowhere feels magical. Definitely appreciated. Some of these I was aware of (argument parsing is a non-priority for now), but I didn't expect the inner attribute, closure and macro cases. Definitely on my todo-list now. The closure case in particular seems gnarly.
I'm not sure how that would work, especially since I'm not trying to match syn's features. One fuzzing test that could be useful would be to check that
What would that involve? It sounds like you've already done most of the work? Anyway, if you want to make a PR adding fuzzing to venial, I'd definitely be interested in merging it. |
That's great to hear :)
I'll think a bit about it. For example, both
That sounds good. Although I assume that parsing the token stream to a declaration and then printing it again is lossy. So maybe it needs to be done twice? Something like: let decl = parse_declaration(ts);
let ts2 = quote!(#decl);
let decl2 = parse_declaration(ts2);
// now check that `decl and `decl2` are consistent?
// maybe with:
let ts3 = quote!(#decl2);
assert!(ts2 == ts3); // ? Also, I have noticed that venial is very permissive and will accept declarations that really don't make sense. So maybe this test should only be performed when
Mostly the work involves improving the fuzzer itself and writing a few more assertions in the fuzz test. I would also like to improve fuzzcheck’s APIs a bit.
Great! I'll try to make a PR soon, even if everything isn't ready yet, so that you have a chance to see what it looks like and can offer some feedback. |
For example, one of the improvements I have had to make is to give the fuzzer the ability to detect infinite loops. There seems to be one as of commit 7958766 for this token stream: struct a (>) |
It shouldn't be, assuming the parsing succeeds. The only case where there may be loss is when parsing doc comments (eg But aside from that (and whitespace and comments, but those don't appear in a TokenStream), parsing-then-quoting should be a no-op. If it isn't, that's a bug.
The parser assumes that it's working for a derive macro; that means the TokenStream it receives has already been parsed and validated (if there's a parse error, the compilation is halted before calling macros). Also, the parser allows code that's syntactically valid, even when it's semantically invalid. The rule of thumb is "if it compiles with a #[cfg(FALSE)]
enum Foobar {
pub A,
pub B,
pub C,
} In any case, that doesn't change the base invariant:
Ouch. |
That code refuses to parse, actually. I'm tempted to open a syn issue. All the other snippets parse. |
These tests cover inputs venial can't parse. Inputs are from #3
Alright, I've fixed the infinite loop; it now panics in those cases, for the reasons explained above (venial assumes input is valid). I've added panicking tests for all the inputs you've given me. I'll fix them over time. |
Since I'm planning to release a 1.0 soon and then put venial in maintenance mode, I might pick this up again. I need to look into cargo-fuzzcheck and see how I can run it on my computer. |
Hi!
About a year ago I wrote a crate called decent-synquote-alternative, which has basically the same goal as venial. It is not as well written though: I didn't have a clear scope for it and I wrote it in a very naive way. It is also not well tested at all. But it offers an alternative to
quote!
that I thought was more ergonomic and could maybe make compile times better. I used that crate to write the fuzzcheck proc macros.Anyway, now I'm considering replacing
decent-synquote-alternative
withvenial
. It has almost every feature I want, and it seems to be better written. So I thought I'd contribute :)I am in the process of releasing a crate called
fuzzcheck_proc_macro
which makes it possible to fuzz-test functions that take aTokenStream
as input. I have tested the first prototype onvenial
. The first fuzz-test I tried is, basically:So it tries to parse an arbitrary token stream and ensures that
venial
accepts everything thatsyn
accepts.I tested it on commit
b09a976d44849e0c8573f5d8da4f5a8e50b35aab
, and within a few minutes, I found a few examples thatsyn
is happy to parse butvenial
can't:There might be more, but I think that's all I found so far. I visualised the code coverage of the fuzz-test (using
fuzzcheck-view
) withinvenial
and it is 100%. The code coverage withinsyn
is also good, but it takes much longer to reach all relevant code. There, running the fuzzer for about an hour (at least for the first run) might be necessary.Most of those differences are completely acceptable I think. In that case, we can write a function
fn accept_input(x: &syn::DeriveInput) -> bool
that returnstrue
whenever we're okay withvenial
not parsing it. Then we can call this function before panicking within the fuzz-test, which ensures it keeps making progress.A more interesting fuzz-test would try to compare the results between
syn
andvenial
and ensure that they match. That shouldn't be too complicated to write but will take a bit more time.Let me know if you're interested in using a fuzzer for
venial
, then I can work a bit more on it and publish what I have on GitHub. Otherwise, I hope the list I have provided is already useful :)Have a good day!
The text was updated successfully, but these errors were encountered: