More builtins and semantic improvements (#66)

- base64 builtins
- base64url builtins
- jsonschema builtins
- json.remove builtin
- handle composite index variables
- use dashu_float since rust_decimal has lesser precision

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2023-12-21 13:34:48 -08:00
committed by GitHub
parent 577e1aa8db
commit f6140b6be5
12 changed files with 668 additions and 153 deletions
@@ -20,7 +20,7 @@ cases:
z {
x = 1/3
y = 0.3333333333333333333333333333
y = 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
x == y
}
query: data.test
@@ -96,14 +96,14 @@ cases:
- 1152921504606846976
- 1152921504606846976
p4:
- 1.1805916207174113e21
- 1.1805916207174113e21
- 1.1805916207174113e21
- 1.1805916207174113e21
- 1.2089258196146292e24
- 1.2089258196146292e24
- 1.2089258196146292e24
- 1.2089258196146292e24
- 1180591620717411303424
- 1180591620717411303424
- 1180591620717411303424
- 1180591620717411303424
- 1208925819614629174706176
- 1208925819614629174706176
- 1208925819614629174706176
- 1208925819614629174706176
p5: [1, 1]
- note: extra argument
+7
View File
@@ -4,6 +4,8 @@ any
arithmetic
array
assignments
base64builtins
base64urlbuiltins
bitsand
bitsnegate
bitsor
@@ -14,6 +16,7 @@ casts
comparisonexpr
completedoc
compositebasedereference
compositereferences
comprehensions
containskeyword
cryptohmacequal
@@ -29,6 +32,7 @@ defaultkeyword
disjunction
elsekeyword
embeddedvirtualdoc
eqexpr
evaltermexpr
every
example
@@ -38,10 +42,13 @@ functions
globmatch
globquotemeta
helloworld
hexbuiltins
indexing
indirectreferences
inputvalues
intersection
invalidkeyerror
jsonfilter
jsonfilteridempotent
jwtencodesignheadererrors
jwtencodesignpayloaderrors
+33 -1
View File
@@ -61,7 +61,15 @@ fn eval_test_case(case: &TestCase) -> Result<Value> {
engine.set_input(input.clone());
}
if let Some(input_term) = &case.input_term {
let input = Value::from_json_str(&input_term)?;
let input = match engine.eval_query(input_term.clone(), true)?.result.last() {
Some(r) if r.expressions.last().is_some() => r
.expressions
.last()
.expect("no expressions in result")
.value
.clone(),
_ => bail!("no results in evaluated input term"),
};
engine.set_input(input);
}
if let Some(modules) = &case.modules {
@@ -89,6 +97,22 @@ fn eval_test_case(case: &TestCase) -> Result<Value> {
Value::from_json_str(&result.to_string())
}
fn json_schema_tests_check(actual: &Value, expected: &Value) -> bool {
// Fetch `x` binding.
let actual = &actual[0][&Value::String("x".into())];
let expected = &expected[0][&Value::String("x".into())];
match (actual, expected) {
(Value::Array(actual), Value::Array(expected))
if actual.len() == expected.len() && actual.len() == 2 =>
{
// Only check the result since error messages may be different.
actual[0] == expected[0]
}
_ => false,
}
}
fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
println!("OPA TESTSUITE: {opa_tests_dir}");
let tests_path = Path::new(&opa_tests_dir);
@@ -126,7 +150,15 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
let test: YamlTest = serde_yaml::from_str(&yaml_str)?;
for case in &test.cases {
let is_json_schema_test = case.note.starts_with("json_verify_schema")
|| case.note.starts_with("json_match_schema");
match (eval_test_case(case), &case.want_result) {
(Ok(actual), Some(expected))
if is_json_schema_test && json_schema_tests_check(&actual, &expected) =>
{
entry.0 += 1;
}
(Ok(actual), Some(expected)) if &actual == expected => {
entry.0 += 1;
}
+2 -2
View File
@@ -79,7 +79,7 @@ fn match_vec(s: &Span, vec: &Vec<Ref<Expr>>, v: &Value) -> Result<()> {
Ok(())
}
fn match_object(s: &Span, fields: &Vec<(Span, Ref<Expr>, Ref<Expr>)>, v: &Value) -> Result<()> {
fn match_object(s: &Span, fields: &[(Span, Ref<Expr>, Ref<Expr>)], v: &Value) -> Result<()> {
if skip_value(v) {
return Ok(());
}
@@ -525,7 +525,7 @@ fn match_rule_body(b: &RuleBody, v: &Value) -> Result<()> {
match_query(&b.query, &v["query"])
}
fn match_rule_bodies(span: &Span, bodies: &Vec<RuleBody>, v: &Value) -> Result<()> {
fn match_rule_bodies(span: &Span, bodies: &[RuleBody], v: &Value) -> Result<()> {
if skip_value(v) {
return Ok(());
}