diff --git a/src/docker.rs b/src/docker.rs index ce3f095..9bb19a0 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -5,6 +5,8 @@ use std::collections::HashMap; use std::process::{Command, Stdio}; +use serde::{Deserialize, Serialize}; + #[derive(Default, Clone, Eq, PartialEq)] pub struct Docker; @@ -14,6 +16,12 @@ impl Docker { } } +#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] +pub struct Log { + pub stdout: String, + pub stderr: String, +} + impl Docker { pub fn version(&self) -> String { let version = Command::new("docker") @@ -74,12 +82,15 @@ impl Docker { let out = out.trim(); out.parse::().unwrap() } - pub fn get_logs(&self, name: &str) -> String { + pub fn get_logs(&self, name: &str) -> Log { let output = Command::new("docker") .args(["logs", name]) .output() .expect("unable to get logs"); - String::from_utf8(output.stdout).unwrap() + Log { + stderr: String::from_utf8(output.stderr).unwrap(), + stdout: String::from_utf8(output.stdout).unwrap(), + } } pub async fn block_till_container_exists(&self, name: &str, mut timeout: usize) -> bool { @@ -153,10 +164,10 @@ mod tests { } let logs = d.get_logs(&name); - println!("{logs}"); - assert!(logs.contains("running")); - assert!(logs.contains("FOO=BAR")); - assert!(logs.contains("BAZ=BOO")); + println!("{:?}", logs); + assert!(logs.stdout.contains("running")); + assert!(logs.stdout.contains("FOO=BAR")); + assert!(logs.stdout.contains("BAZ=BOO")); assert_eq!(d.get_exit_status(&name), 0); d.rm_container(&name, true); } diff --git a/src/docker_compose.rs b/src/docker_compose.rs index d9d53f1..1a66e8d 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; use serde_json::Value as JValue; -use crate::docker::Docker; +use crate::docker::{Docker, Log}; #[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)] pub struct Container { @@ -72,7 +72,7 @@ impl DockerCompose { child.wait().unwrap(); } - pub fn logs(&self, service: &str) -> String { + pub fn logs(&self, service: &str) -> Log { self.docker.get_logs(service) } @@ -111,7 +111,7 @@ mod tests { assert_eq!(services.len(), 2); for service in services.iter() { let logs = cmp.logs(&service.name); - assert!(logs.contains(&format!("NAME={}", service.name))); + assert!(logs.stdout.contains(&format!("NAME={}", service.name))); } cmp.down(true, true); assert!(cmp.services().is_empty()); diff --git a/src/runner/init_scripts.rs b/src/runner/init_scripts.rs index 70ce15f..1a9d978 100644 --- a/src/runner/init_scripts.rs +++ b/src/runner/init_scripts.rs @@ -104,7 +104,10 @@ mod tests { let init = init.get(0).unwrap(); assert!(init.success); assert_eq!(init.exit_code, 0); - assert!(init.container.logs.contains("All Good")); + assert!( + init.container.logs.stdout.contains("All Good") + || init.container.logs.stderr.contains("All Good") + ); compose.down(true, true); } } diff --git a/src/runner/results.rs b/src/runner/results.rs index 5d7d4e6..a2c65b2 100644 --- a/src/runner/results.rs +++ b/src/runner/results.rs @@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize}; use url::Url; use crate::complaince::suite::Suite; +use crate::docker::Log; #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] pub struct ArchivableInitResult { @@ -27,9 +28,10 @@ pub struct ArchivableTestResult { #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] pub struct ArchivableContainer { - pub logs: String, + pub logs: Log, pub name: String, } + #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] pub struct ArchivableTest { pub name: String, diff --git a/src/runner/suite.rs b/src/runner/suite.rs index 34337e5..128c0af 100644 --- a/src/runner/suite.rs +++ b/src/runner/suite.rs @@ -132,9 +132,14 @@ impl SuiteRunnerState { } async fn collect_results(mut self, ctx: &dyn MinAppContext) -> ArchivableSuiteResult { + const TIMEOUT: usize = 40; + let mut tests = Vec::with_capacity(self.tests.len()); for (_auth, mut r) in self.tests.drain() { let result = r.rx.recv().await.unwrap(); + ctx.docker_() + .block_till_container_exists(&r.container_name, TIMEOUT) + .await; let log = ctx.docker_().get_logs(&r.container_name); ctx.docker_().rm_container(&r.container_name, true); let container = ArchivableContainer { @@ -307,19 +312,36 @@ mod tests { archivable_test.result.logs, format!("{}{LOGS}", archivable_test.result.container.name) ); - println!("{}", archivable_test.result.container.logs); - assert!(archivable_test.result.container.logs.contains("FTEST_AUTH")); - assert!(archivable_test.result.container.logs.contains("FTEST_HOST")); + println!("{:?}", archivable_test.result.container.logs); assert!(archivable_test .result .container .logs + .stdout + .contains("FTEST_AUTH")); + assert!(archivable_test + .result + .container + .logs + .stdout + .contains("FTEST_HOST")); + assert!(archivable_test + .result + .container + .logs + .stdout .contains("FTEST_TARGET_HOST")); - assert!(archivable_test.result.container.logs.contains("FTEST_USER")); assert!(archivable_test .result .container .logs + .stdout + .contains("FTEST_USER")); + assert!(archivable_test + .result + .container + .logs + .stdout .contains(&format!("TEST_NAME={}", t.name))); } } diff --git a/templates/index.html b/templates/index.html index 2a99ec1..5f513e8 100644 --- a/templates/index.html +++ b/templates/index.html @@ -22,7 +22,11 @@

Logs

{{ test.result.logs | linebreaksbr }}

Container Logs: {{ test.result.container.name }}

- {{ test.result.container.logs | linebreaksbr }} +
STDOUT
+ {{ test.result.container.logs.stdout | linebreaksbr }} +
STDERR
+ {{ test.result.container.logs.stderr | linebreaksbr }} + {% endfor %} {% endfor %} {% if payload.results.init_containers %} @@ -40,7 +44,10 @@

[FAILED] {{init.container.name}}

{% endif %} - {{ init.container.logs | linebreaksbr }} +

STDOUT

+ {{ init.container.logs.stdout | linebreaksbr }} +

STDERR

+ {{ init.container.logs.stderr | linebreaksbr }} {% endfor %} {% endif %}