use std::io::Write;
use dataprof::{DataProfilerError, EngineType, Profiler};
#[test]
fn missing_file_reports_the_real_path_not_unknown() {
let path = "definitely/does/not/exist/sales.csv";
let err = Profiler::new()
.analyze_file(path)
.expect_err("a missing file must be an error");
assert_eq!(err.category(), "file_not_found");
let msg = err.to_string();
assert!(msg.contains(path), "message should name the file: {msg}");
assert!(
!msg.contains("unknown"),
"path must not be 'unknown': {msg}"
);
}
#[test]
fn unsupported_format_does_not_overclaim() {
let mut file = tempfile::Builder::new().suffix(".xlsx").tempfile().unwrap();
write!(file, "not really a spreadsheet").unwrap();
file.flush().unwrap();
let err = Profiler::new()
.infer_schema(file.path())
.expect_err("xlsx is not a supported format");
assert_eq!(err.category(), "unsupported_format");
let msg = err.to_string();
assert!(
msg.contains("CSV"),
"message should list real formats: {msg}"
);
#[cfg(feature = "parquet")]
assert!(
msg.contains("Parquet"),
"a parquet build should advertise Parquet: {msg}"
);
#[cfg(not(feature = "parquet"))]
assert!(
!msg.contains("Parquet"),
"must not advertise Parquet without the feature: {msg}"
);
}
#[test]
fn non_utf8_csv_reports_one_clean_encoding_diagnostic() {
let mut file = tempfile::Builder::new().suffix(".csv").tempfile().unwrap();
file.write_all(b"name,city\nJos\xE9,Z\xFCrich\n").unwrap();
file.flush().unwrap();
for engine in [
EngineType::Auto,
EngineType::Incremental,
EngineType::Columnar,
] {
let err = Profiler::new()
.engine(engine)
.analyze_file(file.path())
.expect_err("non-UTF-8 CSV must fail rather than silently mis-decode");
assert_eq!(err.category(), "encoding");
let rendered = err.to_string();
assert!(!rendered.contains("unknown"), "{rendered}");
assert!(rendered.to_lowercase().contains("utf-8"), "{rendered}");
assert!(
rendered.contains("iconv"),
"gives a re-encode command: {rendered}"
);
assert!(!rendered.contains("All engines failed"), "{rendered}");
assert!(
!rendered.to_lowercase().contains("check file permissions"),
"encoding failure must not blame permissions: {rendered}"
);
}
}
#[test]
fn all_engines_failed_message_is_not_doubled() {
let err = DataProfilerError::AllEnginesFailed {
message: "Primary (Incremental): boom. Fallback (Arrow): boom.".to_string(),
};
let rendered = err.to_string();
assert_eq!(
rendered.matches("All engines failed").count(),
1,
"{rendered}"
);
}
#[test]
fn ragged_csv_is_not_mislabeled_as_encoding() {
let mut file = tempfile::Builder::new().suffix(".csv").tempfile().unwrap();
file.write_all(b"a,b\n\"unterminated,2\n").unwrap();
file.flush().unwrap();
if let Err(err) = Profiler::new().analyze_file(file.path()) {
assert_ne!(
err.category(),
"encoding",
"valid UTF-8 is not an encoding fault"
);
}
}
#[test]
fn error_suggestion_is_reachable_without_parsing_the_message() {
let err = DataProfilerError::unsupported_format("xlsx");
assert!(
err.suggestion().is_some(),
"actionable errors expose a structured suggestion"
);
}