-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #252 from bend-n/libtest
support libtest json output
- Loading branch information
Showing
4 changed files
with
177 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "cargo_metadata" | ||
version = "0.18.0" | ||
version = "0.18.1" | ||
authors = ["Oliver Schneider <[email protected]>"] | ||
repository = "https://github.com/oli-obk/cargo_metadata" | ||
description = "structured access to the output of `cargo metadata`" | ||
|
@@ -21,6 +21,7 @@ thiserror = "1.0.31" | |
[features] | ||
default = [] | ||
builder = ["derive_builder"] | ||
unstable = [] | ||
|
||
[package.metadata.cargo_metadata_test] | ||
some_field = true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
//! Parses output of [libtest](https://github.com/rust-lang/rust/blob/master/library/test/src/formatters/json.rs). | ||
//! | ||
//! Since this module parses output in an unstable format, all structs in this module may change at any time, and are exempt from semver guarantees. | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// Suite related event | ||
#[derive(Debug, PartialEq, Deserialize, Serialize)] | ||
#[serde(tag = "event")] | ||
#[serde(rename_all = "lowercase")] | ||
/// Suite event | ||
pub enum SuiteEvent { | ||
/// emitted on the start of a test run, and the start of the doctests | ||
Started { | ||
/// number of tests in this suite | ||
test_count: usize, | ||
}, | ||
/// the suite has finished | ||
Ok { | ||
/// the number of tests that passed | ||
passed: usize, | ||
/// the number of tests that failed | ||
failed: usize, | ||
/// number of tests that were ignored | ||
ignored: usize, | ||
/// number of benchmarks run | ||
measured: usize, | ||
/// i think this is based on what you specify in the cargo test argument | ||
filtered_out: usize, | ||
/// how long the suite took to run | ||
exec_time: f32, | ||
}, | ||
/// the suite has at least one failing test | ||
Failed { | ||
/// the number of tests that passed | ||
passed: usize, | ||
/// the number of tests that failed | ||
failed: usize, | ||
/// number of tests that were ignored | ||
ignored: usize, | ||
/// i think its something to do with benchmarks? | ||
measured: usize, | ||
/// i think this is based on what you specify in the cargo test argument | ||
filtered_out: usize, | ||
/// how long the suite took to run | ||
exec_time: f32, | ||
}, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Deserialize, Serialize)] | ||
#[serde(tag = "event")] | ||
#[serde(rename_all = "lowercase")] | ||
/// Test event | ||
pub enum TestEvent { | ||
/// a new test starts | ||
Started { | ||
/// the name of this test | ||
name: String, | ||
}, | ||
/// the test has finished | ||
Ok { | ||
/// which one | ||
name: String, | ||
/// in how long | ||
exec_time: f32, | ||
/// what did it say? | ||
stdout: Option<String>, | ||
}, | ||
/// the test has failed | ||
Failed { | ||
/// which one | ||
name: String, | ||
/// in how long | ||
exec_time: f32, | ||
/// why? | ||
stdout: Option<String>, | ||
/// it timed out? | ||
reason: Option<String>, | ||
/// what message | ||
message: Option<String>, | ||
}, | ||
/// the test has been ignored | ||
Ignored { | ||
/// which one | ||
name: String, | ||
}, | ||
/// the test has timed out | ||
Timeout { | ||
/// which one | ||
name: String, | ||
}, | ||
} | ||
|
||
impl TestEvent { | ||
/// Get the name of this test | ||
pub fn name(&self) -> &str { | ||
let (Self::Started { name } | ||
| Self::Ok { name, .. } | ||
| Self::Ignored { name } | ||
| Self::Failed { name, .. } | ||
| Self::Timeout { name }) = self; | ||
name | ||
} | ||
|
||
/// Get the stdout of this test, if available. | ||
pub fn stdout(&self) -> Option<&str> { | ||
match self { | ||
Self::Ok { stdout, .. } | Self::Failed { stdout, .. } => stdout.as_deref(), | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, PartialEq, Deserialize, Serialize)] | ||
/// Represents the output of `cargo test -- -Zunstable-options --report-time --show-output --format json`. | ||
/// | ||
/// requires --report-time | ||
/// | ||
/// # Stability | ||
/// | ||
/// As this struct is for interfacing with the unstable libtest json output, this struct may change at any time, without semver guarantees. | ||
#[serde(tag = "type")] | ||
#[serde(rename_all = "lowercase")] | ||
pub enum TestMessage { | ||
/// suite related message | ||
Suite(SuiteEvent), | ||
/// test related message | ||
Test(TestEvent), | ||
/// bench related message | ||
Bench { | ||
/// name of benchmark | ||
name: String, | ||
/// distribution | ||
median: f32, | ||
/// deviation | ||
deviation: f32, | ||
/// thruput in MiB per second | ||
mib_per_second: Option<f32>, | ||
}, | ||
} | ||
|
||
#[test] | ||
fn deser() { | ||
macro_rules! run { | ||
($($input:literal parses to $output:expr),+) => { | ||
$(assert_eq!(dbg!(serde_json::from_str::<TestMessage>($input)).unwrap(), $output);)+ | ||
}; | ||
} | ||
run![ | ||
r#"{ "type": "suite", "event": "started", "test_count": 2 }"# parses to TestMessage::Suite(SuiteEvent::Started { test_count: 2 }), | ||
r#"{ "type": "test", "event": "started", "name": "fail" }"# parses to TestMessage::Test(TestEvent::Started { name: "fail".into() }), | ||
r#"{ "type": "test", "name": "fail", "event": "ok", "exec_time": 0.000003428, "stdout": "hello world" }"# parses to TestMessage::Test(TestEvent::Ok { name: "fail".into(), exec_time: 0.000003428, stdout: Some("hello world".into()) }), | ||
r#"{ "type": "test", "event": "started", "name": "nope" }"# parses to TestMessage::Test(TestEvent::Started { name: "nope".into() }), | ||
r#"{ "type": "test", "name": "nope", "event": "ignored" }"# parses to TestMessage::Test(TestEvent::Ignored { name: "nope".into() }), | ||
r#"{ "type": "suite", "event": "ok", "passed": 1, "failed": 0, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": 0.000684028 }"# parses to TestMessage::Suite(SuiteEvent::Ok { passed: 1, failed: 0, ignored: 1, measured: 0, filtered_out: 0, exec_time: 0.000684028 }) | ||
]; | ||
|
||
run![ | ||
r#"{ "type": "suite", "event": "started", "test_count": 2 }"# parses to TestMessage::Suite(SuiteEvent::Started { test_count: 2 }), | ||
r#"{ "type": "test", "event": "started", "name": "fail" }"# parses to TestMessage::Test(TestEvent::Started { name: "fail".into() }), | ||
r#"{ "type": "test", "event": "started", "name": "benc" }"# parses to TestMessage::Test(TestEvent::Started { name: "benc".into() }), | ||
r#"{ "type": "bench", "name": "benc", "median": 0, "deviation": 0 }"# parses to TestMessage::Bench { name: "benc".into(), median: 0., deviation: 0., mib_per_second: None }, | ||
r#"{ "type": "test", "name": "fail", "event": "failed", "exec_time": 0.000081092, "stdout": "thread 'fail' panicked" }"# parses to TestMessage::Test(TestEvent::Failed { name: "fail".into(), exec_time: 0.000081092, stdout: Some("thread 'fail' panicked".into()), reason: None, message: None} ), | ||
r#"{ "type": "suite", "event": "failed", "passed": 0, "failed": 1, "ignored": 0, "measured": 1, "filtered_out": 0, "exec_time": 0.000731068 }"# parses to TestMessage::Suite(SuiteEvent::Failed { passed: 0, failed: 1, ignored: 0, measured: 1, filtered_out: 0, exec_time: 0.000731068 }) | ||
]; | ||
} |