@@ -887,6 +887,41 @@ impl From<BooleanBuffer> for BooleanArray {
887887#[ cfg( test) ]
888888mod tests {
889889 use super :: * ;
890+
891+ // Captures the values-buffer identity for a BooleanArray so tests can assert
892+ // whether an operation reused the original allocation or produced a new one.
893+ struct PointerInfo {
894+ ptr : * const u8 ,
895+ offset : usize ,
896+ len : usize ,
897+ }
898+
899+ impl PointerInfo {
900+ // Record the current values buffer pointer plus bit offset/length. The
901+ // offset/length checks ensure a logically equivalent slice wasn't rebuilt
902+ // with a different view over the same allocation.
903+ fn new ( array : & BooleanArray ) -> Self {
904+ Self {
905+ ptr : array. values ( ) . inner ( ) . as_ptr ( ) ,
906+ offset : array. values ( ) . offset ( ) ,
907+ len : array. values ( ) . len ( ) ,
908+ }
909+ }
910+
911+ // Assert that the array still points at the exact same values buffer and
912+ // preserves the same bit view.
913+ fn assert_same ( & self , array : & BooleanArray ) {
914+ assert_eq ! ( array. values( ) . inner( ) . as_ptr( ) , self . ptr) ;
915+ assert_eq ! ( array. values( ) . offset( ) , self . offset) ;
916+ assert_eq ! ( array. values( ) . len( ) , self . len) ;
917+ }
918+
919+ // Assert that the array now points at a different values allocation,
920+ // indicating the operation fell back to an allocating path.
921+ fn assert_different ( & self , array : & BooleanArray ) {
922+ assert_ne ! ( array. values( ) . inner( ) . as_ptr( ) , self . ptr) ;
923+ }
924+ }
890925 use arrow_buffer:: Buffer ;
891926 use rand:: { Rng , rng} ;
892927
@@ -1330,20 +1365,24 @@ mod tests {
13301365 #[ test]
13311366 fn test_bitwise_unary_mut_unshared ( ) {
13321367 let arr = BooleanArray :: from ( vec ! [ true , false , true , false ] ) ;
1368+ let info = PointerInfo :: new ( & arr) ;
13331369 let result = arr. bitwise_unary_mut ( |x| !x) . unwrap ( ) ;
13341370 let expected = BooleanArray :: from ( vec ! [ false , true , false , true ] ) ;
13351371 assert_eq ! ( result, expected) ;
1372+ info. assert_same ( & result) ;
13361373 }
13371374
13381375 #[ test]
13391376 fn test_bitwise_unary_mut_shared ( ) {
13401377 let arr = BooleanArray :: from ( vec ! [ true , false , true , false ] ) ;
1378+ let info = PointerInfo :: new ( & arr) ;
13411379 let _shared = arr. clone ( ) ;
13421380 let result = arr. bitwise_unary_mut ( |x| !x) ;
13431381 assert ! ( result. is_err( ) ) ;
13441382
13451383 let returned = result. unwrap_err ( ) ;
13461384 assert_eq ! ( returned, BooleanArray :: from( vec![ true , false , true , false ] ) ) ;
1385+ info. assert_same ( & returned) ;
13471386 }
13481387
13491388 #[ test]
@@ -1360,9 +1399,21 @@ mod tests {
13601399 #[ test]
13611400 fn test_bitwise_unary_mut_or_clone_shared ( ) {
13621401 let arr = BooleanArray :: from ( vec ! [ true , false , true ] ) ;
1402+ let info = PointerInfo :: new ( & arr) ;
13631403 let _shared = arr. clone ( ) ;
13641404 let result = arr. bitwise_unary_mut_or_clone ( |x| !x) ;
13651405 assert_eq ! ( result, BooleanArray :: from( vec![ false , true , false ] ) ) ;
1406+ info. assert_different ( & result) ;
1407+ }
1408+
1409+ #[ test]
1410+ fn test_bitwise_unary_mut_or_clone_unshared ( ) {
1411+ // Covers the uniquely-owned fast path in bitwise_unary_mut_or_clone.
1412+ let arr = BooleanArray :: from ( vec ! [ true , false , true ] ) ;
1413+ let info = PointerInfo :: new ( & arr) ;
1414+ let result = arr. bitwise_unary_mut_or_clone ( |x| !x) ;
1415+ assert_eq ! ( result, BooleanArray :: from( vec![ false , true , false ] ) ) ;
1416+ info. assert_same ( & result) ;
13661417 }
13671418
13681419 #[ test]
@@ -1419,20 +1470,25 @@ mod tests {
14191470 #[ test]
14201471 fn test_bitwise_bin_op_mut_unshared ( ) {
14211472 let a = BooleanArray :: from ( vec ! [ true , false , true , true ] ) ;
1473+ let info = PointerInfo :: new ( & a) ;
14221474 let b = BooleanArray :: from ( vec ! [ true , true , false , true ] ) ;
14231475 let result = a. bitwise_bin_op_mut ( & b, |a, b| a & b) . unwrap ( ) ;
14241476 assert_eq ! ( result, BooleanArray :: from( vec![ true , false , false , true ] ) ) ;
1477+ info. assert_same ( & result) ;
14251478 }
14261479
14271480 #[ test]
14281481 fn test_bitwise_bin_op_mut_shared ( ) {
14291482 let a = BooleanArray :: from ( vec ! [ true , false , true , true ] ) ;
1483+ let info = PointerInfo :: new ( & a) ;
14301484 let _shared = a. clone ( ) ;
14311485 let result = a. bitwise_bin_op_mut (
14321486 & BooleanArray :: from ( vec ! [ true , true , false , true ] ) ,
14331487 |a, b| a & b,
14341488 ) ;
14351489 assert ! ( result. is_err( ) ) ;
1490+ let returned = result. unwrap_err ( ) ;
1491+ info. assert_same ( & returned) ;
14361492 }
14371493
14381494 #[ test]
@@ -1451,17 +1507,20 @@ mod tests {
14511507 #[ test]
14521508 fn test_bitwise_bin_op_mut_or_clone_shared ( ) {
14531509 let a = BooleanArray :: from ( vec ! [ true , false , true , true ] ) ;
1510+ let info = PointerInfo :: new ( & a) ;
14541511 let _shared = a. clone ( ) ;
14551512 let b = BooleanArray :: from ( vec ! [ true , true , false , true ] ) ;
14561513 let result = a. bitwise_bin_op_mut_or_clone ( & b, |a, b| a & b) ;
14571514 assert_eq ! ( result, BooleanArray :: from( vec![ true , false , false , true ] ) ) ;
1515+ info. assert_different ( & result) ;
14581516 }
14591517
14601518 #[ test]
14611519 fn test_bitwise_bin_op_mut_or_clone_shared_with_nulls ( ) {
14621520 // When the buffer is shared, _mut_or_clone falls back to bitwise_bin_op.
14631521 // The null union must only be applied once, not double-applied.
14641522 let a = BooleanArray :: from ( vec ! [ Some ( true ) , None , Some ( true ) , Some ( false ) ] ) ;
1523+ let info = PointerInfo :: new ( & a) ;
14651524 let _shared = a. clone ( ) ;
14661525 let b = BooleanArray :: from ( vec ! [ Some ( true ) , Some ( true ) , None , Some ( true ) ] ) ;
14671526
@@ -1472,6 +1531,24 @@ mod tests {
14721531 assert_eq ! ( result. null_count( ) , 2 ) ;
14731532 assert ! ( result. is_null( 1 ) ) ;
14741533 assert ! ( result. is_null( 2 ) ) ;
1534+ info. assert_different ( & result) ;
1535+ }
1536+
1537+ #[ test]
1538+ fn test_bitwise_bin_op_mut_or_clone_unshared_with_nulls ( ) {
1539+ // Covers the uniquely-owned fast path in bitwise_bin_op_mut_or_clone,
1540+ // including null union on the in-place path.
1541+ let a = BooleanArray :: from ( vec ! [ Some ( true ) , None , Some ( true ) , Some ( false ) ] ) ;
1542+ let info = PointerInfo :: new ( & a) ;
1543+ let b = BooleanArray :: from ( vec ! [ Some ( true ) , Some ( true ) , None , Some ( true ) ] ) ;
1544+ let result = a. bitwise_bin_op_mut_or_clone ( & b, |a, b| a & b) ;
1545+
1546+ assert_eq ! ( result. null_count( ) , 2 ) ;
1547+ assert ! ( result. is_null( 1 ) ) ;
1548+ assert ! ( result. is_null( 2 ) ) ;
1549+ assert ! ( result. value( 0 ) ) ;
1550+ assert ! ( !result. value( 3 ) ) ;
1551+ info. assert_same ( & result) ;
14751552 }
14761553
14771554 #[ test]
0 commit comments