use approx::assert_abs_diff_eq;
use arrow_array::Float64Array;
use ndarrow::{AsNdarray, NdarrowError};
#[test]
fn validated_succeeds_on_no_nulls() {
let arr = Float64Array::from(vec![1.0, 2.0, 3.0]);
let view = arr.as_ndarray().unwrap();
assert_eq!(view.len(), 3);
assert_abs_diff_eq!(view[0], 1.0);
assert_abs_diff_eq!(view[2], 3.0);
}
#[test]
fn validated_fails_on_single_null() {
let arr = Float64Array::from(vec![Some(1.0), None, Some(3.0)]);
let err = arr.as_ndarray().unwrap_err();
match err {
NdarrowError::NullsPresent { null_count } => assert_eq!(null_count, 1),
other => panic!("expected NullsPresent, got: {other}"),
}
}
#[test]
fn validated_fails_on_all_nulls() {
let arr = Float64Array::from(vec![None, None, None]);
let err = arr.as_ndarray().unwrap_err();
match err {
NdarrowError::NullsPresent { null_count } => assert_eq!(null_count, 3),
other => panic!("expected NullsPresent, got: {other}"),
}
}
#[test]
fn validated_null_check_is_o1() {
let data: Vec<f64> = (0..100_000).map(f64::from).collect();
let arr = Float64Array::from(data);
let view = arr.as_ndarray().unwrap();
assert_eq!(view.len(), 100_000);
}
#[test]
fn unchecked_succeeds_on_no_nulls() {
let arr = Float64Array::from(vec![10.0, 20.0, 30.0]);
let view = unsafe { arr.as_ndarray_unchecked() };
assert_eq!(view.len(), 3);
assert_abs_diff_eq!(view[1], 20.0);
}
#[test]
fn masked_no_nulls_returns_none_mask() {
let arr = Float64Array::from(vec![1.0, 2.0, 3.0]);
let (view, mask) = arr.as_ndarray_masked();
assert_eq!(view.len(), 3);
assert!(mask.is_none(), "no nulls should produce None mask");
}
#[test]
fn masked_with_nulls_returns_valid_mask() {
let arr = Float64Array::from(vec![Some(1.0), None, Some(3.0), None, Some(5.0)]);
let (view, mask) = arr.as_ndarray_masked();
assert_eq!(view.len(), 5);
let nulls = mask.expect("should have a validity bitmap");
assert!(nulls.is_valid(0));
assert!(!nulls.is_valid(1));
assert!(nulls.is_valid(2));
assert!(!nulls.is_valid(3));
assert!(nulls.is_valid(4));
}
#[test]
fn masked_view_can_be_used_with_mask() {
let arr = Float64Array::from(vec![Some(10.0), None, Some(30.0), None, Some(50.0)]);
let (view, mask) = arr.as_ndarray_masked();
let nulls = mask.unwrap();
let sum: f64 =
view.iter().enumerate().filter(|(i, _)| nulls.is_valid(*i)).map(|(_, v)| v).sum();
assert_abs_diff_eq!(sum, 90.0); }
#[test]
fn masked_all_nulls() {
let arr = Float64Array::from(vec![None, None, None]);
let (view, mask) = arr.as_ndarray_masked();
assert_eq!(view.len(), 3);
let nulls = mask.unwrap();
assert!(!nulls.is_valid(0));
assert!(!nulls.is_valid(1));
assert!(!nulls.is_valid(2));
}
#[test]
fn fsl_validated_rejects_outer_nulls() {
use std::sync::Arc;
use arrow_array::FixedSizeListArray;
use arrow_buffer::NullBuffer;
use arrow_schema::Field;
let values = Float64Array::from(vec![1.0, 2.0, 3.0, 4.0]);
let field = Arc::new(Field::new("item", arrow_schema::DataType::Float64, false));
let nulls = NullBuffer::from(vec![true, false]); let fsl = FixedSizeListArray::new(field, 2, Arc::new(values), Some(nulls));
let err =
ndarrow::fixed_size_list_as_array2::<arrow_array::types::Float64Type>(&fsl).unwrap_err();
match err {
NdarrowError::NullsPresent { null_count } => assert_eq!(null_count, 1),
other => panic!("expected NullsPresent, got: {other}"),
}
}
#[test]
fn fsl_masked_returns_outer_bitmap() {
use std::sync::Arc;
use arrow_array::FixedSizeListArray;
use arrow_buffer::NullBuffer;
use arrow_schema::Field;
let values = Float64Array::from(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
let field = Arc::new(Field::new("item", arrow_schema::DataType::Float64, false));
let nulls = NullBuffer::from(vec![true, false, true]); let fsl = FixedSizeListArray::new(field, 2, Arc::new(values), Some(nulls));
let (view, mask) =
ndarrow::fixed_size_list_as_array2_masked::<arrow_array::types::Float64Type>(&fsl).unwrap();
assert_eq!(view.dim(), (3, 2));
let outer_nulls = mask.unwrap();
assert!(outer_nulls.is_valid(0));
assert!(!outer_nulls.is_valid(1));
assert!(outer_nulls.is_valid(2));
}
#[test]
fn fsl_masked_rejects_inner_component_nulls() {
use std::sync::Arc;
use arrow_array::FixedSizeListArray;
use arrow_schema::Field;
let values = Float64Array::from(vec![Some(1.0), None, Some(3.0), Some(4.0)]);
let field = Arc::new(Field::new("item", arrow_schema::DataType::Float64, true));
let fsl = FixedSizeListArray::new(field, 2, Arc::new(values), None);
let err = ndarrow::fixed_size_list_as_array2_masked::<arrow_array::types::Float64Type>(&fsl)
.unwrap_err();
match err {
NdarrowError::NullsPresent { null_count } => assert_eq!(null_count, 1),
other => panic!("expected NullsPresent, got: {other}"),
}
}
#[test]
fn error_display_is_informative() {
let arr = Float64Array::from(vec![Some(1.0), None]);
let err = arr.as_ndarray().unwrap_err();
let msg = err.to_string();
assert!(msg.contains('1'), "should mention the null count");
assert!(msg.contains("null"), "should mention nulls");
}