@@ -90,6 +90,178 @@ let subscriptGetTests : [SubscriptGetTest] = [
90
90
SubscriptGetTest(rangeSelection: .offsets(-100, 100)),
91
91
]
92
92
93
+ struct SubscriptSetTest {
94
+ // SubscriptSetTest operates on a `(end - start)` sized buffer containing
95
+ // monotonically increasing integers from `start` to `end - 1`.
96
+ static let start = 0
97
+ static let end = 10
98
+
99
+ let rangeSelection: RangeSelection
100
+
101
+ let replacementValues: [OpaqueValue<Int>]
102
+ let replacementValuesClosed: [OpaqueValue<Int>]
103
+
104
+ /// The values that should be expected by slicing the UBP, or `nil` if the
105
+ /// test is expected to crash.
106
+ let expectedValues: [Int]?
107
+ let expectedValuesClosed: [Int]?
108
+
109
+ let loc: SourceLoc
110
+
111
+ static var elementCount = (end - start)
112
+
113
+ /// Create and populate an `UnsafeMutableBufferPointer` for use with unit
114
+ /// tests.
115
+ /// PRECONDITION: `memory` must be allocated with space for
116
+ /// `SubscriptSetTest.elementCount` elements.
117
+ func createUnsafeMutableBufferPointer(
118
+ from memory: UnsafeMutablePointer<OpaqueValue<Int>>
119
+ ) -> UnsafeMutableBufferPointer<OpaqueValue<Int>>
120
+ {
121
+ for i in SubscriptSetTest.start..<SubscriptSetTest.end {
122
+ memory[i] = OpaqueValue(i)
123
+ }
124
+ return UnsafeMutableBufferPointer(
125
+ start: memory,
126
+ count: SubscriptSetTest.elementCount)
127
+ }
128
+
129
+ /// Create and populate a mutable buffer pointer slice for use with unit
130
+ /// tests.
131
+ /// PRECONDITION: `memory` must be allocated with space for
132
+ /// `replacementValues.count` elements.
133
+ func replacementValuesSlice(
134
+ from memory: UnsafeMutablePointer<OpaqueValue<Int>>,
135
+ replacementValues: [OpaqueValue<Int>]
136
+ ) -> MutableRandomAccessSlice<UnsafeMutableBufferPointer<OpaqueValue<Int>>>
137
+ {
138
+ for (i, value) in replacementValues.enumerated() {
139
+ memory[i] = value
140
+ }
141
+ let buffer = UnsafeMutableBufferPointer(
142
+ start: memory,
143
+ count: replacementValues.count)
144
+ let fullRange = RangeSelection.full.range(in: buffer)
145
+ return buffer[fullRange]
146
+ }
147
+
148
+ init(
149
+ rangeSelection: RangeSelection,
150
+ replacementValues: [Int],
151
+ replacementValuesClosed: [Int]? = nil,
152
+ expectedValues: [Int]? = nil,
153
+ expectedValuesClosed: [Int]? = nil,
154
+ file: String = #file, line: UInt = #line
155
+ ) {
156
+ self.rangeSelection = rangeSelection
157
+ self.replacementValues = replacementValues.map { OpaqueValue($0) }
158
+ if let replacements = replacementValuesClosed {
159
+ self.replacementValuesClosed = replacements.map { OpaqueValue($0) }
160
+ } else {
161
+ self.replacementValuesClosed = self.replacementValues
162
+ }
163
+ self.expectedValues = expectedValues
164
+ self.expectedValuesClosed = expectedValuesClosed ?? expectedValues
165
+ self.loc = SourceLoc(file, line, comment: "test data")
166
+ }
167
+ }
168
+
169
+ let subscriptSetTests : [SubscriptSetTest] = [
170
+ // Valid, empty.
171
+ SubscriptSetTest(
172
+ rangeSelection: .emptyRange,
173
+ replacementValues: [],
174
+ expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
175
+
176
+ // Valid, edges.
177
+ SubscriptSetTest(
178
+ rangeSelection: .leftEdge,
179
+ replacementValues: [],
180
+ replacementValuesClosed: [9001],
181
+ expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
182
+ expectedValuesClosed: [9001, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
183
+ SubscriptSetTest(
184
+ rangeSelection: .rightEdge,
185
+ replacementValues: [],
186
+ replacementValuesClosed: [9001],
187
+ expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
188
+ expectedValuesClosed: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9001]),
189
+
190
+ // Valid, internal.
191
+ SubscriptSetTest(
192
+ rangeSelection: .leftHalf,
193
+ replacementValues: [10, 11, 12, 13, 14],
194
+ expectedValues: [10, 11, 12, 13, 14, 5, 6, 7, 8, 9]),
195
+ SubscriptSetTest(
196
+ rangeSelection: .rightHalf,
197
+ replacementValues: [10, 11, 12, 13, 14],
198
+ expectedValues: [0, 1, 2, 3, 4, 10, 11, 12, 13, 14]),
199
+ SubscriptSetTest(
200
+ rangeSelection: .middle,
201
+ replacementValues: [10, 11, 12, 13, 14, 15],
202
+ expectedValues: [0, 1, 10, 11, 12, 13, 14, 15, 8, 9]),
203
+ SubscriptSetTest(
204
+ rangeSelection: .full,
205
+ replacementValues: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
206
+ expectedValues: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),
207
+
208
+ // Invalid, range and replacement count mismatch.
209
+ SubscriptSetTest(
210
+ rangeSelection: .leftEdge,
211
+ replacementValues: [],
212
+ replacementValuesClosed: [9]),
213
+ SubscriptSetTest(
214
+ rangeSelection: .leftEdge,
215
+ replacementValues: [9, 9],
216
+ replacementValuesClosed: [9, 9, 9]),
217
+ SubscriptSetTest(
218
+ rangeSelection: .offsets(1, 2),
219
+ replacementValues: [],
220
+ replacementValuesClosed: [9]),
221
+ SubscriptSetTest(
222
+ rangeSelection: .offsets(1, 2),
223
+ replacementValues: [9, 9],
224
+ replacementValuesClosed: [9, 9, 9]),
225
+ SubscriptSetTest(
226
+ rangeSelection: .offsets(2, 5),
227
+ replacementValues: [9, 9],
228
+ replacementValuesClosed: [9, 9, 9]),
229
+ SubscriptSetTest(
230
+ rangeSelection: .offsets(2, 5),
231
+ replacementValues: [9, 9, 9, 9],
232
+ replacementValuesClosed: [9, 9, 9, 9, 9]),
233
+
234
+ // Invalid, bottom out of bounds.
235
+ SubscriptSetTest(
236
+ rangeSelection: .offsets(-1, -1),
237
+ replacementValues: []),
238
+ SubscriptSetTest(
239
+ rangeSelection: .offsets(-1, 0),
240
+ replacementValues: [9]),
241
+ SubscriptSetTest(
242
+ rangeSelection: .offsets(-3, 5),
243
+ replacementValues: [9, 9, 9, 9, 9, 9, 9, 9]),
244
+
245
+ // Invalid, top out of bounds.
246
+ SubscriptSetTest(
247
+ rangeSelection: .offsets(10, 10),
248
+ replacementValues: []),
249
+ SubscriptSetTest(
250
+ rangeSelection: .offsets(9, 10),
251
+ replacementValues: [9]),
252
+ SubscriptSetTest(
253
+ rangeSelection: .offsets(8, 15),
254
+ replacementValues: [9, 9, 9, 9, 9, 9, 9]),
255
+
256
+ // Invalid, both out of bounds.
257
+ SubscriptSetTest(
258
+ rangeSelection: .offsets(-1, 10),
259
+ replacementValues: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]),
260
+ SubscriptSetTest(
261
+ rangeSelection: .offsets(-2, 11),
262
+ replacementValues: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]),
263
+ ]
264
+
93
265
94
266
// Test Suites
95
267
@@ -228,6 +400,50 @@ ${SelfName}TestSuite.test("subscript/${RangeName}/get").forEach(in: subscriptGet
228
400
229
401
% end
230
402
403
+ % for RangeName in ['range', 'countableRange', 'closedRange', 'countableClosedRange']:
404
+ UnsafeMutableBufferPointerTestSuite.test("subscript/${RangeName}/set")
405
+ .forEach(in: subscriptSetTests) { (test) in
406
+
407
+ let expectedValues: [Int]?
408
+ let replacementValues: [OpaqueValue<Int>]
409
+ % if 'closed' in RangeName.lower():
410
+ if test.rangeSelection.isEmpty {
411
+ return
412
+ }
413
+ expectedValues = test.expectedValuesClosed
414
+ replacementValues = test.replacementValuesClosed
415
+ % else:
416
+ expectedValues = test.expectedValues
417
+ replacementValues = test.replacementValues
418
+ % end
419
+
420
+ let elementCount = SubscriptSetTest.elementCount
421
+
422
+ var memory = UnsafeMutablePointer<OpaqueValue<Int>>(
423
+ allocatingCapacity: elementCount)
424
+ var sliceMemory = UnsafeMutablePointer<OpaqueValue<Int>>(
425
+ allocatingCapacity: replacementValues.count)
426
+ var buffer = test.createUnsafeMutableBufferPointer(from: memory)
427
+ defer {
428
+ memory.deallocateCapacity(elementCount)
429
+ sliceMemory.deallocateCapacity(replacementValues.count)
430
+ }
431
+
432
+ let range = test.rangeSelection.${RangeName}(in: buffer)
433
+ let replacementSlice = test.replacementValuesSlice(
434
+ from: sliceMemory,
435
+ replacementValues: replacementValues)
436
+
437
+ if expectedValues == nil { expectCrashLater() }
438
+ buffer[range] = replacementSlice
439
+ expectEqual(
440
+ expectedValues!,
441
+ buffer.map { $0.value },
442
+ stackTrace: SourceLocStack().with(test.loc)
443
+ )
444
+ }
445
+ % end
446
+
231
447
UnsafeMutableBufferPointerTestSuite.test("changeElementViaBuffer") {
232
448
let count = 4
233
449
let allocated = UnsafeMutablePointer<Float>(allocatingCapacity: count)
0 commit comments