refactor(id) - move to clap and add more tests (#1628)

This commit is contained in:
Sylvestre Ledru 2020-11-21 09:52:50 +01:00 committed by GitHub
parent 41ba5ed913
commit 5efaa0bf32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 143 additions and 41 deletions

1
Cargo.lock generated
View file

@ -1669,6 +1669,7 @@ dependencies = [
name = "uu_id"
version = "0.0.1"
dependencies = [
"clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)",
"uucore 0.0.4",
"uucore_procs 0.0.4",
]

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/id.rs"
[dependencies]
clap = "2.33"
uucore = { version=">=0.0.4", package="uucore", path="../../uucore", features=["entries", "process"] }
uucore_procs = { version=">=0.0.4", package="uucore_procs", path="../../uucore_procs" }

View file

@ -15,8 +15,12 @@
#![allow(non_camel_case_types)]
#![allow(dead_code)]
extern crate clap;
#[macro_use]
extern crate uucore;
use clap::{App, Arg};
use std::ffi::CStr;
use uucore::entries::{self, Group, Locate, Passwd};
pub use uucore::libc;
@ -68,50 +72,100 @@ mod audit {
}
}
static SYNTAX: &str = "[OPTION]... [USER]";
static SUMMARY: &str = "Print user and group information for the specified USER,\n or (when USER omitted) for the current user.";
static ABOUT: &str = "Display user and group information for the specified USER,\n or (when USER omitted) for the current user.";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static OPT_AUDIT: &str = "audit";
static OPT_EFFECTIVE_USER: &str = "effective-user";
static OPT_GROUP: &str = "group";
static OPT_GROUPS: &str = "groups";
static OPT_HUMAN_READABLE: &str = "human-readable";
static OPT_NAME: &str = "name";
static OPT_PASSWORD: &str = "password";
static OPT_REAL_ID: &str = "real-id";
static ARG_USERS: &str = "users";
fn get_usage() -> String {
format!("{0} [OPTION]... [USER]", executable!())
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args.collect_str();
let usage = get_usage();
let mut opts = app!(SYNTAX, SUMMARY, "");
opts.optflag(
"A",
"",
"Display the process audit (not available on Linux)",
);
opts.optflag("G", "groups", "Display the different group IDs");
opts.optflag("g", "group", "Display the effective group ID as a number");
opts.optflag(
"n",
"",
"Display the name of the user or group ID for the -G, -g and -u options",
);
opts.optflag("P", "", "Display the id as a password file entry");
opts.optflag("p", "", "Make the output human-readable");
opts.optflag("r", "", "Display the real ID for the -g and -u options");
opts.optflag("u", "user", "Display the effective user ID as a number");
let matches = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_AUDIT)
.short("A")
.help("Display the process audit (not available on Linux)"),
)
.arg(
Arg::with_name(OPT_EFFECTIVE_USER)
.short("u")
.long("user")
.help("Display the effective user ID as a number"),
)
.arg(
Arg::with_name(OPT_GROUP)
.short("g")
.long(OPT_GROUP)
.help("Display the effective group ID as a number"),
)
.arg(
Arg::with_name(OPT_GROUPS)
.short("G")
.long(OPT_GROUPS)
.help("Display the different group IDs"),
)
.arg(
Arg::with_name(OPT_HUMAN_READABLE)
.short("p")
.help("Make the output human-readable"),
)
.arg(
Arg::with_name(OPT_NAME)
.short("n")
.help("Display the name of the user or group ID for the -G, -g and -u options"),
)
.arg(
Arg::with_name(OPT_PASSWORD)
.short("P")
.help("Display the id as a password file entry"),
)
.arg(
Arg::with_name(OPT_REAL_ID)
.short("r")
.help("Display the real ID for the -g and -u options"),
)
.arg(Arg::with_name(ARG_USERS).multiple(true).takes_value(true))
.get_matches_from(args);
let matches = opts.parse(args);
let users: Vec<String> = matches
.values_of(ARG_USERS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
if matches.opt_present("A") {
if matches.is_present(OPT_AUDIT) {
auditid();
return 0;
}
let possible_pw = if matches.free.is_empty() {
let possible_pw = if users.is_empty() {
None
} else {
match Passwd::locate(matches.free[0].as_str()) {
match Passwd::locate(users[0].as_str()) {
Ok(p) => Some(p),
Err(_) => crash!(1, "No such user/group: {}", matches.free[0]),
Err(_) => crash!(1, "No such user/group: {}", users[0]),
}
};
let nflag = matches.opt_present("n");
let uflag = matches.opt_present("u");
let gflag = matches.opt_present("g");
let rflag = matches.opt_present("r");
let nflag = matches.is_present(OPT_NAME);
let uflag = matches.is_present(OPT_EFFECTIVE_USER);
let gflag = matches.is_present(OPT_GROUP);
let rflag = matches.is_present(OPT_REAL_ID);
if gflag {
let id = possible_pw
@ -143,7 +197,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
return 0;
}
if matches.opt_present("G") {
if matches.is_present(OPT_GROUPS) {
println!(
"{}",
if nflag {
@ -167,12 +221,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
return 0;
}
if matches.opt_present("P") {
if matches.is_present(OPT_PASSWORD) {
pline(possible_pw.map(|v| v.uid()));
return 0;
};
if matches.opt_present("p") {
if matches.is_present(OPT_HUMAN_READABLE) {
pretty(possible_pw);
return 0;
}

View file

@ -1,5 +1,17 @@
use crate::common::util::*;
fn return_whoami_username() -> String {
let scene = TestScenario::new("whoami");
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return String::from("");
}
result.stdout.trim().to_string()
}
#[test]
fn test_id() {
let scene = TestScenario::new(util_name!());
@ -29,18 +41,14 @@ fn test_id() {
#[test]
fn test_id_from_name() {
let mut scene = TestScenario::new("whoami");
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let username = return_whoami_username();
if username == "" {
// Sometimes, the CI is failing here
return;
}
let username = result.stdout.trim();
scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg(username).succeeds();
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg(&username).succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
@ -139,3 +147,41 @@ fn test_id_user() {
let s1 = String::from(result.stdout.trim());
assert!(s1.parse::<f64>().is_ok());
}
#[test]
fn test_id_pretty_print() {
let username = return_whoami_username();
if username == "" {
// Sometimes, the CI is failing here
return;
}
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-p").run();
if result.stdout.trim() == "" {
// Sometimes, the CI is failing here with
// old rust versions on Linux
return;
}
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
assert!(result.stdout.contains(&username));
}
#[test]
fn test_id_password_style() {
let username = return_whoami_username();
if username == "" {
// Sometimes, the CI is failing here
return;
}
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-P").succeeds();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
assert!(result.success);
assert!(result.stdout.starts_with(&username));
}