1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 03:57:44 +00:00

Merge pull request #828 from cbjadwani/uniq_add_tests

Uniq add tests
This commit is contained in:
Heather 2016-02-29 10:50:59 +04:00
commit 49a67bae33
19 changed files with 278 additions and 32 deletions

View file

@ -171,6 +171,7 @@ TEST_PROGS := \
truncate \ truncate \
tsort \ tsort \
unexpand \ unexpand \
uniq \
unlink \ unlink \
wc wc

View file

@ -16,7 +16,6 @@ extern crate getopts;
extern crate uucore; extern crate uucore;
use getopts::{Matches, Options}; use getopts::{Matches, Options};
use std::cmp::min;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, BufWriter, Read, stdin, stdout, Write}; use std::io::{BufRead, BufReader, BufWriter, Read, stdin, stdout, Write};
use std::path::Path; use std::path::Path;
@ -45,7 +44,7 @@ impl Uniq {
for io_line in reader.lines() { for io_line in reader.lines() {
let line = crash_if_err!(1, io_line); let line = crash_if_err!(1, io_line);
if !lines.is_empty() && self.cmp_key(&self.skip_fields(&lines[0])) != self.cmp_key(&self.skip_fields(&line)) { if !lines.is_empty() && self.cmp_key(&lines[0]) != self.cmp_key(&line) {
let print_delimiter = delimiters == "prepend" || (delimiters == "separate" && first_line_printed); let print_delimiter = delimiters == "prepend" || (delimiters == "separate" && first_line_printed);
first_line_printed |= self.print_lines(writer, &lines, print_delimiter); first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
lines.truncate(0); lines.truncate(0);
@ -59,47 +58,41 @@ impl Uniq {
} }
fn skip_fields(&self, line: &str) -> String { fn skip_fields(&self, line: &str) -> String {
match self.skip_fields { if let Some(skip_fields) = self.skip_fields {
Some(skip_fields) => if line.split_whitespace().count() > skip_fields {
if line.split_whitespace().count() > skip_fields { let mut field = 0;
let mut field = 0; let mut i = 0;
let mut i = 0; while field < skip_fields && i < line.len() {
while field < skip_fields && i < line.len() { while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() { i = i + 1;
i = i + 1;
}
while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
i = i + 1;
}
field = field + 1;
} }
line[i..].to_owned() while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
} else { i = i + 1;
"".to_owned() }
}, field = field + 1;
None => line[..].to_owned() }
line[i..].to_owned()
} else {
"".to_owned()
}
} else {
line[..].to_owned()
} }
} }
fn cmp_key(&self, line: &str) -> String { fn cmp_key(&self, line: &str) -> String {
let len = line.len(); let fields_to_check = &self.skip_fields(line);
let len = fields_to_check.len();
if len > 0 { if len > 0 {
let slice_start = match self.slice_start { fields_to_check.chars()
Some(i) => min(i, len - 1), .skip(self.slice_start.unwrap_or(0))
None => 0 .take(self.slice_stop.unwrap_or(len))
};
let slice_stop = match self.slice_stop {
Some(i) => min(slice_start + i, len),
None => len
};
line[slice_start..slice_stop].chars()
.map(|c| match c { .map(|c| match c {
'a' ... 'z' if self.ignore_case => ((c as u8) - 32) as char, 'a' ... 'z' if self.ignore_case => ((c as u8) - 32) as char,
_ => c, _ => c,
}).collect() }).collect()
} else { } else {
line.to_owned() fields_to_check.to_owned()
} }
} }

View file

@ -0,0 +1,9 @@
aaaaa 1
Xbbbb 2
XXbbb 2
ccccc 3
Xdddd 3
XXddd 3
XXXdd 1
eeee
fff

View file

@ -0,0 +1,2 @@
aaa aa a
aa a

View file

@ -0,0 +1,6 @@
aaaaa 1
Xbbbb 2
ccccc 3
Xdddd 3
eeee
fff

View file

@ -0,0 +1,7 @@
aaaaa 1
Xbbbb 2
ccccc 3
Xdddd 3
XXXdd 1
eeee
fff

View file

@ -0,0 +1,5 @@
aaaaa 1
Xbbbb 2
ccccc 3
XXXdd 1
eeee

12
tests/fixtures/uniq/skip-chars.txt vendored Normal file
View file

@ -0,0 +1,12 @@
aaaaa 1
Xbbbb 2
XXbbb 2
ccccc 3
Xcccc 3
ccccc 3
Xdddd 3
XXddd 3
XXXdd 1
XXXdd 1
eeee
fff

8
tests/fixtures/uniq/skip-fields.txt vendored Normal file
View file

@ -0,0 +1,8 @@
aaa aa a
ZZZ aa a
ZZZ aa a
ZZZ bb a
ZZZ bb a
aa a
a

View file

@ -0,0 +1,22 @@
bbbbb ⅱ
bbbbb ⅱ
ccccc ⅲ
ccccc ⅲ
ccccc ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
fffff ⅲ
fffff ⅲ
ggggg ⅲ
ggggg ⅲ
ggggg ⅲ
GGGGG ⅲ
GGGGG ⅲ

View file

@ -0,0 +1,21 @@
bbbbb ⅱ
bbbbb ⅱ
ccccc ⅲ
ccccc ⅲ
ccccc ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
fffff ⅲ
fffff ⅲ
ggggg ⅲ
ggggg ⅲ
ggggg ⅲ
GGGGG ⅲ
GGGGG ⅲ

View file

@ -0,0 +1,16 @@
bbbbb ⅱ
bbbbb ⅱ
ccccc ⅲ
ccccc ⅲ
ccccc ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
fffff ⅲ
fffff ⅲ
ggggg ⅲ
ggggg ⅲ
ggggg ⅲ
GGGGG ⅲ
GGGGG ⅲ

View file

@ -0,0 +1,8 @@
1 aaaaa
2 bbbbb ⅱ
3 ccccc ⅲ
4 ddddd ⅲ
1 eeeee ⅲ
2 fffff ⅲ
3 ggggg ⅲ
2 GGGGG ⅲ

View file

@ -0,0 +1,7 @@
aaaaa
bbbbb ⅱ
ccccc ⅲ
ddddd ⅲ
eeeee ⅲ
fffff ⅲ
ggggg ⅲ

View file

@ -0,0 +1,6 @@
bbbbb ⅱ
ccccc ⅲ
ddddd ⅲ
fffff ⅲ
ggggg ⅲ
GGGGG ⅲ

View file

@ -0,0 +1,8 @@
aaaaa
bbbbb ⅱ
ccccc ⅲ
ddddd ⅲ
eeeee ⅲ
fffff ⅲ
ggggg ⅲ
GGGGG ⅲ

View file

@ -0,0 +1,2 @@
aaaaa
eeeee ⅲ

18
tests/fixtures/uniq/sorted.txt vendored Normal file
View file

@ -0,0 +1,18 @@
aaaaa
bbbbb ⅱ
bbbbb ⅱ
ccccc ⅲ
ccccc ⅲ
ccccc ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
ddddd ⅲ
eeeee ⅲ
fffff ⅲ
fffff ⅲ
ggggg ⅲ
ggggg ⅲ
ggggg ⅲ
GGGGG ⅲ
GGGGG ⅲ

95
tests/uniq.rs Normal file
View file

@ -0,0 +1,95 @@
#[macro_use]
mod common;
use common::util::*;
static UTIL_NAME: &'static str = "uniq";
static INPUT: &'static str = "sorted.txt";
static SKIP_CHARS: &'static str = "skip-chars.txt";
static SKIP_FIELDS: &'static str = "skip-fields.txt";
#[test]
fn test_stdin_default() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-simple.expected"));
}
#[test]
fn test_single_default() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.arg(INPUT).run();
assert_eq!(result.stdout, at.read("sorted-simple.expected"));
}
#[test]
fn test_stdin_counts() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-c"]).run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-counts.expected"));
}
#[test]
fn test_stdin_skip_1_char() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-s1"]).run_piped_stdin(at.read(SKIP_CHARS));
assert_eq!(result.stdout, at.read("skip-1-char.expected"));
}
#[test]
fn test_stdin_skip_5_chars() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-s5"]).run_piped_stdin(at.read(SKIP_CHARS));
assert_eq!(result.stdout, at.read("skip-5-chars.expected"));
}
#[test]
fn test_stdin_skip_and_check_2_chars() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-s3", "-w2"]).run_piped_stdin(at.read(SKIP_CHARS));
assert_eq!(result.stdout, at.read("skip-3-check-2-chars.expected"));
}
#[test]
fn test_stdin_skip_1_field() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-f2"]).run_piped_stdin(at.read(SKIP_FIELDS));
assert_eq!(result.stdout, at.read("skip-2-fields.expected"));
}
#[test]
fn test_stdin_all_repeated() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["--all-repeated"]).run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-all-repeated.expected"));
}
#[test]
fn test_stdin_all_repeated_separate() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["--all-repeated", "separate"]).run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-all-repeated-separate.expected"));
}
#[test]
fn test_stdin_all_repeated_prepend() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["--all-repeated", "prepend"]).run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-all-repeated-prepend.expected"));
}
#[test]
fn test_stdin_unique_only() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-u"]).run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-unique-only.expected"));
}
#[test]
fn test_stdin_repeated_only() {
let (at, mut ucmd) = testing(UTIL_NAME);
let result = ucmd.args(&["-d"]).run_piped_stdin(at.read(INPUT));
assert_eq!(result.stdout, at.read("sorted-repeated-only.expected"));
}