use sheeter_engine::{external_sort_delimited, SortSpec, Transforms};
fn sort(input: &str, spec: &str, chunk: usize) -> String {
let mut out = Vec::new();
external_sort_delimited(
input.as_bytes(),
b',',
&mut out,
b',',
&Transforms::default(),
&SortSpec::parse(spec).unwrap(),
chunk,
)
.unwrap();
String::from_utf8(out).unwrap()
}
#[test]
fn sort_ascending() {
let out = sort("n\n3\n1\n2\n", "n", 1000);
assert_eq!(out, "n\n1\n2\n3\n");
}
#[test]
fn sort_descending() {
let out = sort("n\n3\n1\n2\n", "n desc", 1000);
assert_eq!(out, "n\n3\n2\n1\n");
}
#[test]
fn sort_numeric_not_lexical() {
let out = sort("n\n10\n2\n33\n", "n", 1000);
assert_eq!(out, "n\n2\n10\n33\n");
}
#[test]
fn sort_multi_key() {
let input = "a,b\n2,x\n1,y\n2,w\n1,z\n";
let out = sort(input, "a,b desc", 1000);
assert_eq!(out, "a,b\n1,z\n1,y\n2,x\n2,w\n");
}
#[test]
fn sort_external_spill() {
let mut input = String::from("n\n");
for i in (0..20).rev() {
input.push_str(&format!("{i}\n"));
}
let out = sort(&input, "n", 2);
let mut expected = String::from("n\n");
for i in 0..20 {
expected.push_str(&format!("{i}\n"));
}
assert_eq!(out, expected);
}
#[test]
fn sort_with_filter() {
let t = Transforms {
filter: Some(sheeter_engine::Filter::parse("n >= 3").unwrap()),
..Default::default()
};
let mut out = Vec::new();
external_sort_delimited(
b"n\n5\n2\n4\n1\n3\n".as_slice(),
b',',
&mut out,
b',',
&t,
&SortSpec::parse("n").unwrap(),
1000,
)
.unwrap();
assert_eq!(String::from_utf8(out).unwrap(), "n\n3\n4\n5\n");
}
#[test]
fn sort_with_dedup() {
let t = Transforms {
dedup: Some(Vec::new()),
..Default::default()
};
let mut out = Vec::new();
external_sort_delimited(
b"n\n2\n1\n2\n3\n1\n".as_slice(),
b',',
&mut out,
b',',
&t,
&SortSpec::parse("n").unwrap(),
1000,
)
.unwrap();
assert_eq!(String::from_utf8(out).unwrap(), "n\n1\n2\n3\n");
}
#[test]
fn sort_with_dedup_by_column() {
let t = Transforms {
dedup: Some(vec!["email".to_string()]),
..Default::default()
};
let mut out = Vec::new();
external_sort_delimited(
b"email,name\nb@x.com,Bob\na@x.com,Alice\nb@x.com,Robert\n".as_slice(),
b',',
&mut out,
b',',
&t,
&SortSpec::parse("email").unwrap(),
1000,
)
.unwrap();
let result = String::from_utf8(out).unwrap();
assert_eq!(result.lines().count(), 3, "one duplicate removed: {result}");
assert!(result.contains("Alice"));
}
#[test]
fn sort_limit_interacts_correctly() {
let t = Transforms {
limit: Some(2),
..Default::default()
};
let mut out = Vec::new();
external_sort_delimited(
b"n\n3\n1\n2\n4\n".as_slice(),
b',',
&mut out,
b',',
&t,
&SortSpec::parse("n").unwrap(),
1000,
)
.unwrap();
assert_eq!(String::from_utf8(out).unwrap(), "n\n1\n3\n");
}