Skip to content

Commit 78df79a

Browse files
committed
apply test kill patch
Signed-off-by: Akiyama <[email protected]>
1 parent 7042027 commit 78df79a

File tree

5 files changed

+208
-2
lines changed

5 files changed

+208
-2
lines changed

tests/contest/contest/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::tests::hooks::get_hooks_tests;
1717
use crate::tests::hostname::get_hostname_test;
1818
use crate::tests::intel_rdt::get_intel_rdt_test;
1919
use crate::tests::io_priority::get_io_priority_test;
20+
use crate::tests::kill::get_kill_test;
2021
use crate::tests::lifecycle::{ContainerCreate, ContainerLifecycle};
2122
use crate::tests::linux_ns_itype::get_ns_itype_tests;
2223
use crate::tests::mounts_recursive::get_mounts_recursive_test;
@@ -129,6 +130,7 @@ fn main() -> Result<()> {
129130
let no_pivot = get_no_pivot_test();
130131
let process_oom_score_adj = get_process_oom_score_adj_test();
131132
let fd_control = get_fd_control_test();
133+
let kill = get_kill_test();
132134

133135
tm.add_test_group(Box::new(cl));
134136
tm.add_test_group(Box::new(cc));
@@ -160,6 +162,7 @@ fn main() -> Result<()> {
160162
tm.add_test_group(Box::new(no_pivot));
161163
tm.add_test_group(Box::new(process_oom_score_adj));
162164
tm.add_test_group(Box::new(fd_control));
165+
tm.add_test_group(Box::new(kill));
163166

164167
tm.add_test_group(Box::new(io_priority_test));
165168
tm.add_cleanup(Box::new(cgroups::cleanup_v1));
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
use std::time::Duration;
2+
3+
use anyhow::{anyhow, Context, Result};
4+
use oci_spec::runtime::{ProcessBuilder, Spec, SpecBuilder};
5+
use test_framework::{Test, TestGroup, TestResult};
6+
7+
use crate::tests::lifecycle::ContainerLifecycle;
8+
9+
fn create_spec(args: &[&str]) -> Result<Spec> {
10+
let args_vec: Vec<String> = args.iter().map(|&a| a.into()).collect();
11+
let spec = SpecBuilder::default()
12+
.process(
13+
ProcessBuilder::default()
14+
.args(args_vec)
15+
.build()
16+
.context("failed to build process spec")?,
17+
)
18+
.build()
19+
.context("failed to build spec")?;
20+
Ok(spec)
21+
}
22+
23+
fn failed_and_delete(text: String, container: ContainerLifecycle) -> TestResult {
24+
let delete_result = container.delete();
25+
match delete_result {
26+
TestResult::Passed => TestResult::Failed(anyhow!(text)),
27+
TestResult::Failed(err) => TestResult::Failed(anyhow!(
28+
"{}; also container deletion failed: {:?}",
29+
text,
30+
err
31+
)),
32+
_ => TestResult::Failed(anyhow!("{}; unexpected delete result", text)),
33+
}
34+
}
35+
36+
fn merge_test_results(kill_result: TestResult, delete_result: TestResult) -> TestResult {
37+
match (kill_result, delete_result) {
38+
(TestResult::Failed(err), _) => TestResult::Failed(err),
39+
(TestResult::Passed, TestResult::Failed(err)) => {
40+
TestResult::Failed(anyhow!("Delete failed: {:?}", err))
41+
}
42+
(TestResult::Passed, TestResult::Passed) => TestResult::Passed,
43+
_ => TestResult::Failed(anyhow!("Unexpected result")),
44+
}
45+
}
46+
47+
fn kill_with_empty_id_test() -> TestResult {
48+
let mut container = ContainerLifecycle::new();
49+
50+
// kill with empty id
51+
container.set_id("");
52+
match container.kill() {
53+
TestResult::Failed(_) => TestResult::Passed,
54+
TestResult::Passed => TestResult::Failed(anyhow!(
55+
"Expected killing container with empty id to fail, but was successful"
56+
)),
57+
_ => TestResult::Failed(anyhow!(
58+
"Unexpected killing container with empty id test result"
59+
)),
60+
}
61+
}
62+
63+
fn kill_non_existed_container() -> TestResult {
64+
let container = ContainerLifecycle::new();
65+
66+
// kill for non existed container
67+
match container.kill() {
68+
TestResult::Failed(_) => TestResult::Passed,
69+
TestResult::Passed => TestResult::Failed(anyhow!(
70+
"Expected killing non existed container to fail, but was successful"
71+
)),
72+
_ => TestResult::Failed(anyhow!(
73+
"Unexpected killing non existed container test result"
74+
)),
75+
}
76+
}
77+
78+
fn kill_created_container_test() -> TestResult {
79+
let container = ContainerLifecycle::new();
80+
81+
// kill created container
82+
match container.create() {
83+
TestResult::Passed => {}
84+
_ => return failed_and_delete("Failed to create container".to_string(), container),
85+
}
86+
let kill_result = container.kill();
87+
let delete_result = container.delete();
88+
merge_test_results(kill_result, delete_result)
89+
}
90+
91+
fn kill_stopped_container_test() -> TestResult {
92+
let container = ContainerLifecycle::new();
93+
let spec = create_spec(&["true"]).unwrap();
94+
95+
// kill stopped container
96+
match container.create_with_spec(spec) {
97+
TestResult::Passed => {}
98+
_ => return failed_and_delete("Failed to create container".to_string(), container),
99+
}
100+
match container.start() {
101+
TestResult::Passed => {}
102+
_ => return failed_and_delete("Failed to start container".to_string(), container),
103+
}
104+
container.waiting_for_status(Duration::from_secs(10), Duration::from_secs(1), "stopped");
105+
let kill_result = match container.kill() {
106+
TestResult::Failed(_) => TestResult::Passed,
107+
TestResult::Passed => TestResult::Failed(anyhow!("Expected failure but got success")),
108+
_ => TestResult::Failed(anyhow!("Unexpected test result")),
109+
};
110+
let delete_result = container.delete();
111+
merge_test_results(kill_result, delete_result)
112+
}
113+
114+
fn kill_start_container_test() -> TestResult {
115+
let container = ContainerLifecycle::new();
116+
let spec = create_spec(&["sleep", "30"]).unwrap();
117+
118+
// kill start container
119+
match container.create_with_spec(spec) {
120+
TestResult::Passed => {}
121+
_ => return failed_and_delete("Failed to recreate container".to_string(), container),
122+
}
123+
124+
match container.start() {
125+
TestResult::Passed => {}
126+
_ => return failed_and_delete(("Failed to start container").to_string(), container),
127+
}
128+
container.waiting_for_status(Duration::from_secs(10), Duration::from_secs(1), "running");
129+
let kill_result = container.kill();
130+
let delete_result = container.delete();
131+
merge_test_results(kill_result, delete_result)
132+
}
133+
134+
pub fn get_kill_test() -> TestGroup {
135+
let mut test_group = TestGroup::new("kill_container");
136+
137+
let kill_with_empty_id_test =
138+
Test::new("kill_with_empty_id_test", Box::new(kill_with_empty_id_test));
139+
let kill_non_existed_container = Test::new(
140+
"kill_non_existed_container",
141+
Box::new(kill_non_existed_container),
142+
);
143+
let kill_created_container_test = Test::new(
144+
"kill_created_container_test",
145+
Box::new(kill_created_container_test),
146+
);
147+
let kill_stopped_container_test = Test::new(
148+
"kill_stopped_container_test",
149+
Box::new(kill_stopped_container_test),
150+
);
151+
let kill_start_container_test = Test::new(
152+
"kill_start_container_test",
153+
Box::new(kill_start_container_test),
154+
);
155+
test_group.add(vec![
156+
Box::new(kill_with_empty_id_test),
157+
Box::new(kill_non_existed_container),
158+
Box::new(kill_created_container_test),
159+
Box::new(kill_stopped_container_test),
160+
Box::new(kill_start_container_test),
161+
]);
162+
test_group
163+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod kill_test;
2+
3+
pub use kill_test::get_kill_test;

tests/contest/contest/src/tests/lifecycle/container_lifecycle.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use std::thread::sleep;
2-
use std::time::Duration;
2+
use std::time::{Duration, Instant};
33

4+
use anyhow::anyhow;
5+
use oci_spec::runtime::Spec;
46
use test_framework::{TestResult, TestableGroup};
57

68
use super::util::criu_installed;
79
use super::{checkpoint, create, delete, exec, kill, start, state};
8-
use crate::utils::{generate_uuid, prepare_bundle};
10+
use crate::utils::{generate_uuid, get_state, prepare_bundle, set_config, State};
911

1012
// By experimenting, somewhere around 50 is enough for youki process
1113
// to get the kill signal and shut down
@@ -33,10 +35,19 @@ impl ContainerLifecycle {
3335
}
3436
}
3537

38+
pub fn set_id(&mut self, id: &str) {
39+
self.container_id = id.to_string();
40+
}
41+
3642
pub fn create(&self) -> TestResult {
3743
create::create(self.project_path.path(), &self.container_id).into()
3844
}
3945

46+
pub fn create_with_spec(&self, spec: Spec) -> TestResult {
47+
set_config(&self.project_path, &spec).unwrap();
48+
create::create(self.project_path.path(), &self.container_id).into()
49+
}
50+
4051
#[allow(dead_code)]
4152
pub fn exec(&self, cmd: Vec<&str>, expected_output: Option<&str>) -> TestResult {
4253
exec::exec(
@@ -86,6 +97,31 @@ impl ContainerLifecycle {
8697
&self.container_id,
8798
)
8899
}
100+
101+
pub fn waiting_for_status(
102+
&self,
103+
retry_timeout: Duration,
104+
poll_interval: Duration,
105+
target_status: &str,
106+
) -> TestResult {
107+
let start = Instant::now();
108+
while start.elapsed() < retry_timeout {
109+
let (out, err) = get_state(&self.container_id, &self.project_path).unwrap();
110+
if !err.is_empty() {
111+
self.kill();
112+
self.delete();
113+
return TestResult::Failed(anyhow!("error in state : {}", err));
114+
}
115+
116+
let state: State = serde_json::from_str(&out).unwrap();
117+
118+
if state.status == target_status {
119+
return TestResult::Passed;
120+
}
121+
sleep(poll_interval);
122+
}
123+
TestResult::Failed(anyhow!("error pod status is not update"))
124+
}
89125
}
90126

91127
impl TestableGroup for ContainerLifecycle {

tests/contest/contest/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod hooks;
77
pub mod hostname;
88
pub mod intel_rdt;
99
pub mod io_priority;
10+
pub mod kill;
1011
pub mod lifecycle;
1112
pub mod linux_ns_itype;
1213
pub mod mounts_recursive;

0 commit comments

Comments
 (0)