Skip to content

Commit

Permalink
apply test kill patch
Browse files Browse the repository at this point in the history
Signed-off-by: Akiyama <[email protected]>
  • Loading branch information
YamasouA committed Feb 4, 2025
1 parent 7042027 commit 78df79a
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 2 deletions.
3 changes: 3 additions & 0 deletions tests/contest/contest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::tests::hooks::get_hooks_tests;
use crate::tests::hostname::get_hostname_test;
use crate::tests::intel_rdt::get_intel_rdt_test;
use crate::tests::io_priority::get_io_priority_test;
use crate::tests::kill::get_kill_test;
use crate::tests::lifecycle::{ContainerCreate, ContainerLifecycle};
use crate::tests::linux_ns_itype::get_ns_itype_tests;
use crate::tests::mounts_recursive::get_mounts_recursive_test;
Expand Down Expand Up @@ -129,6 +130,7 @@ fn main() -> Result<()> {
let no_pivot = get_no_pivot_test();
let process_oom_score_adj = get_process_oom_score_adj_test();
let fd_control = get_fd_control_test();
let kill = get_kill_test();

tm.add_test_group(Box::new(cl));
tm.add_test_group(Box::new(cc));
Expand Down Expand Up @@ -160,6 +162,7 @@ fn main() -> Result<()> {
tm.add_test_group(Box::new(no_pivot));
tm.add_test_group(Box::new(process_oom_score_adj));
tm.add_test_group(Box::new(fd_control));
tm.add_test_group(Box::new(kill));

tm.add_test_group(Box::new(io_priority_test));
tm.add_cleanup(Box::new(cgroups::cleanup_v1));
Expand Down
163 changes: 163 additions & 0 deletions tests/contest/contest/src/tests/kill/kill_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use std::time::Duration;

use anyhow::{anyhow, Context, Result};
use oci_spec::runtime::{ProcessBuilder, Spec, SpecBuilder};
use test_framework::{Test, TestGroup, TestResult};

use crate::tests::lifecycle::ContainerLifecycle;

fn create_spec(args: &[&str]) -> Result<Spec> {
let args_vec: Vec<String> = args.iter().map(|&a| a.into()).collect();
let spec = SpecBuilder::default()
.process(
ProcessBuilder::default()
.args(args_vec)
.build()
.context("failed to build process spec")?,
)
.build()
.context("failed to build spec")?;
Ok(spec)
}

fn failed_and_delete(text: String, container: ContainerLifecycle) -> TestResult {
let delete_result = container.delete();
match delete_result {
TestResult::Passed => TestResult::Failed(anyhow!(text)),
TestResult::Failed(err) => TestResult::Failed(anyhow!(
"{}; also container deletion failed: {:?}",
text,
err
)),
_ => TestResult::Failed(anyhow!("{}; unexpected delete result", text)),
}
}

fn merge_test_results(kill_result: TestResult, delete_result: TestResult) -> TestResult {
match (kill_result, delete_result) {
(TestResult::Failed(err), _) => TestResult::Failed(err),
(TestResult::Passed, TestResult::Failed(err)) => {
TestResult::Failed(anyhow!("Delete failed: {:?}", err))
}
(TestResult::Passed, TestResult::Passed) => TestResult::Passed,
_ => TestResult::Failed(anyhow!("Unexpected result")),
}
}

fn kill_with_empty_id_test() -> TestResult {
let mut container = ContainerLifecycle::new();

// kill with empty id
container.set_id("");
match container.kill() {
TestResult::Failed(_) => TestResult::Passed,
TestResult::Passed => TestResult::Failed(anyhow!(
"Expected killing container with empty id to fail, but was successful"
)),
_ => TestResult::Failed(anyhow!(
"Unexpected killing container with empty id test result"
)),
}
}

fn kill_non_existed_container() -> TestResult {
let container = ContainerLifecycle::new();

// kill for non existed container
match container.kill() {
TestResult::Failed(_) => TestResult::Passed,
TestResult::Passed => TestResult::Failed(anyhow!(
"Expected killing non existed container to fail, but was successful"
)),
_ => TestResult::Failed(anyhow!(
"Unexpected killing non existed container test result"
)),
}
}

fn kill_created_container_test() -> TestResult {
let container = ContainerLifecycle::new();

// kill created container
match container.create() {
TestResult::Passed => {}
_ => return failed_and_delete("Failed to create container".to_string(), container),
}
let kill_result = container.kill();
let delete_result = container.delete();
merge_test_results(kill_result, delete_result)
}

fn kill_stopped_container_test() -> TestResult {
let container = ContainerLifecycle::new();
let spec = create_spec(&["true"]).unwrap();

// kill stopped container
match container.create_with_spec(spec) {
TestResult::Passed => {}
_ => return failed_and_delete("Failed to create container".to_string(), container),
}
match container.start() {
TestResult::Passed => {}
_ => return failed_and_delete("Failed to start container".to_string(), container),
}
container.waiting_for_status(Duration::from_secs(10), Duration::from_secs(1), "stopped");
let kill_result = match container.kill() {
TestResult::Failed(_) => TestResult::Passed,
TestResult::Passed => TestResult::Failed(anyhow!("Expected failure but got success")),
_ => TestResult::Failed(anyhow!("Unexpected test result")),
};
let delete_result = container.delete();
merge_test_results(kill_result, delete_result)
}

fn kill_start_container_test() -> TestResult {
let container = ContainerLifecycle::new();
let spec = create_spec(&["sleep", "30"]).unwrap();

// kill start container
match container.create_with_spec(spec) {
TestResult::Passed => {}
_ => return failed_and_delete("Failed to recreate container".to_string(), container),
}

match container.start() {
TestResult::Passed => {}
_ => return failed_and_delete(("Failed to start container").to_string(), container),
}
container.waiting_for_status(Duration::from_secs(10), Duration::from_secs(1), "running");
let kill_result = container.kill();
let delete_result = container.delete();
merge_test_results(kill_result, delete_result)
}

pub fn get_kill_test() -> TestGroup {
let mut test_group = TestGroup::new("kill_container");

let kill_with_empty_id_test =
Test::new("kill_with_empty_id_test", Box::new(kill_with_empty_id_test));
let kill_non_existed_container = Test::new(
"kill_non_existed_container",
Box::new(kill_non_existed_container),
);
let kill_created_container_test = Test::new(
"kill_created_container_test",
Box::new(kill_created_container_test),
);
let kill_stopped_container_test = Test::new(
"kill_stopped_container_test",
Box::new(kill_stopped_container_test),
);
let kill_start_container_test = Test::new(
"kill_start_container_test",
Box::new(kill_start_container_test),
);
test_group.add(vec![
Box::new(kill_with_empty_id_test),
Box::new(kill_non_existed_container),
Box::new(kill_created_container_test),
Box::new(kill_stopped_container_test),
Box::new(kill_start_container_test),
]);
test_group
}
3 changes: 3 additions & 0 deletions tests/contest/contest/src/tests/kill/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod kill_test;

pub use kill_test::get_kill_test;
40 changes: 38 additions & 2 deletions tests/contest/contest/src/tests/lifecycle/container_lifecycle.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::thread::sleep;
use std::time::Duration;
use std::time::{Duration, Instant};

use anyhow::anyhow;
use oci_spec::runtime::Spec;
use test_framework::{TestResult, TestableGroup};

use super::util::criu_installed;
use super::{checkpoint, create, delete, exec, kill, start, state};
use crate::utils::{generate_uuid, prepare_bundle};
use crate::utils::{generate_uuid, get_state, prepare_bundle, set_config, State};

// By experimenting, somewhere around 50 is enough for youki process
// to get the kill signal and shut down
Expand Down Expand Up @@ -33,10 +35,19 @@ impl ContainerLifecycle {
}
}

pub fn set_id(&mut self, id: &str) {
self.container_id = id.to_string();
}

pub fn create(&self) -> TestResult {
create::create(self.project_path.path(), &self.container_id).into()
}

pub fn create_with_spec(&self, spec: Spec) -> TestResult {
set_config(&self.project_path, &spec).unwrap();
create::create(self.project_path.path(), &self.container_id).into()
}

#[allow(dead_code)]
pub fn exec(&self, cmd: Vec<&str>, expected_output: Option<&str>) -> TestResult {
exec::exec(
Expand Down Expand Up @@ -86,6 +97,31 @@ impl ContainerLifecycle {
&self.container_id,
)
}

pub fn waiting_for_status(
&self,
retry_timeout: Duration,
poll_interval: Duration,
target_status: &str,
) -> TestResult {
let start = Instant::now();
while start.elapsed() < retry_timeout {
let (out, err) = get_state(&self.container_id, &self.project_path).unwrap();
if !err.is_empty() {
self.kill();
self.delete();
return TestResult::Failed(anyhow!("error in state : {}", err));
}

let state: State = serde_json::from_str(&out).unwrap();

if state.status == target_status {
return TestResult::Passed;
}
sleep(poll_interval);
}
TestResult::Failed(anyhow!("error pod status is not update"))
}
}

impl TestableGroup for ContainerLifecycle {
Expand Down
1 change: 1 addition & 0 deletions tests/contest/contest/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod hooks;
pub mod hostname;
pub mod intel_rdt;
pub mod io_priority;
pub mod kill;
pub mod lifecycle;
pub mod linux_ns_itype;
pub mod mounts_recursive;
Expand Down

0 comments on commit 78df79a

Please sign in to comment.