///|
/// 官方 JSON-Schema-Test-Suite(draft2020-12)一致性跑分器。
/// 运行:`moon run cmd/conformance`
///
/// 统计口径:
/// - pass :校验结论与官方期望一致
/// - fail :校验结论与官方期望不一致(引擎 bug)
/// - skip :模式含本引擎尚不支持的关键词,strict 模式编译期拒绝
/// (跳过整组,计入透明报告而非伪装成失败)
fn main {
let mut pass = 0
let mut fail = 0
let mut skip = 0
let mut groups = 0
let mut compile_err_groups = 0
let failures : Array[String] = []
let skip_reasons : Array[String] = []
let per_file : Array[String] = []
for pair in suite_files {
let (name, content) = pair
let mut f_pass = 0
let mut f_fail = 0
let mut f_skip = 0
let groups_json : Json? = Some(@moonschema.parse(content)) catch {
_ => None
}
let groups_json = match groups_json {
Some(g) => g
None => {
per_file.push("\{name}: SUITE PARSE ERROR")
continue
}
}
guard groups_json is Array(file_groups) else {
per_file.push("\{name}: SUITE SHAPE ERROR")
continue
}
for g in file_groups {
guard g is Object(gobj) else { continue }
groups += 1
let gdesc = match gobj.get("description") {
Some(String(s)) => s
_ => "?"
}
let schema = match gobj.get("schema") {
Some(s) => s
None => continue
}
let tests = match gobj.get("tests") {
Some(Array(t)) => t
_ => continue
}
let compiled : @moonschema.Schema? = Some(@moonschema.compile(schema)) catch {
e => {
compile_err_groups += 1
if skip_reasons.length() < 12 {
let where_ = "\{name}/\{gdesc}"
skip_reasons.push("\{where_} -> \{e}")
}
None
}
}
for t in tests {
guard t is Object(tobj) else { continue }
let expect = match tobj.get("valid") {
Some(True) => true
Some(False) => false
_ => continue
}
let data = tobj.get("data") |> get_or(Json::null())
match compiled {
Some(v) => {
let actual = v.check(data)
if actual == expect {
pass += 1
f_pass += 1
} else {
fail += 1
f_fail += 1
if failures.length() < 25 {
let tdesc = match tobj.get("description") {
Some(String(s)) => s
_ => "?"
}
failures.push(
"\{name} / \{gdesc} / \{tdesc}: expected \{expect}, got \{actual} [data=\{data.stringify()}]",
)
}
}
}
None => {
skip += 1
f_skip += 1
}
}
}
}
per_file.push("\{name}: \{f_pass} pass, \{f_fail} fail, \{f_skip} skip")
}
println("== JSON-Schema-Test-Suite (draft2020-12) ==")
println("")
for line in per_file {
println(" \{line}")
}
println("")
println("groups: \{groups} (compile-rejected: \{compile_err_groups})")
println("pass: \{pass} fail: \{fail} skip: \{skip}")
let judged = pass + fail
if judged > 0 {
let rate = pass.to_double() * 100.0 / judged.to_double()
println("pass rate (of judged \{judged}): \{rate}%")
}
if skip_reasons.length() > 0 {
println("")
println("compile rejection samples:")
for r in skip_reasons {
println(" \{r}")
}
}
if failures.length() > 0 {
println("")
println("failure samples:")
for r in failures {
println(" \{r}")
}
}
}
///|
fn get_or(v : Json?, default : Json) -> Json {
match v {
Some(x) => x
None => default
}
}