Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/flycheck/src/test_runner.rs')
-rw-r--r--crates/flycheck/src/test_runner.rs76
1 files changed, 76 insertions, 0 deletions
diff --git a/crates/flycheck/src/test_runner.rs b/crates/flycheck/src/test_runner.rs
new file mode 100644
index 0000000000..6dac5899ee
--- /dev/null
+++ b/crates/flycheck/src/test_runner.rs
@@ -0,0 +1,76 @@
+//! This module provides the functionality needed to run `cargo test` in a background
+//! thread and report the result of each test in a channel.
+
+use std::process::Command;
+
+use crossbeam_channel::Receiver;
+use serde::Deserialize;
+use toolchain::Tool;
+
+use crate::command::{CommandHandle, ParseFromLine};
+
+#[derive(Debug, Deserialize)]
+#[serde(tag = "event", rename_all = "camelCase")]
+pub enum TestState {
+ Started,
+ Ok,
+ Ignored,
+ Failed { stdout: String },
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(tag = "type", rename_all = "camelCase")]
+pub enum CargoTestMessage {
+ Test {
+ name: String,
+ #[serde(flatten)]
+ state: TestState,
+ },
+ Suite,
+ Finished,
+}
+
+impl ParseFromLine for CargoTestMessage {
+ fn from_line(line: &str, error: &mut String) -> Option<Self> {
+ let mut deserializer = serde_json::Deserializer::from_str(line);
+ deserializer.disable_recursion_limit();
+ if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) {
+ return Some(message);
+ }
+
+ error.push_str(line);
+ error.push('\n');
+ None
+ }
+
+ fn from_eof() -> Option<Self> {
+ Some(CargoTestMessage::Finished)
+ }
+}
+
+#[derive(Debug)]
+pub struct CargoTestHandle {
+ handle: CommandHandle<CargoTestMessage>,
+}
+
+// Example of a cargo test command:
+// cargo test -- module::func -Z unstable-options --format=json
+
+impl CargoTestHandle {
+ pub fn new(path: Option<&str>) -> std::io::Result<Self> {
+ let mut cmd = Command::new(Tool::Cargo.path());
+ cmd.env("RUSTC_BOOTSTRAP", "1");
+ cmd.arg("test");
+ cmd.arg("--");
+ if let Some(path) = path {
+ cmd.arg(path);
+ }
+ cmd.args(["-Z", "unstable-options"]);
+ cmd.arg("--format=json");
+ Ok(Self { handle: CommandHandle::spawn(cmd)? })
+ }
+
+ pub fn receiver(&self) -> &Receiver<CargoTestMessage> {
+ &self.handle.receiver
+ }
+}