diff --git a/Cargo.toml b/Cargo.toml index 5f52ca4..676e9a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ doc = true [dependencies] chrono = { version = "=0.4.35", features = ["serde"] } clap = { version = "=4.2.4", features = ["derive"] } +derive_builder = "0.20.0" lazy_static = "1.4.0" log = "0.4.17" regex = "1.9.1" diff --git a/crates/test_base/src/lib.rs b/crates/test_base/src/lib.rs index 67726ef..e1af77c 100644 --- a/crates/test_base/src/lib.rs +++ b/crates/test_base/src/lib.rs @@ -5,12 +5,17 @@ use std::path::PathBuf; use simple_logger::SimpleLogger; use test_context::TestContext; +#[derive(Debug, Clone)] pub struct BaseTestContext { /// 项目的根目录 project_base_path: PathBuf, } impl BaseTestContext { + const CONFIG_V1_DIR: &'static str = "tests/data/dadk_config_v1"; + const FAKE_DRAGONOS_SYSROOT: &'static str = "tests/data/fake_dragonos_sysroot"; + const FAKE_DADK_CACHE_ROOT: &'static str = "tests/data/fake_dadk_cache_root"; + /// 获取项目的根目录 pub fn project_base_path(&self) -> &PathBuf { &self.project_base_path @@ -23,7 +28,34 @@ impl BaseTestContext { /// 获取`xxx.dadk`配置文件的目录 pub fn config_v1_dir(&self) -> PathBuf { - self.abs_path("tests/data/dadk_config_v1") + self.abs_path(Self::CONFIG_V1_DIR) + } + + fn ensure_fake_dragonos_dir_exist(&self) { + let fake_dragonos_dir = self.fake_dragonos_sysroot(); + if !fake_dragonos_dir.exists() { + std::fs::create_dir_all(&fake_dragonos_dir).ok(); + } + } + + fn ensure_fake_dadk_cache_root_exist(&self) { + std::env::set_var( + "DADK_CACHE_ROOT", + self.fake_dadk_cache_root().to_str().unwrap(), + ); + let fake_dadk_cache_root = self.fake_dadk_cache_root(); + if !fake_dadk_cache_root.exists() { + std::fs::create_dir_all(&fake_dadk_cache_root).ok(); + } + } + + pub fn fake_dadk_cache_root(&self) -> PathBuf { + self.abs_path(Self::FAKE_DADK_CACHE_ROOT) + } + + /// 获取假的DragonOS sysroot目录 + pub fn fake_dragonos_sysroot(&self) -> PathBuf { + self.abs_path(Self::FAKE_DRAGONOS_SYSROOT) } } @@ -31,11 +63,14 @@ impl TestContext for BaseTestContext { fn setup() -> Self { let logger = SimpleLogger::new().with_level(log::LevelFilter::Debug); - logger.init().unwrap(); + logger.init().ok(); // 获取DADK项目的根目录 let mut project_base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); project_base_path.pop(); project_base_path.pop(); - BaseTestContext { project_base_path } + let r = BaseTestContext { project_base_path }; + r.ensure_fake_dragonos_dir_exist(); + r.ensure_fake_dadk_cache_root_exist(); + r } } diff --git a/src/console/clean.rs b/src/console/clean.rs index e44bbec..0ef9f15 100644 --- a/src/console/clean.rs +++ b/src/console/clean.rs @@ -3,7 +3,7 @@ use std::{fmt::Display, str::FromStr}; use clap::{Args, Subcommand}; /// 清理缓存的级别 -#[derive(Debug, Args, Clone, Copy)] +#[derive(Debug, Args, Clone, Copy, PartialEq, Eq)] pub struct CleanArg { #[arg(default_value = "src")] /// 清理缓存的级别 @@ -18,7 +18,7 @@ pub struct CleanArg { pub level: CleanLevel, } -#[derive(Debug, Subcommand, Clone, Copy)] +#[derive(Debug, Subcommand, Clone, Copy, PartialEq, Eq)] pub enum CleanLevel { /// 清理所有缓存 All, diff --git a/src/console/mod.rs b/src/console/mod.rs index c06959f..e7d8994 100644 --- a/src/console/mod.rs +++ b/src/console/mod.rs @@ -59,7 +59,7 @@ fn parse_check_dir_exists(path: &str) -> Result { } /// @brief 要执行的操作 -#[derive(Debug, Subcommand, Clone, Copy)] +#[derive(Debug, Subcommand, Clone, Copy, PartialEq, Eq)] pub enum Action { /// 构建所有项目 Build, diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 0000000..4246dfa --- /dev/null +++ b/src/context.rs @@ -0,0 +1,141 @@ +use std::{path::PathBuf, process::exit}; + +use derive_builder::Builder; +use log::error; +#[cfg(test)] +use test_base::{test_context::TestContext, BaseTestContext}; + +use crate::{console::Action, executor::cache::cache_root_init, scheduler::task_deque::TASK_DEQUE}; + +#[derive(Debug, Builder)] +#[builder(setter(into))] +pub struct DadkExecuteContext { + /// DragonOS sysroot在主机上的路径 + sysroot_dir: Option, + /// DADK任务配置文件所在目录 + config_dir: Option, + /// 要执行的操作 + action: Action, + /// 并行线程数量 + thread_num: Option, + /// dadk缓存根目录 + cache_dir: Option, + + #[cfg(test)] + base_test_context: Option, +} + +impl DadkExecuteContext { + pub fn init(&self) { + // 初始化缓存目录 + let r: Result<(), crate::executor::ExecutorError> = + cache_root_init(self.cache_dir().cloned()); + if r.is_err() { + error!("Failed to init cache root: {:?}", r.unwrap_err()); + exit(1); + } + + if let Some(thread) = self.thread_num() { + TASK_DEQUE.lock().unwrap().set_thread(thread); + } + + if self.action() == &Action::New { + return; + } + + if self.config_dir().is_none() { + error!("Config dir is required for action: {:?}", self.action()); + exit(1); + } + + if self.sysroot_dir().is_none() { + error!( + "dragonos sysroot dir is required for action: {:?}", + self.action() + ); + exit(1); + } + } + pub fn sysroot_dir(&self) -> Option<&PathBuf> { + self.sysroot_dir.as_ref() + } + + pub fn config_dir(&self) -> Option<&PathBuf> { + self.config_dir.as_ref() + } + + pub fn action(&self) -> &Action { + &self.action + } + + pub fn thread_num(&self) -> Option { + self.thread_num + } + + pub fn cache_dir(&self) -> Option<&PathBuf> { + self.cache_dir.as_ref() + } +} + +#[cfg(test)] +pub trait TestContextExt: TestContext { + fn base_context(&self) -> &BaseTestContext; + + fn execute_context(&self) -> &DadkExecuteContext; +} + +#[cfg(test)] +pub struct DadkExecuteContextTestBuildV1 { + context: DadkExecuteContext, +} + +#[cfg(test)] +impl TestContext for DadkExecuteContextTestBuildV1 { + fn setup() -> Self { + let base_context = BaseTestContext::setup(); + let context = DadkExecuteContextBuilder::default() + .sysroot_dir(Some(base_context.fake_dragonos_sysroot())) + .config_dir(Some(base_context.config_v1_dir())) + .action(Action::Build) + .thread_num(None) + .cache_dir(Some(base_context.fake_dadk_cache_root())) + .base_test_context(Some(base_context)) + .build() + .expect("Failed to build DadkExecuteContextTestBuildV1"); + context.init(); + DadkExecuteContextTestBuildV1 { context } + } +} + +#[cfg(test)] +impl TestContextExt for DadkExecuteContextTestBuildV1 { + fn base_context(&self) -> &BaseTestContext { + self.base_test_context.as_ref().unwrap() + } + + fn execute_context(&self) -> &DadkExecuteContext { + &self.context + } +} + +macro_rules! impl_deref_for_test_context { + ($context:ty) => { + #[cfg(test)] + impl std::ops::Deref for $context { + type Target = DadkExecuteContext; + + fn deref(&self) -> &Self::Target { + &self.context + } + } + + #[cfg(test)] + impl std::ops::DerefMut for $context { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.context + } + } + }; +} + +impl_deref_for_test_context!(DadkExecuteContextTestBuildV1); diff --git a/src/executor/cache.rs b/src/executor/cache.rs index 7889536..bbae690 100644 --- a/src/executor/cache.rs +++ b/src/executor/cache.rs @@ -1,4 +1,7 @@ -use std::{path::PathBuf, sync::Arc}; +use std::{ + path::PathBuf, + sync::{Arc, Once}, +}; use log::info; @@ -30,14 +33,17 @@ pub fn cache_root_init(path: Option) -> Result<(), ExecutorError> { } else { // 如果没有设置环境变量,则使用默认值 // 默认值为当前目录下的.cache目录 - let cwd = std::env::current_dir().map_err(|e| ExecutorError::IoError(e))?; + let cwd = std::env::current_dir().map_err(|e| ExecutorError::IoError(e.to_string()))?; let cwd = cwd.to_str(); if cwd.is_none() { - return Err(ExecutorError::IoError(std::io::Error::new( - std::io::ErrorKind::Other, - "Current dir is not a valid unicode string", - ))); + return Err(ExecutorError::IoError( + std::io::Error::new( + std::io::ErrorKind::Other, + "Current dir is not a valid unicode string", + ) + .to_string(), + )); } let cwd = cwd.unwrap(); @@ -46,12 +52,13 @@ pub fn cache_root_init(path: Option) -> Result<(), ExecutorError> { } else { // 如果有设置缓存根目录,则使用设置的值 let path = path.unwrap(); - let x = path - .to_str() - .ok_or(ExecutorError::IoError(std::io::Error::new( + let x = path.to_str().ok_or(ExecutorError::IoError( + std::io::Error::new( std::io::ErrorKind::Other, "Cache root dir is not a valid unicode string", - )))?; + ) + .to_string(), + ))?; cache_root = x.to_string(); } @@ -60,17 +67,21 @@ pub fn cache_root_init(path: Option) -> Result<(), ExecutorError> { // 如果缓存根目录不存在,则创建 if !cache_root.exists() { info!("Cache root dir not exists, create it: {:?}", cache_root); - std::fs::create_dir_all(&cache_root).map_err(|e| ExecutorError::IoError(e))?; + std::fs::create_dir_all(&cache_root).map_err(|e| ExecutorError::IoError(e.to_string()))?; } else if !cache_root.is_dir() { // 如果缓存根目录不是目录,则报错 - return Err(ExecutorError::IoError(std::io::Error::new( - std::io::ErrorKind::NotADirectory, - format!("Cache root dir is not a directory: {:?}", cache_root), - ))); + return Err(ExecutorError::IoError( + std::io::Error::new( + std::io::ErrorKind::NotADirectory, + format!("Cache root dir is not a directory: {:?}", cache_root), + ) + .to_string(), + )); } // 初始化缓存根目录 - CACHE_ROOT.init(cache_root); + static CACHE_ROOT_INIT_ONCE: Once = Once::new(); + CACHE_ROOT_INIT_ONCE.call_once(|| CACHE_ROOT.init(cache_root)); // 设置环境变量 std::env::set_var("DADK_CACHE_ROOT", CACHE_ROOT.get().to_str().unwrap()); @@ -186,14 +197,18 @@ impl CacheDir { pub fn create(&self) -> Result<(), ExecutorError> { if !self.path.exists() { info!("Cache dir not exists, create it: {:?}", self.path); - std::fs::create_dir_all(&self.path).map_err(|e| ExecutorError::IoError(e))?; + std::fs::create_dir_all(&self.path) + .map_err(|e| ExecutorError::IoError(e.to_string()))?; info!("Cache dir: [{:?}] created.", self.path); } else if !self.path.is_dir() { // 如果路径类别不是目录,则报错 - return Err(ExecutorError::IoError(std::io::Error::new( - std::io::ErrorKind::NotADirectory, - format!("Cache dir is not a directory: {:?}", self.path), - ))); + return Err(ExecutorError::IoError( + std::io::Error::new( + std::io::ErrorKind::NotADirectory, + format!("Cache dir is not a directory: {:?}", self.path), + ) + .to_string(), + )); } return Ok(()); @@ -204,7 +219,7 @@ impl CacheDir { let x = self .path .read_dir() - .map_err(|e| ExecutorError::IoError(e))?; + .map_err(|e| ExecutorError::IoError(e.to_string()))?; for _ in x { return Ok(false); } @@ -219,7 +234,7 @@ impl CacheDir { pub fn remove_self_recursive(&self) -> Result<(), ExecutorError> { let path = &self.path; if path.exists() { - std::fs::remove_dir_all(path).map_err(|e| ExecutorError::IoError(e))?; + std::fs::remove_dir_all(path).map_err(|e| ExecutorError::IoError(e.to_string()))?; } return Ok(()); } @@ -253,7 +268,7 @@ impl TaskDataDir { pub fn save_task_log(&self, task_log: &TaskLog) -> Result<(), ExecutorError> { let path = self.dir.path.join(Self::TASK_LOG_FILE_NAME); let content = toml::to_string(task_log).unwrap(); - std::fs::write(&path, content).map_err(|e| ExecutorError::IoError(e))?; + std::fs::write(&path, content).map_err(|e| ExecutorError::IoError(e.to_string()))?; return Ok(()); } } diff --git a/src/executor/mod.rs b/src/executor/mod.rs index e0200fe..e8e792c 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -99,9 +99,9 @@ impl Executor { info!("Execute task: {}", self.entity.task().name_version()); let r = self.do_execute(); - self.save_task_data(r); + self.save_task_data(r.clone()); info!("Task {} finished", self.entity.task().name_version()); - return Ok(()); + return r; } /// # 保存任务数据 @@ -479,10 +479,13 @@ impl Executor { let mut child = command .stdin(Stdio::inherit()) .spawn() - .map_err(|e| ExecutorError::IoError(e))?; + .map_err(|e| ExecutorError::IoError(e.to_string()))?; // 等待子进程结束 - let r = child.wait().map_err(|e| ExecutorError::IoError(e)); + let r = child + .wait() + .map_err(|e| ExecutorError::IoError(e.to_string())); + debug!("Command finished: {:?}", r); if r.is_ok() { let r = r.unwrap(); if r.success() { @@ -594,11 +597,11 @@ impl EnvVar { /// # 任务执行器错误枚举 #[allow(dead_code)] -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ExecutorError { /// 准备执行环境错误 PrepareEnvError(String), - IoError(std::io::Error), + IoError(String), /// 构建执行错误 TaskFailed(String), /// 安装错误 @@ -646,3 +649,90 @@ pub fn prepare_env(sched_entities: &SchedEntities) -> Result<(), ExecutorError> return Ok(()); } + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use test_base::test_context::{self as test_context, test_context}; + + use crate::{ + context::{DadkExecuteContextTestBuildV1, TestContextExt}, + executor::Executor, + parser::Parser, + scheduler::Scheduler, + }; + + fn setup_executor(config_file: PathBuf, ctx: &T) -> Executor { + let task = Parser::new(ctx.base_context().config_v1_dir()).parse_config_file(&config_file); + assert!(task.is_ok(), "parse error: {:?}", task); + let scheduler = Scheduler::new( + ctx.base_context().fake_dragonos_sysroot(), + *ctx.execute_context().action(), + vec![], + ); + + assert!(scheduler.is_ok(), "Create scheduler error: {:?}", scheduler); + + let mut scheduler = scheduler.unwrap(); + + let entity = scheduler.add_task(config_file, task.unwrap()); + + assert!(entity.is_ok(), "Add task error: {:?}", entity); + let entity = entity.unwrap(); + let executor = Executor::new( + entity.clone(), + *ctx.execute_context().action(), + ctx.base_context().fake_dragonos_sysroot(), + ); + + assert!(executor.is_ok(), "Create executor error: {:?}", executor); + + let executor = executor.unwrap(); + return executor; + } + + /// 测试能否正确设置本地环境变量 + #[test_context(DadkExecuteContextTestBuildV1)] + #[test] + fn set_local_env(ctx: &DadkExecuteContextTestBuildV1) { + let config_file_path = ctx + .base_context() + .config_v1_dir() + .join("app_normal_with_env_0_1_0.dadk"); + let mut executor = setup_executor(config_file_path, ctx); + + let r = executor.prepare_local_env(); + assert!(r.is_ok(), "Prepare local env error: {:?}", r); + assert_ne!(executor.local_envs.envs.len(), 0); + + assert!(executor.local_envs.get("DADK_CURRENT_BUILD_DIR").is_some()); + assert!(executor.local_envs.get("CC").is_some()); + assert_eq!(executor.local_envs.get("CC").unwrap().value, "abc-gcc"); + + let x = executor.execute(); + assert!(x.is_ok(), "Execute error: {:?}", x); + } + + /// 测试执行错误时,能否感知到错误 + #[test_context(DadkExecuteContextTestBuildV1)] + #[test] + fn execute_should_capture_error(ctx: &DadkExecuteContextTestBuildV1) { + let config_file_path = ctx + .base_context() + .config_v1_dir() + .join("app_normal_with_env_fail_0_1_0.dadk"); + let mut executor = setup_executor(config_file_path, ctx); + + let r = executor.prepare_local_env(); + assert!(r.is_ok(), "Prepare local env error: {:?}", r); + assert_ne!(executor.local_envs.envs.len(), 0); + + assert!(executor.local_envs.get("DADK_CURRENT_BUILD_DIR").is_some()); + assert!(executor.local_envs.get("CC").is_some()); + assert_eq!(executor.local_envs.get("CC").unwrap().value, "abc-gcc1"); + + let x = executor.execute(); + assert!(x.is_err(), "Executor cannot catch error when build error"); + } +} diff --git a/src/lib.rs b/src/lib.rs index 6039f2c..0cf87aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,11 +103,12 @@ use simple_logger::SimpleLogger; use crate::{ console::{interactive::InteractiveConsole, CommandLineArgs}, - executor::cache::cache_root_init, - scheduler::{task_deque::TASK_DEQUE, Scheduler}, + context::DadkExecuteContextBuilder, + scheduler::Scheduler, }; mod console; +mod context; mod executor; pub mod parser; mod scheduler; @@ -121,34 +122,45 @@ pub fn dadk_main() { let args = CommandLineArgs::parse(); info!("DADK run with args: {:?}", &args); + + let context = DadkExecuteContextBuilder::default() + .sysroot_dir(args.dragonos_dir) + .config_dir(args.config_dir) + .action(args.action) + .thread_num(args.thread) + .cache_dir(args.cache_dir) + .build() + .expect("Failed to build execute context"); + + context.init(); // DragonOS sysroot在主机上的路径 - let dragonos_dir = args.dragonos_dir.clone(); - let config_dir = args.config_dir.clone(); - let action = args.action; - let thread = args.thread; + info!( "DragonOS sysroot dir: {}", - dragonos_dir - .as_ref() + context + .sysroot_dir() .map_or_else(|| "None".to_string(), |d| d.display().to_string()) ); info!( "Config dir: {}", - config_dir - .as_ref() + context + .config_dir() .map_or_else(|| "None".to_string(), |d| d.display().to_string()) ); - info!("Action: {:?}", action); + info!("Action: {:?}", context.action()); info!( "Thread num: {}", - thread - .as_ref() - .map_or_else(|| "None".to_string(), |d| d.to_string()) + context.thread_num().map_or_else(|| 0, |t| t) ); - match action { + match context.action() { console::Action::New => { - let r = InteractiveConsole::new(dragonos_dir.clone(), config_dir.clone(), action).run(); + let r = InteractiveConsole::new( + context.sysroot_dir().cloned(), + context.config_dir().cloned(), + *context.action(), + ) + .run(); if r.is_err() { error!("Failed to run interactive console: {:?}", r.unwrap_err()); exit(1); @@ -158,28 +170,7 @@ pub fn dadk_main() { _ => {} } - if let Some(thread) = thread { - TASK_DEQUE.lock().unwrap().set_thread(thread); - } - - // 初始化缓存目录 - let r = cache_root_init(args.cache_dir); - if r.is_err() { - error!("Failed to init cache root: {:?}", r.unwrap_err()); - exit(1); - } - - let config_dir = args.config_dir.unwrap_or_else(|| { - error!("Config dir not specified"); - exit(1); - }); - - let dragonos_dir = args.dragonos_dir.unwrap_or_else(|| { - error!("DragonOS sysroot dir not specified"); - exit(1); - }); - - let mut parser = parser::Parser::new(config_dir); + let mut parser = parser::Parser::new(context.config_dir().unwrap().clone()); let r = parser.parse(); if r.is_err() { exit(1); @@ -187,7 +178,11 @@ pub fn dadk_main() { let tasks: Vec<(PathBuf, DADKTask)> = r.unwrap(); // info!("Parsed tasks: {:?}", tasks); - let scheduler = Scheduler::new(dragonos_dir, action, tasks); + let scheduler = Scheduler::new( + context.sysroot_dir().cloned().unwrap(), + *context.action(), + tasks, + ); if scheduler.is_err() { exit(1); } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 9568f9f..3ace9e3 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -200,7 +200,7 @@ impl Parser { /// /// * `Ok(DADKTask)` - 生成好的任务 /// * `Err(ParserError)` - 解析错误 - fn parse_config_file(&self, config_file: &PathBuf) -> Result { + pub(super) fn parse_config_file(&self, config_file: &PathBuf) -> Result { let content = std::fs::read_to_string(config_file).map_err(|e| ParserError { config_file: Some(config_file.clone()), error: InnerParserError::IoError(e), diff --git a/src/scheduler/mod.rs b/src/scheduler/mod.rs index 9c10dcc..0d89abb 100644 --- a/src/scheduler/mod.rs +++ b/src/scheduler/mod.rs @@ -329,7 +329,11 @@ impl Scheduler { /// # 添加一个任务 /// /// 添加任务到调度器中,如果任务已经存在,则返回错误 - pub fn add_task(&mut self, path: PathBuf, task: DADKTask) -> Result<(), SchedulerError> { + pub fn add_task( + &mut self, + path: PathBuf, + task: DADKTask, + ) -> Result, SchedulerError> { let id: i32 = self.generate_task_id(); let indegree: usize = 0; let children = Vec::new(); @@ -362,7 +366,7 @@ impl Scheduler { self.target.add(entity.clone()); info!("Task added: {}", entity.task().name_version()); - return Ok(()); + return Ok(entity); } fn generate_task_id(&self) -> i32 { diff --git a/tests/data/.gitignore b/tests/data/.gitignore new file mode 100644 index 0000000..8672062 --- /dev/null +++ b/tests/data/.gitignore @@ -0,0 +1,2 @@ +fake_dragonos_sysroot +fake_dadk_cache_root diff --git a/tests/data/apps/app_normal_with_env/build.sh b/tests/data/apps/app_normal_with_env/build.sh new file mode 100644 index 0000000..1648495 --- /dev/null +++ b/tests/data/apps/app_normal_with_env/build.sh @@ -0,0 +1,9 @@ +echo "app_normal_with_env: build" +# 判断CC环境变量是否为'abc-gcc' +if [ "$CC" != "abc-gcc" ]; then + echo "CC is not abc-gcc" + exit 1 +else + echo "[OK]: CC is abc-gcc" +fi + diff --git a/tests/data/apps/app_normal_with_env_fail/build.sh b/tests/data/apps/app_normal_with_env_fail/build.sh new file mode 100644 index 0000000..93f574a --- /dev/null +++ b/tests/data/apps/app_normal_with_env_fail/build.sh @@ -0,0 +1,9 @@ +echo "app_normal_with_env_fail: build" +# 判断CC环境变量是否为'abc-gcc' +if [ "$CC" != "abc-gcc" ]; then + echo "CC is not abc-gcc" + exit 1 +else + echo "[OK]: CC is abc-gcc" +fi + diff --git a/tests/data/dadk_config_v1/app_normal_with_env_0_1_0.dadk b/tests/data/dadk_config_v1/app_normal_with_env_0_1_0.dadk new file mode 100644 index 0000000..33b3af1 --- /dev/null +++ b/tests/data/dadk_config_v1/app_normal_with_env_0_1_0.dadk @@ -0,0 +1,30 @@ +{ + "name": "app_normal_with_env", + "version": "0.1.0", + "description": "A normal app with env", + "rust_target": null, + "task_type": { + "BuildFromSource": { + "Local": { + "path": "tests/data/apps/app_normal_with_env" + } + } + }, + "depends": [], + "build": { + "build_command": "bash build.sh" + }, + "install": { + "in_dragonos_path": "/" + }, + "clean": { + "clean_command": null + }, + "envs": [ + { + "key": "CC", + "value": "abc-gcc" + } + ], + "build_once": false +} diff --git a/tests/data/dadk_config_v1/app_normal_with_env_fail_0_1_0.dadk b/tests/data/dadk_config_v1/app_normal_with_env_fail_0_1_0.dadk new file mode 100644 index 0000000..a9e04e8 --- /dev/null +++ b/tests/data/dadk_config_v1/app_normal_with_env_fail_0_1_0.dadk @@ -0,0 +1,30 @@ +{ + "name": "app_normal_with_env_fail", + "version": "0.1.0", + "description": "A normal app with env which should failed", + "rust_target": null, + "task_type": { + "BuildFromSource": { + "Local": { + "path": "tests/data/apps/app_normal_with_env_fail" + } + } + }, + "depends": [], + "build": { + "build_command": "bash build.sh" + }, + "install": { + "in_dragonos_path": "/" + }, + "clean": { + "clean_command": null + }, + "envs": [ + { + "key": "CC", + "value": "abc-gcc1" + } + ], + "build_once": false +}