More library functions (#51)

- units.parse, units.parse_bytes
- json.is_valid, json.marshal, json.unmarshal
- yaml.is_valid, yaml.marshal, yaml.unmarshal
- object.subset
- set_diff

* Also print number of errors due to each missing function
* Also lock down fully passing OPA suites

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2023-11-22 14:19:23 -08:00
committed by GitHub
parent e838d5af65
commit 4db2270dcf
14 changed files with 650 additions and 31 deletions
@@ -0,0 +1,153 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
cases:
- note: all
data: {}
modules:
- |
package test
# Supportex by OPA
a = [ "E", "e", "P", "p", "T", "t" , "G" , "g" , "M" , "K" , "k" , "m" ]
# Not supported by OPA
b = [ "Q", "R", "Y", "Z", "h", "da", "d", "c",
"μ", "n", "f", "a", "z", "y", "r", "q"
]
c = [
"ki", "Ki", "kI", "KI",
"mi", "Mi", "mI", "MI",
"gi", "Gi", "gI", "GI",
"ti", "Ti", "tI", "TI",
"pi", "Pi", "pI", "PI",
"ei", "Ei", "eI", "EI",
]
d = [
"zi", "Zi", "zI", "ZI",
"yi", "Yi", "yI", "YI",
]
results = {
"p1" : [ units.parse(s) | s = concat("", ["1", a[_]]) ],
"p2" : [ units.parse(s) | s = concat("", ["1", b[_]]) ],
"p3" : [ units.parse(s) | s = concat("", ["1", c[_]]) ],
"p4" : [ units.parse(s) | s = concat("", ["1", d[_]]) ],
# No suffix, quoted.
"p5" : [ units.parse("1"), units.parse("\"1\"") ]
}
query: data.test.results
want_result:
p1:
- 1e18
- 1e18
- 1e15
- 1e15
- 1e12
- 1e12
- 1e9
- 1e9
- 1e6
- 1e3
- 1e3
- 1e-3
p2:
- 1e30
- 1e27
- 1e24
- 1e21
- 1e2
- 1e1
- 1e-1
- 1e-2
- 1e-6
- 1e-9
- 1e-15
- 1e-18
- 1e-21
- 1e-24
- 1e-27
- 1e-30
p3:
- 1024
- 1024
- 1024
- 1024
- 1048576
- 1048576
- 1048576
- 1048576
- 1073741824
- 1073741824
- 1073741824
- 1073741824
- 1099511627776
- 1099511627776
- 1099511627776
- 1099511627776
- 1125899906842624
- 1125899906842624
- 1125899906842624
- 1125899906842624
- 1152921504606846976
- 1152921504606846976
- 1152921504606846976
- 1152921504606846976
p4:
- 1.1805916207174113e21
- 1.1805916207174113e21
- 1.1805916207174113e21
- 1.1805916207174113e21
- 1.2089258196146292e24
- 1.2089258196146292e24
- 1.2089258196146292e24
- 1.2089258196146292e24
p5: [1, 1]
- note: extra argument
data: {}
modules:
- |
package test
a = units.parse("1m", "")
query: data.test
error: expects 1 argument
- note: zero arguments
data: {}
modules:
- |
package test
a = units.parse()
query: data.test
error: expects 1 argument
- note: array
data: {}
modules:
- |
package test
a = units.parse(["1"])
query: data.test
error: expects string argument
- note: space
data: {}
modules:
- |
package test
a = units.parse("1 m")
query: data.test
error: spaces not allowed in resource string
- note: b suffix not supported
data: {}
modules:
- |
package test
a = units.parse("1mb")
query: data.test
want_result: {}
@@ -0,0 +1,115 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
cases:
- note: all
data: {}
modules:
- |
package test
a = [
"y",
"z",
"e",
"p",
"t",
"g",
"m",
"k",
]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", a[_], "i"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", a[_], "i", "b"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", a[_], "i", "B"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", a[_], "I"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", a[_], "I", "b"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", a[_], "I", "B"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", upper(a[_]), "i", "b"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", upper(a[_]), "i", "B"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", upper(a[_]), "I", "b"])]
p1 = [ units.parse_bytes(s) | s = concat("", ["1", upper(a[_]), "I", "B"])]
b = [
"q",
"r",
"y",
"z",
"e",
"p",
"t",
"g",
"m",
"k",
]
p2 = [ units.parse_bytes(s) | s = concat("", ["1", b[_], "b"])]
p2 = [ units.parse_bytes(s) | s = concat("", ["1", b[_], "B"])]
p2 = [ units.parse_bytes(s) | s = concat("", ["1", upper(b[_]), "b"])]
p2 = [ units.parse_bytes(s) | s = concat("", ["1", upper(b[_]), "B"])]
results= {
"p1": p1,
"p2": p2,
}
query: data.test.results
want_result:
p1:
- 1.2089258196146292e24
- 1.1805916207174113e21
- 1152921504606846976
- 1125899906842624
- 1099511627776
- 1073741824
- 1048576
- 1024
p2:
- 1e30
- 1e27
- 1e24
- 1e21
- 1e18
- 1e15
- 1e12
- 1e9
- 1e6
- 1e3
- note: extra argument
data: {}
modules:
- |
package test
a = units.parse_bytes("1m", "")
query: data.test
error: expects 1 argument
- note: zero arguments
data: {}
modules:
- |
package test
a = units.parse_bytes()
query: data.test
error: expects 1 argument
- note: array
data: {}
modules:
- |
package test
a = units.parse_bytes(["1"])
query: data.test
error: expects string argument
- note: space
data: {}
modules:
- |
package test
a = units.parse_bytes("1 m")
query: data.test
error: spaces not allowed in resource string
+42
View File
@@ -0,0 +1,42 @@
aggregates
all
any
array
assignments
bitsand
bitsnegate
bitsor
bitsshiftright
bitsxor
comparisonexpr
completedoc
compositebasedereference
dataderef
embeddedvirtualdoc
evaltermexpr
example
fix1863
intersection
invalidkeyerror
jsonfilteridempotent
nestedreferences
objectfilteridempotent
objectfilternonstringkey
objectremoveidempotent
objectremovenonstringkey
partialsetdoc
rand
replacen
semvercompare
sets
subset
topdowndynamicdispatch
trim
trimleft
trimprefix
trimright
trimsuffix
typebuiltin
typenamebuiltin
union
units
+23 -8
View File
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
use regorus::*;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::BTreeMap;
use std::io::{self, Write};
use std::path::Path;
use std::process::Command;
@@ -72,7 +72,7 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
let tests_path = Path::new(&opa_tests_dir);
let mut status = BTreeMap::<String, (u32, u32)>::new();
let mut n = 0;
let mut missing_functions = BTreeSet::new();
let mut missing_functions = BTreeMap::new();
for entry in WalkDir::new(&opa_tests_dir)
.sort_by_file_name()
.into_iter()
@@ -93,7 +93,7 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
continue;
}
let run_test = folders.is_empty() || folders.iter().any(|f| path_dir_str.contains(f));
let run_test = folders.is_empty() || folders.iter().any(|f| &path_dir_str == f);
if !run_test {
continue;
}
@@ -108,24 +108,35 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
(Ok(actual), Some(expected)) if &actual == expected => {
entry.0 += 1;
}
(Ok(actual), None)
if actual == Value::new_array()
&& case.want_error.is_none()
&& case.error.is_none() =>
{
entry.0 += 1;
}
(Err(_), None) if case.want_error.is_some() => {
// Expected failure.
entry.0 += 1;
}
(r, _) => {
print!("\n{} failed.", case.note);
dbg!((&case, &r));
if let Err(e) = r {
let msg = e.to_string();
let pat = "could not find function ";
if let Some(pos) = msg.find(pat) {
let fcn = &msg[pos + pat.len()..];
missing_functions.insert(fcn.to_string());
missing_functions
.entry(fcn.to_string())
.and_modify(|e| *e += 1)
.or_insert(1);
}
}
let path = Path::new("target/opa/failures").join(path_dir);
std::fs::create_dir_all(path.clone())?;
let mut cmd = "target/debug/examples/regorus eval".to_string();
let mut cmd = "cargo run --example dregorus eval".to_string();
if let Some(data) = &case.data {
let json_path = path.join(format!("data{n}.json"));
cmd += format!(" -d {}", json_path.display()).as_str();
@@ -163,7 +174,7 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
}
}
println!("\nTESTSUITE STATUS");
println!("\nOPA TESTSUITE STATUS");
println!(" {:40} {:4} {:4}", "FOLDER", "PASS", "FAIL");
let (mut npass, mut nfail) = (0, 0);
for (dir, (pass, fail)) in status {
@@ -187,9 +198,13 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
if !missing_functions.is_empty() {
println!("\nMISSING FUNCTIONS");
for (idx, fcn) in missing_functions.iter().enumerate() {
println!("\x1b[31m {:4}: {fcn}\x1b[0m", idx + 1);
println!(" {:4} {:40} {}", "", "FUNCTION", "FAILURES");
let mut ncalls = 0;
for (idx, (fcn, calls)) in missing_functions.iter().enumerate() {
println!("\x1b[31m {:4}: {fcn:40} {calls}\x1b[0m", idx + 1);
ncalls += calls;
}
println!("\x1b[31m {:4} {:40} {ncalls}\x1b[0m", "", "TOTAL");
}
if nfail != 0 {