// Runs the upstream OpenFGA conformance matrix and prints a summary.
//
// Usage: moon run cmd/conformance -- [--json] [ ...]
// With no file arguments both pinned upstream files are used.
///|
fn default_paths() -> Array[String] {
[
".upstream/openfga/consolidated_1_1_tests.yaml", ".upstream/openfga/abac_tests.yaml",
]
}
///|
fn totals_json(
check : @conf.CategoryReport,
list_objects : @conf.CategoryReport,
list_users : @conf.CategoryReport,
) -> Json {
let fields : Map[String, Json] = Map([])
for report in [check, list_objects, list_users] {
fields[report.kind] = Json::object(
Map([
("total", Json::number(report.total.to_double())),
("passed", Json::number(report.passed.to_double())),
("failed", Json::number(report.failed.to_double())),
("skipped", Json::number(report.skipped.to_double())),
]),
)
}
Json::object(fields)
}
///|
fn main {
let args = @env.args()
let paths : Array[String] = []
let mut json_output = false
for i in 1.. None }
match report {
Some(value) => {
if json_output {
files.push(@conf.report_to_json(value))
} else {
println(@conf.format_report(value))
}
failures = failures +
value.check.failed +
value.list_objects.failed +
value.list_users.failed
total_check = total_check + value.check.total
total_check_passed = total_check_passed + value.check.passed
total_check_failed = total_check_failed + value.check.failed
total_check_skipped = total_check_skipped + value.check.skipped
total_objects = total_objects + value.list_objects.total
total_objects_passed = total_objects_passed + value.list_objects.passed
total_objects_failed = total_objects_failed + value.list_objects.failed
total_objects_skipped = total_objects_skipped +
value.list_objects.skipped
total_users = total_users + value.list_users.total
total_users_passed = total_users_passed + value.list_users.passed
total_users_failed = total_users_failed + value.list_users.failed
total_users_skipped = total_users_skipped + value.list_users.skipped
}
None => {
println("cannot read conformance file: " + path)
read_error = true
}
}
}
let check_totals = @conf.CategoryReport::{
kind: "check",
total: total_check,
passed: total_check_passed,
failed: total_check_failed,
skipped: total_check_skipped,
failures: [],
categories: [],
}
let object_totals = @conf.CategoryReport::{
kind: "list_objects",
total: total_objects,
passed: total_objects_passed,
failed: total_objects_failed,
skipped: total_objects_skipped,
failures: [],
categories: [],
}
let user_totals = @conf.CategoryReport::{
kind: "list_users",
total: total_users,
passed: total_users_passed,
failed: total_users_failed,
skipped: total_users_skipped,
failures: [],
categories: [],
}
if json_output {
let root : Map[String, Json] = Map([])
root["files"] = Json::array(files)
root["totals"] = totals_json(check_totals, object_totals, user_totals)
println(Json::object(root).stringify(indent=2))
} else {
println(
"totals: check " +
total_check_passed.to_string() +
"/" +
total_check.to_string() +
", list_objects " +
total_objects_passed.to_string() +
"/" +
total_objects.to_string() +
", list_users " +
total_users_passed.to_string() +
"/" +
total_users.to_string(),
)
}
if read_error {
@sys.exit(2)
} else if failures > 0 {
@sys.exit(1)
}
}