use std::error::Error;
use strum::*;
#[derive(
Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Display, EnumString, EnumIter,
)]
pub enum YoctoFailureKind {
#[strum(serialize = "do_build")]
DoBuild,
#[strum(serialize = "do_compile")]
DoCompile,
#[strum(serialize = "do_compile_ptest_base")]
DoCompilePtestBase,
#[strum(serialize = "do_configure")]
DoConfigure,
#[strum(serialize = "do_configure_ptest_base")]
DoConfigurePtestBase,
#[strum(serialize = "do_deploy")]
DoDeploy,
#[strum(serialize = "do_fetch")]
DoFetch,
#[default]
#[strum(serialize = "misc")]
Misc,
}
impl YoctoFailureKind {
pub fn parse_from_logfilename(fname: &str) -> Result<Self, Box<dyn Error>> {
for variant in YoctoFailureKind::iter() {
let variant_as_str = variant.to_string();
if fname.contains(&variant_as_str) {
return Ok(variant);
}
}
Err(format!("Could not determine task from input: {fname}").into())
}
}
pub fn yocto_error_summary(log: &str) -> Result<String, Box<dyn Error>> {
const YOCTO_ERROR_SUMMARY_SIGNATURE: &str = "--- Error summary ---";
let error_summary = log
.split(YOCTO_ERROR_SUMMARY_SIGNATURE)
.collect::<Vec<&str>>()
.pop()
.ok_or("No error summary found")?;
Ok(error_summary.trim().to_string())
}
pub fn trim_trailing_just_recipes(log: &str) -> Result<String, Box<dyn Error>> {
let trimmed = log
.lines()
.rev()
.skip_while(|line| line.starts_with("error: Recipe"))
.collect::<Vec<&str>>()
.iter()
.rev()
.fold(String::with_capacity(log.len()), |acc, line| {
acc + line + "\n"
});
Ok(trimmed)
}
pub fn find_yocto_failure_log_str(log: &str) -> Result<&str, Box<dyn Error>> {
let log_file_line = log
.lines()
.find(|line| line.contains("Logfile of failure stored in"))
.ok_or("No log file line found")?;
Ok(log_file_line)
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
use std::str::FromStr;
const ERROR_SUMMARY_TEST_STR: &str = r#"ERROR: sqlite3-native-3_3.43.2-r0 do_fetch: Bitbake Fetcher Error: MalformedUrl('${SOURCE_MIRROR_URL}')
ERROR: Logfile of failure stored in: /app/yocto/build/tmp/work/x86_64-linux/sqlite3-native/3.43.2/temp/log.do_fetch.21616
ERROR: Task (virtual:native:/app/yocto/build/../poky/meta/recipes-support/sqlite/sqlite3_3.43.2.bb:do_fetch) failed with exit code '1'
2024-02-11 00:09:04 - ERROR - Command "/app/yocto/poky/bitbake/bin/bitbake -c build test-template-ci-xilinx-image package-index" failed with error 1"#;
#[test]
fn test_determine_yocto_error_kind() {
let task = "do_build";
assert_eq!(
YoctoFailureKind::from_str(task).unwrap(),
YoctoFailureKind::DoBuild
);
}
#[test]
fn test_yocto_error_from_error_message() {
let log_file_line = ERROR_SUMMARY_TEST_STR
.lines()
.find(|line| line.contains("Logfile of failure stored in"))
.ok_or("No log file line found")
.unwrap();
dbg!(log_file_line);
let logfile_path = log_file_line
.split("Logfile of failure stored in: ")
.collect::<Vec<&str>>()
.pop()
.ok_or("No log file found");
let path = std::path::PathBuf::from(logfile_path.unwrap());
let fname = path.file_stem().unwrap().to_str().unwrap();
let yocto_failure = YoctoFailureKind::parse_from_logfilename(fname).unwrap();
assert_eq!(yocto_failure, YoctoFailureKind::DoFetch);
}
}