From e3aa2c080c329bf201c7392a1c35bf61146ca2a7 Mon Sep 17 00:00:00 2001 From: Tony Duan Date: Sat, 4 Jun 2022 16:05:53 +0800 Subject: [PATCH] test: hooks integration test See #361 Signed-off-by: Tony Duan --- .../integration_test/src/main.rs | 3 + .../src/tests/hooks/invoke.rs | 100 ++++++++++++++++++ .../integration_test/src/tests/hooks/mod.rs | 2 + .../integration_test/src/tests/mod.rs | 1 + 4 files changed, 106 insertions(+) create mode 100644 tests/rust-integration-tests/integration_test/src/tests/hooks/invoke.rs create mode 100644 tests/rust-integration-tests/integration_test/src/tests/hooks/mod.rs diff --git a/tests/rust-integration-tests/integration_test/src/main.rs b/tests/rust-integration-tests/integration_test/src/main.rs index 07acbff6c..f7fdb833e 100644 --- a/tests/rust-integration-tests/integration_test/src/main.rs +++ b/tests/rust-integration-tests/integration_test/src/main.rs @@ -1,6 +1,7 @@ mod tests; mod utils; +use crate::tests::hooks::get_hooks_tests; use crate::tests::lifecycle::{ContainerCreate, ContainerLifecycle}; use crate::tests::linux_ns_itype::get_ns_itype_tests; use crate::tests::pidfile::get_pidfile_test; @@ -78,6 +79,7 @@ fn main() -> Result<()> { let huge_tlb = get_tlb_test(); let pidfile = get_pidfile_test(); let ns_itype = get_ns_itype_tests(); + let hooks = get_hooks_tests(); let cgroup_v1_pids = cgroups::pids::get_test_group(); let cgroup_v1_cpu = cgroups::cpu::v1::get_test_group(); let cgroup_v2_cpu = cgroups::cpu::v2::get_test_group(); @@ -92,6 +94,7 @@ fn main() -> Result<()> { tm.add_test_group(&huge_tlb); tm.add_test_group(&pidfile); tm.add_test_group(&ns_itype); + tm.add_test_group(&hooks); tm.add_test_group(&cgroup_v1_pids); tm.add_test_group(&cgroup_v1_cpu); tm.add_test_group(&cgroup_v2_cpu); diff --git a/tests/rust-integration-tests/integration_test/src/tests/hooks/invoke.rs b/tests/rust-integration-tests/integration_test/src/tests/hooks/invoke.rs new file mode 100644 index 000000000..68f436fc8 --- /dev/null +++ b/tests/rust-integration-tests/integration_test/src/tests/hooks/invoke.rs @@ -0,0 +1,100 @@ +use anyhow::anyhow; +use oci_spec::runtime::{Hook, HookBuilder, HooksBuilder, ProcessBuilder, Spec, SpecBuilder}; +use std::{fs::File, io::Read}; +use test_framework::{Test, TestGroup, TestResult}; + +use crate::utils::{ + create_container, delete_container, generate_uuid, prepare_bundle, set_config, + test_utils::start_container, +}; + +const HOOK_OUTPUT_FILE: &str = "output"; + +fn create_hook_output_file() { + std::fs::File::create(HOOK_OUTPUT_FILE).expect("fail to create hook output file"); +} + +fn delete_hook_output_file() { + std::fs::remove_file(HOOK_OUTPUT_FILE).expect("fail to remove hook output file"); +} + +fn write_log_hook(content: &str) -> Hook { + let output = std::fs::canonicalize(HOOK_OUTPUT_FILE).unwrap(); + let output = output.to_str().unwrap(); + HookBuilder::default() + .path("/bin/sh") + .args(vec![ + "sh".to_string(), + "-c".to_string(), + format!("echo '{}' >> {}", content, output,), + ]) + .build() + .expect("could not build hook") +} + +fn get_spec() -> Spec { + SpecBuilder::default() + .process( + ProcessBuilder::default() + .args(vec!["true".to_string()]) + .build() + .unwrap(), + ) + .hooks( + HooksBuilder::default() + .prestart(vec![ + write_log_hook("pre-start1 called"), + write_log_hook("pre-start2 called"), + ]) + .poststart(vec![ + write_log_hook("post-start1 called"), + write_log_hook("post-start2 called"), + ]) + .poststop(vec![ + write_log_hook("post-stop1 called"), + write_log_hook("post-stop2 called"), + ]) + .build() + .expect("could not build hooks"), + ) + .build() + .unwrap() +} + +fn get_test<'a>(test_name: &'static str) -> Test<'a> { + Test::new( + test_name, + Box::new(move || { + create_hook_output_file(); + let spec = get_spec(); + let id = generate_uuid(); + let id_str = id.to_string(); + let bundle = prepare_bundle(&id).unwrap(); + set_config(&bundle, &spec).unwrap(); + create_container(&id_str, &bundle).unwrap().wait().unwrap(); + start_container(&id_str, &bundle).unwrap().wait().unwrap(); + delete_container(&id_str, &bundle).unwrap().wait().unwrap(); + let log = { + let mut output = File::open("output").expect("cannot open hook log"); + let mut log = String::new(); + output + .read_to_string(&mut log) + .expect("fail to read hook log"); + log + }; + delete_hook_output_file(); + if log != "pre-start1 called\npre-start2 called\npost-start1 called\npost-start2 called\npost-stop1 called\npost-stop2 called\n".to_string() { + return TestResult::Failed(anyhow!( + "error : hooks must be called in the listed order" + )); + } + TestResult::Passed + }), + ) +} + +pub fn get_hooks_tests<'a>() -> TestGroup<'a> { + let mut tg = TestGroup::new("hooks"); + tg.add(vec![Box::new(get_test("hooks"))]); + tg +} diff --git a/tests/rust-integration-tests/integration_test/src/tests/hooks/mod.rs b/tests/rust-integration-tests/integration_test/src/tests/hooks/mod.rs new file mode 100644 index 000000000..492b86a87 --- /dev/null +++ b/tests/rust-integration-tests/integration_test/src/tests/hooks/mod.rs @@ -0,0 +1,2 @@ +mod invoke; +pub use invoke::get_hooks_tests; diff --git a/tests/rust-integration-tests/integration_test/src/tests/mod.rs b/tests/rust-integration-tests/integration_test/src/tests/mod.rs index 40ec8cfb6..fac7d2b4e 100644 --- a/tests/rust-integration-tests/integration_test/src/tests/mod.rs +++ b/tests/rust-integration-tests/integration_test/src/tests/mod.rs @@ -1,4 +1,5 @@ pub mod cgroups; +pub mod hooks; pub mod lifecycle; pub mod linux_ns_itype; pub mod pidfile;