mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
feat(azure_policy): test runner, compiler fixes, and example program (#700)
Adds the YAML test runner that exercises the companion test data PRs, plus several compiler fixes surfaced during testing: - Removed parameter register caching that produced wrong results inside short-circuiting allOf/anyOf blocks; added literal-index caching for parameter defaults to avoid repeated O(n) literal-table scans - Simplified cross-resource effect details to only emit roleDefinitionIds and type (deployment templates are not evaluated for compliance) - Replaced guid/uniqueString builtins with clear "unsupported" errors - Normalized datetime output to ISO 8601 with Z suffix - Added azure_policy parser MAX_COL constant (8192) for long template expressions, keeping the global DEFAULT_MAX_COL at 1024 - Added rvm to azure_policy feature dependencies since the compiler targets RVM bytecode Also restructures the example binary into examples/regorus/ with new azure-policy-eval and azure-policy-aliases subcommands, adds C# alias normalization tests, and documents Azure Policy support in the README. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
7f42115b63
commit
4c92fb4d92
@@ -8,7 +8,7 @@
|
||||
//! `"if"` / `"then"` structure. The test runner extracts the `"if"` constraint
|
||||
//! JSON and parses it with `parse_constraint`.
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{bail, Result};
|
||||
use regorus::languages::azure_policy::parser;
|
||||
use regorus::Source;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -64,8 +64,8 @@ fn should_run_test_case(case_note: &str) -> bool {
|
||||
///
|
||||
/// Returns `None` if parsing fails or there is no `"if"` key (the caller
|
||||
/// should feed the raw string to `parse_constraint` for error tests).
|
||||
fn extract_if_json(policy_rule_json: &str) -> Option<String> {
|
||||
let v: serde_json::Value = serde_json::from_str(policy_rule_json).ok()?;
|
||||
fn extract_if_json(source_json: &str) -> Option<String> {
|
||||
let v: serde_json::Value = serde_json::from_str(source_json).ok()?;
|
||||
let if_value = v.get("if")?;
|
||||
Some(if_value.to_string())
|
||||
}
|
||||
@@ -102,12 +102,12 @@ fn yaml_test_impl(file: &str) -> Result<()> {
|
||||
|
||||
let expects_parse_error = case.want_parse_error == Some(true);
|
||||
|
||||
let input_json = if let Some(ref rule) = case.policy_rule {
|
||||
let source_json = if let Some(ref rule) = case.policy_rule {
|
||||
rule.clone()
|
||||
} else if let Some(ref rule) = test.policy_rule {
|
||||
rule.clone()
|
||||
} else {
|
||||
panic!("case '{}': must specify 'policy_rule'", case.note);
|
||||
bail!("case '{}': must specify 'policy_rule'", case.note);
|
||||
};
|
||||
|
||||
let parse_level = case.parse_level.as_deref().unwrap_or("constraint");
|
||||
@@ -115,35 +115,33 @@ fn yaml_test_impl(file: &str) -> Result<()> {
|
||||
let parse_result = match parse_level {
|
||||
"policy_rule" => {
|
||||
// Parse the full policy_rule JSON with parse_policy_rule.
|
||||
let source = Source::from_contents(format!("test:{}", case.note), input_json)?;
|
||||
let source = Source::from_contents(format!("test:{}", case.note), source_json)?;
|
||||
parser::parse_policy_rule(&source).map(|_| ())
|
||||
}
|
||||
"policy_definition" => {
|
||||
// Parse the full policy definition JSON with parse_policy_definition.
|
||||
let source = Source::from_contents(format!("test:{}", case.note), input_json)?;
|
||||
let source = Source::from_contents(format!("test:{}", case.note), source_json)?;
|
||||
parser::parse_policy_definition(&source).map(|_| ())
|
||||
}
|
||||
"constraint" => {
|
||||
// Extract the "if" constraint JSON. If extraction fails
|
||||
// (malformed JSON or missing "if" key), feed the raw
|
||||
// input to parse_constraint — it should fail,
|
||||
// matching want_parse_error.
|
||||
let constraint_json = match extract_if_json(&input_json) {
|
||||
Some(json) => json,
|
||||
None => input_json,
|
||||
};
|
||||
// (malformed JSON or missing "if" key), feed the raw source
|
||||
// JSON to parse_constraint — it should fail, matching
|
||||
// want_parse_error.
|
||||
let constraint_json =
|
||||
extract_if_json(&source_json).unwrap_or_else(|| source_json.clone());
|
||||
let source = Source::from_contents(format!("test:{}", case.note), constraint_json)?;
|
||||
parser::parse_constraint(&source).map(|_| ())
|
||||
}
|
||||
other => {
|
||||
panic!("case '{}': unknown parse_level '{}'", case.note, other);
|
||||
bail!("case '{}': unknown parse_level '{}'", case.note, other);
|
||||
}
|
||||
};
|
||||
|
||||
match parse_result {
|
||||
Ok(()) => {
|
||||
if expects_parse_error {
|
||||
panic!(
|
||||
bail!(
|
||||
"case '{}': expected parse error but parsing succeeded",
|
||||
case.note
|
||||
);
|
||||
@@ -154,7 +152,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
|
||||
if expects_parse_error {
|
||||
println!("passed (expected parse error: {})", e);
|
||||
} else {
|
||||
panic!("case '{}': unexpected parse error: {}", case.note, e);
|
||||
bail!("case '{}': unexpected parse error: {}", case.note, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user