diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7540e8d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "conformance_tests/cel-spec"] + path = conformance_tests/cel-spec + url = git@github.com:google/cel-spec.git +[submodule "conformance_tests/googleapis"] + path = conformance_tests/googleapis + url = git@github.com:googleapis/googleapis.git diff --git a/Cargo.toml b/Cargo.toml index 3125f83..611e833 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,3 @@ [workspace] -members = ["parser", "program", "web"] \ No newline at end of file +members = ["parser", "program", "web", "cel_spec"] +resolver = "1" \ No newline at end of file diff --git a/cel_spec/Cargo.toml b/cel_spec/Cargo.toml new file mode 100644 index 0000000..87f91f9 --- /dev/null +++ b/cel_spec/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "cel_spec" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +prost = "0.12" +prost-types = "0.12" +prost-reflect = { version = "0.13.0", features = ["text-format"]} +quote = "1.0.35" +program = { path = "../program" } + +[build_dependencies] +prost-build = "0.12.3" diff --git a/cel_spec/build.rs b/cel_spec/build.rs new file mode 100644 index 0000000..e755986 --- /dev/null +++ b/cel_spec/build.rs @@ -0,0 +1,13 @@ +use std::{env, io::Result, path::PathBuf}; + +fn main() -> Result<()> { + let out = env::var("OUT_DIR").expect("OUT_DIR environment variable not set"); + let out = PathBuf::from(out).join("cel.bin"); + let mut config = prost_build::Config::new(); + config.disable_comments(&["."]); + config.file_descriptor_set_path(out); + config.compile_protos( + &["cel-spec/proto/test/v1/simple.proto"], + &["cel-spec/proto/", "googleapis/"], + ) +} diff --git a/cel_spec/src/lib.rs b/cel_spec/src/lib.rs new file mode 100644 index 0000000..77fdeb8 --- /dev/null +++ b/cel_spec/src/lib.rs @@ -0,0 +1,44 @@ +use proc_macro::TokenStream; +use quote::{format_ident, quote, ToTokens}; + +const BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/cel.bin")); + +#[proc_macro] +pub fn cel_test(attr: TokenStream) -> TokenStream { + println!("attr: \"{}\"", attr.to_string()); + use prost_reflect::{DescriptorPool, DynamicMessage}; + + let pool = DescriptorPool::decode(BYTES.as_ref()).unwrap(); + let message_descriptor = pool.get_message_by_name("google.api.expr.test.v1.SimpleTestFile").unwrap(); + let bytes = include_str!("../cel-spec/tests/simple/testdata/basic.textproto"); + let suite = DynamicMessage::parse_text_format(message_descriptor, &bytes).unwrap(); + + let mut ast = String::new(); + for section in suite.get_field_by_name("section").unwrap().as_list().unwrap() { + let section = section.as_message().unwrap(); + let sname = section.get_field_by_name("name").unwrap(); + + ast.push_str(format!("pub mod {}{{", sname.as_str().unwrap()).as_str()); + + for case in section.get_field_by_name("test").unwrap().as_list().unwrap() { + let case = case.as_message().unwrap(); + let name = case.get_field_by_name("name").unwrap(); + let expr = case.get_field_by_name("expr").unwrap(); + + let name = format_ident!("{}", name.as_str().unwrap()); + let expr = expr.as_str().unwrap(); + ast.push_str( + "e!{ + #[test] + fn #name() { + assert!(program::Program::new(#expr).expect("failed to compile").execute(program::context::Context::default())); + } + }.to_string() + ) + } + + ast.push_str("}"); + break; + } + ast.parse().unwrap() +} \ No newline at end of file diff --git a/cel_spec/tests/test.rs b/cel_spec/tests/test.rs new file mode 100644 index 0000000..01703d6 --- /dev/null +++ b/cel_spec/tests/test.rs @@ -0,0 +1,6 @@ + +extern crate cel_spec; + +cel_spec::cel_test!(suite = "basic"); + + diff --git a/program/Cargo.toml b/program/Cargo.toml index 9606b56..293a1d5 100644 --- a/program/Cargo.toml +++ b/program/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" parser = {path = "../parser"} ordered-float = "4.2.0" ordered_hash_map = "0.4.0" +prost-reflect = "0.13.0" \ No newline at end of file diff --git a/web/Cargo.toml b/web/Cargo.toml index 6daa73f..a4bd8b8 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -9,6 +9,3 @@ crate-type = ["cdylib"] [dependencies] program = {path = "../program"} wasm-bindgen = "0.2" - -[profile.release] -panic = "unwind" \ No newline at end of file