Skip to content

Commit

Permalink
test: 为executor添加环境变量检测及错误检测的测试用例,并修复了任务执行错误后仍继续运行的bug (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
fslongjin authored Apr 27, 2024
1 parent 20afb02 commit 820df76
Show file tree
Hide file tree
Showing 15 changed files with 439 additions and 78 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
41 changes: 38 additions & 3 deletions crates/test_base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -23,19 +28,49 @@ 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)
}
}

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
}
}
4 changes: 2 additions & 2 deletions src/console/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
/// 清理缓存的级别
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/console/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn parse_check_dir_exists(path: &str) -> Result<PathBuf, String> {
}

/// @brief 要执行的操作
#[derive(Debug, Subcommand, Clone, Copy)]
#[derive(Debug, Subcommand, Clone, Copy, PartialEq, Eq)]
pub enum Action {
/// 构建所有项目
Build,
Expand Down
141 changes: 141 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -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<PathBuf>,
/// DADK任务配置文件所在目录
config_dir: Option<PathBuf>,
/// 要执行的操作
action: Action,
/// 并行线程数量
thread_num: Option<usize>,
/// dadk缓存根目录
cache_dir: Option<PathBuf>,

#[cfg(test)]
base_test_context: Option<BaseTestContext>,
}

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<usize> {
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);
63 changes: 39 additions & 24 deletions src/executor/cache.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{path::PathBuf, sync::Arc};
use std::{
path::PathBuf,
sync::{Arc, Once},
};

use log::info;

Expand Down Expand Up @@ -30,14 +33,17 @@ pub fn cache_root_init(path: Option<PathBuf>) -> 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();

Expand All @@ -46,12 +52,13 @@ pub fn cache_root_init(path: Option<PathBuf>) -> 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();
}

Expand All @@ -60,17 +67,21 @@ pub fn cache_root_init(path: Option<PathBuf>) -> 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());
Expand Down Expand Up @@ -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(());
Expand All @@ -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);
}
Expand All @@ -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(());
}
Expand Down Expand Up @@ -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(());
}
}
Loading

0 comments on commit 820df76

Please sign in to comment.