Skip to content

Commit

Permalink
Refactor test_util code to be more reusable
Browse files Browse the repository at this point in the history
  • Loading branch information
YJDoc2 committed Sep 27, 2021
1 parent af0af70 commit 3254c78
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 148 deletions.
3 changes: 2 additions & 1 deletion youki_integration_test/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions youki_integration_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ tar = "0.4"
flate2 = "1.0"
test_framework = { version = "0.1.0", path = "../test_framework"}
anyhow = "1.0"
lazy_static = "1.4.0"
once_cell = "1.8.0"
oci-spec = "0.5.1"
which = "4.2.2"
which = "4.2.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
151 changes: 55 additions & 96 deletions youki_integration_test/src/tests/tlb/tlb_test.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
use crate::utils::{
delete_container, generate_uuid, get_state, prepare_bundle, set_config, start_runtime,
stop_runtime,
};
use crate::utils::test_outside_container;
use anyhow::anyhow;
use oci_spec::runtime::LinuxBuilder;
use oci_spec::runtime::{LinuxHugepageLimitBuilder, LinuxResourcesBuilder};
use oci_spec::runtime::{Spec, SpecBuilder};
use std::io::Result;
use std::path::PathBuf;
use std::process::ExitStatus;
use test_framework::{ConditionalTest, TestGroup, TestResult};

struct RunData {
id: uuid::Uuid,
result: Result<ExitStatus>,
stdout: String,
stderr: String,
}

fn check_hugetlb() -> bool {
PathBuf::from("/sys/fs/cgroup/hugetlb").exists()
}
Expand All @@ -43,65 +31,47 @@ fn make_hugetlb_spec(page_size: &str, limit: i64) -> Spec {
.unwrap()
}

fn run_tlb_test(page: &str, limit: i64) -> RunData {
let spec = make_hugetlb_spec(page, limit);

let id = generate_uuid();
let bundle = prepare_bundle(&id).unwrap();
set_config(&bundle, &spec).unwrap();

let r = start_runtime(&id, &bundle).unwrap().wait();
let (out, err) = get_state(&id, &bundle).unwrap();
stop_runtime(&id, &bundle).unwrap().wait().unwrap();
delete_container(&id, &bundle).unwrap().wait().unwrap();
RunData {
id: id,
result: r,
stdout: out,
stderr: err,
}
}

fn test_wrong_tlb() -> TestResult {
// 3 MB pagesize is wrong, as valid values must be a power of 2
let page = "3MB";
let limit = 100 * 3 * 1024 * 1024;
let rdata = run_tlb_test(&page, limit);
match rdata.result {
Err(e) => TestResult::Err(anyhow!(e)),
Ok(res) => {
if !rdata.stdout.is_empty() {
return TestResult::Err(anyhow!(
"stdout of state command was non-empty : {}",
rdata.stdout
));
}
if rdata.stderr.is_empty() {
return TestResult::Err(anyhow!("stderr of state command was empty"));
}
if res.success() {
// The operation should not have succeeded as pagesize was not power of 2
TestResult::Err(anyhow!("Invalid page size of {} was allowed", page))
} else {
TestResult::Ok
let spec = make_hugetlb_spec(page, limit);
test_outside_container(spec, &|data| {
match data.exit_status {
Err(e) => TestResult::Err(anyhow!(e)),
Ok(res) => {
if data.state.is_some() {
return TestResult::Err(anyhow!(
"stdout of state command was non-empty : {:?}",
data.state
));
}
if data.state_err.is_empty() {
return TestResult::Err(anyhow!("stderr of state command was empty"));
}
if res.success() {
// The operation should not have succeeded as pagesize was not power of 2
TestResult::Err(anyhow!("Invalid page size of {} was allowed", page))
} else {
TestResult::Ok
}
}
}
}
})
}

fn extract_page_size(dir_name: &str) -> String {
let name_stripped = dir_name.strip_prefix("hugepages-").unwrap();
let size = name_stripped.strip_suffix("kB").unwrap();
let size: u64 = size.parse().unwrap();

let size_moniker = if size >= (1 << 20) {
if size >= (1 << 20) {
(size >> 20).to_string() + "GB"
} else if size >= (1 << 10) {
(size >> 10).to_string() + "MB"
} else {
size.to_string() + "KB"
};
return size_moniker;
}
}

fn get_tlb_sizes() -> Vec<String> {
Expand Down Expand Up @@ -145,51 +115,40 @@ fn test_valid_tlb() -> TestResult {
let tlb_sizes = get_tlb_sizes();
for size in tlb_sizes.iter() {
let spec = make_hugetlb_spec(size, limit);

let id = generate_uuid();
let bundle = prepare_bundle(&id).unwrap();
set_config(&bundle, &spec).unwrap();

let r = start_runtime(&id, &bundle).unwrap().wait();
let (out, err) = get_state(&id, &bundle).unwrap();
stop_runtime(&id, &bundle).unwrap().wait().unwrap();
let rdata = RunData {
id: id,
result: r,
stdout: out,
stderr: err,
};
match rdata.result {
Err(e) => return TestResult::Err(anyhow!(e)),
Ok(res) => {
if !rdata.stderr.is_empty() {
return TestResult::Err(anyhow!(
"stderr of state command was not-empty : {}",
rdata.stderr
));
}
if rdata.stdout.is_empty() {
return TestResult::Err(anyhow!("stdout of state command was empty"));
}
if !rdata.stdout.contains(&format!(r#""id": "{}""#, rdata.id))
|| !rdata.stdout.contains(r#""status": "created""#)
{
todo!();
return TestResult::Err(anyhow!(""));
}
if !res.success() {
return TestResult::Err(anyhow!(
"Setting valid page size of {} was gave error",
size
));
let res = test_outside_container(spec, &|data| {
match data.exit_status {
Err(e) => return TestResult::Err(anyhow!(e)),
Ok(res) => {
if !data.state_err.is_empty() {
return TestResult::Err(anyhow!(
"stderr of state command was not-empty : {}",
data.state_err
));
}
if data.state.is_none() {
return TestResult::Err(anyhow!("stdout of state command was invalid"));
}
let state = data.state.unwrap();
if state.id != data.id || state.status != "created" {
return TestResult::Err(anyhow!("invalid container state : expected id {} and status created, got id {} and state {}",data.id,state.id,state.status));
}
if !res.success() {
return TestResult::Err(anyhow!(
"Setting valid page size of {} was gave error",
size
));
}
}
}
let r = validate_tlb(&data.id, size, limit);
if matches!(r, TestResult::Err(_)) {
return r;
}
TestResult::Ok
});
if matches!(res, TestResult::Err(_)) {
return res;
}
let r = validate_tlb(&rdata.id.to_string(), size, limit);
if matches!(r, TestResult::Err(_)) {
return r;
}
delete_container(&id, &bundle).unwrap().wait().unwrap();
}
TestResult::Ok
}
Expand Down
7 changes: 4 additions & 3 deletions youki_integration_test/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub mod support;
pub mod temp_dir;
pub mod test_utils;
pub use support::{get_project_path, get_runtime_path, set_runtime_path};
pub use support::{
generate_uuid, get_project_path, get_runtime_path, prepare_bundle, set_config, set_runtime_path,
};
pub use temp_dir::{create_temp_dir, TempDir};
pub use test_utils::{
delete_container, generate_uuid, get_state, prepare_bundle, set_config, start_runtime,
stop_runtime,
delete_container, get_state, start_runtime, stop_runtime, test_outside_container, ContainerData,
};
49 changes: 47 additions & 2 deletions youki_integration_test/src/utils/support.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use super::{create_temp_dir, TempDir};
use anyhow::Result;
use flate2::read::GzDecoder;
use oci_spec::runtime::Spec;
use once_cell::sync::OnceCell;
use rand::Rng;
use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::fs::File;
use std::path::{Path, PathBuf};
use tar::Archive;
use uuid::Uuid;

static RUNTIME_PATH: OnceCell<PathBuf> = OnceCell::new();

Expand All @@ -21,3 +28,41 @@ pub fn get_project_path() -> PathBuf {
Err(e) => panic!("directory is not found, {}", e),
}
}

/// This will generate the UUID needed when creating the container.
pub fn generate_uuid() -> Uuid {
let mut rng = rand::thread_rng();
const CHARSET: &[u8] = b"0123456789abcdefABCDEF";

let rand_string: String = (0..32)
.map(|_| {
let idx = rng.gen_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect();

match Uuid::parse_str(&rand_string) {
Ok(uuid) => uuid,
Err(e) => panic!("can not parse uuid, {}", e),
}
}

/// Creates a bundle directory in a temp directory
pub fn prepare_bundle(id: &Uuid) -> Result<TempDir> {
let temp_dir = create_temp_dir(id)?;
let tar_file_name = "bundle.tar.gz";
let tar_path = std::env::current_dir()?.join(tar_file_name);
std::fs::copy(tar_path.clone(), (&temp_dir).join(tar_file_name))?;
let tar_gz = File::open(tar_path)?;
let tar = GzDecoder::new(tar_gz);
let mut archive = Archive::new(tar);
archive.unpack(&temp_dir)?;
Ok(temp_dir)
}

/// Sets the config.json file as per given spec
pub fn set_config<P: AsRef<Path>>(project_path: P, config: &Spec) -> Result<()> {
let path = project_path.as_ref().join("bundle").join("config.json");
config.save(path)?;
Ok(())
}
Loading

0 comments on commit 3254c78

Please sign in to comment.