diff --git a/ci-web/Cargo.lock b/ci-web/Cargo.lock
index 4bc9e4c0..87041f85 100644
--- a/ci-web/Cargo.lock
+++ b/ci-web/Cargo.lock
@@ -157,6 +157,7 @@ dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
+ "serde",
"wasm-bindgen",
"windows-targets",
]
@@ -174,14 +175,13 @@ dependencies = [
"die",
"file-lock",
"git2",
- "glob",
"libc",
"memoize",
- "multimap",
"querystring",
"regex",
"serde",
"serde_derive",
+ "serde_json",
"toml",
]
@@ -289,12 +289,6 @@ dependencies = [
"url",
]
-[[package]]
-name = "glob"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
-
[[package]]
name = "heck"
version = "0.4.1"
@@ -455,15 +449,6 @@ dependencies = [
"syn 1.0.109",
]
-[[package]]
-name = "multimap"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
-dependencies = [
- "serde",
-]
-
[[package]]
name = "num-traits"
version = "0.2.17"
@@ -562,6 +547,12 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+[[package]]
+name = "ryu"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
+
[[package]]
name = "serde"
version = "1.0.196"
@@ -582,6 +573,17 @@ dependencies = [
"syn 2.0.48",
]
+[[package]]
+name = "serde_json"
+version = "1.0.113"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
[[package]]
name = "strsim"
version = "0.10.0"
diff --git a/ci-web/Cargo.toml b/ci-web/Cargo.toml
index 3a28d1cb..85938249 100644
--- a/ci-web/Cargo.toml
+++ b/ci-web/Cargo.toml
@@ -11,7 +11,6 @@ build = "src/build.rs"
cgi = "0.6"
git2 = "0.16"
querystring = "1.1.0"
-multimap = "0.8.3"
die = "0.2.0"
libc = "0.2"
toml = "0.5.9"
@@ -19,12 +18,12 @@ serde = "1.0.145"
serde_derive = "1.0.145"
regex = "1"
memoize = "0.3.1"
-glob = "0.3.0"
clap = { version = "4.0.32", features = ["derive"] }
file-lock = "2.1.6"
capnp = "0.19.*"
anyhow = "1.0.71"
-chrono = "0.4.26"
+chrono = { version = "0.4.26", features = ["serde"] }
+serde_json = "1.0.113"
[build-dependencies]
capnpc = "0.19.*"
diff --git a/ci-web/src/bin/cgi.rs b/ci-web/src/bin/cgi.rs
index 31137ca4..e6b6bf0f 100644
--- a/ci-web/src/bin/cgi.rs
+++ b/ci-web/src/bin/cgi.rs
@@ -13,7 +13,7 @@ const STYLESHEET: &str = "bootstrap.min.css";
fn filter_results(r: TestResultsMap, tests_matching: &Regex) -> TestResultsMap {
r.iter()
.filter(|i| tests_matching.is_match(&i.0) )
- .map(|(k, v)| (k.clone(), *v))
+ .map(|(k, v)| (k.clone(), v.clone()))
.collect()
}
@@ -45,9 +45,9 @@ fn commit_get_results(ci: &Ci, commit: &git2::Commit) -> CommitResults {
let tests = commitdir_get_results_filtered(ci, &id);
CommitResults {
- id: id,
+ id,
message: commit.message().unwrap().to_string(),
- tests: tests,
+ tests,
}
}
@@ -254,6 +254,7 @@ fn ci_commit(ci: &Ci) -> cgi::Response {
writeln!(&mut out, "
", result.status.table_class()).unwrap();
writeln!(&mut out, " {} | ", name).unwrap();
writeln!(&mut out, " {} | ", result.status.to_str()).unwrap();
+ writeln!(&mut out, " {} | ", result.msg.unwrap_or("".to_string())).unwrap();
writeln!(&mut out, " {}s | ", result.duration).unwrap();
writeln!(&mut out, " log | ", &commit_id, name).unwrap();
writeln!(&mut out, " full log | ", &commit_id, name).unwrap();
diff --git a/ci-web/src/bin/gen-commit-summary.rs b/ci-web/src/bin/gen-commit-summary.rs
index 8ec43d1b..63e6ea67 100644
--- a/ci-web/src/bin/gen-commit-summary.rs
+++ b/ci-web/src/bin/gen-commit-summary.rs
@@ -18,5 +18,6 @@ fn main() {
}
let ktestrc = ktestrc.unwrap();
- commit_update_results_from_fs(&ktestrc, &args.commit);
+ let commit_dir = ktestrc.output_dir.join(&args.commit);
+ commit_update_results_from_fs(&commit_dir);
}
diff --git a/ci-web/src/lib.rs b/ci-web/src/lib.rs
index 83553288..877925da 100644
--- a/ci-web/src/lib.rs
+++ b/ci-web/src/lib.rs
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::fs::read_to_string;
use std::fs::File;
use std::io::prelude::*;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use serde_derive::Deserialize;
use toml;
use anyhow;
@@ -58,17 +58,19 @@ pub use testresult_capnp::test_result::Status as TestStatus;
impl TestStatus {
fn from_str(status: &str) -> TestStatus {
+ let status = status.to_lowercase();
+
if status.is_empty() {
TestStatus::Inprogress
- } else if status.contains("IN PROGRESS") {
+ } else if status.contains("in progress") {
TestStatus::Inprogress
- } else if status.contains("PASSED") {
+ } else if status.contains("passed") {
TestStatus::Passed
- } else if status.contains("FAILED") {
+ } else if status.contains("failed") {
TestStatus::Failed
- } else if status.contains("NOTRUN") {
+ } else if status.contains("notrun") {
TestStatus::Notrun
- } else if status.contains("NOT STARTED") {
+ } else if status.contains("not started") {
TestStatus::Notstarted
} else {
TestStatus::Unknown
@@ -98,35 +100,54 @@ impl TestStatus {
}
}
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug, Deserialize)]
+pub struct TestResultJson {
+ pub status: String,
+ pub msg: Option,
+ pub duration: u64,
+}
+
+#[derive(Clone, Debug)]
pub struct TestResult {
- pub status: TestStatus,
- pub starttime: DateTime,
- pub duration: u64,
+ pub status: TestStatus,
+ pub msg: Option,
+ pub starttime: DateTime,
+ pub duration: u64,
}
pub type TestResultsMap = BTreeMap;
-fn commitdir_get_results_fs(ktestrc: &Ktestrc, commit_id: &String) -> TestResultsMap {
+fn commitdir_get_results_fs(commit_dir: &Path) -> TestResultsMap {
fn read_test_result(testdir: &std::fs::DirEntry) -> Option {
let mut f = File::open(&testdir.path().join("status")).ok()?;
- let mut status = String::new();
- f.read_to_string(&mut status).ok()?;
+ let mut status_str = String::new();
+ f.read_to_string(&mut status_str).ok()?;
+
+ let status_str = status_str.trim();
+
+ println!("status_str: {:?}", status_str);
+
+ let status_json: TestResultJson = serde_json::from_str(&status_str).ok()?;
+
+ println!("status_json: {:?}", status_json);
Some(TestResult {
- status: TestStatus::from_str(&status),
- starttime: f.metadata().ok()?.modified().ok()?.into(),
- duration: read_to_string(&testdir.path().join("duration")).unwrap_or("0".to_string()).parse().unwrap_or(0),
+ status: TestStatus::from_str(&status_json.status),
+ msg: status_json.msg,
+ starttime: f.metadata().ok()?.modified().ok()?.into(),
+ duration: status_json.duration,
})
}
let mut results = BTreeMap::new();
- let results_dir = ktestrc.output_dir.join(commit_id).read_dir();
+ let results_dir = commit_dir.read_dir();
if let Ok(results_dir) = results_dir {
for d in results_dir.filter_map(|i| i.ok()) {
- if let Some(r) = read_test_result(&d) {
+ let r = read_test_result(&d);
+ println!("{:?}", r);
+ if let Some(r) = r {
results.insert(d.file_name().into_string().unwrap(), r);
}
}
@@ -138,7 +159,7 @@ fn commitdir_get_results_fs(ktestrc: &Ktestrc, commit_id: &String) -> TestResult
use testresult_capnp::test_results;
use capnp::serialize;
-fn results_to_capnp(ktestrc: &Ktestrc, commit_id: &String, results_in: &TestResultsMap) -> anyhow::Result<()> {
+fn results_to_capnp(commit_dir: &Path, results_in: &TestResultsMap) -> anyhow::Result<()> {
let mut message = capnp::message::Builder::new_default();
let results = message.init_root::();
let mut result_list = results.init_entries(results_in.len().try_into().unwrap());
@@ -151,8 +172,8 @@ fn results_to_capnp(ktestrc: &Ktestrc, commit_id: &String, results_in: &TestResu
result.set_status(result_in.status);
}
- let fname = ktestrc.output_dir.join(commit_id.clone() + ".capnp");
- let fname_new = ktestrc.output_dir.join(commit_id.clone() + ".capnp.new");
+ let fname = commit_dir.with_extension("capnp");
+ let fname_new = commit_dir.with_extension("capnp.new");
let mut out = File::create(&fname_new)?;
@@ -163,10 +184,10 @@ fn results_to_capnp(ktestrc: &Ktestrc, commit_id: &String, results_in: &TestResu
Ok(())
}
-pub fn commit_update_results_from_fs(ktestrc: &Ktestrc, commit_id: &String) {
- let results = commitdir_get_results_fs(&ktestrc, commit_id);
+pub fn commit_update_results_from_fs(commit_dir: &Path) {
+ let results = commitdir_get_results_fs(commit_dir);
- results_to_capnp(ktestrc, commit_id, &results)
+ results_to_capnp(commit_dir, &results)
.map_err(|e| eprintln!("error generating capnp: {}", e)).ok();
}
@@ -180,9 +201,10 @@ pub fn commitdir_get_results(ktestrc: &Ktestrc, commit_id: &String) -> anyhow::R
let mut results = BTreeMap::new();
for e in entries {
let r = TestResult {
- status: e.get_status()?,
- starttime: Utc.timestamp_opt(e.get_starttime(), 0).unwrap(),
- duration: e.get_duration()
+ status: e.get_status()?,
+ msg: e.get_msg()?.to_string().ok(),
+ starttime: Utc.timestamp_opt(e.get_starttime(), 0).unwrap(),
+ duration: e.get_duration()
};
results.insert(e.get_name()?.to_string()?, r);
diff --git a/ci-web/src/testresult.capnp b/ci-web/src/testresult.capnp
index 56999548..7bc49b77 100644
--- a/ci-web/src/testresult.capnp
+++ b/ci-web/src/testresult.capnp
@@ -13,6 +13,7 @@ struct TestResult {
notstarted @4;
unknown @5;
}
+ msg @4: Text;
}
struct TestResults {
diff --git a/lib/supervisor.c b/lib/supervisor.c
index f1d95cc4..f357cf07 100644
--- a/lib/supervisor.c
+++ b/lib/supervisor.c
@@ -149,11 +149,9 @@ static char *test_is_starting(const char *line)
return ret;
}
-static bool test_is_ending(char *line)
+static const char *test_is_ending(const char *line)
{
- return str_starts_with(line, "========= PASSED ") ||
- str_starts_with(line, "========= FAILED ") ||
- str_starts_with(line, "========= NOTRUN");
+ return str_starts_with(line, "========= FINISH ");
}
static FILE *popen_with_pid(char *argv[], pid_t *child)
@@ -224,13 +222,10 @@ static void test_start(char *new_test, struct timespec now)
set_timeout(default_timeout);
}
-static void test_end(struct timespec now)
+static void test_end(void)
{
- write_test_file("duration", "%li", now.tv_sec - current_test_start.tv_sec);
-
fclose(current_test_log);
current_test_log = NULL;
-
set_timeout(default_timeout);
}
@@ -327,19 +322,17 @@ int main(int argc, char *argv[])
set_timeout(default_timeout);
again:
while ((len = getline(&line, &n, childf)) >= 0) {
- struct timespec now = xclock_gettime(CLOCK_MONOTONIC);
-
strim(line);
- char *output = mprintf("%.5lu %s\n", now.tv_sec - start.tv_sec, line);
-
read_watchdog(line);
- char *new_test = test_is_starting(line);
+ struct timespec now = xclock_gettime(CLOCK_MONOTONIC);
+ char *output = mprintf("%.5lu %s\n", now.tv_sec - start.tv_sec, line);
/* If a test is starting, close logfile for previous test: */
+ char *new_test = test_is_starting(line);
if (current_test_log && new_test)
- test_end(now);
+ test_end();
if (new_test)
test_start(new_test, now);
@@ -349,9 +342,11 @@ int main(int argc, char *argv[])
fputs(output, logfile);
fputs(output, stdout);
- if (current_test_log && test_is_ending(line)) {
- write_test_file("status", "%s\n", line);
- test_end(now);
+ const char *statusline;
+ if (current_test_log &&
+ (statusline = test_is_ending(line))) {
+ write_test_file("status", "%s\n", statusline);
+ test_end();
}
if (exit_on_failure && str_starts_with(line, "TEST FAILED"))
diff --git a/tests/prelude.sh b/tests/prelude.sh
index 46ff822b..598b2048 100644
--- a/tests/prelude.sh
+++ b/tests/prelude.sh
@@ -237,6 +237,8 @@ run_tests()
local start=$(date '+%s')
local ret=0
+
+ rm -f /tmp/ktest-test-msg
(set -e; run_test $i)
ret=$?
local finish=$(date '+%s')
@@ -249,12 +251,20 @@ run_tests()
echo
if [[ $ret = 0 ]]; then
- echo "========= PASSED $i in $(($finish - $start))s"
+ local status=passed
tests_passed+=($i)
else
- echo "========= FAILED $i in $(($finish - $start))s"
+ local status=failed
tests_failed+=($i)
+ fi
+
+ if [[ ! -f /tmp/ktest-test-msg ]]; then
+ echo "========= FINISH { \"status\": \"$status\", \"duration\": $(($finish - $start)) }"
+ else
+ echo "========= FINISH { \"status\": \"$status\", \"duration\": $(($finish - $start)), \"statusline\": \"$(cat /tmp/ktest-test-msg)\" }"
+ fi
+ if [[ $ret != 0 ]]; then
# Try to clean up after a failed test so we can run the rest of
# the tests - unless failfast is enabled, or there was only one
# test to run: