use super::*;
use crate::matrix::parquet::{write_named_table, Column};
use crate::matrix::test_support::{scratch, scratch_gz, write_gz_members};
fn names(v: &[Box<str>]) -> Vec<&str> {
v.iter().map(std::convert::AsRef::as_ref).collect()
}
#[test]
fn plain_txt_one_name_per_line() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "genes.txt", "CD8A\nMS4A1\nLYZ\n");
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1", "LYZ"]);
}
#[test]
fn tsv_gene_celltype_keeps_only_the_gene_column() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(
&dir,
"markers.tsv",
"gene\tcelltype\nCD8A\tT cell\nMS4A1\tB cell\nLYZ\tMonocyte\n",
);
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1", "LYZ"]);
}
#[test]
fn csv_without_header_falls_back_to_first_column() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "markers.csv", "CD8A,T cell\nMS4A1,B cell\n");
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1"]);
}
#[test]
fn header_selects_the_named_column() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(
&dir,
"markers.tsv",
"celltype\tsymbol\nT cell\tCD8A\nB cell\tMS4A1\n",
);
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1"]);
}
#[test]
fn unrecognized_header_is_treated_as_data() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "genes.txt", "CD8A\nMS4A1\n");
assert_eq!(read_name_list(&f).unwrap().len(), 2);
}
#[test]
fn duplicates_and_blank_lines_are_dropped() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "genes.txt", "CD8A\n\nMS4A1\nCD8A\n \nLYZ\n");
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1", "LYZ"]);
}
#[test]
fn whitespace_separated_with_ragged_indent() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "genes.txt", " CD8A T cell\nMS4A1 B cell\n");
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1"]);
}
#[test]
fn quoted_csv_fields_are_unquoted() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(
&dir,
"genes.csv",
"\"gene\",\"celltype\"\n\"CD8A\",\"T cell\"\n",
);
let got = read_name_list(&f).unwrap();
assert_eq!(names(&got), ["CD8A"]);
}
#[test]
fn empty_file_is_an_error() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "genes.txt", "\n\n");
assert!(read_name_list(&f).is_err());
}
#[test]
fn parquet_gene_celltype_keeps_only_the_gene_column() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("markers.parquet");
let path = path.to_string_lossy().into_owned();
let genes: Vec<Box<str>> = vec!["CD8A".into(), "MS4A1".into(), "LYZ".into()];
let celltypes: Vec<Box<str>> = vec!["T cell".into(), "B cell".into(), "Monocyte".into()];
write_named_table(
&path,
"gene",
&genes,
&[("celltype".into(), Column::Str(&celltypes))],
)
.unwrap();
let got = read_name_list(&path).unwrap();
assert_eq!(names(&got), ["CD8A", "MS4A1", "LYZ"]);
}
#[test]
fn a_non_numeric_first_line_is_a_header() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "t.tsv", "gene\ts0\ts1\ng0\t1\t2\n");
assert_eq!(detect_header_row_numeric(&f, &['\t', ',']), Some(0));
}
#[test]
fn an_all_numeric_first_line_is_data() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "t.tsv", "g0\t1\t2\ng1\t3\t4\n");
assert_eq!(detect_header_row_numeric(&f, &['\t', ',']), None);
}
#[test]
fn quoted_numbers_are_still_numbers() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "t.csv", "\"g0\",\"1.5\",\"2\"\n");
assert_eq!(detect_header_row_numeric(&f, &['\t', ',']), None);
}
#[test]
fn header_detection_reads_through_gzip() {
let dir = tempfile::tempdir().unwrap();
let f = scratch_gz(&dir, "t.tsv.gz", "gene\ts0\ts1\ng0\t1\t2\n");
assert_eq!(detect_header_row_numeric(&f, &['\t', ',']), Some(0));
}
#[test]
fn first_line_fields_are_unquoted_and_trimmed() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "t.csv", "\"gene\", s0 ,s1\r\ng0,1,2\n");
let got = first_line_fields(&f, &['\t', ',']).unwrap();
assert_eq!(names(&got), ["gene", "s0", "s1"]);
}
#[test]
fn r_missing_values_do_not_make_a_data_row_a_header() {
let dir = tempfile::tempdir().unwrap();
let f = scratch(&dir, "t.tsv", "g0\tNA\t2\ng1\t3\tN/A\n");
assert_eq!(detect_header_row_numeric(&f, &['\t', ',']), None);
}
#[test]
fn a_multi_member_gzip_is_read_to_the_end() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("names.txt.gz");
write_gz_members(&path, "CD8A\nMS4A1\nLYZ\nNKG7\nGNLY\n", 3, true);
let got: Vec<String> = open_buf_reader(path.to_str().unwrap())
.unwrap()
.lines()
.map(|l| l.unwrap())
.collect();
assert_eq!(got, ["CD8A", "MS4A1", "LYZ", "NKG7", "GNLY"]);
}
#[test]
fn file_stem_drops_parquet_and_vcf_extensions_too() {
assert_eq!(
file_stem("a/Whole_Blood.v10.eQTLs.signif_pairs.parquet"),
"Whole_Blood.v10.eQTLs.signif_pairs"
);
assert_eq!(file_stem("ieu-a-2.vcf.gz"), "ieu-a-2");
assert_eq!(file_stem("x/goa_human.gaf.gz"), "goa_human");
}