libs/test-utils: share test code by create a new crate

More and more Rust code is introduced, the test utils original in agent
should be made easy to share, move it into a new crate will make it
easy to share between different crates.

Fixes: #4925

Signed-off-by: Bin Liu <bin@hyper.sh>
This commit is contained in:
Bin Liu 2022-08-16 17:40:30 +08:00 committed by bin liu
parent 334c7b3355
commit 34746496b7
19 changed files with 177 additions and 115 deletions

8
src/agent/Cargo.lock generated
View File

@ -651,6 +651,7 @@ dependencies = [
"slog-stdlog",
"sysinfo",
"tempfile",
"test-utils",
"thiserror",
"tokio",
"tokio-vsock",
@ -1769,6 +1770,13 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "test-utils"
version = "0.1.0"
dependencies = [
"nix 0.24.2",
]
[[package]]
name = "textwrap"
version = "0.15.0"

View File

@ -66,6 +66,7 @@ clap = { version = "3.0.1", features = ["derive"] }
[dev-dependencies]
tempfile = "3.1.0"
test-utils = { path = "../libs/test-utils" }
[workspace]
members = [

View File

@ -432,7 +432,7 @@ fn get_container_pipe_size(param: &str) -> Result<i32> {
#[cfg(test)]
mod tests {
use crate::assert_result;
use test_utils::assert_result;
use super::*;
use anyhow::anyhow;

View File

@ -49,8 +49,6 @@ mod pci;
pub mod random;
mod sandbox;
mod signal;
#[cfg(test)]
mod test_utils;
mod uevent;
mod util;
mod version;
@ -401,7 +399,8 @@ use std::os::unix::io::{FromRawFd, RawFd};
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::test_utils::TestUserType;
use test_utils::TestUserType;
use test_utils::{assert_result, skip_if_not_root, skip_if_root};
#[tokio::test]
async fn test_create_logger_task() {

View File

@ -1016,8 +1016,6 @@ fn parse_options(option_list: Vec<String>) -> HashMap<String, String> {
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::test_utils::TestUserType;
use crate::{skip_if_not_root, skip_loop_by_user, skip_loop_if_not_root, skip_loop_if_root};
use protobuf::RepeatedField;
use protocols::agent::FSGroup;
use std::fs::File;
@ -1025,6 +1023,10 @@ mod tests {
use std::io::Write;
use std::path::PathBuf;
use tempfile::tempdir;
use test_utils::TestUserType;
use test_utils::{
skip_if_not_root, skip_loop_by_user, skip_loop_if_not_root, skip_loop_if_root,
};
#[test]
fn test_mount() {

View File

@ -187,9 +187,10 @@ impl fmt::Debug for NamespaceType {
#[cfg(test)]
mod tests {
use super::{Namespace, NamespaceType};
use crate::{mount::remove_mounts, skip_if_not_root};
use crate::mount::remove_mounts;
use nix::sched::CloneFlags;
use tempfile::Builder;
use test_utils::skip_if_not_root;
#[tokio::test]
async fn test_setup_persistent_ns() {

View File

@ -724,10 +724,10 @@ impl Address {
#[cfg(test)]
mod tests {
use super::*;
use crate::skip_if_not_root;
use rtnetlink::packet;
use std::iter;
use std::process::Command;
use test_utils::skip_if_not_root;
#[tokio::test]
async fn find_link_by_name() {

View File

@ -76,11 +76,11 @@ fn do_setup_guest_dns(logger: Logger, dns_list: Vec<String>, src: &str, dst: &st
#[cfg(test)]
mod tests {
use super::*;
use crate::skip_if_not_root;
use nix::mount;
use std::fs::File;
use std::io::Write;
use tempfile::tempdir;
use test_utils::skip_if_not_root;
#[test]
fn test_setup_guest_dns() {

View File

@ -53,9 +53,9 @@ pub fn reseed_rng(data: &[u8]) -> Result<()> {
#[cfg(test)]
mod tests {
use super::*;
use crate::skip_if_not_root;
use std::fs::File;
use std::io::prelude::*;
use test_utils::skip_if_not_root;
#[test]
fn test_reseed_rng() {

View File

@ -1987,14 +1987,12 @@ fn load_kernel_module(module: &protocols::agent::KernelModule) -> Result<()> {
#[cfg(test)]
mod tests {
use super::*;
use crate::{
assert_result, namespace::Namespace, protocols::agent_ttrpc_async::AgentService as _,
skip_if_not_root,
};
use crate::{namespace::Namespace, protocols::agent_ttrpc_async::AgentService as _};
use nix::mount;
use nix::sched::{unshare, CloneFlags};
use oci::{Hook, Hooks, Linux, LinuxNamespace};
use tempfile::{tempdir, TempDir};
use test_utils::{assert_result, skip_if_not_root};
use ttrpc::{r#async::TtrpcContext, MessageHeader};
fn mk_ttrpc_context() -> TtrpcContext {

View File

@ -471,7 +471,7 @@ fn online_memory(logger: &Logger) -> Result<()> {
#[cfg(test)]
mod tests {
use super::*;
use crate::{mount::baremount, skip_if_not_root};
use crate::mount::baremount;
use anyhow::{anyhow, Error};
use nix::mount::MsFlags;
use oci::{Linux, Root, Spec};
@ -484,6 +484,7 @@ mod tests {
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use tempfile::{tempdir, Builder, TempDir};
use test_utils::skip_if_not_root;
fn bind_mount(src: &str, dst: &str, logger: &Logger) -> Result<(), Error> {
let src_path = Path::new(src);

View File

@ -1,99 +0,0 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
#![allow(clippy::module_inception)]
#[cfg(test)]
pub mod test_utils {
#[derive(Debug, PartialEq)]
pub enum TestUserType {
RootOnly,
NonRootOnly,
Any,
}
#[macro_export]
macro_rules! skip_if_root {
() => {
if nix::unistd::Uid::effective().is_root() {
println!("INFO: skipping {} which needs non-root", module_path!());
return;
}
};
}
#[macro_export]
macro_rules! skip_if_not_root {
() => {
if !nix::unistd::Uid::effective().is_root() {
println!("INFO: skipping {} which needs root", module_path!());
return;
}
};
}
#[macro_export]
macro_rules! skip_loop_if_root {
($msg:expr) => {
if nix::unistd::Uid::effective().is_root() {
println!(
"INFO: skipping loop {} in {} which needs non-root",
$msg,
module_path!()
);
continue;
}
};
}
#[macro_export]
macro_rules! skip_loop_if_not_root {
($msg:expr) => {
if !nix::unistd::Uid::effective().is_root() {
println!(
"INFO: skipping loop {} in {} which needs root",
$msg,
module_path!()
);
continue;
}
};
}
// Parameters:
//
// 1: expected Result
// 2: actual Result
// 3: string used to identify the test on error
#[macro_export]
macro_rules! assert_result {
($expected_result:expr, $actual_result:expr, $msg:expr) => {
if $expected_result.is_ok() {
let expected_value = $expected_result.as_ref().unwrap();
let actual_value = $actual_result.unwrap();
assert!(*expected_value == actual_value, "{}", $msg);
} else {
assert!($actual_result.is_err(), "{}", $msg);
let expected_error = $expected_result.as_ref().unwrap_err();
let expected_error_msg = format!("{:?}", expected_error);
let actual_error_msg = format!("{:?}", $actual_result.unwrap_err());
assert!(expected_error_msg == actual_error_msg, "{}", $msg);
}
};
}
#[macro_export]
macro_rules! skip_loop_by_user {
($msg:expr, $user:expr) => {
if $user == TestUserType::RootOnly {
skip_loop_if_not_root!($msg);
} else if $user == TestUserType::NonRootOnly {
skip_loop_if_root!($msg);
}
};
}
}

View File

@ -528,10 +528,10 @@ impl BindWatcher {
mod tests {
use super::*;
use crate::mount::is_mounted;
use crate::skip_if_not_root;
use nix::unistd::{Gid, Uid};
use std::fs;
use std::thread;
use test_utils::skip_if_not_root;
async fn create_test_storage(dir: &Path, id: &str) -> Result<(protos::Storage, PathBuf)> {
let src_path = dir.join(format!("src{}", id));

7
src/libs/Cargo.lock generated
View File

@ -1021,6 +1021,13 @@ dependencies = [
"winapi",
]
[[package]]
name = "test-utils"
version = "0.1.0"
dependencies = [
"nix 0.24.2",
]
[[package]]
name = "thiserror"
version = "1.0.30"

View File

@ -6,5 +6,6 @@ members = [
"safe-path",
"protocols",
"oci",
"test-utils",
]
resolver = "2"

View File

@ -10,3 +10,4 @@ Currently it provides following library crates:
| [system utilities](kata-sys-util/) | Collection of facilities and helpers to access system services. |
| [types](kata-types/) | Collection of constants and data types shared by multiple Kata Containers components. |
| [safe-path](safe-path/) | Utilities to safely resolve filesystem paths. |
| [test utilities](test-utils/) | Utilities to share test code. |

View File

@ -0,0 +1,15 @@
[package]
name = "test-utils"
version = "0.1.0"
description = "A library for test Rust code"
keywords = ["kata", "container", "test", "utils"]
categories = ["testing"]
authors = ["The Kata Containers community <kata-dev@lists.katacontainers.io>"]
repository = "https://github.com/kata-containers/kata-containers.git"
homepage = "https://katacontainers.io/"
readme = "README.md"
license = "Apache-2.0"
edition = "2018"
[dependencies]
nix = "0.24.2"

View File

@ -0,0 +1,8 @@
Test Utilities
====================
A library to share test code for Rust.
## License
This code is licensed under [Apache-2.0](../../../LICENSE).

View File

@ -0,0 +1,119 @@
// Copyright (c) 2019 Intel Corporation
// Copyright (c) 2022 Ant Group
//
// SPDX-License-Identifier: Apache-2.0
//
#[derive(Debug, PartialEq)]
pub enum TestUserType {
RootOnly,
NonRootOnly,
Any,
}
#[macro_export]
macro_rules! skip_if_root {
() => {
if nix::unistd::Uid::effective().is_root() {
println!("INFO: skipping {} which needs non-root", module_path!());
return;
}
};
}
#[macro_export]
macro_rules! skip_if_not_root {
() => {
if !nix::unistd::Uid::effective().is_root() {
println!("INFO: skipping {} which needs root", module_path!());
return;
}
};
}
#[macro_export]
macro_rules! skip_loop_if_root {
($msg:expr) => {
if nix::unistd::Uid::effective().is_root() {
println!(
"INFO: skipping loop {} in {} which needs non-root",
$msg,
module_path!()
);
continue;
}
};
}
#[macro_export]
macro_rules! skip_loop_if_not_root {
($msg:expr) => {
if !nix::unistd::Uid::effective().is_root() {
println!(
"INFO: skipping loop {} in {} which needs root",
$msg,
module_path!()
);
continue;
}
};
}
// Parameters:
//
// 1: expected Result
// 2: actual Result
// 3: string used to identify the test on error
#[macro_export]
macro_rules! assert_result {
($expected_result:expr, $actual_result:expr, $msg:expr) => {
if $expected_result.is_ok() {
let expected_value = $expected_result.as_ref().unwrap();
let actual_value = $actual_result.unwrap();
assert!(*expected_value == actual_value, "{}", $msg);
} else {
assert!($actual_result.is_err(), "{}", $msg);
let expected_error = $expected_result.as_ref().unwrap_err();
let expected_error_msg = format!("{:?}", expected_error);
let actual_error_msg = format!("{:?}", $actual_result.unwrap_err());
assert!(expected_error_msg == actual_error_msg, "{}", $msg);
}
};
}
#[macro_export]
macro_rules! skip_loop_by_user {
($msg:expr, $user:expr) => {
if $user == TestUserType::RootOnly {
skip_loop_if_not_root!($msg);
} else if $user == TestUserType::NonRootOnly {
skip_loop_if_root!($msg);
}
};
}
#[cfg(test)]
mod tests {
use super::{skip_if_not_root, skip_if_root};
#[test]
fn test_skip_if_not_root() {
skip_if_not_root!();
assert!(
nix::unistd::Uid::effective().is_root(),
"normal user should be skipped"
)
}
#[test]
fn test_skip_if_root() {
skip_if_root!();
assert!(
!nix::unistd::Uid::effective().is_root(),
"root user should be skipped"
)
}
}