@@ -1183,6 +1183,57 @@ class TestData : TestDataSuper {
1183
1183
expectEqual ( Data ( bytes: [ 1 ] ) , slice)
1184
1184
}
1185
1185
1186
+ // This test uses `repeatElement` to produce a sequence -- the produced sequence reports its actual count as its `.underestimatedCount`.
1187
+ func test_appendingNonContiguousSequence_exactCount( ) {
1188
+ var d = Data ( )
1189
+
1190
+ // d should go from .empty representation to .inline.
1191
+ // Appending a small enough sequence to fit in linline should actually be copied.
1192
+ d. append ( contentsOf: repeatElement ( UInt8 ( 0x01 ) , count: 2 ) )
1193
+ expectEqual ( Data ( [ 0x01 , 0x01 ] ) , d)
1194
+
1195
+ // Appending another small sequence should similarly still work.
1196
+ d. append ( contentsOf: repeatElement ( UInt8 ( 0x02 ) , count: 1 ) )
1197
+ expectEqual ( Data ( [ 0x01 , 0x01 , 0x02 ] ) , d)
1198
+
1199
+ // If we append a sequence of elements larger than a single InlineData, the internal append here should buffer.
1200
+ // We want to make sure that buffering in this way does not accidentally drop trailing elements on the floor.
1201
+ d. append ( contentsOf: repeatElement ( UInt8 ( 0x03 ) , count: 24 ) )
1202
+ expectEqual ( Data ( [ 0x01 , 0x01 , 0x02 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 ,
1203
+ 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 ,
1204
+ 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 ] ) , d)
1205
+ }
1206
+
1207
+ // This test is like test_appendingNonContiguousSequence_exactCount but uses a sequence which reports 0 for its `.underestimatedCount`.
1208
+ // This attempts to hit the worst-case scenario of `Data.append<S>(_:)` -- a discontiguous sequence of unknown length.
1209
+ func test_appendingNonContiguousSequence_underestimatedCount( ) {
1210
+ // underestimatedRepeatedElement does the same thing as repeatElement, but reports an `.underestimatedCount` of 0.
1211
+ let underestimatedRepeatedElement = { ( element: UInt8 , count: Int ) in
1212
+ return sequence ( state: count) { ( count: inout Int ) -> UInt8 ? in
1213
+ defer { count -= 1 }
1214
+ return count > 0 ? element : nil
1215
+ }
1216
+ }
1217
+
1218
+ var d = Data ( )
1219
+
1220
+ // d should go from .empty representation to .inline.
1221
+ // Appending a small enough sequence to fit in linline should actually be copied.
1222
+ d. append ( contentsOf: underestimatedRepeatedElement ( UInt8 ( 0x01 ) , 2 ) )
1223
+ expectEqual ( Data ( [ 0x01 , 0x01 ] ) , d)
1224
+
1225
+ // Appending another small sequence should similarly still work.
1226
+ d. append ( contentsOf: underestimatedRepeatedElement ( UInt8 ( 0x02 ) , 1 ) )
1227
+ expectEqual ( Data ( [ 0x01 , 0x01 , 0x02 ] ) , d)
1228
+
1229
+ // If we append a sequence of elements larger than a single InlineData, the internal append here should buffer.
1230
+ // We want to make sure that buffering in this way does not accidentally drop trailing elements on the floor.
1231
+ d. append ( contentsOf: underestimatedRepeatedElement ( UInt8 ( 0x03 ) , 24 ) )
1232
+ expectEqual ( Data ( [ 0x01 , 0x01 , 0x02 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 ,
1233
+ 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 ,
1234
+ 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 , 0x03 ] ) , d)
1235
+ }
1236
+
1186
1237
func test_sequenceInitializers( ) {
1187
1238
let seq = repeatElement ( UInt8 ( 0x02 ) , count: 3 ) // ensure we fall into the sequence case
1188
1239
@@ -3753,6 +3804,8 @@ DataTests.test("test_copyBytes1") { TestData().test_copyBytes1() }
3753
3804
DataTests . test ( " test_copyBytes2 " ) { TestData ( ) . test_copyBytes2 ( ) }
3754
3805
DataTests . test ( " test_sliceOfSliceViaRangeExpression " ) { TestData ( ) . test_sliceOfSliceViaRangeExpression ( ) }
3755
3806
DataTests . test ( " test_appendingSlices " ) { TestData ( ) . test_appendingSlices ( ) }
3807
+ DataTests . test ( " test_appendingNonContiguousSequence_exactCount " ) { TestData ( ) . test_appendingNonContiguousSequence_exactCount ( ) }
3808
+ DataTests . test ( " test_appendingNonContiguousSequence_underestimatedCount " ) { TestData ( ) . test_appendingNonContiguousSequence_underestimatedCount ( ) }
3756
3809
DataTests . test ( " test_sequenceInitializers " ) { TestData ( ) . test_sequenceInitializers ( ) }
3757
3810
DataTests . test ( " test_reversedDataInit " ) { TestData ( ) . test_reversedDataInit ( ) }
3758
3811
DataTests . test ( " test_replaceSubrangeReferencingMutable " ) { TestData ( ) . test_replaceSubrangeReferencingMutable ( ) }
0 commit comments