@@ -521,6 +521,8 @@ class TestNSData: LoopbackServerTest {
521
521
( " test_copyBytes2 " , test_copyBytes2) ,
522
522
( " test_sliceOfSliceViaRangeExpression " , test_sliceOfSliceViaRangeExpression) ,
523
523
( " test_appendingSlices " , test_appendingSlices) ,
524
+ ( " test_appendingNonContiguousSequence_exactCount " , test_appendingNonContiguousSequence_exactCount) ,
525
+ ( " test_appendingNonContiguousSequence_underestimatedCount " , test_appendingNonContiguousSequence_underestimatedCount) ,
524
526
( " test_sequenceInitializers " , test_sequenceInitializers) ,
525
527
( " test_reversedDataInit " , test_reversedDataInit) ,
526
528
( " test_replaceSubrangeReferencingMutable " , test_replaceSubrangeReferencingMutable) ,
@@ -4391,6 +4393,55 @@ extension TestNSData {
4391
4393
d2. append ( slice)
4392
4394
XCTAssertEqual ( Data ( [ 1 ] ) , slice)
4393
4395
}
4396
+
4397
+ // This test uses `repeatElement` to produce a sequence -- the produced sequence reports its actual count as its `.underestimatedCount`.
4398
+ func test_appendingNonContiguousSequence_exactCount( ) {
4399
+ var d = Data ( )
4400
+
4401
+ // d should go from .empty representation to .inline.
4402
+ // Appending a small enough sequence to fit in .inline should actually be copied.
4403
+ d. append ( contentsOf: 0x00 ... 0x01 )
4404
+ expectEqual ( Data ( [ 0x00 , 0x01 ] ) , d)
4405
+
4406
+ // Appending another small sequence should similarly still work.
4407
+ d. append ( contentsOf: 0x02 ... 0x02 )
4408
+ expectEqual ( Data ( [ 0x00 , 0x01 , 0x02 ] ) , d)
4409
+
4410
+ // If we append a sequence of elements larger than a single InlineData, the internal append here should buffer.
4411
+ // We want to make sure that buffering in this way does not accidentally drop trailing elements on the floor.
4412
+ d. append ( contentsOf: 0x03 ... 0x2F )
4413
+ expectEqual ( Data ( [ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
4414
+ 0x08 , 0x09 , 0x0A , 0x0B , 0x0C , 0x0D , 0x0E , 0x0F ,
4415
+ 0x10 , 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 ,
4416
+ 0x18 , 0x19 , 0x1A , 0x1B , 0x1C , 0x1D , 0x1E , 0x1F ,
4417
+ 0x20 , 0x21 , 0x22 , 0x23 , 0x24 , 0x25 , 0x26 , 0x27 ,
4418
+ 0x28 , 0x29 , 0x2A , 0x2B , 0x2C , 0x2D , 0x2E , 0x2F ] ) , d)
4419
+ }
4420
+
4421
+ // This test is like test_appendingNonContiguousSequence_exactCount but uses a sequence which reports 0 for its `.underestimatedCount`.
4422
+ // This attempts to hit the worst-case scenario of `Data.append<S>(_:)` -- a discontiguous sequence of unknown length.
4423
+ func test_appendingNonContiguousSequence_underestimatedCount( ) {
4424
+ var d = Data ( )
4425
+
4426
+ // d should go from .empty representation to .inline.
4427
+ // Appending a small enough sequence to fit in .inline should actually be copied.
4428
+ d. append ( contentsOf: ( 0x00 ... 0x01 ) . makeIterator ( ) ) // `.makeIterator()` produces a sequence whose `.underestimatedCount` is 0.
4429
+ expectEqual ( Data ( [ 0x00 , 0x01 ] ) , d)
4430
+
4431
+ // Appending another small sequence should similarly still work.
4432
+ d. append ( contentsOf: ( 0x02 ... 0x02 ) . makeIterator ( ) ) // `.makeIterator()` produces a sequence whose `.underestimatedCount` is 0.
4433
+ expectEqual ( Data ( [ 0x00 , 0x01 , 0x02 ] ) , d)
4434
+
4435
+ // If we append a sequence of elements larger than a single InlineData, the internal append here should buffer.
4436
+ // We want to make sure that buffering in this way does not accidentally drop trailing elements on the floor.
4437
+ d. append ( contentsOf: ( 0x03 ... 0x2F ) . makeIterator ( ) ) // `.makeIterator()` produces a sequence whose `.underestimatedCount` is 0.
4438
+ expectEqual ( Data ( [ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
4439
+ 0x08 , 0x09 , 0x0A , 0x0B , 0x0C , 0x0D , 0x0E , 0x0F ,
4440
+ 0x10 , 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 ,
4441
+ 0x18 , 0x19 , 0x1A , 0x1B , 0x1C , 0x1D , 0x1E , 0x1F ,
4442
+ 0x20 , 0x21 , 0x22 , 0x23 , 0x24 , 0x25 , 0x26 , 0x27 ,
4443
+ 0x28 , 0x29 , 0x2A , 0x2B , 0x2C , 0x2D , 0x2E , 0x2F ] ) , d)
4444
+ }
4394
4445
4395
4446
func test_sequenceInitializers( ) {
4396
4447
let seq = repeatElement ( UInt8 ( 0x02 ) , count: 3 ) // ensure we fall into the sequence case
0 commit comments