mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 14:52:41 +00:00
5e7d58650d
The code for creating a Passwd from the fields of the raw syscall result assumed that the syscall would return valid C strings in all non-error cases. This is not true, and at least one platform (Android) will populate the fields with null pointers where they are not supported. To fix this and prevent the error from happening again, this commit changes `cstr2string(ptr)` to check for a null pointer, and return an `Option<String>`, with `None` being the null pointer case. While arguably it should be the caller's job to check for a null pointer before calling (since the safety precondition is that the pointer is to a valid C string), relying on the type checker to force remembering this edge case is safer in the long run.
111 lines
3.8 KiB
Rust
111 lines
3.8 KiB
Rust
// * This file is part of the uutils coreutils package.
|
|
// *
|
|
// * For the full copyright and license information, please view the LICENSE
|
|
// * file that was distributed with this source code.
|
|
|
|
extern crate uucore;
|
|
|
|
use crate::common::util::*;
|
|
|
|
use self::uucore::entries::{Locate, Passwd};
|
|
|
|
extern crate pinky;
|
|
pub use self::pinky::*;
|
|
|
|
#[test]
|
|
fn test_capitalize() {
|
|
assert_eq!("Zbnmasd", "zbnmasd".capitalize()); // spell-checker:disable-line
|
|
assert_eq!("Abnmasd", "Abnmasd".capitalize()); // spell-checker:disable-line
|
|
assert_eq!("1masd", "1masd".capitalize()); // spell-checker:disable-line
|
|
assert_eq!("", "".capitalize());
|
|
}
|
|
|
|
#[test]
|
|
fn test_long_format() {
|
|
let login = "root";
|
|
let pw: Passwd = Passwd::locate(login).unwrap();
|
|
let user_info = pw.user_info.unwrap_or_default();
|
|
let user_dir = pw.user_dir.unwrap_or_default();
|
|
let user_shell = pw.user_shell.unwrap_or_default();
|
|
let real_name = user_info.replace('&', &pw.name.capitalize());
|
|
let ts = TestScenario::new(util_name!());
|
|
ts.ucmd().arg("-l").arg(login).succeeds().stdout_is(format!(
|
|
"Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n",
|
|
login, real_name, user_dir, user_shell
|
|
));
|
|
|
|
ts.ucmd()
|
|
.arg("-lb")
|
|
.arg(login)
|
|
.succeeds()
|
|
.stdout_is(format!(
|
|
"Login name: {:<28}In real life: {1}\n\n",
|
|
login, real_name
|
|
));
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn test_long_format_multiple_users() {
|
|
// multiple instances of one account we know exists,
|
|
// the account of the test runner,
|
|
// and an account that (probably) doesn't exist
|
|
let runner = match std::env::var("USER") {
|
|
Ok(user) => user,
|
|
Err(_) => "".to_string(),
|
|
};
|
|
let args = ["-l", "root", "root", "root", &runner, "no_such_user"];
|
|
let ts = TestScenario::new(util_name!());
|
|
let expect = unwrap_or_return!(expected_result(&ts, &args));
|
|
|
|
ts.ucmd()
|
|
.args(&args)
|
|
.succeeds()
|
|
.stdout_is(expect.stdout_str())
|
|
.stderr_is(expect.stderr_str());
|
|
}
|
|
|
|
#[test]
|
|
fn test_long_format_wo_user() {
|
|
// "no username specified; at least one must be specified when using -l"
|
|
new_ucmd!().arg("-l").fails();
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn test_short_format_i() {
|
|
// allow whitespace variation
|
|
// * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant
|
|
let args = ["-i"];
|
|
let ts = TestScenario::new(util_name!());
|
|
let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
|
|
let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
|
|
let v_actual: Vec<&str> = actual.split_whitespace().collect();
|
|
let v_expect: Vec<&str> = expect.split_whitespace().collect();
|
|
assert_eq!(v_actual, v_expect);
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn test_short_format_q() {
|
|
// allow whitespace variation
|
|
// * minor whitespace differences occur between platform built-in outputs; specifically, the number of trailing TABs may be variant
|
|
let args = ["-q"];
|
|
let ts = TestScenario::new(util_name!());
|
|
let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
|
|
let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
|
|
let v_actual: Vec<&str> = actual.split_whitespace().collect();
|
|
let v_expect: Vec<&str> = expect.split_whitespace().collect();
|
|
assert_eq!(v_actual, v_expect);
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn test_no_flag() {
|
|
let ts = TestScenario::new(util_name!());
|
|
let actual = ts.ucmd().succeeds().stdout_move_str();
|
|
let expect = unwrap_or_return!(expected_result(&ts, &[])).stdout_move_str();
|
|
let v_actual: Vec<&str> = actual.split_whitespace().collect();
|
|
let v_expect: Vec<&str> = expect.split_whitespace().collect();
|
|
assert_eq!(v_actual, v_expect);
|
|
}
|