mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
Using the pty helper function for the more bin testing
This commit is contained in:
parent
29adc24d0e
commit
10bcf65afa
1 changed files with 201 additions and 93 deletions
|
|
@ -3,144 +3,252 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use std::io::IsTerminal;
|
||||
|
||||
#[cfg(unix)]
|
||||
use nix::unistd::{read, write};
|
||||
#[cfg(unix)]
|
||||
use std::fs::File;
|
||||
#[cfg(unix)]
|
||||
use std::fs::{Permissions, set_permissions};
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
#[cfg(unix)]
|
||||
use uutests::util::pty_path;
|
||||
use uutests::{at_and_ucmd, new_ucmd};
|
||||
|
||||
#[cfg(unix)]
|
||||
fn run_more_with_pty(
|
||||
args: &[&str],
|
||||
file: &str,
|
||||
content: &str,
|
||||
) -> (uutests::util::UChild, std::os::fd::OwnedFd, String) {
|
||||
let (path, controller, _replica) = pty_path();
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.write(file, content);
|
||||
|
||||
let mut child = ucmd
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.args(args)
|
||||
.arg(file)
|
||||
.run_no_wait();
|
||||
|
||||
child.delay(100);
|
||||
let mut output = vec![0u8; 1024];
|
||||
let n = read(&controller, &mut output).unwrap();
|
||||
let output_str = String::from_utf8_lossy(&output[..n]).to_string();
|
||||
|
||||
(child, controller, output_str)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn quit_more(controller: &std::os::fd::OwnedFd, mut child: uutests::util::UChild) {
|
||||
write(controller, b"q").unwrap();
|
||||
child.delay(50);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_no_arg() {
|
||||
if std::io::stdout().is_terminal() {
|
||||
new_ucmd!()
|
||||
.terminal_simulation(true)
|
||||
.fails()
|
||||
.stderr_contains("more: bad usage");
|
||||
}
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.fails()
|
||||
.stderr_contains("more: bad usage");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_valid_arg() {
|
||||
if std::io::stdout().is_terminal() {
|
||||
let args_list: Vec<&[&str]> = vec![
|
||||
&["-c"],
|
||||
&["--clean-print"],
|
||||
&["-p"],
|
||||
&["--print-over"],
|
||||
&["-s"],
|
||||
&["--squeeze"],
|
||||
&["-u"],
|
||||
&["--plain"],
|
||||
&["-n", "10"],
|
||||
&["--lines", "0"],
|
||||
&["--number", "0"],
|
||||
&["-F", "10"],
|
||||
&["--from-line", "0"],
|
||||
&["-P", "something"],
|
||||
&["--pattern", "-1"],
|
||||
];
|
||||
for args in args_list {
|
||||
test_alive(args);
|
||||
}
|
||||
let args_list: Vec<&[&str]> = vec![
|
||||
&["-c"],
|
||||
&["--clean-print"],
|
||||
&["-p"],
|
||||
&["--print-over"],
|
||||
&["-s"],
|
||||
&["--squeeze"],
|
||||
&["-u"],
|
||||
&["--plain"],
|
||||
&["-n", "10"],
|
||||
&["--lines", "0"],
|
||||
&["--number", "0"],
|
||||
&["-F", "10"],
|
||||
&["--from-line", "0"],
|
||||
&["-P", "something"],
|
||||
&["--pattern", "-1"],
|
||||
];
|
||||
for args in args_list {
|
||||
test_alive(args);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn test_alive(args: &[&str]) {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let (path, controller, _replica) = pty_path();
|
||||
|
||||
let content = "test content";
|
||||
let file = "test_file";
|
||||
at.write(file, content);
|
||||
|
||||
let mut cmd = ucmd.args(args).arg(file).run_no_wait();
|
||||
let mut child = ucmd
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.args(args)
|
||||
.arg(file)
|
||||
.run_no_wait();
|
||||
|
||||
// wait for more to start and display the file
|
||||
while cmd.is_alive() && !cmd.stdout_all().contains(content) {
|
||||
cmd.delay(50);
|
||||
}
|
||||
child.delay(100);
|
||||
|
||||
assert!(cmd.is_alive(), "Command should still be alive");
|
||||
assert!(child.is_alive(), "Command should still be alive");
|
||||
|
||||
// cleanup
|
||||
cmd.kill();
|
||||
write(&controller, b"q").unwrap();
|
||||
child.delay(50);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_invalid_arg() {
|
||||
if std::io::stdout().is_terminal() {
|
||||
new_ucmd!().arg("--invalid").fails();
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("--invalid")
|
||||
.fails();
|
||||
|
||||
new_ucmd!().arg("--lines").arg("-10").fails();
|
||||
new_ucmd!().arg("--number").arg("-10").fails();
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("--lines")
|
||||
.arg("-10")
|
||||
.fails();
|
||||
|
||||
new_ucmd!().arg("--from-line").arg("-10").fails();
|
||||
}
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("--from-line")
|
||||
.arg("-10")
|
||||
.fails();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_file_arg() {
|
||||
// Run the test only if there's a valid terminal, else do nothing
|
||||
// Maybe we could capture the error, i.e. "Device not found" in that case
|
||||
// but I am leaving this for later
|
||||
if std::io::stdout().is_terminal() {
|
||||
// Directory as argument
|
||||
new_ucmd!()
|
||||
.arg(".")
|
||||
.succeeds()
|
||||
.stderr_contains("'.' is a directory.");
|
||||
// Directory as argument
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg(".")
|
||||
.succeeds()
|
||||
.stderr_contains("'.' is a directory.");
|
||||
|
||||
// Single argument errors
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.mkdir_all("folder");
|
||||
ucmd.arg("folder")
|
||||
.succeeds()
|
||||
.stderr_contains("is a directory");
|
||||
// Single argument errors
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.mkdir_all("folder");
|
||||
ucmd.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("folder")
|
||||
.succeeds()
|
||||
.stderr_contains("is a directory");
|
||||
|
||||
new_ucmd!()
|
||||
.arg("nonexistent_file")
|
||||
.succeeds()
|
||||
.stderr_contains("No such file or directory");
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("nonexistent_file")
|
||||
.succeeds()
|
||||
.stderr_contains("No such file or directory");
|
||||
|
||||
// Multiple nonexistent files
|
||||
new_ucmd!()
|
||||
.arg("file2")
|
||||
.arg("file3")
|
||||
.succeeds()
|
||||
.stderr_contains("file2")
|
||||
.stderr_contains("file3");
|
||||
}
|
||||
// Multiple nonexistent files
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
new_ucmd!()
|
||||
.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("file2")
|
||||
.arg("file3")
|
||||
.succeeds()
|
||||
.stderr_contains("file2")
|
||||
.stderr_contains("file3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_family = "unix")]
|
||||
#[cfg(unix)]
|
||||
fn test_invalid_file_perms() {
|
||||
if std::io::stdout().is_terminal() {
|
||||
use std::fs::{Permissions, set_permissions};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let permissions = Permissions::from_mode(0o244);
|
||||
at.make_file("invalid-perms.txt");
|
||||
set_permissions(at.plus("invalid-perms.txt"), permissions).unwrap();
|
||||
ucmd.arg("invalid-perms.txt")
|
||||
.succeeds()
|
||||
.stderr_contains("permission denied");
|
||||
}
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let permissions = Permissions::from_mode(0o244);
|
||||
at.make_file("invalid-perms.txt");
|
||||
set_permissions(at.plus("invalid-perms.txt"), permissions).unwrap();
|
||||
ucmd.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg("invalid-perms.txt")
|
||||
.succeeds()
|
||||
.stderr_contains("permission denied");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_more_non_utf8_paths() {
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
if std::io::stdout().is_terminal() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file_name = std::ffi::OsStr::from_bytes(b"test_\xFF\xFE.txt");
|
||||
// Create test file with normal name first
|
||||
at.write(
|
||||
&file_name.to_string_lossy(),
|
||||
"test content for non-UTF-8 file",
|
||||
);
|
||||
let (path, _controller, _replica) = pty_path();
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file_name = std::ffi::OsStr::from_bytes(b"test_\xFF\xFE.txt");
|
||||
// Create test file with normal name first
|
||||
at.write(
|
||||
&file_name.to_string_lossy(),
|
||||
"test content for non-UTF-8 file",
|
||||
);
|
||||
|
||||
// Test that more can handle non-UTF-8 filenames without crashing
|
||||
ucmd.arg(file_name).succeeds();
|
||||
}
|
||||
// Test that more can handle non-UTF-8 filenames without crashing
|
||||
ucmd.set_stdin(File::open(&path).unwrap())
|
||||
.set_stdout(File::create(&path).unwrap())
|
||||
.arg(file_name)
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_basic_display() {
|
||||
let (child, controller, output) = run_more_with_pty(&[], "test.txt", "line1\nline2\nline3\n");
|
||||
assert!(output.contains("line1"));
|
||||
quit_more(&controller, child);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_squeeze_blank_lines() {
|
||||
let (child, controller, output) =
|
||||
run_more_with_pty(&["-s"], "test.txt", "line1\n\n\n\nline2\n");
|
||||
assert!(output.contains("line1"));
|
||||
quit_more(&controller, child);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_pattern_search() {
|
||||
let (child, controller, output) = run_more_with_pty(
|
||||
&["-P", "target"],
|
||||
"test.txt",
|
||||
"foo\nbar\nbaz\ntarget\nend\n",
|
||||
);
|
||||
assert!(output.contains("target"));
|
||||
assert!(!output.contains("foo"));
|
||||
quit_more(&controller, child);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_from_line_option() {
|
||||
let (child, controller, output) =
|
||||
run_more_with_pty(&["-F", "2"], "test.txt", "line1\nline2\nline3\nline4\n");
|
||||
assert!(output.contains("line2"));
|
||||
assert!(!output.contains("line1"));
|
||||
quit_more(&controller, child);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue