@@ -1439,6 +1439,50 @@ private final class DataTests {
14391439 #expect( data. count == 0 )
14401440 }
14411441 }
1442+
1443+ @Test func validateMutation_cow_mutableBytes( ) {
1444+ var data = Data ( count: 32 )
1445+ holdReference ( data) {
1446+ var bytes = data. mutableBytes
1447+ bytes. storeBytes ( of: 1 , toByteOffset: 0 , as: UInt8 . self)
1448+
1449+ #expect( data [ 0 ] == 1 )
1450+ #expect( heldData ? [ 0 ] == 0 )
1451+ }
1452+
1453+ var data2 = Data ( count: 32 )
1454+ // Escape the pointer to compare after a mutation without dereferencing the pointer
1455+ let originalPointer = data2. withUnsafeBytes { $0. baseAddress }
1456+
1457+ var bytes = data2. mutableBytes
1458+ bytes. storeBytes ( of: 1 , toByteOffset: 0 , as: UInt8 . self)
1459+ #expect( data2 [ 0 ] == 1 )
1460+ data2. withUnsafeBytes {
1461+ #expect( $0. baseAddress == originalPointer)
1462+ }
1463+ }
1464+
1465+ @Test func validateMutation_cow_mutableSpan( ) {
1466+ var data = Data ( count: 32 )
1467+ holdReference ( data) {
1468+ var bytes = data. mutableSpan
1469+ bytes [ 0 ] = 1
1470+
1471+ #expect( data [ 0 ] == 1 )
1472+ #expect( heldData ? [ 0 ] == 0 )
1473+ }
1474+
1475+ var data2 = Data ( count: 32 )
1476+ // Escape the pointer to compare after a mutation without dereferencing the pointer
1477+ let originalPointer = data2. withUnsafeBytes { $0. baseAddress }
1478+
1479+ var bytes = data2. mutableSpan
1480+ bytes [ 0 ] = 1
1481+ #expect( data2 [ 0 ] == 1 )
1482+ data2. withUnsafeBytes {
1483+ #expect( $0. baseAddress == originalPointer)
1484+ }
1485+ }
14421486
14431487 @Test func sliceHash( ) {
14441488 let base1 = Data ( [ 0 , 0xFF , 0xFF , 0 ] )
@@ -2505,17 +2549,16 @@ extension DataTests {
25052549// These tests require allocating an extremely large amount of data and are serialized to prevent the test runner from using all available memory at once
25062550@Suite( " Large Data Tests " , . serialized)
25072551struct LargeDataTests {
2508- @Test
2509- func largeSliceDataSpan( ) throws {
25102552#if _pointerBitWidth(_64)
2511- let count = Int ( Int32 . max)
2553+ let largeCount = Int ( Int32 . max)
25122554#elseif _pointerBitWidth(_32)
2513- let count = Int ( Int16 . max)
2555+ let largeCount = Int ( Int16 . max)
25142556#else
25152557#error("This test needs updating")
25162558#endif
2517-
2518- let source = Data ( repeating: 0 , count: count) . dropFirst ( )
2559+ @Test
2560+ func largeSliceDataSpan( ) throws {
2561+ let source = Data ( repeating: 0 , count: largeCount) . dropFirst ( )
25192562 #expect( source. startIndex != 0 )
25202563 let span = source. span
25212564 let isEmpty = span. isEmpty
@@ -2524,20 +2567,11 @@ struct LargeDataTests {
25242567
25252568 @Test
25262569 func largeSliceDataMutableSpan( ) throws {
2527- #if _pointerBitWidth(_64)
2528- var count = Int ( Int32 . max)
2529- #elseif _pointerBitWidth(_32)
2530- var count = Int ( Int16 . max)
2531- #else
2532- #error("This test needs updating")
2533- #endif
2534-
25352570#if !canImport(Darwin) || FOUNDATION_FRAMEWORK
2536- var source = Data ( repeating: 0 , count: count ) . dropFirst ( )
2571+ var source = Data ( repeating: 0 , count: largeCount ) . dropFirst ( )
25372572 #expect( source. startIndex != 0 )
2538- count = source. count
25392573 var span = source. mutableSpan
2540- #expect( span. count == count )
2574+ #expect( span. count == largeCount - 1 )
25412575 let i = try #require( span. indices. dropFirst ( ) . randomElement ( ) )
25422576 span [ i] = . max
25432577 #expect( source [ i] == 0 )
@@ -2547,23 +2581,62 @@ struct LargeDataTests {
25472581
25482582 @Test
25492583 func largeSliceDataMutableRawSpan( ) throws {
2550- #if _pointerBitWidth(_64)
2551- var count = Int ( Int32 . max)
2552- #elseif _pointerBitWidth(_32)
2553- var count = Int ( Int16 . max)
2554- #else
2555- #error("This test needs updating")
2556- #endif
2557-
2558- var source = Data ( repeating: 0 , count: count) . dropFirst ( )
2584+ var source = Data ( repeating: 0 , count: largeCount) . dropFirst ( )
25592585 #expect( source. startIndex != 0 )
2560- count = source. count
25612586 var span = source. mutableBytes
25622587 let byteCount = span. byteCount
2563- #expect( byteCount == count )
2588+ #expect( byteCount == largeCount - 1 )
25642589 let i = try #require( span. byteOffsets. dropFirst ( ) . randomElement ( ) )
25652590 span. storeBytes ( of: - 1 , toByteOffset: i, as: Int8 . self)
25662591 #expect( source [ i] == 0 )
25672592 #expect( source [ i+ 1 ] == . max)
25682593 }
2594+
2595+ @Test func validateMutation_cow_largeMutableBytes( ) {
2596+ // Avoid copying a large data on platforms with constrained memory limits
2597+ #if !canImport(Darwin) || os(macOS)
2598+ var data = Data ( count: largeCount)
2599+ let heldData = data
2600+ var bytes = data. mutableBytes
2601+ bytes. storeBytes ( of: 1 , toByteOffset: 0 , as: UInt8 . self)
2602+
2603+ #expect( data [ 0 ] == 1 )
2604+ #expect( heldData [ 0 ] == 0 )
2605+ #endif
2606+
2607+ var data2 = Data ( count: largeCount)
2608+ // Escape the pointer to compare after a mutation without dereferencing the pointer
2609+ let originalPointer = data2. withUnsafeBytes { $0. baseAddress }
2610+
2611+ var bytes2 = data2. mutableBytes
2612+ bytes2. storeBytes ( of: 1 , toByteOffset: 0 , as: UInt8 . self)
2613+ #expect( data2 [ 0 ] == 1 )
2614+ data2. withUnsafeBytes {
2615+ #expect( $0. baseAddress == originalPointer)
2616+ }
2617+ }
2618+
2619+ @Test func validateMutation_cow_largeMutableSpan( ) {
2620+ // Avoid copying a large data on platforms with constrained memory limits
2621+ #if !canImport(Darwin) || os(macOS)
2622+ var data = Data ( count: largeCount)
2623+ let heldData = data
2624+ var bytes = data. mutableSpan
2625+ bytes [ 0 ] = 1
2626+
2627+ #expect( data [ 0 ] == 1 )
2628+ #expect( heldData [ 0 ] == 0 )
2629+ #endif
2630+
2631+ var data2 = Data ( count: largeCount)
2632+ // Escape the pointer to compare after a mutation without dereferencing the pointer
2633+ let originalPointer = data2. withUnsafeBytes { $0. baseAddress }
2634+
2635+ var bytes2 = data2. mutableSpan
2636+ bytes2 [ 0 ] = 1
2637+ #expect( data2 [ 0 ] == 1 )
2638+ data2. withUnsafeBytes {
2639+ #expect( $0. baseAddress == originalPointer)
2640+ }
2641+ }
25692642}
0 commit comments