1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
6#[serde(rename_all = "kebab-case")]
7pub enum ScenarioCategory {
8 McpCore,
9 McpExperimental,
10 ChioExtension,
11 Infra,
12}
13
14impl ScenarioCategory {
15 pub fn heading(self) -> &'static str {
16 match self {
17 Self::McpCore => "MCP Core",
18 Self::McpExperimental => "MCP Experimental",
19 Self::ChioExtension => "Chio Extensions",
20 Self::Infra => "Infrastructure",
21 }
22 }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
26#[serde(rename_all = "kebab-case")]
27pub enum Transport {
28 Stdio,
29 StreamableHttp,
30}
31
32impl Transport {
33 pub fn label(self) -> &'static str {
34 match self {
35 Self::Stdio => "stdio",
36 Self::StreamableHttp => "streamable-http",
37 }
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
42#[serde(rename_all = "snake_case")]
43pub enum PeerRole {
44 ClientToChioServer,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49pub enum DeploymentMode {
50 WrappedStdio,
51 NativeStdio,
52 RemoteHttp,
53}
54
55impl DeploymentMode {
56 pub fn label(self) -> &'static str {
57 match self {
58 Self::WrappedStdio => "wrapped-stdio",
59 Self::NativeStdio => "native-stdio",
60 Self::RemoteHttp => "remote-http",
61 }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase")]
67pub struct RequiredCapabilities {
68 #[serde(default)]
69 pub server: Vec<String>,
70 #[serde(default)]
71 pub client: Vec<String>,
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct ScenarioDescriptor {
77 pub id: String,
78 pub title: String,
79 pub area: String,
80 pub category: ScenarioCategory,
81 pub spec_versions: Vec<String>,
82 #[serde(default)]
83 pub transport: Vec<Transport>,
84 #[serde(default)]
85 pub peer_roles: Vec<PeerRole>,
86 #[serde(default)]
87 pub deployment_modes: Vec<DeploymentMode>,
88 #[serde(default)]
89 pub required_capabilities: RequiredCapabilities,
90 #[serde(default)]
91 pub tags: Vec<String>,
92 pub expected: ResultStatus,
93 #[serde(default)]
94 pub timeout_ms: Option<u64>,
95 #[serde(default)]
96 pub notes: Option<String>,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
100#[serde(rename_all = "kebab-case")]
101pub enum ResultStatus {
102 Pass,
103 Fail,
104 Unsupported,
105 Skipped,
106 Xfail,
107}
108
109impl ResultStatus {
110 pub fn label(self) -> &'static str {
111 match self {
112 Self::Pass => "pass",
113 Self::Fail => "fail",
114 Self::Unsupported => "unsupported",
115 Self::Skipped => "skipped",
116 Self::Xfail => "xfail",
117 }
118 }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
122#[serde(rename_all = "kebab-case")]
123pub enum AssertionOutcome {
124 Pass,
125 Fail,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130pub struct AssertionResult {
131 pub name: String,
132 pub status: AssertionOutcome,
133 #[serde(default)]
134 pub message: Option<String>,
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase")]
139pub struct ScenarioResult {
140 pub scenario_id: String,
141 pub peer: String,
142 pub peer_role: PeerRole,
143 pub deployment_mode: DeploymentMode,
144 pub transport: Transport,
145 pub spec_version: String,
146 pub category: ScenarioCategory,
147 pub status: ResultStatus,
148 pub duration_ms: u64,
149 #[serde(default)]
150 pub assertions: Vec<AssertionResult>,
151 #[serde(default)]
152 pub notes: Option<String>,
153 #[serde(default)]
154 pub artifacts: BTreeMap<String, String>,
155 #[serde(default)]
156 pub failure_kind: Option<String>,
157 #[serde(default)]
158 pub failure_message: Option<String>,
159 #[serde(default)]
160 pub expected_failure: Option<bool>,
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Default)]
164pub struct CompatibilityReport {
165 pub scenarios: Vec<ScenarioDescriptor>,
166 pub results: Vec<ScenarioResult>,
167}