@@ -3883,6 +3883,99 @@ class TestData : TestDataSuper {
3883
3883
}
3884
3884
}
3885
3885
}
3886
+
3887
+ // This is a (potentially invalid) sequence that produces a configurable number of 42s and has a freely customizable `underestimatedCount`.
3888
+ struct TestSequence : Sequence {
3889
+ typealias Element = UInt8
3890
+ struct Iterator : IteratorProtocol {
3891
+ var _remaining : Int
3892
+ init ( _ count: Int ) {
3893
+ _remaining = count
3894
+ }
3895
+ mutating func next( ) -> UInt8 ? {
3896
+ guard _remaining > 0 else { return nil }
3897
+ _remaining -= 1
3898
+ return 42
3899
+ }
3900
+ }
3901
+ let underestimatedCount : Int
3902
+ let count : Int
3903
+
3904
+ func makeIterator( ) -> Iterator {
3905
+ return Iterator ( count)
3906
+ }
3907
+ }
3908
+
3909
+ func test_init_TestSequence( ) {
3910
+ // Underestimated count
3911
+ do {
3912
+ let d = Data ( TestSequence ( underestimatedCount: 0 , count: 10 ) )
3913
+ expectEqual ( 10 , d. count)
3914
+ expectEqual ( Array ( repeating: 42 as UInt8 , count: 10 ) , Array ( d) )
3915
+ }
3916
+
3917
+ // Very underestimated count (to exercise realloc path)
3918
+ do {
3919
+ let d = Data ( TestSequence ( underestimatedCount: 0 , count: 1000 ) )
3920
+ expectEqual ( 1000 , d. count)
3921
+ expectEqual ( Array ( repeating: 42 as UInt8 , count: 1000 ) , Array ( d) )
3922
+ }
3923
+
3924
+ // Exact count
3925
+ do {
3926
+ let d = Data ( TestSequence ( underestimatedCount: 10 , count: 10 ) )
3927
+ expectEqual ( 10 , d. count)
3928
+ expectEqual ( Array ( repeating: 42 as UInt8 , count: 10 ) , Array ( d) )
3929
+ }
3930
+
3931
+ // Overestimated count. This is an illegal case, so trapping would be fine.
3932
+ // However, for compatibility with the implementation in Swift 5, Data
3933
+ // handles this case by simply truncating itself to the actual size.
3934
+ do {
3935
+ let d = Data ( TestSequence ( underestimatedCount: 20 , count: 10 ) )
3936
+ expectEqual ( 10 , d. count)
3937
+ expectEqual ( Array ( repeating: 42 as UInt8 , count: 10 ) , Array ( d) )
3938
+ }
3939
+ }
3940
+
3941
+ func test_append_TestSequence( ) {
3942
+ let base = Data ( Array ( repeating: 23 as UInt8 , count: 10 ) )
3943
+
3944
+ // Underestimated count
3945
+ do {
3946
+ var d = base
3947
+ d. append ( contentsOf: TestSequence ( underestimatedCount: 0 , count: 10 ) )
3948
+ expectEqual ( 20 , d. count)
3949
+ expectEqual ( Array ( base) + Array( repeating: 42 as UInt8 , count: 10 ) ,
3950
+ Array ( d) )
3951
+ }
3952
+
3953
+ // Very underestimated count (to exercise realloc path)
3954
+ do {
3955
+ var d = base
3956
+ d. append ( contentsOf: TestSequence ( underestimatedCount: 0 , count: 1000 ) )
3957
+ expectEqual ( 1010 , d. count)
3958
+ expectEqual ( Array ( base) + Array( repeating: 42 as UInt8 , count: 1000 ) , Array ( d) )
3959
+ }
3960
+
3961
+ // Exact count
3962
+ do {
3963
+ var d = base
3964
+ d. append ( contentsOf: TestSequence ( underestimatedCount: 10 , count: 10 ) )
3965
+ expectEqual ( 20 , d. count)
3966
+ expectEqual ( Array ( base) + Array( repeating: 42 as UInt8 , count: 10 ) , Array ( d) )
3967
+ }
3968
+
3969
+ // Overestimated count. This is an illegal case, so trapping would be fine.
3970
+ // However, for compatibility with the implementation in Swift 5, Data
3971
+ // handles this case by simply truncating itself to the actual size.
3972
+ do {
3973
+ var d = base
3974
+ d. append ( contentsOf: TestSequence ( underestimatedCount: 20 , count: 10 ) )
3975
+ expectEqual ( 20 , d. count)
3976
+ expectEqual ( Array ( base) + Array( repeating: 42 as UInt8 , count: 10 ) , Array ( d) )
3977
+ }
3978
+ }
3886
3979
}
3887
3980
3888
3981
#if !FOUNDATION_XCTEST
@@ -4208,6 +4301,8 @@ if #available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) {
4208
4301
}
4209
4302
DataTests . test ( " test_increaseCount " ) { TestData ( ) . test_increaseCount ( ) }
4210
4303
DataTests . test ( " test_decreaseCount " ) { TestData ( ) . test_decreaseCount ( ) }
4304
+ DataTests . test ( " test_increaseCount " ) { TestData ( ) . test_init_TestSequence ( ) }
4305
+ DataTests . test ( " test_decreaseCount " ) { TestData ( ) . test_append_TestSequence ( ) }
4211
4306
4212
4307
4213
4308
// XCTest does not have a crash detection, whereas lit does
0 commit comments