Skip to content

Commit 57e0f41

Browse files
committed
Using the pty helper function for the more bin testing
1 parent bc0d474 commit 57e0f41

File tree

1 file changed

+207
-99
lines changed

1 file changed

+207
-99
lines changed

tests/by-util/test_more.rs

Lines changed: 207 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -3,144 +3,252 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
use std::io::IsTerminal;
7-
6+
#[cfg(unix)]
7+
use nix::unistd::{read, write};
8+
#[cfg(unix)]
9+
use std::fs::File;
10+
#[cfg(unix)]
11+
use std::fs::{Permissions, set_permissions};
12+
#[cfg(target_os = "linux")]
13+
use std::os::unix::ffi::OsStrExt;
14+
#[cfg(unix)]
15+
use std::os::unix::fs::PermissionsExt;
16+
#[cfg(unix)]
17+
use uutests::util::pty_path;
818
use uutests::{at_and_ucmd, new_ucmd};
919

20+
#[cfg(unix)]
21+
fn run_more_with_pty(
22+
args: &[&str],
23+
file: &str,
24+
content: &str,
25+
) -> (uutests::util::UChild, std::os::fd::OwnedFd, String) {
26+
let (path, controller, _replica) = pty_path();
27+
let (at, mut ucmd) = at_and_ucmd!();
28+
at.write(file, content);
29+
30+
let mut child = ucmd
31+
.set_stdin(File::open(&path).unwrap())
32+
.set_stdout(File::create(&path).unwrap())
33+
.args(args)
34+
.arg(file)
35+
.run_no_wait();
36+
37+
child.delay(100);
38+
let mut output = vec![0u8; 1024];
39+
let n = read(&controller, &mut output).unwrap();
40+
let output_str = String::from_utf8_lossy(&output[..n]).to_string();
41+
42+
(child, controller, output_str)
43+
}
44+
45+
#[cfg(unix)]
46+
fn quit_more(controller: &std::os::fd::OwnedFd, mut child: uutests::util::UChild) {
47+
write(controller, b"q").unwrap();
48+
child.delay(50);
49+
}
50+
1051
#[cfg(unix)]
1152
#[test]
1253
fn test_no_arg() {
13-
if std::io::stdout().is_terminal() {
14-
new_ucmd!()
15-
.terminal_simulation(true)
16-
.fails()
17-
.stderr_contains("more: bad usage");
18-
}
54+
let (path, _controller, _replica) = pty_path();
55+
new_ucmd!()
56+
.set_stdin(File::open(&path).unwrap())
57+
.set_stdout(File::create(&path).unwrap())
58+
.fails()
59+
.stderr_contains("more: bad usage");
1960
}
2061

2162
#[test]
63+
#[cfg(unix)]
2264
fn test_valid_arg() {
23-
if std::io::stdout().is_terminal() {
24-
let args_list: Vec<&[&str]> = vec![
25-
&["-c"],
26-
&["--clean-print"],
27-
&["-p"],
28-
&["--print-over"],
29-
&["-s"],
30-
&["--squeeze"],
31-
&["-u"],
32-
&["--plain"],
33-
&["-n", "10"],
34-
&["--lines", "0"],
35-
&["--number", "0"],
36-
&["-F", "10"],
37-
&["--from-line", "0"],
38-
&["-P", "something"],
39-
&["--pattern", "-1"],
40-
];
41-
for args in args_list {
42-
test_alive(args);
43-
}
65+
let args_list: Vec<&[&str]> = vec![
66+
&["-c"],
67+
&["--clean-print"],
68+
&["-p"],
69+
&["--print-over"],
70+
&["-s"],
71+
&["--squeeze"],
72+
&["-u"],
73+
&["--plain"],
74+
&["-n", "10"],
75+
&["--lines", "0"],
76+
&["--number", "0"],
77+
&["-F", "10"],
78+
&["--from-line", "0"],
79+
&["-P", "something"],
80+
&["--pattern", "-1"],
81+
];
82+
for args in args_list {
83+
test_alive(args);
4484
}
4585
}
4686

87+
#[cfg(unix)]
4788
fn test_alive(args: &[&str]) {
4889
let (at, mut ucmd) = at_and_ucmd!();
90+
let (path, controller, _replica) = pty_path();
4991

5092
let content = "test content";
5193
let file = "test_file";
5294
at.write(file, content);
5395

54-
let mut cmd = ucmd.args(args).arg(file).run_no_wait();
96+
let mut child = ucmd
97+
.set_stdin(File::open(&path).unwrap())
98+
.set_stdout(File::create(&path).unwrap())
99+
.args(args)
100+
.arg(file)
101+
.run_no_wait();
55102

56103
// wait for more to start and display the file
57-
while cmd.is_alive() && !cmd.stdout_all().contains(content) {
58-
cmd.delay(50);
59-
}
104+
child.delay(100);
60105

61-
assert!(cmd.is_alive(), "Command should still be alive");
106+
assert!(child.is_alive(), "Command should still be alive");
62107

63108
// cleanup
64-
cmd.kill();
109+
write(&controller, b"q").unwrap();
110+
child.delay(50);
65111
}
66112

67113
#[test]
114+
#[cfg(unix)]
68115
fn test_invalid_arg() {
69-
if std::io::stdout().is_terminal() {
70-
new_ucmd!().arg("--invalid").fails();
71-
72-
new_ucmd!().arg("--lines").arg("-10").fails();
73-
new_ucmd!().arg("--number").arg("-10").fails();
74-
75-
new_ucmd!().arg("--from-line").arg("-10").fails();
76-
}
116+
let (path, _controller, _replica) = pty_path();
117+
new_ucmd!()
118+
.set_stdin(File::open(&path).unwrap())
119+
.set_stdout(File::create(&path).unwrap())
120+
.arg("--invalid")
121+
.fails();
122+
123+
let (path, _controller, _replica) = pty_path();
124+
new_ucmd!()
125+
.set_stdin(File::open(&path).unwrap())
126+
.set_stdout(File::create(&path).unwrap())
127+
.arg("--lines")
128+
.arg("-10")
129+
.fails();
130+
131+
let (path, _controller, _replica) = pty_path();
132+
new_ucmd!()
133+
.set_stdin(File::open(&path).unwrap())
134+
.set_stdout(File::create(&path).unwrap())
135+
.arg("--from-line")
136+
.arg("-10")
137+
.fails();
77138
}
78139

79140
#[test]
141+
#[cfg(unix)]
80142
fn test_file_arg() {
81-
// Run the test only if there's a valid terminal, else do nothing
82-
// Maybe we could capture the error, i.e. "Device not found" in that case
83-
// but I am leaving this for later
84-
if std::io::stdout().is_terminal() {
85-
// Directory as argument
86-
new_ucmd!()
87-
.arg(".")
88-
.succeeds()
89-
.stderr_contains("'.' is a directory.");
90-
91-
// Single argument errors
92-
let (at, mut ucmd) = at_and_ucmd!();
93-
at.mkdir_all("folder");
94-
ucmd.arg("folder")
95-
.succeeds()
96-
.stderr_contains("is a directory");
97-
98-
new_ucmd!()
99-
.arg("nonexistent_file")
100-
.succeeds()
101-
.stderr_contains("No such file or directory");
102-
103-
// Multiple nonexistent files
104-
new_ucmd!()
105-
.arg("file2")
106-
.arg("file3")
107-
.succeeds()
108-
.stderr_contains("file2")
109-
.stderr_contains("file3");
110-
}
143+
// Directory as argument
144+
let (path, _controller, _replica) = pty_path();
145+
new_ucmd!()
146+
.set_stdin(File::open(&path).unwrap())
147+
.set_stdout(File::create(&path).unwrap())
148+
.arg(".")
149+
.succeeds()
150+
.stderr_contains("'.' is a directory.");
151+
152+
// Single argument errors
153+
let (path, _controller, _replica) = pty_path();
154+
let (at, mut ucmd) = at_and_ucmd!();
155+
at.mkdir_all("folder");
156+
ucmd.set_stdin(File::open(&path).unwrap())
157+
.set_stdout(File::create(&path).unwrap())
158+
.arg("folder")
159+
.succeeds()
160+
.stderr_contains("is a directory");
161+
162+
let (path, _controller, _replica) = pty_path();
163+
new_ucmd!()
164+
.set_stdin(File::open(&path).unwrap())
165+
.set_stdout(File::create(&path).unwrap())
166+
.arg("nonexistent_file")
167+
.succeeds()
168+
.stderr_contains("No such file or directory");
169+
170+
// Multiple nonexistent files
171+
let (path, _controller, _replica) = pty_path();
172+
new_ucmd!()
173+
.set_stdin(File::open(&path).unwrap())
174+
.set_stdout(File::create(&path).unwrap())
175+
.arg("file2")
176+
.arg("file3")
177+
.succeeds()
178+
.stderr_contains("file2")
179+
.stderr_contains("file3");
111180
}
112181

113182
#[test]
114-
#[cfg(target_family = "unix")]
183+
#[cfg(unix)]
115184
fn test_invalid_file_perms() {
116-
if std::io::stdout().is_terminal() {
117-
use std::fs::{Permissions, set_permissions};
118-
use std::os::unix::fs::PermissionsExt;
119-
120-
let (at, mut ucmd) = at_and_ucmd!();
121-
let permissions = Permissions::from_mode(0o244);
122-
at.make_file("invalid-perms.txt");
123-
set_permissions(at.plus("invalid-perms.txt"), permissions).unwrap();
124-
ucmd.arg("invalid-perms.txt")
125-
.succeeds()
126-
.stderr_contains("permission denied");
127-
}
185+
let (path, _controller, _replica) = pty_path();
186+
let (at, mut ucmd) = at_and_ucmd!();
187+
let permissions = Permissions::from_mode(0o244);
188+
at.make_file("invalid-perms.txt");
189+
set_permissions(at.plus("invalid-perms.txt"), permissions).unwrap();
190+
ucmd.set_stdin(File::open(&path).unwrap())
191+
.set_stdout(File::create(&path).unwrap())
192+
.arg("invalid-perms.txt")
193+
.succeeds()
194+
.stderr_contains("permission denied");
128195
}
129196

130197
#[test]
131198
#[cfg(target_os = "linux")]
132199
fn test_more_non_utf8_paths() {
133-
use std::os::unix::ffi::OsStrExt;
134-
if std::io::stdout().is_terminal() {
135-
let (at, mut ucmd) = at_and_ucmd!();
136-
let file_name = std::ffi::OsStr::from_bytes(b"test_\xFF\xFE.txt");
137-
// Create test file with normal name first
138-
at.write(
139-
&file_name.to_string_lossy(),
140-
"test content for non-UTF-8 file",
141-
);
142-
143-
// Test that more can handle non-UTF-8 filenames without crashing
144-
ucmd.arg(file_name).succeeds();
145-
}
200+
let (path, _controller, _replica) = pty_path();
201+
let (at, mut ucmd) = at_and_ucmd!();
202+
let file_name = std::ffi::OsStr::from_bytes(b"test_\xFF\xFE.txt");
203+
// Create test file with normal name first
204+
at.write(
205+
&file_name.to_string_lossy(),
206+
"test content for non-UTF-8 file",
207+
);
208+
209+
// Test that more can handle non-UTF-8 filenames without crashing
210+
ucmd.set_stdin(File::open(&path).unwrap())
211+
.set_stdout(File::create(&path).unwrap())
212+
.arg(file_name)
213+
.succeeds();
214+
}
215+
216+
#[test]
217+
#[cfg(unix)]
218+
fn test_basic_display() {
219+
let (child, controller, output) = run_more_with_pty(&[], "test.txt", "line1\nline2\nline3\n");
220+
assert!(output.contains("line1"));
221+
quit_more(&controller, child);
222+
}
223+
224+
#[test]
225+
#[cfg(unix)]
226+
fn test_squeeze_blank_lines() {
227+
let (child, controller, output) =
228+
run_more_with_pty(&["-s"], "test.txt", "line1\n\n\n\nline2\n");
229+
assert!(output.contains("line1"));
230+
quit_more(&controller, child);
231+
}
232+
233+
#[test]
234+
#[cfg(unix)]
235+
fn test_pattern_search() {
236+
let (child, controller, output) = run_more_with_pty(
237+
&["-P", "target"],
238+
"test.txt",
239+
"foo\nbar\nbaz\ntarget\nend\n",
240+
);
241+
assert!(output.contains("target"));
242+
assert!(!output.contains("foo"));
243+
quit_more(&controller, child);
244+
}
245+
246+
#[test]
247+
#[cfg(unix)]
248+
fn test_from_line_option() {
249+
let (child, controller, output) =
250+
run_more_with_pty(&["-F", "2"], "test.txt", "line1\nline2\nline3\nline4\n");
251+
assert!(output.contains("line2"));
252+
assert!(!output.contains("line1"));
253+
quit_more(&controller, child);
146254
}

0 commit comments

Comments
 (0)