@@ -327,3 +327,225 @@ impl VectorMutOps for FixedSizeListVectorMut {
327327 debug_assert_eq ! ( self . len, self . validity. len( ) ) ;
328328 }
329329}
330+
331+ #[ cfg( test) ]
332+ mod tests {
333+ use std:: sync:: Arc ;
334+
335+ use vortex_dtype:: { DType , PType } ;
336+ use vortex_mask:: { Mask , MaskMut } ;
337+
338+ use super :: * ;
339+ use crate :: { PVectorMut , VectorOps } ;
340+
341+ #[ test]
342+ fn test_core_operations ( ) {
343+ // Test with_capacity constructor.
344+ let dtype = DType :: Primitive ( PType :: I32 , vortex_dtype:: Nullability :: Nullable ) ;
345+ let mut vec = FixedSizeListVectorMut :: with_capacity ( & dtype, 3 , 10 ) ;
346+ assert_eq ! ( vec. len( ) , 0 ) ;
347+ assert_eq ! ( vec. list_size( ) , 3 ) ;
348+ assert ! ( vec. capacity( ) >= 10 ) ;
349+
350+ // Create a vector to extend from.
351+ let elements = Arc :: new (
352+ PVectorMut :: < i32 > :: from_iter ( [ 1 , 2 , 3 , 4 , 5 , 6 ] )
353+ . freeze ( )
354+ . into ( ) ,
355+ ) ;
356+ let validity = Mask :: new_true ( 2 ) ;
357+ let immutable = FixedSizeListVector :: new ( elements, 3 , validity) ;
358+
359+ // Test extend_from_vector.
360+ vec. extend_from_vector ( & immutable) ;
361+ assert_eq ! ( vec. len( ) , 2 ) ;
362+ assert_eq ! ( vec. elements( ) . len( ) , 6 ) ;
363+
364+ // Test append_nulls.
365+ vec. append_nulls ( 3 ) ;
366+ assert_eq ! ( vec. len( ) , 5 ) ;
367+ assert_eq ! ( vec. elements( ) . len( ) , 15 ) ; // 5 lists * 3 elements each.
368+
369+ // Test freeze and accessors.
370+ let frozen = vec. freeze ( ) ;
371+ assert_eq ! ( frozen. len( ) , 5 ) ;
372+ assert_eq ! ( frozen. list_size( ) , 3 ) ;
373+ assert_eq ! ( frozen. elements( ) . len( ) , 15 ) ;
374+ }
375+
376+ #[ test]
377+ fn test_split_unsplit_operations ( ) {
378+ // Create a vector with 6 lists, each containing 2 elements.
379+ let elements = PVectorMut :: < i32 > :: from_iter ( [
380+ 1 , 2 , // List 0
381+ 3 , 4 , // List 1
382+ 5 , 6 , // List 2
383+ 7 , 8 , // List 3
384+ 9 , 10 , // List 4
385+ 11 , 12 , // List 5
386+ ] ) ;
387+ let mut vec =
388+ FixedSizeListVectorMut :: new ( Box :: new ( elements. into ( ) ) , 2 , MaskMut :: new_true ( 6 ) ) ;
389+
390+ // Test split at different positions.
391+
392+ // Split at position 0 (take nothing).
393+ let split = vec. split_off ( 0 ) ;
394+ assert_eq ! ( vec. len( ) , 0 ) ;
395+ assert_eq ! ( split. len( ) , 6 ) ;
396+ vec. unsplit ( split) ;
397+ assert_eq ! ( vec. len( ) , 6 ) ;
398+
399+ // Split at middle position.
400+ let split = vec. split_off ( 3 ) ;
401+ assert_eq ! ( vec. len( ) , 3 ) ;
402+ assert_eq ! ( split. len( ) , 3 ) ;
403+ assert_eq ! ( vec. elements( ) . len( ) , 6 ) ; // 3 lists * 2 elements.
404+ assert_eq ! ( split. elements( ) . len( ) , 6 ) ; // 3 lists * 2 elements.
405+
406+ // Verify the correct elements are in each half.
407+ // First half should have [1,2,3,4,5,6].
408+ // Second half should have [7,8,9,10,11,12].
409+
410+ // Rejoin the parts.
411+ vec. unsplit ( split) ;
412+ assert_eq ! ( vec. len( ) , 6 ) ;
413+ assert_eq ! ( vec. elements( ) . len( ) , 12 ) ;
414+
415+ // Split at the end (take everything).
416+ let split = vec. split_off ( 6 ) ;
417+ assert_eq ! ( vec. len( ) , 6 ) ;
418+ assert_eq ! ( split. len( ) , 0 ) ;
419+ vec. unsplit ( split) ;
420+ assert_eq ! ( vec. len( ) , 6 ) ;
421+ }
422+
423+ #[ test]
424+ fn test_null_handling ( ) {
425+ // Test nullable lists with non-null elements.
426+ let elements = PVectorMut :: < i32 > :: from_iter ( [ 1 , 2 , 3 , 4 , 5 , 6 ] ) ;
427+ let validity = MaskMut :: new_true ( 3 ) ;
428+ // We can't directly set individual validity, but we can create vectors with nulls.
429+
430+ let mut vec = FixedSizeListVectorMut :: new ( Box :: new ( elements. into ( ) ) , 2 , validity) ;
431+
432+ // Append null lists.
433+ vec. append_nulls ( 2 ) ;
434+ assert_eq ! ( vec. len( ) , 5 ) ;
435+
436+ // After freezing, check validity is preserved.
437+ let frozen = vec. freeze ( ) ;
438+ assert_eq ! ( frozen. len( ) , 5 ) ;
439+ assert_eq ! ( frozen. validity( ) . true_count( ) , 3 ) ; // First 3 are valid.
440+
441+ // Test non-null lists with nullable elements.
442+ let elements_with_nulls = PVectorMut :: < i32 > :: from_iter ( [
443+ Some ( 1 ) ,
444+ None ,
445+ Some ( 3 ) , // First list has a null element.
446+ Some ( 4 ) ,
447+ Some ( 5 ) ,
448+ None , // Second list has a null element.
449+ ] ) ;
450+ let validity = MaskMut :: new_true ( 2 ) ; // Both lists are valid.
451+
452+ let mut vec =
453+ FixedSizeListVectorMut :: new ( Box :: new ( elements_with_nulls. into ( ) ) , 3 , validity) ;
454+
455+ assert_eq ! ( vec. len( ) , 2 ) ;
456+ assert_eq ! ( vec. elements( ) . len( ) , 6 ) ;
457+
458+ // Operations should preserve element nullability.
459+ let split = vec. split_off ( 1 ) ;
460+ assert_eq ! ( vec. len( ) , 1 ) ;
461+ assert_eq ! ( split. len( ) , 1 ) ;
462+
463+ vec. unsplit ( split) ;
464+ assert_eq ! ( vec. len( ) , 2 ) ;
465+ }
466+
467+ #[ test]
468+ fn test_edge_cases ( ) {
469+ // Test empty vector (0 lists).
470+ let elements = PVectorMut :: < i32 > :: from_iter ( Vec :: < i32 > :: new ( ) ) ;
471+ let validity = MaskMut :: new_true ( 0 ) ;
472+ let mut vec = FixedSizeListVectorMut :: new ( Box :: new ( elements. into ( ) ) , 3 , validity) ;
473+ assert_eq ! ( vec. len( ) , 0 ) ;
474+ assert_eq ! ( vec. list_size( ) , 3 ) ;
475+ assert_eq ! ( vec. elements( ) . len( ) , 0 ) ;
476+
477+ // Operations on empty vector.
478+ vec. append_nulls ( 1 ) ;
479+ assert_eq ! ( vec. len( ) , 1 ) ;
480+
481+ // Test single element list.
482+ let elements = PVectorMut :: < i32 > :: from_iter ( [ 42 ] ) ;
483+ let validity = MaskMut :: new_true ( 1 ) ;
484+ let vec = FixedSizeListVectorMut :: new (
485+ Box :: new ( elements. into ( ) ) ,
486+ 1 , // List size of 1.
487+ validity,
488+ ) ;
489+ assert_eq ! ( vec. len( ) , 1 ) ;
490+ assert_eq ! ( vec. list_size( ) , 1 ) ;
491+
492+ // Test large list size.
493+ let large_elements: Vec < i32 > = ( 0 ..1000 ) . collect ( ) ;
494+ let elements = PVectorMut :: < i32 > :: from_iter ( large_elements) ;
495+ let validity = MaskMut :: new_true ( 1 ) ; // Single list with 1000 elements.
496+ let vec = FixedSizeListVectorMut :: new ( Box :: new ( elements. into ( ) ) , 1000 , validity) ;
497+ assert_eq ! ( vec. len( ) , 1 ) ;
498+ assert_eq ! ( vec. list_size( ) , 1000 ) ;
499+ assert_eq ! ( vec. elements( ) . len( ) , 1000 ) ;
500+
501+ // Verify operations work correctly.
502+ let frozen = vec. freeze ( ) ;
503+ assert_eq ! ( frozen. len( ) , 1 ) ;
504+ assert_eq ! ( frozen. list_size( ) , 1000 ) ;
505+ }
506+
507+ #[ test]
508+ fn test_capacity_management ( ) {
509+ let dtype = DType :: Primitive ( PType :: I32 , vortex_dtype:: Nullability :: Nullable ) ;
510+
511+ // Test initial capacity from with_capacity.
512+ let mut vec = FixedSizeListVectorMut :: with_capacity ( & dtype, 3 , 10 ) ;
513+ assert ! ( vec. capacity( ) >= 10 ) ;
514+ assert ! ( vec. elements( ) . capacity( ) >= 30 ) ; // At least 10 lists * 3 elements.
515+
516+ // Test reserve works without panicking.
517+ // The exact capacity increase depends on the underlying allocation strategy.
518+ vec. reserve ( 100 ) ;
519+ // After reserving, we should be able to hold at least the current length + reserved amount.
520+ // Since current length is 0, capacity should be at least 100.
521+ assert ! ( vec. capacity( ) >= 100 ) ;
522+
523+ // Test capacity calculation with different list sizes.
524+ let vec2 = FixedSizeListVectorMut :: with_capacity ( & dtype, 5 , 20 ) ;
525+ assert ! ( vec2. capacity( ) >= 20 ) ;
526+ assert ! ( vec2. elements( ) . capacity( ) >= 100 ) ; // At least 20 lists * 5 elements.
527+
528+ // Edge case: capacity when list_size = 0.
529+ // Based on the documentation, capacity is infinite (usize::MAX) for degenerate case.
530+ let vec3 = FixedSizeListVectorMut :: with_capacity ( & dtype, 0 , 10 ) ;
531+ assert_eq ! ( vec3. capacity( ) , usize :: MAX ) ; // Infinite capacity for degenerate case.
532+
533+ // Test that capacity is preserved through operations.
534+ let elements = PVectorMut :: < i32 > :: from_iter ( [ 1 , 2 , 3 , 4 , 5 , 6 ] ) ;
535+ vec. elements = Box :: new ( elements. into ( ) ) ;
536+ vec. validity = MaskMut :: new_true ( 2 ) ;
537+ vec. len = 2 ;
538+ vec. list_size = 3 ;
539+
540+ vec. reserve ( 8 ) ; // Reserve space for 8 more lists.
541+ assert ! ( vec. capacity( ) >= 10 ) ;
542+
543+ // Test that split_off and unsplit work without panicking.
544+ let split = vec. split_off ( 1 ) ;
545+ assert_eq ! ( vec. len( ) , 1 ) ;
546+ assert_eq ! ( split. len( ) , 1 ) ;
547+
548+ vec. unsplit ( split) ;
549+ assert_eq ! ( vec. len( ) , 2 ) ;
550+ }
551+ }
0 commit comments