Skip to content

Commit 23780c3

Browse files
committed
Write unit tests for the rust generator
Tests are added to the crate pdl-tests, which implements a private proc_macro pdl! that generates a rust module from an inline PDL grammar. The tests are added following this pattern: ``` #[pdl_inline(r#" // inline pdl grammar to be tested "#)] #[cfg(test)] mod test_module { #[test] fn test_one() { } // more tests } ```
1 parent 4dbe66d commit 23780c3

File tree

4 files changed

+412
-0
lines changed

4 files changed

+412
-0
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ members = [
33
"pdl-compiler",
44
"pdl-derive",
55
"pdl-runtime",
6+
"pdl-tests",
67
]

pdl-derive/src/lib.rs

+105
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,47 @@ fn pdl_proc_macro(path: syn::LitStr, input: syn::ItemMod) -> TokenStream {
7474
}
7575
}
7676

77+
fn pdl_inline_proc_macro(code: syn::LitStr, input: syn::ItemMod) -> TokenStream {
78+
// Load and parse the grammar.
79+
let mut sources = pdl_compiler::ast::SourceDatabase::new();
80+
let file = match pdl_compiler::parser::parse_inline(&mut sources, "stdin", code.value()) {
81+
Ok(file) => file,
82+
Err(err) => {
83+
let mut buffer = termcolor::Buffer::no_color();
84+
term::emit(&mut buffer, &term::Config::default(), &sources, &err)
85+
.expect("could not emit parser diagnostics");
86+
return syn::Error::new(code.span(), String::from_utf8(buffer.into_inner()).unwrap())
87+
.to_compile_error();
88+
}
89+
};
90+
91+
// Run the analyzer.
92+
let analyzed_file = match pdl_compiler::analyzer::analyze(&file) {
93+
Ok(file) => file,
94+
Err(diagnostics) => {
95+
let mut buffer = termcolor::Buffer::no_color();
96+
diagnostics.emit(&sources, &mut buffer).expect("could not emit analyzer diagnostics");
97+
return syn::Error::new(code.span(), String::from_utf8(buffer.into_inner()).unwrap())
98+
.to_compile_error();
99+
}
100+
};
101+
102+
// Generate the pdl backend implementation.
103+
let parser = pdl_compiler::backends::rust::generate_tokens(&sources, &analyzed_file, &[]);
104+
let mod_ident = input.ident;
105+
let mod_attrs = input.attrs;
106+
let mod_vis = input.vis;
107+
let mod_items = input.content.map(|(_, items)| items).unwrap_or_default();
108+
109+
quote! {
110+
#(#mod_attrs)*
111+
#mod_vis mod #mod_ident {
112+
#parser
113+
#(#mod_items)*
114+
}
115+
}
116+
}
117+
77118
/// The main method that's called by the proc macro
78119
/// (a wrapper around `pest_generator::derive_parser`)
79120
#[proc_macro_attribute]
@@ -86,8 +127,21 @@ pub fn pdl(
86127
pdl_proc_macro(attr, input).into()
87128
}
88129

130+
/// The main method that's called by the proc macro
131+
/// (a wrapper around `pest_generator::derive_parser`)
132+
#[proc_macro_attribute]
133+
pub fn pdl_inline(
134+
attr: proc_macro::TokenStream,
135+
input: proc_macro::TokenStream,
136+
) -> proc_macro::TokenStream {
137+
let attr = parse_macro_input!(attr as syn::LitStr);
138+
let input = parse_macro_input!(input as syn::ItemMod);
139+
pdl_inline_proc_macro(attr, input).into()
140+
}
141+
89142
#[cfg(test)]
90143
mod test {
144+
use super::pdl_inline_proc_macro;
91145
use super::pdl_proc_macro;
92146
use proc_macro2::TokenStream;
93147
use quote::quote;
@@ -167,4 +221,55 @@ mod test {
167221
Some("error[E")
168222
));
169223
}
224+
225+
#[test]
226+
fn test_derive_valid_inline() {
227+
assert!(!is_compile_error(
228+
pdl_inline_proc_macro(
229+
make_attr(quote! {
230+
r#"
231+
little_endian_packets
232+
packet Prout {
233+
x: 8,
234+
}
235+
"# }),
236+
make_input(quote! { mod Test {} }),
237+
),
238+
None
239+
));
240+
}
241+
242+
#[test]
243+
fn test_derive_parser_error_inline() {
244+
assert!(is_compile_error(
245+
pdl_inline_proc_macro(
246+
make_attr(quote! {
247+
r#"
248+
little_endian_packets
249+
enum A {
250+
X = 0
251+
}
252+
"# }),
253+
make_input(quote! { mod Test {} }),
254+
),
255+
Some("error: failed to parse input file")
256+
));
257+
}
258+
259+
#[test]
260+
fn test_derive_analyzer_error_inline() {
261+
assert!(is_compile_error(
262+
pdl_inline_proc_macro(
263+
make_attr(quote! {
264+
r#"
265+
little_endian_packets
266+
packet A {
267+
x: Unknown,
268+
}
269+
"# }),
270+
make_input(quote! { mod Test {} }),
271+
),
272+
Some("error[E")
273+
));
274+
}
170275
}

pdl-tests/Cargo.toml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "pdl-tests"
3+
version = "0.0.0"
4+
publish = false
5+
edition = "2021"
6+
description = "PDL Rust generated code tests"
7+
8+
[dependencies]
9+
bytes = "1.4.0"
10+
thiserror = "1.0.47"
11+
pdl-compiler = {path = "../pdl-compiler"}
12+
pdl-runtime = {path = "../pdl-runtime"}
13+
pdl-derive = {path = "../pdl-derive"}
14+
codespan-reporting = "0.11.1"
15+
proc-macro2 = "1.0.66"
16+
quote = "1.0.33"
17+
syn = {version = "2.0.29", features = ["full"]}
18+
termcolor = "1.2.0"

0 commit comments

Comments
 (0)