From 99bb011f8da6836dc3f3da41abb2c8438778b193 Mon Sep 17 00:00:00 2001 From: thesayyn Date: Sat, 18 May 2024 17:28:36 -0700 Subject: [PATCH] test: enable more tests --- cel-rs/src/program.rs | 2 - cel-rs/src/value.rs | 2 +- cel-rs/tests/test.rs | 11 +++- cel-spec/Cargo.toml | 5 +- cel-spec/src/lib.rs | 117 +++++++++++++++++++++++++++++++----------- 5 files changed, 100 insertions(+), 37 deletions(-) diff --git a/cel-rs/src/program.rs b/cel-rs/src/program.rs index 9cb4348..7aae988 100644 --- a/cel-rs/src/program.rs +++ b/cel-rs/src/program.rs @@ -43,8 +43,6 @@ impl Program { #[cfg(test)] pub mod tests { - use std::rc::Rc; - use crate::{ program, value::{Function, Overload}, diff --git a/cel-rs/src/value.rs b/cel-rs/src/value.rs index de90b92..732af03 100644 --- a/cel-rs/src/value.rs +++ b/cel-rs/src/value.rs @@ -44,7 +44,7 @@ impl Into for Value { Value::String(v) => v.len() > 0, Value::Map(v) => v.len() > 0, Value::List(v) => v.len() > 0, - Value::Function(v) => true, + Value::Function(_v) => true, } } } diff --git a/cel-rs/tests/test.rs b/cel-rs/tests/test.rs index fc12399..1aaa992 100644 --- a/cel-rs/tests/test.rs +++ b/cel-rs/tests/test.rs @@ -1,4 +1,11 @@ - use cel_spec; -cel_spec::suite!(name = "basic"); +cel_spec::suite!( + name = "basic", + include = "self_eval_zeroish", + include = "self_eval_nonzeroish", + include = "variables", + // include = "ffunctions", + // include = "reserved_const", +); + diff --git a/cel-spec/Cargo.toml b/cel-spec/Cargo.toml index 9029286..d511d0f 100644 --- a/cel-spec/Cargo.toml +++ b/cel-spec/Cargo.toml @@ -9,7 +9,10 @@ proc-macro = true [dependencies] prost = "0.12" prost-types = "0.12" -prost-reflect = { version = "0.13.0", features = ["text-format"]} +prost-reflect = { version = "0.13.0", features = ["text-format"] } +syn = { version = "2.0.55", features = ["parsing"] } +static_init = "1.0.3" +darling = "0.20.8" [build_dependencies] prost-build = "0.12.3" diff --git a/cel-spec/src/lib.rs b/cel-spec/src/lib.rs index c746bc8..103e943 100644 --- a/cel-spec/src/lib.rs +++ b/cel-spec/src/lib.rs @@ -1,34 +1,83 @@ +use std::io::Read; use proc_macro::TokenStream; +use static_init::dynamic; +use darling::{Error, FromMeta}; +use darling::ast::NestedMeta; +use prost_reflect::{DescriptorPool, MessageDescriptor, DynamicMessage}; const BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/cel.bin")); +#[dynamic] +static MESSAGE_DESCRIPTOR: MessageDescriptor = { + let pool = DescriptorPool::decode(BYTES.as_ref()).unwrap(); + pool + .get_message_by_name("google.api.expr.test.v1.SimpleTestFile") + .unwrap() +}; -fn get_expected_value(value: &prost_reflect::DynamicMessage) -> String { - let field = value.fields().next().unwrap(); +fn get_expected_value(value: &DynamicMessage) -> String { + let field = value.fields().next().expect("get expected value"); let (m, v, c) = match field.0.name() { - "string_value" => ("String(std::rc::Rc::new(String::from(", format!(r##"r#"{}"#"##, field.1.as_str().unwrap()), ")))"), + "string_value" => ( + "String(std::rc::Rc::new(String::from_utf8(", + format!("{:?}", field.1.as_str().unwrap().as_bytes().to_vec()), + ".to_vec()).unwrap()))", + ), "bool_value" => ("Bool(", format!("{}", field.1.as_bool().unwrap()), ")"), "int64_value" => ("Int(", format!("{}", field.1.as_i64().unwrap()), ")"), "uint64_value" => ("UInt(", format!("{}", field.1.as_u64().unwrap()), ")"), - "double_value" => ("Float(", format!("{}.into()", field.1.as_f64().unwrap()), ")"), - "map_value" => ("Map(", String::from("ordered_hash_map::OrderedHashMap::new().into()"), ")"), - "list_value" => ("List(", String::from("Vec::new().into()"), ")" ), - "bytes_value" => ("Bytes(std::rc::Rc::new(Vec::from(", format!("{:?}", field.1.as_bytes().unwrap().to_vec()), ")))"), - _ => ("Null", String::new(), "") + "double_value" => ( + "Float(", + format!("({}).into()", field.1.as_f64().unwrap()), + ")", + ), + "map_value" => ( + "Map(", + String::from("ordered_hash_map::OrderedHashMap::new().into()"), + ")", + ), + "list_value" => ("List(", String::from("Vec::new().into()"), ")"), + "bytes_value" => ( + "Bytes(std::rc::Rc::new(Vec::from(", + format!("{:?}", field.1.as_bytes().unwrap().to_vec()), + ")))", + ), + _ => ("Null", String::new(), ""), }; format!("cel_rs::value::Value::{}{}{}", m, v, c) } +#[derive(Debug, FromMeta)] +struct MacroArgs { + name: String, + #[darling(multiple, rename = "include")] + includes: Vec, +} + + #[proc_macro] -pub fn suite(attr: TokenStream) -> TokenStream { - println!("attr: \"{}\"", attr.to_string()); - use prost_reflect::{DescriptorPool, DynamicMessage}; +pub fn suite(rargs: TokenStream) -> TokenStream { - 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 attr_args = match NestedMeta::parse_meta_list(rargs.into()) { + Ok(v) => v, + Err(e) => { return TokenStream::from(Error::from(e).write_errors()); } + }; + + let args = match MacroArgs::from_list(&attr_args) { + Ok(v) => v, + Err(e) => { return TokenStream::from(e.write_errors()); } + }; + + let mut file = std::fs::File::open(format!( + "{}/cel-spec/tests/simple/testdata/{}.textproto", + env!("CARGO_MANIFEST_DIR"), + args.name + )) + .expect("could not find the suite"); + + let mut content = String::new(); + file.read_to_string(&mut content) + .expect("can not read the suite file"); + let suite = DynamicMessage::parse_text_format(MESSAGE_DESCRIPTOR.to_owned(), &content).unwrap(); let mut ast = String::new(); for section in suite @@ -39,30 +88,37 @@ pub fn suite(attr: TokenStream) -> TokenStream { { let section = section.as_message().unwrap(); let sname = section.get_field_by_name("name").unwrap(); + let sname = sname.as_str().unwrap(); + let includes = &args.includes; + if includes.into_iter().find(|p| p.as_str() == sname).is_none(){ + println!("skip {}", &sname); + continue; + } - ast.push_str(format!("pub mod {}{{", sname.as_str().unwrap()).as_str()); + ast.push_str(format!("pub mod {}{{", sname).as_str()); for case in section .get_field_by_name("test") - .unwrap() + .expect("test") .as_list() - .unwrap() + .expect("test as list") { - 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 value = case.get_field_by_name("value").unwrap(); + let case = case.as_message().expect("message as case"); + let name = case.get_field_by_name("name").expect("expected name"); + let expr = case.get_field_by_name("expr").expect("expected expr"); + let value = case.get_field_by_name("value").expect("expected value"); - let name = name.as_str().unwrap(); - let expr = expr.as_str().unwrap(); - let value = value.as_message().unwrap(); + let name = name.as_str().expect("name as str"); + let expr = expr.as_str().expect("expr as str"); + let value = value.as_message().expect("value as message"); let expected_value = get_expected_value(value); ast.push_str(&format!(r##" #[test] fn {name}() {{ - let program = cel_rs::Program::new(r#"{expr}"#); - assert!(program.is_ok(), "failed to parse '{{}}'", r#"{expr}"#); + let expr = r#"{expr}"#; + let program = cel_rs::Program::new(expr); + assert!(program.is_ok(), "failed to parse '{{}}'", expr); let program = program.unwrap(); let mut ctx = cel_rs::context::Context::default(); let value = program.eval(&mut ctx); @@ -73,8 +129,7 @@ pub fn suite(attr: TokenStream) -> TokenStream { } ast.push_str("}"); - break; } - //println!("{}", ast); + println!("{}", ast); ast.parse().unwrap() }