Skip to content

Commit 2433ec2

Browse files
authored
fix(json)!: Bring schema up to modern cargo expectations (#99)
2 parents 0633227 + f2a8a5d commit 2433ec2

File tree

8 files changed

+356
-274
lines changed

8 files changed

+356
-274
lines changed

crates/libtest-json/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ schemars = { version = "1.0.0-alpha.17", features = ["preserve_order", "semver1"
3636

3737
[dev-dependencies]
3838
snapbox = "0.6.21"
39+
serde_json = "1.0.96"
3940

4041
[lints]
4142
workspace = true

crates/libtest-json/event.schema.json

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"properties": {
88
"event": {
99
"type": "string",
10-
"const": "discover-start"
10+
"const": "discover_start"
1111
}
1212
},
1313
"required": [
@@ -24,42 +24,47 @@
2424
"$ref": "#/$defs/RunMode"
2525
},
2626
"run": {
27+
"description": "Whether selected to be run by the user",
2728
"type": "boolean"
2829
},
2930
"event": {
3031
"type": "string",
31-
"const": "discover-case"
32+
"const": "discover_case"
3233
}
3334
},
3435
"required": [
3536
"event",
36-
"name",
37-
"mode",
38-
"run"
37+
"name"
3938
]
4039
},
4140
{
4241
"type": "object",
4342
"properties": {
4443
"elapsed_s": {
45-
"$ref": "#/$defs/Elapsed"
44+
"anyOf": [
45+
{
46+
"$ref": "#/$defs/Elapsed"
47+
},
48+
{
49+
"type": "null"
50+
}
51+
]
4652
},
4753
"event": {
4854
"type": "string",
49-
"const": "discover-complete"
55+
"const": "discover_complete"
5056
}
5157
},
5258
"required": [
53-
"event",
54-
"elapsed_s"
59+
"event"
5560
]
5661
},
5762
{
5863
"type": "object",
5964
"properties": {
6065
"event": {
6166
"type": "string",
62-
"const": "suite-start"
67+
"const": "suite_start"
6368
}
6469
},
6570
"required": [
@@ -74,7 +79,7 @@
7479
},
7580
"event": {
7681
"type": "string",
77-
"const": "case-start"
82+
"const": "case_start"
7883
}
7984
},
8085
"required": [
@@ -92,6 +97,7 @@
9297
"$ref": "#/$defs/RunMode"
9398
},
9499
"status": {
100+
"description": "`None` means success",
95101
"anyOf": [
96102
{
97103
"$ref": "#/$defs/RunStatus"
@@ -119,29 +125,34 @@
119125
},
120126
"event": {
121127
"type": "string",
122-
"const": "case-complete"
128+
"const": "case_complete"
123129
}
124130
},
125131
"required": [
126132
"event",
127-
"name",
128-
"mode"
133+
"name"
129134
]
130135
},
131136
{
132137
"type": "object",
133138
"properties": {
134139
"elapsed_s": {
135-
"$ref": "#/$defs/Elapsed"
140+
"anyOf": [
141+
{
142+
"$ref": "#/$defs/Elapsed"
143+
},
144+
{
145+
"type": "null"
146+
}
147+
]
136148
},
137149
"event": {
138150
"type": "string",
139-
"const": "suite-complete"
151+
"const": "suite_complete"
140152
}
141153
},
142154
"required": [
143-
"event",
144-
"elapsed_s"
155+
"event"
145156
]
146157
}
147158
],
@@ -154,26 +165,7 @@
154165
]
155166
},
156167
"Elapsed": {
157-
"$ref": "#/$defs/Duration"
158-
},
159-
"Duration": {
160-
"type": "object",
161-
"properties": {
162-
"secs": {
163-
"type": "integer",
164-
"format": "uint64",
165-
"minimum": 0
166-
},
167-
"nanos": {
168-
"type": "integer",
169-
"format": "uint32",
170-
"minimum": 0
171-
}
172-
},
173-
"required": [
174-
"secs",
175-
"nanos"
176-
]
168+
"type": "string"
177169
},
178170
"RunStatus": {
179171
"type": "string",

crates/libtest-json/src/event.rs

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,65 @@
11
#[derive(Clone, Debug)]
22
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
3-
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
4-
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
3+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
55
#[cfg_attr(feature = "serde", serde(tag = "event"))]
66
pub enum Event {
77
DiscoverStart,
88
DiscoverCase {
99
name: String,
10+
#[cfg_attr(
11+
feature = "serde",
12+
serde(default, skip_serializing_if = "RunMode::is_default")
13+
)]
1014
mode: RunMode,
15+
/// Whether selected to be run by the user
16+
#[cfg_attr(
17+
feature = "serde",
18+
serde(default = "true_default", skip_serializing_if = "is_true")
19+
)]
1120
run: bool,
1221
},
1322
DiscoverComplete {
14-
#[allow(dead_code)]
15-
elapsed_s: Elapsed,
23+
#[cfg_attr(
24+
feature = "serde",
25+
serde(default, skip_serializing_if = "Option::is_none")
26+
)]
27+
elapsed_s: Option<Elapsed>,
1628
},
1729
SuiteStart,
1830
CaseStart {
1931
name: String,
2032
},
2133
CaseComplete {
2234
name: String,
23-
#[allow(dead_code)]
35+
#[cfg_attr(
36+
feature = "serde",
37+
serde(default, skip_serializing_if = "RunMode::is_default")
38+
)]
2439
mode: RunMode,
40+
/// `None` means success
41+
#[cfg_attr(
42+
feature = "serde",
43+
serde(default, skip_serializing_if = "Option::is_none")
44+
)]
2545
status: Option<RunStatus>,
46+
#[cfg_attr(
47+
feature = "serde",
48+
serde(default, skip_serializing_if = "Option::is_none")
49+
)]
2650
message: Option<String>,
27-
#[allow(dead_code)]
51+
#[cfg_attr(
52+
feature = "serde",
53+
serde(default, skip_serializing_if = "Option::is_none")
54+
)]
2855
elapsed_s: Option<Elapsed>,
2956
},
3057
SuiteComplete {
31-
elapsed_s: Elapsed,
58+
#[cfg_attr(
59+
feature = "serde",
60+
serde(default, skip_serializing_if = "Option::is_none")
61+
)]
62+
elapsed_s: Option<Elapsed>,
3263
},
3364
}
3465

@@ -39,10 +70,18 @@ impl Event {
3970
}
4071
}
4172

73+
fn true_default() -> bool {
74+
true
75+
}
76+
77+
fn is_true(yes: &bool) -> bool {
78+
*yes
79+
}
80+
4281
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
4382
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
44-
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
45-
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
83+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
4685
pub enum RunMode {
4786
#[default]
4887
Test,
@@ -56,21 +95,26 @@ impl RunMode {
5695
Self::Bench => "bench",
5796
}
5897
}
98+
99+
fn is_default(&self) -> bool {
100+
*self == Default::default()
101+
}
59102
}
60103

61104
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
62105
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
63-
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
64-
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
106+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
65108
pub enum RunStatus {
66109
Ignored,
67110
Failed,
68111
}
69112

70113
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
71114
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
72-
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
115+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73116
#[cfg_attr(feature = "serde", serde(into = "String"))]
117+
#[cfg_attr(feature = "serde", serde(try_from = "String"))]
74118
pub struct Elapsed(pub std::time::Duration);
75119

76120
impl std::fmt::Display for Elapsed {
@@ -79,6 +123,23 @@ impl std::fmt::Display for Elapsed {
79123
}
80124
}
81125

126+
impl std::str::FromStr for Elapsed {
127+
type Err = std::num::ParseFloatError;
128+
129+
fn from_str(src: &str) -> Result<Self, Self::Err> {
130+
let secs = src.parse()?;
131+
Ok(Elapsed(std::time::Duration::from_secs_f64(secs)))
132+
}
133+
}
134+
135+
impl TryFrom<String> for Elapsed {
136+
type Error = std::num::ParseFloatError;
137+
138+
fn try_from(inner: String) -> Result<Self, Self::Error> {
139+
inner.parse()
140+
}
141+
}
142+
82143
impl From<Elapsed> for String {
83144
fn from(elapsed: Elapsed) -> Self {
84145
elapsed.0.as_secs_f64().to_string()

0 commit comments

Comments
 (0)