Arity for builtins (#28)

Old-style function call

Utility for running opa yaml tests

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2023-10-24 10:11:50 -07:00
committed by GitHub
parent 951bb6b14c
commit 800e594d52
25 changed files with 359 additions and 137 deletions
@@ -19,7 +19,7 @@ cases:
u3 = min(set())
query: data.test
want_result:
x: [ 3, 2 ]
x: [ -1, -1 ]
- note: invalid-null
data: {}
@@ -0,0 +1,19 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
cases:
- note: basic
data: {}
modules:
- |
package test
a = [1, 2, 3, 4]
p = x {
count(a, x)
}
query: data.test.p = x
want_result:
x: 4
+10 -12
View File
@@ -32,7 +32,7 @@ fn basic_array() -> Result<()> {
array_compr_7 = [ 1 | [1, 2, 3][_]; [1, 2][_] >= 2 ]
"#;
let expected = vec![Value::from_json_str(
let expected = [Value::from_json_str(
r#" {
"array": [1, 2, 3],
"array_compr_0": [1],
@@ -46,11 +46,10 @@ fn basic_array() -> Result<()> {
}"#,
)?];
assert_match(
eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
expected,
);
Ok(())
check_output(
&eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
&expected,
)
}
#[test]
@@ -81,7 +80,7 @@ fn basic_set() -> Result<()> {
set_compr_7 = { a | a = [1, 2, 3][_]; [1, 2][_] >= 2 }
"#;
let expected = vec![Value::from_json_str(
let expected = [Value::from_json_str(
r#" {
"set": {
"set!": [1, "string", [2, 3, 4], 567, false]
@@ -115,9 +114,8 @@ fn basic_set() -> Result<()> {
}"#,
)?];
assert_match(
eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
expected,
);
Ok(())
check_output(
&eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
&expected,
)
}
+5 -6
View File
@@ -99,7 +99,7 @@ fn basic() -> Result<()> {
}
"#;
let expected = vec![Value::from_json_str(
let expected = [Value::from_json_str(
r#" {
"array": [1, 2, 3],
"in_array_key_value": true,
@@ -119,9 +119,8 @@ fn basic() -> Result<()> {
}"#,
)?];
assert_match(
eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
expected,
);
Ok(())
check_output(
&eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
&expected,
)
}
+5 -6
View File
@@ -25,7 +25,7 @@ fn basic() -> Result<()> {
Value::from_json_str(r#"{"x": 6}"#)?,
]);
let expected = vec![
let expected = [
Value::from_json_str(
r#" {
"y": {"set!": [6]},
@@ -40,9 +40,8 @@ fn basic() -> Result<()> {
)?,
];
assert_match(
eval_file_first_rule(&[rego.to_owned()], None, Some(input), "data.test", false)?,
expected,
);
Ok(())
check_output(
&eval_file_first_rule(&[rego.to_owned()], None, Some(input), "data.test", false)?,
&expected,
)
}
+5 -6
View File
@@ -31,7 +31,7 @@ fn basic() -> Result<()> {
set = {1, 2, 3}
"#;
let expected = vec![Value::from_json_str(
let expected = [Value::from_json_str(
r#" {
"array": [1, 2, 3],
"nested_array": [1, [2, 3, 4], 5, 6],
@@ -46,9 +46,8 @@ fn basic() -> Result<()> {
}"#,
)?];
assert_match(
eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
expected,
);
Ok(())
check_output(
&eval_file(&[rego.to_owned()], None, None, "data.test", false)?,
&expected,
)
}
+65 -18
View File
@@ -4,12 +4,13 @@
#![cfg(test)]
use std::env;
use std::path::Path;
use anyhow::{bail, Result};
use regorus::*;
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
use test_generator::test_resources;
//use walkdir::WalkDir;
use walkdir::WalkDir;
mod cases;
@@ -154,28 +155,30 @@ fn match_values(computed: &Value, expected: &Value) -> Result<()> {
}
}
pub fn assert_match(computed_results: Vec<Value>, expected_results: Vec<Value>) {
pub fn check_output(computed_results: &[Value], expected_results: &[Value]) -> Result<()> {
if computed_results.len() != expected_results.len() {
panic!(
bail!(
"the number of computed results ({}) and expected results ({}) is not equal",
computed_results.len(),
expected_results.len()
);
}
for (n, expected_result) in expected_results.into_iter().enumerate() {
let expected = match process_value(&expected_result) {
for (n, expected_result) in expected_results.iter().enumerate() {
let expected = match process_value(expected_result) {
Ok(e) => e,
_ => panic!("unable to process value :\n {expected_result:?}"),
_ => bail!("unable to process value :\n {expected_result:?}"),
};
if let Some(computed_result) = computed_results.get(n) {
match match_values(computed_result, &expected) {
Ok(()) => (),
Err(e) => panic!("{}", e),
Err(e) => bail!("{e}"),
}
}
}
Ok(())
}
pub fn eval_file_first_rule(
@@ -198,7 +201,7 @@ pub fn eval_file_first_rule(
lines: query.split('\n').collect(),
};
let mut parser = Parser::new(&source)?;
let expr = parser.parse_membership_expr()?;
let expr = parser.parse_assign_expr()?;
for (idx, _) in regos.iter().enumerate() {
files.push(format!("rego_{idx}"));
@@ -278,7 +281,7 @@ pub fn eval_file(
lines: query.split('\n').collect(),
};
let mut parser = Parser::new(&source)?;
let expr = parser.parse_membership_expr()?;
let expr = parser.parse_assign_expr()?;
for (idx, _) in regos.iter().enumerate() {
files.push(format!("rego_{idx}"));
@@ -435,7 +438,7 @@ struct YamlTest {
cases: Vec<TestCase>,
}
fn yaml_test_impl(file: &str) -> Result<()> {
fn yaml_test_impl(file: &str, is_opa_test: bool) -> Result<()> {
let yaml_str = std::fs::read_to_string(file)?;
let test: YamlTest = serde_yaml::from_str(&yaml_str)?;
@@ -472,7 +475,14 @@ fn yaml_test_impl(file: &str) -> Result<()> {
}
}
assert_match(results, expected_results);
if is_opa_test {
// Convert value to json compatible representation.
let results =
Value::from_json_str(serde_json::to_string(&results)?.as_str())?;
match_values(&results, &expected_results[0])?;
} else {
check_output(&results, &expected_results)?;
}
}
_ => panic!("eval succeeded and did not produce any errors"),
},
@@ -498,8 +508,8 @@ fn yaml_test_impl(file: &str) -> Result<()> {
Ok(())
}
fn yaml_test(file: &str) -> Result<()> {
match yaml_test_impl(file) {
fn yaml_test(file: &str, is_opa_test: bool) -> Result<()> {
match yaml_test_impl(file, is_opa_test) {
Ok(_) => Ok(()),
Err(e) => {
// If Err is returned, it doesn't always get printed by cargo test.
@@ -511,28 +521,65 @@ fn yaml_test(file: &str) -> Result<()> {
#[test]
fn yaml_test_basic() -> Result<()> {
yaml_test("tests/interpreter/cases/basic_001.yaml")
yaml_test("tests/interpreter/cases/basic_001.yaml", false)
}
#[test]
#[ignore = "intended for use by scripts/yaml-test-eval"]
fn one_yaml() -> Result<()> {
let mut file = String::default();
let mut is_opa_test = false;
for a in env::args() {
if a.ends_with(".yaml") {
file = a;
break;
} else if a == "opa-test" {
is_opa_test = true;
}
}
if file.is_empty() {
bail!("missing <policy.rego>");
bail!("missing <yaml-file>");
}
yaml_test(file.as_str())
yaml_test(file.as_str(), is_opa_test)
}
#[test_resources("tests/interpreter/**/*.yaml")]
fn run(path: &str) {
yaml_test(path).unwrap()
yaml_test(path, false).unwrap()
}
#[test]
#[ignore = "intended for running opa test suite"]
fn run_opa_tests() -> Result<()> {
let mut failures = vec![];
for a in env::args() {
if !Path::new(&a).is_dir() {
continue;
}
for entry in WalkDir::new(a)
.sort_by_file_name()
.into_iter()
.filter_map(|e| e.ok())
{
let path = entry.path().to_string_lossy().to_string();
if Path::new(&path).is_dir() {
continue;
}
let yaml = path;
match yaml_test_impl(yaml.as_str(), true) {
Ok(_) => (),
Err(e) => {
failures.push((yaml, e));
}
}
}
}
if !failures.is_empty() {
dbg!(failures);
panic!("failed");
}
Ok(())
}