mirror of
https://github.com/containers/youki
synced 2024-11-23 01:11:58 +01:00
Merge pull request #310 from YJDoc2/add-test-utils
Add integration test utils necessary for implementing rest integration tests
This commit is contained in:
commit
2af52169cf
187
youki_integration_test/Cargo.lock
generated
187
youki_integration_test/Cargo.lock
generated
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
@ -69,6 +71,78 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30"
|
||||
dependencies = [
|
||||
"derive_builder_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_macro"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.15"
|
||||
@ -93,6 +167,12 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
@ -104,6 +184,18 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getset"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
@ -119,6 +211,12 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.7.0"
|
||||
@ -129,6 +227,12 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -151,6 +255,19 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oci-spec"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b33c04af97b8e9e3155d9c530a1260e7e6c8d36a1e7353e54f3aa013d388a0c7"
|
||||
dependencies = [
|
||||
"derive_builder",
|
||||
"getset",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
@ -260,6 +377,43 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
@ -304,6 +458,26 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
@ -346,6 +520,17 @@ version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
@ -386,9 +571,11 @@ dependencies = [
|
||||
"clap_derive",
|
||||
"flate2",
|
||||
"lazy_static",
|
||||
"oci-spec",
|
||||
"once_cell",
|
||||
"rand",
|
||||
"tar",
|
||||
"test_framework",
|
||||
"uuid",
|
||||
"which",
|
||||
]
|
||||
|
@ -20,4 +20,6 @@ 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"
|
||||
once_cell = "1.8.0"
|
||||
oci-spec = "0.5.1"
|
||||
which = "4.2.2"
|
@ -1,2 +1,2 @@
|
||||
pub mod support;
|
||||
pub mod tests;
|
||||
pub mod utils;
|
||||
|
@ -1,17 +1,13 @@
|
||||
mod support;
|
||||
mod tests;
|
||||
mod utils;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use crate::tests::lifecycle::{ContainerCreate, ContainerLifecycle};
|
||||
use crate::utils::support::set_runtime_path;
|
||||
use anyhow::Result;
|
||||
use clap::Clap;
|
||||
use std::path::PathBuf;
|
||||
use test_framework::TestManager;
|
||||
|
||||
use crate::support::cleanup_test;
|
||||
use crate::support::get_project_path;
|
||||
use crate::support::initialize_test;
|
||||
use crate::support::set_runtime_path;
|
||||
use crate::tests::lifecycle::{ContainerCreate, ContainerLifecycle};
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
#[clap(version = "0.0.1", author = "youki team")]
|
||||
struct Opts {
|
||||
@ -43,22 +39,26 @@ fn parse_tests(tests: &[String]) -> Vec<(&str, Option<Vec<&str>>)> {
|
||||
fn main() -> Result<()> {
|
||||
let opts: Opts = Opts::parse();
|
||||
|
||||
let path = std::fs::canonicalize(opts.runtime).expect("Invalid runtime path");
|
||||
set_runtime_path(&path);
|
||||
match std::fs::canonicalize(opts.runtime.clone()) {
|
||||
// runtime path is relative or resolved correctly
|
||||
Ok(path) => set_runtime_path(&path),
|
||||
// runtime path is name of program which probably exists in $PATH
|
||||
Err(_) => match which::which(opts.runtime) {
|
||||
Ok(path) => set_runtime_path(&path),
|
||||
Err(e) => {
|
||||
eprintln!("Error in finding runtime : {}\nexiting.", e);
|
||||
std::process::exit(66);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
let mut tm = TestManager::new();
|
||||
let project_path = get_project_path();
|
||||
|
||||
let cl = ContainerLifecycle::new(&project_path);
|
||||
let cc = ContainerCreate::new(&project_path);
|
||||
let cl = ContainerLifecycle::new();
|
||||
let cc = ContainerCreate::new();
|
||||
|
||||
tm.add_test_group(&cl);
|
||||
tm.add_test_group(&cc);
|
||||
|
||||
if initialize_test(&project_path).is_err() {
|
||||
bail!("Can not initilize test.")
|
||||
}
|
||||
|
||||
if let Some(tests) = opts.tests {
|
||||
let tests_to_run = parse_tests(&tests);
|
||||
tm.run_selected(tests_to_run);
|
||||
@ -66,8 +66,5 @@ fn main() -> Result<()> {
|
||||
tm.run_all();
|
||||
}
|
||||
|
||||
if cleanup_test(&project_path).is_err() {
|
||||
bail!("Can not cleanup test.")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,80 +0,0 @@
|
||||
use flate2::read::GzDecoder;
|
||||
use once_cell::sync::OnceCell;
|
||||
use rand::Rng;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use std::{env, fs, path::Path};
|
||||
use tar::Archive;
|
||||
use uuid::Uuid;
|
||||
|
||||
static RUNTIME_PATH: OnceCell<PathBuf> = OnceCell::new();
|
||||
|
||||
pub fn set_runtime_path(path: &Path) {
|
||||
RUNTIME_PATH.set(path.to_owned()).unwrap();
|
||||
}
|
||||
|
||||
pub fn get_runtime_path() -> &'static PathBuf {
|
||||
RUNTIME_PATH.get().expect("Runtime path is not set")
|
||||
}
|
||||
|
||||
pub fn initialize_test(project_path: &Path) -> Result<(), std::io::Error> {
|
||||
prepare_test_workspace(project_path)
|
||||
}
|
||||
|
||||
pub fn cleanup_test(project_path: &Path) -> Result<(), std::io::Error> {
|
||||
delete_test_workspace(project_path)
|
||||
}
|
||||
|
||||
pub fn get_project_path() -> PathBuf {
|
||||
let current_dir_path_result = env::current_dir();
|
||||
match current_dir_path_result {
|
||||
Ok(path_buf) => path_buf,
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary files to be used for testing are created in the `integration-workspace`.
|
||||
fn prepare_test_workspace(project_path: &Path) -> Result<(), std::io::Error> {
|
||||
let integration_test_workspace_path = project_path.join("integration-workspace");
|
||||
let create_dir_result = fs::create_dir_all(&integration_test_workspace_path);
|
||||
if fs::create_dir_all(&integration_test_workspace_path).is_err() {
|
||||
return create_dir_result;
|
||||
}
|
||||
let tar_file_name = "bundle.tar.gz";
|
||||
let tar_path = integration_test_workspace_path.join(tar_file_name);
|
||||
fs::copy(
|
||||
tar_file_name,
|
||||
&integration_test_workspace_path.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(integration_test_workspace_path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// This deletes all temporary files.
|
||||
fn delete_test_workspace(project_path: &Path) -> Result<(), std::io::Error> {
|
||||
fs::remove_dir_all(project_path.join("integration-workspace"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,18 +1,26 @@
|
||||
use super::{create, kill};
|
||||
use crate::support::generate_uuid;
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::utils::TempDir;
|
||||
use crate::utils::{generate_uuid, prepare_bundle};
|
||||
use test_framework::{TestResult, TestableGroup};
|
||||
|
||||
pub struct ContainerCreate {
|
||||
project_path: PathBuf,
|
||||
project_path: TempDir,
|
||||
container_id: String,
|
||||
}
|
||||
|
||||
impl<'a> Default for ContainerCreate {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ContainerCreate {
|
||||
pub fn new(project_path: &Path) -> Self {
|
||||
pub fn new() -> Self {
|
||||
let id = generate_uuid();
|
||||
let temp_dir = prepare_bundle(&id).unwrap();
|
||||
ContainerCreate {
|
||||
project_path: project_path.to_owned(),
|
||||
container_id: generate_uuid().to_string(),
|
||||
project_path: temp_dir,
|
||||
container_id: id.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,33 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::support::generate_uuid;
|
||||
use crate::utils::{generate_uuid, prepare_bundle, TempDir};
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use test_framework::{TestResult, TestableGroup};
|
||||
|
||||
use super::{create, delete, kill, start, state};
|
||||
|
||||
// By experimenting, somewhere around 50 is enough for youki process
|
||||
// to get the kill signal and shut down
|
||||
// here we add a little buffer time as well
|
||||
const SLEEP_TIME: Duration = Duration::from_millis(75);
|
||||
|
||||
pub struct ContainerLifecycle {
|
||||
project_path: PathBuf,
|
||||
project_path: TempDir,
|
||||
container_id: String,
|
||||
}
|
||||
|
||||
impl Default for ContainerLifecycle {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ContainerLifecycle {
|
||||
pub fn new(project_path: &Path) -> Self {
|
||||
pub fn new() -> Self {
|
||||
let id = generate_uuid();
|
||||
let temp_dir = prepare_bundle(&id).unwrap();
|
||||
ContainerLifecycle {
|
||||
project_path: project_path.to_owned(),
|
||||
container_id: generate_uuid().to_string(),
|
||||
project_path: temp_dir,
|
||||
container_id: id.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +44,11 @@ impl ContainerLifecycle {
|
||||
}
|
||||
|
||||
pub fn kill(&self) -> TestResult {
|
||||
kill::kill(&self.project_path, &self.container_id)
|
||||
let ret = kill::kill(&self.project_path, &self.container_id);
|
||||
// sleep a little, so the youki process actually gets the signal and shuts down
|
||||
// otherwise, the tester moves on to next tests before the youki has gotten signal, and delete test can fail
|
||||
sleep(SLEEP_TIME);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn delete(&self) -> TestResult {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::support::get_runtime_path;
|
||||
use crate::utils::get_runtime_path;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
@ -13,11 +13,11 @@ pub fn create(project_path: &Path, id: &str) -> TestResult {
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("--root")
|
||||
.arg(project_path.join("integration-workspace").join("youki"))
|
||||
.arg(project_path.join("runtime"))
|
||||
.arg("create")
|
||||
.arg(id)
|
||||
.arg("--bundle")
|
||||
.arg(project_path.join("integration-workspace").join("bundle"))
|
||||
.arg(project_path.join("bundle"))
|
||||
.arg(id)
|
||||
.spawn()
|
||||
.expect("Cannot execute create command")
|
||||
.wait();
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::get_result_from_output;
|
||||
use crate::support::get_runtime_path;
|
||||
use crate::utils::get_runtime_path;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
use test_framework::TestResult;
|
||||
@ -9,7 +9,7 @@ pub fn delete(project_path: &Path, id: &str) -> TestResult {
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.arg("--root")
|
||||
.arg(project_path.join("integration-workspace").join("youki"))
|
||||
.arg(project_path.join("runtime"))
|
||||
.arg("delete")
|
||||
.arg(id)
|
||||
.spawn()
|
||||
|
@ -1,30 +1,20 @@
|
||||
use super::get_result_from_output;
|
||||
use crate::support::get_runtime_path;
|
||||
use crate::utils::get_runtime_path;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use test_framework::TestResult;
|
||||
|
||||
// By experimenting, somewhere around 50 is enough for youki process
|
||||
// to get the kill signal and shut down
|
||||
// here we add a little buffer time as well
|
||||
const SLEEP_TIME: u64 = 75;
|
||||
|
||||
pub fn kill(project_path: &Path, id: &str) -> TestResult {
|
||||
let res = Command::new(get_runtime_path())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.arg("--root")
|
||||
.arg(project_path.join("integration-workspace").join("youki"))
|
||||
.arg(project_path.join("runtime"))
|
||||
.arg("kill")
|
||||
.arg(id)
|
||||
.arg("9")
|
||||
.spawn()
|
||||
.expect("failed to execute kill command")
|
||||
.wait_with_output();
|
||||
// sleep a little, so the youki process actually gets the signal and shuts down
|
||||
// otherwise, the tester moves on to next tests before the youki has gotten signal, and delete test can fail
|
||||
sleep(Duration::from_millis(SLEEP_TIME));
|
||||
get_result_from_output(res)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::get_result_from_output;
|
||||
use crate::support::get_runtime_path;
|
||||
use crate::utils::get_runtime_path;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
use test_framework::TestResult;
|
||||
@ -9,7 +9,7 @@ pub fn start(project_path: &Path, id: &str) -> TestResult {
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.arg("--root")
|
||||
.arg(project_path.join("integration-workspace").join("youki"))
|
||||
.arg(project_path.join("runtime"))
|
||||
.arg("start")
|
||||
.arg(id)
|
||||
.spawn()
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::support::get_runtime_path;
|
||||
use crate::utils::get_runtime_path;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::process::{Command, Stdio};
|
||||
@ -9,7 +9,7 @@ pub fn state(project_path: &Path, id: &str) -> TestResult {
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.arg("--root")
|
||||
.arg(project_path.join("integration-workspace").join("youki"))
|
||||
.arg(project_path.join("runtime"))
|
||||
.arg("state")
|
||||
.arg(id)
|
||||
.spawn()
|
||||
|
6
youki_integration_test/src/utils/mod.rs
Normal file
6
youki_integration_test/src/utils/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
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 temp_dir::{create_temp_dir, TempDir};
|
||||
pub use test_utils::{generate_uuid, prepare_bundle, set_config, start_runtime, stop_runtime};
|
23
youki_integration_test/src/utils/support.rs
Normal file
23
youki_integration_test/src/utils/support.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
static RUNTIME_PATH: OnceCell<PathBuf> = OnceCell::new();
|
||||
|
||||
pub fn set_runtime_path(path: &Path) {
|
||||
RUNTIME_PATH.set(path.to_owned()).unwrap();
|
||||
}
|
||||
|
||||
pub fn get_runtime_path() -> &'static PathBuf {
|
||||
RUNTIME_PATH.get().expect("Runtime path is not set")
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_project_path() -> PathBuf {
|
||||
let current_dir_path_result = env::current_dir();
|
||||
match current_dir_path_result {
|
||||
Ok(path_buf) => path_buf,
|
||||
Err(e) => panic!("directory is not found, {}", e),
|
||||
}
|
||||
}
|
59
youki_integration_test/src/utils/temp_dir.rs
Normal file
59
youki_integration_test/src/utils/temp_dir.rs
Normal file
@ -0,0 +1,59 @@
|
||||
///! Thin wrapper struct for creating temp directories
|
||||
///! Taken after cgroups/tempdir
|
||||
use anyhow::Result;
|
||||
use std::{
|
||||
fs,
|
||||
ops::Deref,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct TempDir {
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl TempDir {
|
||||
pub fn new<P: Into<PathBuf>>(path: P) -> Result<Self> {
|
||||
let p = path.into();
|
||||
std::fs::create_dir_all(&p)?;
|
||||
Ok(Self { path: Some(p) })
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
self.path
|
||||
.as_ref()
|
||||
.expect("temp dir has already been removed")
|
||||
}
|
||||
|
||||
pub fn remove(&mut self) {
|
||||
if let Some(p) = &self.path {
|
||||
let _ = fs::remove_dir_all(p);
|
||||
self.path = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempDir {
|
||||
fn drop(&mut self) {
|
||||
self.remove();
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for TempDir {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.path()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for TempDir {
|
||||
type Target = Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.path()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_temp_dir(id: &Uuid) -> Result<TempDir> {
|
||||
let dir = TempDir::new(std::env::temp_dir().join(id.to_string()))?;
|
||||
Ok(dir)
|
||||
}
|
83
youki_integration_test/src/utils/test_utils.rs
Normal file
83
youki_integration_test/src/utils/test_utils.rs
Normal file
@ -0,0 +1,83 @@
|
||||
///! Contains utility functions for testing
|
||||
///! Similar to https://github.com/opencontainers/runtime-tools/blob/master/validation/util/test.go
|
||||
use super::get_runtime_path;
|
||||
use super::{create_temp_dir, TempDir};
|
||||
use anyhow::Result;
|
||||
use flate2::read::GzDecoder;
|
||||
use oci_spec::runtime::Spec;
|
||||
use rand::Rng;
|
||||
use std::fs::File;
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::{fs, path::Path};
|
||||
use tar::Archive;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// 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);
|
||||
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
|
||||
#[allow(dead_code)]
|
||||
pub fn set_config<P: AsRef<Path>>(project_path: P, config: &Spec) -> Result<()> {
|
||||
let path = project_path.as_ref().join("config.json");
|
||||
config.save(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Starts the runtime with given directory as root directory
|
||||
#[allow(dead_code)]
|
||||
pub fn start_runtime<P: AsRef<Path>>(id: &Uuid, dir: P) -> Result<Child> {
|
||||
let res = Command::new(get_runtime_path())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("--root")
|
||||
.arg(dir.as_ref().join("runtime"))
|
||||
.arg("create")
|
||||
.arg(id.to_string())
|
||||
.arg("--bundle")
|
||||
.arg(dir.as_ref().join("bundle"))
|
||||
.spawn()?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Sends a kill command to the given container process
|
||||
#[allow(dead_code)]
|
||||
pub fn stop_runtime<P: AsRef<Path>>(id: &Uuid, dir: P) -> Result<Child> {
|
||||
let res = Command::new(get_runtime_path())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.arg("--root")
|
||||
.arg(dir.as_ref().join("runtime"))
|
||||
.arg("kill")
|
||||
.arg(id.to_string())
|
||||
.arg("9")
|
||||
.spawn()?;
|
||||
Ok(res)
|
||||
}
|
Loading…
Reference in New Issue
Block a user