New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test(jailer): enable multi-threaded test #4438
base: main
Are you sure you want to change the base?
test(jailer): enable multi-threaded test #4438
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4438 +/- ##
==========================================
- Coverage 82.13% 81.66% -0.48%
==========================================
Files 255 243 -12
Lines 31268 29871 -1397
==========================================
- Hits 25683 24394 -1289
+ Misses 5585 5477 -108
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Hello @cm-iwata , Thank you for your contribution! |
@zulinx86 |
Could you please do the following things?:
Thanks! |
It's a matter of taste, but it might be better to use "test(jailer)" rather than "fix(jailer)". "fix" may look like fixing a bug of jailer. I believe it's like improvement of jailer unit tests. |
e0f47d6
to
7ddda51
Compare
3134792
to
33ced74
Compare
@zulinx86
fixed.
I believe I've probably fixed the relevant parts. ※I use GCEfor dev environment.
here is result.
|
pub struct CgroupBuilder<'a> { | ||
version: u8, | ||
hierarchies: HashMap<String, PathBuf>, | ||
mount_points: Vec<CgroupMountPoint>, | ||
proc_mounts_path: &'a str, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may use more memory than before.
It would be better to do:
pub struct CgroupBuilder<'a> { | |
version: u8, | |
hierarchies: HashMap<String, PathBuf>, | |
mount_points: Vec<CgroupMountPoint>, | |
proc_mounts_path: &'a str, | |
} | |
pub struct CgroupBuilder { | |
version: u8, | |
hierarchies: HashMap<String, PathBuf>, | |
mount_points: Vec<CgroupMountPoint>, | |
proc_mounts_path: &'static str, | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JonathanWoollett-Light
Thank you for your suggestion. However, since the field requires dynamic values.
Because it's necessary to isolate the environment between multiple threads running tests.
If static lifetime were used, multiple threads running tests would access the same directory, potentially causing fail tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only saw static strings passed to be used as proc_mounts_path
, if the number of threads in tests is constant we could have a static string for each. Could you point to where a non-static string is used?
This is a nit regardless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although only for testing, dynamic values are used in the following places:
firecracker/src/jailer/src/cgroup.rs
Lines 477 to 479 in 14f8f38
let mock_proc_mounts = format!( | |
"/tmp/firecracker/test/{}/jailer/proc/mounts", | |
rand::rand_alphanumerics(4).into_string().unwrap() |
firecracker/src/jailer/src/cgroup.rs
Line 608 in 14f8f38
let builder = CgroupBuilder::new(1, mock_cgroups.proc_mounts_path.as_str()); |
How about changing the type of proc_mounts_path to Cow<'static, str>? With this change, the production code can accept the constant PROC_MOUNTS, while the test code can dynamically generate a String. What do you think about this approach?
@cm-iwata Could you please squash 3134792 and 33ced74 into one commit? Two identical commits are shown in https://github.com/firecracker-microvm/firecracker/pull/4438/commits. |
src/jailer/src/cgroup.rs
Outdated
pub fn get_mock_proc_mounts() -> String { | ||
format!( | ||
"/tmp/firecracker/test/{}/jailer/proc/mounts", | ||
rand::rand_alphanumerics(4).into_string().unwrap() | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_mock_proc_mounts()
is always called just before MockCgroupFs::new()
. How about putting get_mock_proc_monts()
inside the MockCgroupFs::new()
? By doing this and owning the string, the lifetime parameter <'a>
of MockCgroupFs
can be removed as follows:
- pub fn get_mock_proc_mounts() -> String {
- format!(
- "/tmp/firecracker/test/{}/jailer/proc/mounts",
- rand::rand_alphanumerics(4).into_string().unwrap()
- )
- }
-
#[derive(Debug)]
- pub struct MockCgroupFs<'a> {
+ pub struct MockCgroupFs {
mounts_file: File,
- pub proc_mount_path: &'a str,
+ pub proc_mount_path: String,
}
// Helper object that simulates the layout of the cgroup file system
// This can be used for testing regardless of the availability of a particular
// version of cgroups on the system
- impl<'a> MockCgroupFs<'a> {
+ impl MockCgroupFs {
pub fn create_file_with_contents<P: AsRef<Path> + Debug>(
filename: P,
contents: &str,
@@ -480,10 +473,12 @@ pub mod test_util {
Ok(())
}
- pub fn new(
- mock_proc_mount: &'a str,
- ) -> std::result::Result<MockCgroupFs<'a>, std::io::Error> {
- let mock_proc_dir = Path::new(mock_proc_mount).parent().unwrap();
+ pub fn new() -> std::result::Result<MockCgroupFs, std::io::Error> {
+ let mock_proc_mount = format!(
+ "/tmp/firecracker/test/{}/jailer/proc/mounts",
+ rand::rand_alphanumerics(4).into_string().unwrap()
+ );
+ let mock_proc_dir = Path::new(&mock_proc_mount).parent().unwrap();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/jailer/src/cgroup.rs
Outdated
let f = File::open(PROC_MOUNTS) | ||
.map_err(|err| JailerError::FileOpen(PathBuf::from(PROC_MOUNTS), err))?; | ||
let f = File::open(b.proc_mounts_path) | ||
.map_err(|err| JailerError::FileOpen(PathBuf::from(&b.proc_mounts_path), err))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking, but &
can be removed.
.map_err(|err| JailerError::FileOpen(PathBuf::from(&b.proc_mounts_path), err))?; | |
.map_err(|err| JailerError::FileOpen(PathBuf::from(b.proc_mounts_path), err))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in e77496a
src/jailer/src/cgroup.rs
Outdated
@@ -72,7 +68,8 @@ impl CgroupBuilder { | |||
).map_err(JailerError::RegEx)?; | |||
|
|||
for l in BufReader::new(f).lines() { | |||
let l = l.map_err(|err| JailerError::ReadLine(PathBuf::from(PROC_MOUNTS), err))?; | |||
let l = | |||
l.map_err(|err| JailerError::ReadLine(PathBuf::from(&b.proc_mounts_path), err))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: See #4438 (comment)
l.map_err(|err| JailerError::ReadLine(PathBuf::from(&b.proc_mounts_path), err))?; | |
l.map_err(|err| JailerError::ReadLine(PathBuf::from(b.proc_mounts_path), err))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in e77496a
src/jailer/src/cgroup.rs
Outdated
mounts_file: File, | ||
pub proc_mount_path: &'a str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: the name proc_mounts_path
is used for CgroupBuilder
and the file path /proc/mounts
, so proc_mounts_path
would be preferable here as well.
pub proc_mount_path: &'a str, | |
pub proc_mounts_path: &'a str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in a9979ed
src/jailer/src/cgroup.rs
Outdated
@@ -478,28 +480,45 @@ pub mod test_util { | |||
Ok(()) | |||
} | |||
|
|||
pub fn new() -> std::result::Result<MockCgroupFs, std::io::Error> { | |||
pub fn new( | |||
mock_proc_mount: &'a str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: See #4438 (comment).
mock_proc_mount: &'a str, | |
mock_proc_mounts: &'a str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in a9979ed
Previously, all tests shared same temporary file/directory, causing concurrency conflicts when running tests in multi-threaded. Resolved test concurrency issues by incorporating random strings into file/directory names. Link: firecracker-microvm#4412 Signed-off-by: Tomoya Iwata <iwata.tomoya@classmethod.jp>
e01d256
to
6ec6be2
Compare
Renamed several variables. Because these variables are typically assigned to `/proc/mounts`. Signed-off-by: Tomoya Iwata <iwata.tomoya@classmethod.jp>
Move mocked path prepare process inside `MockCgroupFs::new()`. Signed-off-by: Tomoya Iwata <iwata.tomoya@classmethod.jp>
Remove unnecessary `&` from function call arguments Signed-off-by: Tomoya Iwata <iwata.tomoya@classmethod.jp>
Move mocked path prepare process inside `MockCgroupFs::new()`. Signed-off-by: Tomoya Iwata <iwata.tomoya@classmethod.jp>
I thought the code was functioning correctly after the fix, but I've noticed occasional test failures. 1.Too many open filesSometimes tests fail as follows.
The code causing this issue can be found here. firecracker/src/jailer/src/main.rs Lines 405 to 408 in b2eee19
When running the tests, 100 files are create per thread, it causing the file descriptor limit to be exceeded when running tests in multithread. Changing the loop condition 2. Bad file descriptorEven after fixing 1, tests may still fail.
I believe the cause is the following code. firecracker/src/jailer/src/main.rs Lines 442 to 445 in b2eee19
The error should occur in the following sequence:
Commenting out the above test cases allows the tests to run successfully. Do you have any suggestions for how to fix the code? I couldn't think of any good ideas, so I would appreciate any advice. |
Changes
Previously, all tests shared same temporary file/directory, causing concurrency conflicts when running tests in multi-threaded.
Resolved test concurrency issues by incorporating random strings into file/directory names.
Reason
Fixes #4412
License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md
.PR Checklist
PR.
CHANGELOG.md
.TODO
s link to an issue.contribution quality standards.
rust-vmm
.