Skip to content

Commit

Permalink
Merge pull request #20 from solc42/main
Browse files Browse the repository at this point in the history
ISSUE-15 support macos build
  • Loading branch information
bootjp committed Aug 2, 2022
2 parents f841525 + a4d293e commit 603165a
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ structopt = "0.3.21"
unix_mode = "0.1.1"
use = "0.0.0"
users = "0.11.0"

[dev-dependencies]
assert_cmd = "2.0.4"
ctor = "0.1.23"
39 changes: 22 additions & 17 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
use anyhow::Result;
use chrono::{Local, TimeZone};
use filesize::PathExt;
use humansize::{file_size_opts as options, FileSize};
use prettytable::format;
use prettytable::Table;
use std::path::PathBuf;
use std::process;
use std::{fs, os::unix::prelude::CommandExt};
use std::{io::Read, os::linux::fs::MetadataExt};
use std::io::Read;

#[cfg(target_os = "linux")]
use std::os::linux::fs::MetadataExt;
#[cfg(target_os = "macos")]
use std::os::macos::fs::MetadataExt;

use structopt::StructOpt;
use users::{get_group_by_gid, get_user_by_uid};

#[derive(StructOpt)]
struct Cli {
path: String,
#[structopt(long = "headless", long_help ="Do not print column names")]
is_headless: bool,
}

const SIZE_LESS: u64 = 1024 * 10;
Expand All @@ -38,7 +44,7 @@ fn main() -> Result<()> {

read_file(&mut file)
} else {
list_dir(&path)
list_dir(&path, args.is_headless)
};
}

Expand All @@ -51,16 +57,18 @@ fn read_file(file: &mut fs::File) -> Result<()> {

#[macro_use]
extern crate prettytable;
fn list_dir(path: &PathBuf) -> Result<()> {
fn list_dir(path: &PathBuf, is_headless: bool) -> Result<()> {
let mut table = Table::new();
table.set_titles(row![
"permission",
"user",
"group",
"name",
"last-modify",
"size"
]);
if !is_headless {
table.set_titles(row![
"permission",
"user",
"group",
"name",
"last-modify",
"size"
]);
}
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
let mut paths: Vec<_> = fs::read_dir(path)?.map(|r| r.unwrap()).collect();

Expand All @@ -83,10 +91,7 @@ fn list_dir(path: &PathBuf) -> Result<()> {
.map(|g| g.name().to_str().unwrap_or_default().to_owned())
.unwrap_or_default();
let stat = meta.st_mode();
let size = path
.size_on_disk()?
.file_size(options::CONVENTIONAL)
.unwrap_or_default();
let size = meta.st_size();
let lmtime = Local.timestamp(meta.st_mtime(), 0);

let file_name = match path.file_name() {
Expand Down
127 changes: 127 additions & 0 deletions tests/cli_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use assert_cmd::assert::OutputAssertExt;
use assert_cmd::cargo::CommandCargoExt;
use filetime::{set_file_mtime, FileTime};
use std::fs;
#[cfg(target_os = "linux")]
use std::os::linux::fs::MetadataExt;
#[cfg(target_os = "macos")]
use std::os::macos::fs::MetadataExt;
use std::os::unix::fs::PermissionsExt;
use std::process::Command;
use std::time::Duration;

#[cfg(test)]
#[ctor::ctor]
fn init() {
set_example_permissions();
set_example_modification_time();
}

fn bcat_at_examples() -> Command {
let mut cmd = Command::cargo_bin("bcat").unwrap();
cmd.current_dir("tests/examples");
cmd
}

#[test]
fn file_argument() {
let exp_stdout = fs::read_to_string("./tests/cli_tests_expected/file_arg_stdout.txt").unwrap();
bcat_at_examples()
.arg("./a_file.txt")
.assert()
.success()
.stdout(exp_stdout)
.stderr("");
}

#[test]
fn args_help() {
let exp_stdout = fs::read_to_string("./tests/cli_tests_expected/help_stdout.txt").unwrap();
bcat_at_examples()
.arg("--help")
.assert()
.success()
.stdout(exp_stdout)
.stderr("");
}

/**
* NB:
* Test is very fragile atm:
* - expects that test files owner/groups is the current user/group.
* - changes files/dirs modification time during execution, to allow stdout check vs expected times
* - changes files/dirs permission, which in general will not be same on all os/envs
* - substitutes size for directory, cause in general it will not be the same on all os
*
* BUT its good to have real render =)
*/
#[test]
fn dir_argument_headless() {
let user = users::get_current_username()
.expect("Failed to get current user name for test preparation");
let group = users::get_current_groupname()
.expect("Failed to get current user group for test preparation");
let dir_size_bytes = fs::File::open("./tests/examples/a_dir_name")
.unwrap()
.metadata()
.unwrap()
.st_size();
let dir_size_bytes = dir_size_bytes.to_string();

let exp_stdout = fs::read_to_string("./tests/cli_tests_expected/dir_arg_stdout.txt").unwrap();

let exp_stdout = exp_stdout.replace("<USER_PH>", user.to_string_lossy().as_ref());
let exp_stdout = exp_stdout.replace("<GROUP_PH>", group.to_string_lossy().as_ref());
let exp_stdout = exp_stdout.replace("<DIR_SIZE_PH>", &dir_size_bytes);

bcat_at_examples()
.arg("./")
.arg("--headless")
.assert()
.success()
.stdout(exp_stdout)
.stderr("");
}

#[test]
fn no_args_err() {
let exp_stderr = fs::read_to_string("./tests/cli_tests_expected/noargs_stderr.txt").unwrap();
bcat_at_examples()
.assert()
.failure()
.stdout("")
.stderr(exp_stderr);
}

fn set_example_permissions() {
fs::set_permissions(
"./tests/examples/a_file.txt",
fs::Permissions::from_mode(0o644),
)
.unwrap();
fs::set_permissions(
"./tests/examples/b_file.txt",
fs::Permissions::from_mode(0o644),
)
.unwrap();
fs::set_permissions(
"./tests/examples/a_dir_name",
fs::Permissions::from_mode(0o755),
)
.unwrap();
fs::set_permissions(
"./tests/examples/b_dir_name",
fs::Permissions::from_mode(0o755),
)
.unwrap();
}

fn set_example_modification_time() {
let ft = FileTime::from_system_time(std::time::UNIX_EPOCH + Duration::from_secs(10));
set_file_mtime("./tests/examples/a_file.txt", ft).unwrap();
set_file_mtime("./tests/examples/b_file.txt", ft).unwrap();

let ft = FileTime::from_system_time(std::time::UNIX_EPOCH + Duration::from_secs(3610));
set_file_mtime("./tests/examples/a_dir_name", ft).unwrap();
set_file_mtime("./tests/examples/b_dir_name", ft).unwrap();
}
4 changes: 4 additions & 0 deletions tests/cli_tests_expected/dir_arg_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
drwxr-xr-x | <USER_PH> | <GROUP_PH> | a_dir_name | 1970-01-01 04:00:10 +03:00 | <DIR_SIZE_PH>
-rw-r--r-- | <USER_PH> | <GROUP_PH> | a_file.txt | 1970-01-01 03:00:10 +03:00 | 20
drwxr-xr-x | <USER_PH> | <GROUP_PH> | b_dir_name | 1970-01-01 04:00:10 +03:00 | <DIR_SIZE_PH>
-rw-r--r-- | <USER_PH> | <GROUP_PH> | b_file.txt | 1970-01-01 03:00:10 +03:00 | 34
3 changes: 3 additions & 0 deletions tests/cli_tests_expected/file_arg_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
line 1
line 2
line 3
20 changes: 20 additions & 0 deletions tests/cli_tests_expected/help_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
bcat 0.1.3

USAGE:
bcat [FLAGS] <path>

FLAGS:
-h, --help
Prints help information

--headless
Do not print column names

-V, --version
Prints version information


ARGS:
<path>


7 changes: 7 additions & 0 deletions tests/cli_tests_expected/noargs_stderr.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: The following required arguments were not provided:
<path>

USAGE:
bcat [FLAGS] <path>

For more information try --help
Empty file added tests/examples/a_dir_name/.keep
Empty file.
3 changes: 3 additions & 0 deletions tests/examples/a_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
line 1
line 2
line 3
Empty file added tests/examples/b_dir_name/.keep
Empty file.
1 change: 1 addition & 0 deletions tests/examples/b_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
some payload to get non empty size

0 comments on commit 603165a

Please sign in to comment.