pmap: implemented more-extended and most-extended options (#415)

* pmap: implemented more-extended and most-extended options

* fixed lint errors

* fixed test_pmap lint error

* Update tests/by-util/test_pmap.rs

Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>

* Update tests/by-util/test_pmap.rs

Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>

* fixed typo

---------

Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>
This commit is contained in:
estodi
2025-05-14 06:20:02 -07:00
committed by GitHub
parent 23ad5d8f14
commit 1dafe8db4c
5 changed files with 1138 additions and 148 deletions
+124 -5
View File
@@ -107,6 +107,36 @@ fn test_extended() {
}
}
#[test]
#[cfg(target_os = "linux")]
fn test_more_extended() {
let pid = process::id();
let arg = "-X";
let result = new_ucmd!()
.arg(arg)
.arg(pid.to_string())
.succeeds()
.stdout_move_str();
assert_more_extended_format(pid, &result);
}
#[test]
#[cfg(target_os = "linux")]
fn test_most_extended() {
let pid = process::id();
let arg = "--XX";
let result = new_ucmd!()
.arg(arg)
.arg(pid.to_string())
.succeeds()
.stdout_move_str();
assert_most_extended_format(pid, &result);
}
#[test]
#[cfg(target_os = "linux")]
fn test_extended_permission_denied() {
@@ -211,10 +241,10 @@ fn assert_extended_format(pid: u32, s: &str) {
let line_count = lines.len();
let re = Regex::new(&format!("^{pid}: .+[^ ]$")).unwrap();
assert!(re.is_match(lines[0]));
assert!(re.is_match(lines[0]), "failing line: '{}'", lines[0]);
let expected_header = "Address Kbytes RSS Dirty Mode Mapping";
assert_eq!(expected_header, lines[1]);
assert_eq!(expected_header, lines[1], "failing line: '{}'", lines[1]);
let re = Regex::new(
r"^[0-9a-f]{16} +[1-9][0-9]* +\d+ +\d+ (-|r)(-|w)(-|x)(-|s)- ( \[ (anon|stack) \]|[a-zA-Z0-9._-]+)$",
@@ -222,16 +252,105 @@ fn assert_extended_format(pid: u32, s: &str) {
.unwrap();
for line in lines.iter().take(line_count - 2).skip(2) {
assert!(re.is_match(line), "failing line: {line}");
assert!(re.is_match(line), "failing line: '{line}'");
}
let expected_separator = "---------------- ------- ------- ------- ";
assert_eq!(expected_separator, lines[line_count - 2]);
assert_eq!(
expected_separator,
lines[line_count - 2],
"failing line: '{}'",
lines[line_count - 2]
);
let re = Regex::new(r"^total kB +[1-9][0-9]* +\d+ +\d+$").unwrap();
assert!(
re.is_match(lines[line_count - 1]),
"failing line: {}",
"failing line: '{}'",
lines[line_count - 1]
);
}
// Ensure `s` has the following more extended format (-X):
//
// 1234: /some/path
// Address Perm Offset Device Inode Size Rss Pss Pss_Dirty Referenced Anonymous LazyFree ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible Mapping
// 000073eb5f4c7000 r-xp 0000000000036000 008:00008 2274176 1284 1148 1148 0 1148 0 0 0 0 0 0 0 0 0 0 ld-linux-x86-64.so.2
// 00007ffd588fc000 r--p 0000000000000000 000:00000 2274176 20 20 20 20 20 20 0 0 0 0 0 0 0 0 0 [stack]
// ffffffffff600000 rw-p 0000000000000000 000:00000 2274176 36 36 36 36 36 36 0 0 0 0 0 0 0 0 0 (one intentional trailing space)
// ...
// ==== ==== ==== ========= ========== ========= ======== ============== ============= ============== =============== ==== ======= ====== =========== (one intentional trailing space)
// 4164 3448 2826 552 3448 552 0 0 0 0 0 0 0 0 0 KB (one intentional trailing space)
#[cfg(target_os = "linux")]
fn assert_more_extended_format(pid: u32, s: &str) {
let lines: Vec<_> = s.lines().collect();
let line_count = lines.len();
let re = Regex::new(&format!("^{pid}: .+[^ ]$")).unwrap();
assert!(re.is_match(lines[0]));
let re = Regex::new(r"^ Address Perm Offset Device Inode +Size +Rss +Pss +Pss_Dirty +Referenced +Anonymous( +KSM)? +LazyFree +ShmemPmdMapped +FilePmdMapped +Shared_Hugetlb +Private_Hugetlb +Swap +SwapPss +Locked +THPeligible( +ProtectionKey)? +Mapping$").unwrap();
assert!(re.is_match(lines[1]), "failing line: '{}'", lines[1]);
let re = Regex::new(r"^[0-9a-f]{16} (-|r)(-|w)(-|x)(p|s) [0-9a-f]{16} [0-9a-f]{3}:[0-9a-f]{5} +\d+ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? (|\[[a-zA-Z_ ]+\]|[a-zA-Z0-9._-]+)$").unwrap();
for line in lines.iter().take(line_count - 2).skip(2) {
assert!(re.is_match(line), "failing line: '{line}'");
}
let re = Regex::new(r"^ +=+ =+ =+ =+ =+ =+( =+)? =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? $").unwrap();
assert!(
re.is_match(lines[line_count - 2]),
"failing line: '{}'",
lines[line_count - 2]
);
let re = Regex::new(r"^ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? KB $").unwrap();
assert!(
re.is_match(lines[line_count - 1]),
"failing line: '{}'",
lines[line_count - 1]
);
}
// Ensure `s` has the following most extended format (--XX):
//
// 1234: /some/path
// Address Perm Offset Device Inode Size KernelPageSize MMUPageSize Rss Pss Pss_Dirty Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous LazyFree AnonHugePages ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPeligible VmFlags Mapping
// 000073eb5f4c7000 r-xp 0000000000036000 008:00008 2274176 1284 4 4 1148 1148 0 0 0 1148 0 1148 0 0 0 0 0 0 0 0 0 0 0 rd ex mr mw me ld-linux-x86-64.so.2
// 00007ffd588fc000 r--p 0000000000000000 000:00000 2274176 20 4 4 20 20 20 0 0 0 20 20 20 0 0 0 0 0 0 0 0 0 0 rd mr mw me ac [stack]
// ffffffffff600000 rw-p 0000000000000000 000:00000 2274176 36 4 4 36 36 36 0 0 0 36 36 36 0 0 0 0 0 0 0 0 0 0 rd wr mr mw me ac (one intentional trailing space)
// ...
// ==== ============== =========== ==== ==== ========= ============ ============ ============= ============= ========== ========= ======== ============= ============== ============= ============== =============== ==== ======= ====== =========== (one intentional trailing space)
// 4164 92 92 3448 2880 552 1132 0 1764 552 3448 552 0 0 0 0 0 0 0 0 0 0 KB (one intentional trailing space)
#[cfg(target_os = "linux")]
fn assert_most_extended_format(pid: u32, s: &str) {
let lines: Vec<_> = s.lines().collect();
let line_count = lines.len();
let re = Regex::new(&format!("^{pid}: .+[^ ]$")).unwrap();
assert!(re.is_match(lines[0]));
let re = Regex::new(r"^ Address Perm Offset Device Inode +Size +KernelPageSize +MMUPageSize +Rss +Pss +Pss_Dirty +Shared_Clean +Shared_Dirty +Private_Clean +Private_Dirty +Referenced +Anonymous( +KSM)? +LazyFree +AnonHugePages +ShmemPmdMapped +FilePmdMapped +Shared_Hugetlb +Private_Hugetlb +Swap +SwapPss +Locked +THPeligible( +ProtectionKey)? +VmFlags +Mapping$").unwrap();
assert!(re.is_match(lines[1]), "failing line: '{}'", lines[1]);
let re = Regex::new(r"^[0-9a-f]{16} (-|r)(-|w)(-|x)(p|s) [0-9a-f]{16} [0-9a-f]{3}:[0-9a-f]{5} +\d+ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +([a-z][a-z] )*(|\[[a-zA-Z_ ]+\]|[a-zA-Z0-9._-]+)$").unwrap();
for line in lines.iter().take(line_count - 2).skip(2) {
assert!(re.is_match(line), "failing line: '{line}'");
}
let re = Regex::new(r"^ +=+ =+ =+ =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? =+ =+ =+ =+ =+ =+ =+ =+ =+ =+( =+)? $").unwrap();
assert!(
re.is_match(lines[line_count - 2]),
"failing line: '{}'",
lines[line_count - 2]
);
let re = Regex::new(r"^ +[1-9][0-9]* +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+( +\d+)? KB $").unwrap();
assert!(
re.is_match(lines[line_count - 1]),
"failing line: '{}'",
lines[line_count - 1]
);
}