feat: capture stderr as well
This commit is contained in:
parent
36c64878e0
commit
86c63f75ab
6 changed files with 62 additions and 17 deletions
|
@ -5,6 +5,8 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Default, Clone, Eq, PartialEq)]
|
#[derive(Default, Clone, Eq, PartialEq)]
|
||||||
pub struct Docker;
|
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 {
|
impl Docker {
|
||||||
pub fn version(&self) -> String {
|
pub fn version(&self) -> String {
|
||||||
let version = Command::new("docker")
|
let version = Command::new("docker")
|
||||||
|
@ -74,12 +82,15 @@ impl Docker {
|
||||||
let out = out.trim();
|
let out = out.trim();
|
||||||
out.parse::<isize>().unwrap()
|
out.parse::<isize>().unwrap()
|
||||||
}
|
}
|
||||||
pub fn get_logs(&self, name: &str) -> String {
|
pub fn get_logs(&self, name: &str) -> Log {
|
||||||
let output = Command::new("docker")
|
let output = Command::new("docker")
|
||||||
.args(["logs", name])
|
.args(["logs", name])
|
||||||
.output()
|
.output()
|
||||||
.expect("unable to get logs");
|
.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 {
|
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);
|
let logs = d.get_logs(&name);
|
||||||
println!("{logs}");
|
println!("{:?}", logs);
|
||||||
assert!(logs.contains("running"));
|
assert!(logs.stdout.contains("running"));
|
||||||
assert!(logs.contains("FOO=BAR"));
|
assert!(logs.stdout.contains("FOO=BAR"));
|
||||||
assert!(logs.contains("BAZ=BOO"));
|
assert!(logs.stdout.contains("BAZ=BOO"));
|
||||||
assert_eq!(d.get_exit_status(&name), 0);
|
assert_eq!(d.get_exit_status(&name), 0);
|
||||||
d.rm_container(&name, true);
|
d.rm_container(&name, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::sync::Arc;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value as JValue;
|
use serde_json::Value as JValue;
|
||||||
|
|
||||||
use crate::docker::Docker;
|
use crate::docker::{Docker, Log};
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
|
@ -72,7 +72,7 @@ impl DockerCompose {
|
||||||
child.wait().unwrap();
|
child.wait().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logs(&self, service: &str) -> String {
|
pub fn logs(&self, service: &str) -> Log {
|
||||||
self.docker.get_logs(service)
|
self.docker.get_logs(service)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ mod tests {
|
||||||
assert_eq!(services.len(), 2);
|
assert_eq!(services.len(), 2);
|
||||||
for service in services.iter() {
|
for service in services.iter() {
|
||||||
let logs = cmp.logs(&service.name);
|
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);
|
cmp.down(true, true);
|
||||||
assert!(cmp.services().is_empty());
|
assert!(cmp.services().is_empty());
|
||||||
|
|
|
@ -104,7 +104,10 @@ mod tests {
|
||||||
let init = init.get(0).unwrap();
|
let init = init.get(0).unwrap();
|
||||||
assert!(init.success);
|
assert!(init.success);
|
||||||
assert_eq!(init.exit_code, 0);
|
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);
|
compose.down(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::complaince::suite::Suite;
|
use crate::complaince::suite::Suite;
|
||||||
|
use crate::docker::Log;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
pub struct ArchivableInitResult {
|
pub struct ArchivableInitResult {
|
||||||
|
@ -27,9 +28,10 @@ pub struct ArchivableTestResult {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
pub struct ArchivableContainer {
|
pub struct ArchivableContainer {
|
||||||
pub logs: String,
|
pub logs: Log,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
pub struct ArchivableTest {
|
pub struct ArchivableTest {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
@ -132,9 +132,14 @@ impl SuiteRunnerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn collect_results(mut self, ctx: &dyn MinAppContext) -> ArchivableSuiteResult {
|
async fn collect_results(mut self, ctx: &dyn MinAppContext) -> ArchivableSuiteResult {
|
||||||
|
const TIMEOUT: usize = 40;
|
||||||
|
|
||||||
let mut tests = Vec::with_capacity(self.tests.len());
|
let mut tests = Vec::with_capacity(self.tests.len());
|
||||||
for (_auth, mut r) in self.tests.drain() {
|
for (_auth, mut r) in self.tests.drain() {
|
||||||
let result = r.rx.recv().await.unwrap();
|
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);
|
let log = ctx.docker_().get_logs(&r.container_name);
|
||||||
ctx.docker_().rm_container(&r.container_name, true);
|
ctx.docker_().rm_container(&r.container_name, true);
|
||||||
let container = ArchivableContainer {
|
let container = ArchivableContainer {
|
||||||
|
@ -307,19 +312,36 @@ mod tests {
|
||||||
archivable_test.result.logs,
|
archivable_test.result.logs,
|
||||||
format!("{}{LOGS}", archivable_test.result.container.name)
|
format!("{}{LOGS}", archivable_test.result.container.name)
|
||||||
);
|
);
|
||||||
println!("{}", archivable_test.result.container.logs);
|
println!("{:?}", archivable_test.result.container.logs);
|
||||||
assert!(archivable_test.result.container.logs.contains("FTEST_AUTH"));
|
|
||||||
assert!(archivable_test.result.container.logs.contains("FTEST_HOST"));
|
|
||||||
assert!(archivable_test
|
assert!(archivable_test
|
||||||
.result
|
.result
|
||||||
.container
|
.container
|
||||||
.logs
|
.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"));
|
.contains("FTEST_TARGET_HOST"));
|
||||||
assert!(archivable_test.result.container.logs.contains("FTEST_USER"));
|
|
||||||
assert!(archivable_test
|
assert!(archivable_test
|
||||||
.result
|
.result
|
||||||
.container
|
.container
|
||||||
.logs
|
.logs
|
||||||
|
.stdout
|
||||||
|
.contains("FTEST_USER"));
|
||||||
|
assert!(archivable_test
|
||||||
|
.result
|
||||||
|
.container
|
||||||
|
.logs
|
||||||
|
.stdout
|
||||||
.contains(&format!("TEST_NAME={}", t.name)));
|
.contains(&format!("TEST_NAME={}", t.name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,11 @@
|
||||||
<h4>Logs</h4>
|
<h4>Logs</h4>
|
||||||
<code>{{ test.result.logs | linebreaksbr }}</code>
|
<code>{{ test.result.logs | linebreaksbr }}</code>
|
||||||
<h4>Container Logs: {{ test.result.container.name }}</h4>
|
<h4>Container Logs: {{ test.result.container.name }}</h4>
|
||||||
<code>{{ test.result.container.logs | linebreaksbr }}</code>
|
<h5>STDOUT</h5>
|
||||||
|
<code>{{ test.result.container.logs.stdout | linebreaksbr }}</code>
|
||||||
|
<h5>STDERR</h5>
|
||||||
|
<code>{{ test.result.container.logs.stderr | linebreaksbr }}</code>
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
{% endfor %} {% endfor %} {% if payload.results.init_containers %}
|
{% endfor %} {% endfor %} {% if payload.results.init_containers %}
|
||||||
|
|
||||||
|
@ -40,7 +44,10 @@
|
||||||
<h3 class="test__name">[FAILED] {{init.container.name}}</h3>
|
<h3 class="test__name">[FAILED] {{init.container.name}}</h3>
|
||||||
</summary>
|
</summary>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<code>{{ init.container.logs | linebreaksbr }}</code>
|
<h4>STDOUT</h4>
|
||||||
|
<code>{{ init.container.logs.stdout | linebreaksbr }}</code>
|
||||||
|
<h4>STDERR</h4>
|
||||||
|
<code>{{ init.container.logs.stderr | linebreaksbr }}</code>
|
||||||
</details>
|
</details>
|
||||||
{% endfor %} {% endif %}
|
{% endfor %} {% endif %}
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Add table
Reference in a new issue