Skip to content

Commit f0b693b

Browse files
committed
feat(codeguard): 15.2 Go/Kotlin/Swift/Ruby 联合路径验收(20 测试全绿)
新增 4 种语言的 WASM+原生联合路径测试: - go_wasm_combined_path.rs: 5 测试 - kotlin_wasm_combined_path.rs: 5 测试 - swift_wasm_combined_path.rs: 5 测试 - ruby_wasm_combined_path.rs: 5 测试 每种语言覆盖:WASM 候选不冒充/grammar 未验证不声称 clean/ 原生优先/缺工具初检/安装指引。 15.2 联合路径验收累计 8 种语言(Java/Python/TypeScript/Rust/Go/Kotlin/Swift/Ruby)。 20/20 测试全绿。
1 parent 86942dd commit f0b693b

4 files changed

Lines changed: 388 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Go WASM+原生联合路径全链路验证。
2+
3+
#![cfg(feature = "wasm-precheck")]
4+
5+
use std::process::Command;
6+
7+
fn ensure_clean_dir(name: &str) -> std::path::PathBuf {
8+
let tmp = std::env::temp_dir().join(name);
9+
let _ = std::fs::remove_dir_all(&tmp);
10+
std::fs::create_dir_all(&tmp).unwrap();
11+
tmp
12+
}
13+
14+
#[test]
15+
fn wasm_candidates_are_not_confirmed_violations() {
16+
let root = ensure_clean_dir("codeguard-go-wasm-candidate");
17+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
18+
.args(["check", "go", root.to_str().unwrap(), "--format=json"])
19+
.output()
20+
.expect("无法运行 codeguard check");
21+
let stdout = String::from_utf8_lossy(&output.stdout);
22+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
23+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
24+
for obs in observations {
25+
let status = obs["status"].as_str().unwrap_or("");
26+
assert!(status.starts_with("candidate") || status == "observed_partial" || status == "not_run" || status == "incomplete", "WASM 观察不应标记为已确认违规: {status}");
27+
}
28+
}
29+
let _ = std::fs::remove_dir_all(&root);
30+
}
31+
32+
#[test]
33+
fn unverified_grammar_does_not_claim_clean() {
34+
let root = ensure_clean_dir("codeguard-go-wasm-clean");
35+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
36+
.args(["check", "go", root.to_str().unwrap(), "--format=json"])
37+
.output()
38+
.expect("无法运行 codeguard check");
39+
let stdout = String::from_utf8_lossy(&output.stdout);
40+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
41+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
42+
for obs in observations {
43+
let qualified = obs["grammar_qualified"].as_bool().unwrap_or(false);
44+
if !qualified {
45+
let status = obs["status"].as_str().unwrap_or("");
46+
assert_ne!(status, "clean", "grammar 未验证时不能声称 clean");
47+
}
48+
}
49+
}
50+
let _ = std::fs::remove_dir_all(&root);
51+
}
52+
53+
#[test]
54+
fn native_preferred_over_wasm() {
55+
let root = ensure_clean_dir("codeguard-go-native-pref");
56+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
57+
.args(["check", "all", root.to_str().unwrap(), "--format=json"])
58+
.output()
59+
.expect("无法运行 codeguard check all");
60+
let stdout = String::from_utf8_lossy(&output.stdout);
61+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
62+
let delivery = report["delivery_decision"].as_str().unwrap_or("");
63+
assert_ne!(delivery, "allow", "grammar 未完全验证时不应签发 allow");
64+
let _ = std::fs::remove_dir_all(&root);
65+
}
66+
67+
#[test]
68+
fn missing_tool_initial_check_gives_guidance() {
69+
let root = ensure_clean_dir("codeguard-go-missing-tool");
70+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
71+
.args(["check", "go", root.to_str().unwrap(), "--format=json"])
72+
.output()
73+
.expect("无法运行 codeguard check");
74+
let stdout = String::from_utf8_lossy(&output.stdout);
75+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
76+
let next_action = report["syntax_candidates"]["next_action"].as_str().unwrap_or("");
77+
assert!(!next_action.is_empty(), "缺工具初检应给出下一步指引");
78+
assert_eq!(output.status.code(), Some(3), "缺工具时退出码应为 3");
79+
let _ = std::fs::remove_dir_all(&root);
80+
}
81+
82+
#[test]
83+
fn installation_guidance_in_category_candidates() {
84+
let root = ensure_clean_dir("codeguard-go-install-guide");
85+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
86+
.args(["check", "go", root.to_str().unwrap(), "--format=json"])
87+
.output()
88+
.expect("无法运行 codeguard check");
89+
let stdout = String::from_utf8_lossy(&output.stdout);
90+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
91+
if let Some(candidates) = report["category_candidates"].as_array() {
92+
for cat in candidates {
93+
assert!(cat["capability_status"].as_str().map(|s| !s.is_empty()).unwrap_or(false), "每个类别应有 capability_status");
94+
}
95+
}
96+
let _ = std::fs::remove_dir_all(&root);
97+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Kotlin WASM+原生联合路径全链路验证。
2+
3+
#![cfg(feature = "wasm-precheck")]
4+
5+
use std::process::Command;
6+
7+
fn ensure_clean_dir(name: &str) -> std::path::PathBuf {
8+
let tmp = std::env::temp_dir().join(name);
9+
let _ = std::fs::remove_dir_all(&tmp);
10+
std::fs::create_dir_all(&tmp).unwrap();
11+
tmp
12+
}
13+
14+
#[test]
15+
fn wasm_candidates_are_not_confirmed_violations() {
16+
let root = ensure_clean_dir("codeguard-kotlin-wasm-candidate");
17+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
18+
.args(["check", "kotlin", root.to_str().unwrap(), "--format=json"])
19+
.output()
20+
.expect("无法运行 codeguard check");
21+
let stdout = String::from_utf8_lossy(&output.stdout);
22+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
23+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
24+
for obs in observations {
25+
let status = obs["status"].as_str().unwrap_or("");
26+
assert!(status.starts_with("candidate") || status == "observed_partial" || status == "not_run" || status == "incomplete", "WASM 观察不应标记为已确认违规: {status}");
27+
}
28+
}
29+
let _ = std::fs::remove_dir_all(&root);
30+
}
31+
32+
#[test]
33+
fn unverified_grammar_does_not_claim_clean() {
34+
let root = ensure_clean_dir("codeguard-kotlin-wasm-clean");
35+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
36+
.args(["check", "kotlin", root.to_str().unwrap(), "--format=json"])
37+
.output()
38+
.expect("无法运行 codeguard check");
39+
let stdout = String::from_utf8_lossy(&output.stdout);
40+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
41+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
42+
for obs in observations {
43+
let qualified = obs["grammar_qualified"].as_bool().unwrap_or(false);
44+
if !qualified {
45+
let status = obs["status"].as_str().unwrap_or("");
46+
assert_ne!(status, "clean", "grammar 未验证时不能声称 clean");
47+
}
48+
}
49+
}
50+
let _ = std::fs::remove_dir_all(&root);
51+
}
52+
53+
#[test]
54+
fn native_preferred_over_wasm() {
55+
let root = ensure_clean_dir("codeguard-kotlin-native-pref");
56+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
57+
.args(["check", "all", root.to_str().unwrap(), "--format=json"])
58+
.output()
59+
.expect("无法运行 codeguard check all");
60+
let stdout = String::from_utf8_lossy(&output.stdout);
61+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
62+
let delivery = report["delivery_decision"].as_str().unwrap_or("");
63+
assert_ne!(delivery, "allow", "grammar 未完全验证时不应签发 allow");
64+
let _ = std::fs::remove_dir_all(&root);
65+
}
66+
67+
#[test]
68+
fn missing_tool_initial_check_gives_guidance() {
69+
let root = ensure_clean_dir("codeguard-kotlin-missing-tool");
70+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
71+
.args(["check", "kotlin", root.to_str().unwrap(), "--format=json"])
72+
.output()
73+
.expect("无法运行 codeguard check");
74+
let stdout = String::from_utf8_lossy(&output.stdout);
75+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
76+
let next_action = report["syntax_candidates"]["next_action"].as_str().unwrap_or("");
77+
assert!(!next_action.is_empty(), "缺工具初检应给出下一步指引");
78+
assert_eq!(output.status.code(), Some(3), "缺工具时退出码应为 3");
79+
let _ = std::fs::remove_dir_all(&root);
80+
}
81+
82+
#[test]
83+
fn installation_guidance_in_category_candidates() {
84+
let root = ensure_clean_dir("codeguard-kotlin-install-guide");
85+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
86+
.args(["check", "kotlin", root.to_str().unwrap(), "--format=json"])
87+
.output()
88+
.expect("无法运行 codeguard check");
89+
let stdout = String::from_utf8_lossy(&output.stdout);
90+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
91+
if let Some(candidates) = report["category_candidates"].as_array() {
92+
for cat in candidates {
93+
assert!(cat["capability_status"].as_str().map(|s| !s.is_empty()).unwrap_or(false), "每个类别应有 capability_status");
94+
}
95+
}
96+
let _ = std::fs::remove_dir_all(&root);
97+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Ruby WASM+原生联合路径全链路验证。
2+
3+
#![cfg(feature = "wasm-precheck")]
4+
5+
use std::process::Command;
6+
7+
fn ensure_clean_dir(name: &str) -> std::path::PathBuf {
8+
let tmp = std::env::temp_dir().join(name);
9+
let _ = std::fs::remove_dir_all(&tmp);
10+
std::fs::create_dir_all(&tmp).unwrap();
11+
tmp
12+
}
13+
14+
#[test]
15+
fn wasm_candidates_are_not_confirmed_violations() {
16+
let root = ensure_clean_dir("codeguard-ruby-wasm-candidate");
17+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
18+
.args(["check", "ruby", root.to_str().unwrap(), "--format=json"])
19+
.output()
20+
.expect("无法运行 codeguard check");
21+
let stdout = String::from_utf8_lossy(&output.stdout);
22+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
23+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
24+
for obs in observations {
25+
let status = obs["status"].as_str().unwrap_or("");
26+
assert!(status.starts_with("candidate") || status == "observed_partial" || status == "not_run" || status == "incomplete", "WASM 观察不应标记为已确认违规: {status}");
27+
}
28+
}
29+
let _ = std::fs::remove_dir_all(&root);
30+
}
31+
32+
#[test]
33+
fn unverified_grammar_does_not_claim_clean() {
34+
let root = ensure_clean_dir("codeguard-ruby-wasm-clean");
35+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
36+
.args(["check", "ruby", root.to_str().unwrap(), "--format=json"])
37+
.output()
38+
.expect("无法运行 codeguard check");
39+
let stdout = String::from_utf8_lossy(&output.stdout);
40+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
41+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
42+
for obs in observations {
43+
let qualified = obs["grammar_qualified"].as_bool().unwrap_or(false);
44+
if !qualified {
45+
let status = obs["status"].as_str().unwrap_or("");
46+
assert_ne!(status, "clean", "grammar 未验证时不能声称 clean");
47+
}
48+
}
49+
}
50+
let _ = std::fs::remove_dir_all(&root);
51+
}
52+
53+
#[test]
54+
fn native_preferred_over_wasm() {
55+
let root = ensure_clean_dir("codeguard-ruby-native-pref");
56+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
57+
.args(["check", "all", root.to_str().unwrap(), "--format=json"])
58+
.output()
59+
.expect("无法运行 codeguard check all");
60+
let stdout = String::from_utf8_lossy(&output.stdout);
61+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
62+
let delivery = report["delivery_decision"].as_str().unwrap_or("");
63+
assert_ne!(delivery, "allow", "grammar 未完全验证时不应签发 allow");
64+
let _ = std::fs::remove_dir_all(&root);
65+
}
66+
67+
#[test]
68+
fn missing_tool_initial_check_gives_guidance() {
69+
let root = ensure_clean_dir("codeguard-ruby-missing-tool");
70+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
71+
.args(["check", "ruby", root.to_str().unwrap(), "--format=json"])
72+
.output()
73+
.expect("无法运行 codeguard check");
74+
let stdout = String::from_utf8_lossy(&output.stdout);
75+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
76+
let next_action = report["syntax_candidates"]["next_action"].as_str().unwrap_or("");
77+
assert!(!next_action.is_empty(), "缺工具初检应给出下一步指引");
78+
assert_eq!(output.status.code(), Some(3), "缺工具时退出码应为 3");
79+
let _ = std::fs::remove_dir_all(&root);
80+
}
81+
82+
#[test]
83+
fn installation_guidance_in_category_candidates() {
84+
let root = ensure_clean_dir("codeguard-ruby-install-guide");
85+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
86+
.args(["check", "ruby", root.to_str().unwrap(), "--format=json"])
87+
.output()
88+
.expect("无法运行 codeguard check");
89+
let stdout = String::from_utf8_lossy(&output.stdout);
90+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
91+
if let Some(candidates) = report["category_candidates"].as_array() {
92+
for cat in candidates {
93+
assert!(cat["capability_status"].as_str().map(|s| !s.is_empty()).unwrap_or(false), "每个类别应有 capability_status");
94+
}
95+
}
96+
let _ = std::fs::remove_dir_all(&root);
97+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Swift WASM+原生联合路径全链路验证。
2+
3+
#![cfg(feature = "wasm-precheck")]
4+
5+
use std::process::Command;
6+
7+
fn ensure_clean_dir(name: &str) -> std::path::PathBuf {
8+
let tmp = std::env::temp_dir().join(name);
9+
let _ = std::fs::remove_dir_all(&tmp);
10+
std::fs::create_dir_all(&tmp).unwrap();
11+
tmp
12+
}
13+
14+
#[test]
15+
fn wasm_candidates_are_not_confirmed_violations() {
16+
let root = ensure_clean_dir("codeguard-swift-wasm-candidate");
17+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
18+
.args(["check", "swift", root.to_str().unwrap(), "--format=json"])
19+
.output()
20+
.expect("无法运行 codeguard check");
21+
let stdout = String::from_utf8_lossy(&output.stdout);
22+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
23+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
24+
for obs in observations {
25+
let status = obs["status"].as_str().unwrap_or("");
26+
assert!(status.starts_with("candidate") || status == "observed_partial" || status == "not_run" || status == "incomplete", "WASM 观察不应标记为已确认违规: {status}");
27+
}
28+
}
29+
let _ = std::fs::remove_dir_all(&root);
30+
}
31+
32+
#[test]
33+
fn unverified_grammar_does_not_claim_clean() {
34+
let root = ensure_clean_dir("codeguard-swift-wasm-clean");
35+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
36+
.args(["check", "swift", root.to_str().unwrap(), "--format=json"])
37+
.output()
38+
.expect("无法运行 codeguard check");
39+
let stdout = String::from_utf8_lossy(&output.stdout);
40+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
41+
if let Some(observations) = report["syntax_candidates"]["observations"].as_array() {
42+
for obs in observations {
43+
let qualified = obs["grammar_qualified"].as_bool().unwrap_or(false);
44+
if !qualified {
45+
let status = obs["status"].as_str().unwrap_or("");
46+
assert_ne!(status, "clean", "grammar 未验证时不能声称 clean");
47+
}
48+
}
49+
}
50+
let _ = std::fs::remove_dir_all(&root);
51+
}
52+
53+
#[test]
54+
fn native_preferred_over_wasm() {
55+
let root = ensure_clean_dir("codeguard-swift-native-pref");
56+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
57+
.args(["check", "all", root.to_str().unwrap(), "--format=json"])
58+
.output()
59+
.expect("无法运行 codeguard check all");
60+
let stdout = String::from_utf8_lossy(&output.stdout);
61+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
62+
let delivery = report["delivery_decision"].as_str().unwrap_or("");
63+
assert_ne!(delivery, "allow", "grammar 未完全验证时不应签发 allow");
64+
let _ = std::fs::remove_dir_all(&root);
65+
}
66+
67+
#[test]
68+
fn missing_tool_initial_check_gives_guidance() {
69+
let root = ensure_clean_dir("codeguard-swift-missing-tool");
70+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
71+
.args(["check", "swift", root.to_str().unwrap(), "--format=json"])
72+
.output()
73+
.expect("无法运行 codeguard check");
74+
let stdout = String::from_utf8_lossy(&output.stdout);
75+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
76+
let next_action = report["syntax_candidates"]["next_action"].as_str().unwrap_or("");
77+
assert!(!next_action.is_empty(), "缺工具初检应给出下一步指引");
78+
assert_eq!(output.status.code(), Some(3), "缺工具时退出码应为 3");
79+
let _ = std::fs::remove_dir_all(&root);
80+
}
81+
82+
#[test]
83+
fn installation_guidance_in_category_candidates() {
84+
let root = ensure_clean_dir("codeguard-swift-install-guide");
85+
let output = Command::new(env!("CARGO_BIN_EXE_codeguard"))
86+
.args(["check", "swift", root.to_str().unwrap(), "--format=json"])
87+
.output()
88+
.expect("无法运行 codeguard check");
89+
let stdout = String::from_utf8_lossy(&output.stdout);
90+
let report: serde_json::Value = serde_json::from_str(&stdout).expect("JSON 解析失败");
91+
if let Some(candidates) = report["category_candidates"].as_array() {
92+
for cat in candidates {
93+
assert!(cat["capability_status"].as_str().map(|s| !s.is_empty()).unwrap_or(false), "每个类别应有 capability_status");
94+
}
95+
}
96+
let _ = std::fs::remove_dir_all(&root);
97+
}

0 commit comments

Comments
 (0)