Commit

Author:

Hash:

Timestamp:

+65 -0 +/-1 browse

Kevin Schoon [me@kevinschoon.com]

8ba3b225aaaed1c920ac47ede3084aa69464e91d

Sun, 23 Aug 2026 17:11:01 +0000 (4 weeks ago)

add executor test for failed workflows
1diff --git a/ayllu-build/src/executor.rs b/ayllu-build/src/executor.rs
2index 2dcaf85..cce9ba9 100644
3--- a/ayllu-build/src/executor.rs
4+++ b/ayllu-build/src/executor.rs
5 @@ -253,6 +253,8 @@ impl Executor {
6 mod test {
7 use std::{cell::RefCell, collections::HashMap, time::Duration};
8
9+ use ayllu_database::build::State;
10+
11 use crate::{
12 config::Image,
13 error::Error,
14 @@ -282,6 +284,7 @@ mod test {
15 #[derive(Default)]
16 pub struct FakeRuntime {
17 actions: RefCell<Vec<Action>>,
18+ execution_failures: HashMap<i32, ()>,
19 }
20
21 impl Runtime for FakeRuntime {
22 @@ -312,6 +315,9 @@ mod test {
23 self.actions
24 .borrow_mut()
25 .push(Action::Step(manifest_id, workflow_id, step_id));
26+ if self.execution_failures.contains_key(&step_id) {
27+ return Ok((1, Duration::from_secs(1)));
28+ }
29 Ok((0, Duration::from_secs(1)))
30 }
31
32 @@ -395,11 +401,70 @@ mod test {
33 let mut db = ayllu_database::Wrapper::new_ro(&test_db_file).unwrap();
34 let mut ptr = db.call();
35 let build_result = ptr.manifest_summary(1).unwrap();
36+ assert!(build_result.manifest.state == State::Passed);
37 build_result.workflows.iter().for_each(|wf| {
38 println!("{} {}", wf.workflow.id, wf.workflow.name);
39+ assert!(wf.workflow.state == State::Passed);
40 wf.steps.iter().for_each(|step| {
41 println!("{} {}", step.step.id, step.step.name);
42+ assert!(step.step.state == State::Passed);
43 })
44 });
45 }
46+
47+ #[test]
48+ fn execute_build_failure() {
49+ let tmp_file = tempfile::tempdir().unwrap();
50+ let work_dir = tmp_file.path().join("cache");
51+ let test_db_file = tmp_file.path().join("test.sqlite");
52+ let manifest_source_file = tmp_file.path().join("manifest.json");
53+ std::fs::write(&manifest_source_file, TEST_MANIFEST).unwrap();
54+ ayllu_database::migrate(&test_db_file).unwrap();
55+ let source = Source::Path {
56+ path: Some(manifest_source_file),
57+ };
58+ let executor = ExecutorBuilder::default()
59+ .config(crate::config::Config {
60+ database: ayllu_config::Database {
61+ path: test_db_file.to_path_buf(),
62+ ..Default::default()
63+ },
64+ build: crate::config::Build {
65+ work_dir,
66+ images: HashMap::from_iter(vec![("noop".to_string(), Image::default())]),
67+ ..Default::default()
68+ },
69+ ..Default::default()
70+ })
71+ .debug(false)
72+ .build()
73+ .unwrap();
74+
75+ let mut rt = FakeRuntime {
76+ execution_failures: HashMap::from_iter(vec![(2, ())]),
77+ ..Default::default()
78+ };
79+
80+ executor.evaluate(&source, &mut rt).unwrap();
81+ let actions = rt.actions.take();
82+ // NOTE that workflows are reversed when loaded into the graph so their
83+ // IDs are backwards.
84+ assert!(actions.eq(&vec![
85+ Action::Workflow(1, 1),
86+ Action::Step(1, 1, 1),
87+ Action::Workflow(1, 2),
88+ Action::Step(1, 2, 2)
89+ ]));
90+ let mut db = ayllu_database::Wrapper::new_ro(&test_db_file).unwrap();
91+ let mut ptr = db.call();
92+ let build_result = ptr.manifest_summary(1).unwrap();
93+ assert!(build_result.manifest.state == State::Failed);
94+ let mut results = build_result.workflows.iter();
95+ let set_1 = results.next().unwrap();
96+ assert!(set_1.workflow.state == State::Passed);
97+ assert!(set_1.steps.first().unwrap().step.state == State::Passed);
98+ let set_2 = results.next().unwrap();
99+ assert!(set_2.workflow.state == State::Failed);
100+ assert!(set_2.steps.first().unwrap().step.state == State::Failed);
101+ }
102 }