use xportrs::{
Agency, Column, ColumnData, ColumnNames, Dataset, DomainCode, Error, IntoIter, Issue, Iter,
IterMut, Label, Severity, TextMode, ValidatedWrite, VariableName, VariableRole, Verbosity,
XptReaderBuilder, XptVersion, XptWriterBuilder,
};
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
#[test]
fn public_types_are_send() {
assert_send::<Dataset>();
assert_send::<Column>();
assert_send::<ColumnData>();
assert_send::<DomainCode>();
assert_send::<Label>();
assert_send::<VariableName>();
assert_send::<VariableRole>();
assert_send::<Agency>();
assert_send::<XptVersion>();
assert_send::<Severity>();
assert_send::<Issue>();
assert_send::<TextMode>();
assert_send::<Verbosity>();
assert_send::<Error>();
}
#[test]
fn public_types_are_sync() {
assert_sync::<Dataset>();
assert_sync::<Column>();
assert_sync::<ColumnData>();
assert_sync::<DomainCode>();
assert_sync::<Label>();
assert_sync::<VariableName>();
assert_sync::<VariableRole>();
assert_sync::<Agency>();
assert_sync::<XptVersion>();
assert_sync::<Severity>();
assert_sync::<Issue>();
assert_sync::<TextMode>();
assert_sync::<Verbosity>();
assert_sync::<Error>();
}
fn assert_debug<T: std::fmt::Debug>() {}
#[test]
fn public_types_implement_debug() {
assert_debug::<Dataset>();
assert_debug::<Column>();
assert_debug::<ColumnData>();
assert_debug::<DomainCode>();
assert_debug::<Label>();
assert_debug::<VariableName>();
assert_debug::<VariableRole>();
assert_debug::<Agency>();
assert_debug::<XptVersion>();
assert_debug::<Severity>();
assert_debug::<Issue>();
assert_debug::<TextMode>();
assert_debug::<Verbosity>();
assert_debug::<Error>();
assert_debug::<XptReaderBuilder>();
assert_debug::<XptWriterBuilder>();
assert_debug::<ValidatedWrite>();
}
#[test]
fn debug_representation_is_never_empty() {
let domain_code = DomainCode::new("AE");
let debug_str = format!("{:?}", domain_code);
assert!(
!debug_str.is_empty(),
"DomainCode Debug should not be empty"
);
let label = Label::new("Test Label");
let debug_str = format!("{:?}", label);
assert!(!debug_str.is_empty(), "Label Debug should not be empty");
let variable_name = VariableName::new("USUBJID");
let debug_str = format!("{:?}", variable_name);
assert!(
!debug_str.is_empty(),
"VariableName Debug should not be empty"
);
let severity = Severity::Error;
let debug_str = format!("{:?}", severity);
assert!(!debug_str.is_empty(), "Severity Debug should not be empty");
let agency = Agency::FDA;
let debug_str = format!("{:?}", agency);
assert!(!debug_str.is_empty(), "Agency Debug should not be empty");
let version = XptVersion::V5;
let debug_str = format!("{:?}", version);
assert!(
!debug_str.is_empty(),
"XptVersion Debug should not be empty"
);
let empty_data = ColumnData::F64(vec![]);
let debug_str = format!("{:?}", empty_data);
assert!(
!debug_str.is_empty(),
"Empty ColumnData Debug should not be empty"
);
let empty_dataset = Dataset::new("AE", vec![]).unwrap();
let debug_str = format!("{:?}", empty_dataset);
assert!(
!debug_str.is_empty(),
"Empty Dataset Debug should not be empty"
);
}
fn assert_error<T: std::error::Error>() {}
#[test]
fn error_implements_std_error() {
assert_error::<Error>();
}
#[test]
fn error_is_send_sync_static() {
fn assert_error_bounds<T: std::error::Error + Send + Sync + 'static>() {}
assert_error_bounds::<Error>();
}
fn assert_clone<T: Clone>() {}
fn assert_partial_eq<T: PartialEq>() {}
fn assert_eq<T: Eq>() {}
fn assert_hash<T: std::hash::Hash>() {}
fn assert_display<T: std::fmt::Display>() {}
fn assert_default<T: Default>() {}
#[test]
fn common_traits_clone() {
assert_clone::<Dataset>();
assert_clone::<Column>();
assert_clone::<ColumnData>();
assert_clone::<DomainCode>();
assert_clone::<Label>();
assert_clone::<VariableName>();
assert_clone::<VariableRole>();
assert_clone::<Agency>();
assert_clone::<XptVersion>();
assert_clone::<Severity>();
assert_clone::<Issue>();
}
#[test]
fn common_traits_partial_eq() {
assert_partial_eq::<Dataset>();
assert_partial_eq::<Column>();
assert_partial_eq::<ColumnData>();
assert_partial_eq::<DomainCode>();
assert_partial_eq::<Label>();
assert_partial_eq::<VariableName>();
assert_partial_eq::<VariableRole>();
assert_partial_eq::<Agency>();
assert_partial_eq::<XptVersion>();
assert_partial_eq::<Severity>();
assert_partial_eq::<Issue>();
}
#[test]
fn common_traits_eq() {
assert_eq::<DomainCode>();
assert_eq::<Label>();
assert_eq::<VariableName>();
assert_eq::<VariableRole>();
assert_eq::<Agency>();
assert_eq::<XptVersion>();
assert_eq::<Severity>();
assert_eq::<Issue>();
}
#[test]
fn common_traits_hash() {
assert_hash::<DomainCode>();
assert_hash::<Label>();
assert_hash::<VariableName>();
assert_hash::<VariableRole>();
assert_hash::<Agency>();
assert_hash::<XptVersion>();
assert_hash::<Severity>();
}
#[test]
fn common_traits_display() {
assert_display::<Dataset>();
assert_display::<Column>();
assert_display::<ColumnData>();
assert_display::<DomainCode>();
assert_display::<Label>();
assert_display::<VariableName>();
assert_display::<VariableRole>();
assert_display::<Agency>();
assert_display::<XptVersion>();
assert_display::<Severity>();
assert_display::<Issue>();
assert_display::<Error>();
}
#[test]
fn display_format_dataset() {
let dataset = Dataset::new(
"AE",
vec![
Column::new("A", ColumnData::F64(vec![Some(1.0), Some(2.0)])),
Column::new(
"B",
ColumnData::String(vec![Some("x".into()), Some("y".into())]),
),
],
)
.unwrap();
let display = format!("{}", dataset);
assert!(display.contains("AE"), "Display should contain domain code");
assert!(
display.contains("2 rows"),
"Display should contain row count"
);
assert!(
display.contains("2 cols"),
"Display should contain column count"
);
}
#[test]
fn display_format_column() {
let col = Column::new("USUBJID", ColumnData::String(vec![Some("01-001".into())]));
let display = format!("{}", col);
assert!(
display.contains("USUBJID"),
"Display should contain column name"
);
assert!(
display.contains("String"),
"Display should contain data type"
);
}
#[test]
fn display_format_column_data() {
let data = ColumnData::F64(vec![Some(1.0), Some(2.0), Some(3.0)]);
let display = format!("{}", data);
assert!(display.contains("F64"), "Display should contain type");
assert!(display.contains("3"), "Display should contain length");
}
#[test]
fn common_traits_default() {
assert_default::<XptVersion>();
assert_default::<TextMode>();
assert_default::<Verbosity>();
}
fn assert_ord<T: Ord>() {}
#[test]
fn common_traits_ord() {
assert_ord::<Severity>(); assert_ord::<XptVersion>();
}
#[test]
fn severity_ordering() {
assert!(Severity::Info < Severity::Warning);
assert!(Severity::Warning < Severity::Error);
assert!(Severity::Info < Severity::Error);
}
#[test]
fn xpt_version_ordering() {
assert!(XptVersion::V5 < XptVersion::V8);
}
#[test]
fn conversion_naming_conventions() {
let domain_code = DomainCode::new("AE");
let _: &str = domain_code.as_str();
let _: String = domain_code.into_inner();
let label = Label::new("Test");
let _: &str = label.as_str();
let _: String = label.into_inner();
let variable_name = VariableName::new("AGE");
let _: &str = variable_name.as_str();
let _: String = variable_name.into_inner();
}
#[test]
fn getter_naming_conventions() {
let dataset = Dataset::new(
"AE",
vec![Column::new(
"USUBJID",
ColumnData::String(vec![Some("01-001".into())]),
)],
)
.unwrap();
let _: &str = dataset.domain_code();
let _: Option<&str> = dataset.dataset_label();
let _: &[Column] = dataset.columns();
let _: usize = dataset.nrows();
let _: usize = dataset.ncols();
let column = &dataset.columns()[0];
let _: &str = column.name();
let _: Option<VariableRole> = column.role();
let _: &ColumnData = column.data();
}
#[test]
fn constructor_conventions() {
let _ = DomainCode::new("AE");
let _ = Label::new("Test");
let _ = Column::new("VAR", ColumnData::F64(vec![]));
let _ = Column::with_role("VAR", VariableRole::Identifier, ColumnData::F64(vec![]));
let _ = Dataset::with_label("AE", "Label", vec![]);
}
#[test]
fn iterator_type_names() {
let dataset = Dataset::new(
"AE",
vec![Column::new(
"USUBJID",
ColumnData::String(vec![Some("01-001".into())]),
)],
)
.unwrap();
let _: Iter<'_> = dataset.iter();
let _: ColumnNames<'_> = dataset.column_names();
let _: IntoIter = dataset.clone().into_iter();
}
#[test]
fn iterator_types_are_debug() {
assert_debug::<Iter<'_>>();
assert_debug::<IterMut<'_>>();
assert_debug::<IntoIter>();
assert_debug::<ColumnNames<'_>>();
}
#[test]
fn iterator_types_are_send_sync() {
assert_send::<Iter<'_>>();
assert_sync::<Iter<'_>>();
assert_send::<IterMut<'_>>();
assert_sync::<IterMut<'_>>();
assert_send::<IntoIter>();
assert_sync::<IntoIter>();
assert_send::<ColumnNames<'_>>();
assert_sync::<ColumnNames<'_>>();
}
#[test]
fn dataset_implements_index_by_position() {
let dataset = Dataset::new(
"AE",
vec![
Column::new("A", ColumnData::F64(vec![Some(1.0)])),
Column::new("B", ColumnData::F64(vec![Some(2.0)])),
],
)
.unwrap();
assert_eq!(dataset[0].name(), "A");
assert_eq!(dataset[1].name(), "B");
}
#[test]
fn dataset_implements_index_by_name() {
let dataset = Dataset::new(
"AE",
vec![
Column::new("USUBJID", ColumnData::String(vec![Some("01-001".into())])),
Column::new("AESEQ", ColumnData::F64(vec![Some(1.0)])),
],
)
.unwrap();
assert_eq!(dataset["USUBJID"].name(), "USUBJID");
assert_eq!(dataset["AESEQ"].name(), "AESEQ");
}
#[test]
fn dataset_implements_extend() {
let mut dataset = Dataset::new(
"AE",
vec![Column::new("A", ColumnData::F64(vec![Some(1.0)]))],
)
.unwrap();
dataset.extend([
Column::new("B", ColumnData::F64(vec![Some(2.0)])),
Column::new("C", ColumnData::F64(vec![Some(3.0)])),
]);
assert_eq!(dataset.ncols(), 3);
assert_eq!(dataset[1].name(), "B");
assert_eq!(dataset[2].name(), "C");
}
#[test]
fn validation_at_construction() {
let result = Dataset::new(
"AE",
vec![
Column::new("A", ColumnData::F64(vec![Some(1.0)])),
Column::new("B", ColumnData::F64(vec![Some(1.0), Some(2.0)])),
],
);
assert!(result.is_err(), "Should reject mismatched column lengths");
}