// RUN: %target-run-simple-swiftgyb // REQUIRES: executable_test import StdlibUnittest import StdlibCollectionUnittest // Tests struct SubscriptGetTest { // SubscriptGetTest operates on a `(end - start)` sized buffer containing // monotonically increasing integers from `start` to `end - 1`. static let start = 0 static let end = 20 let rangeSelection: RangeSelection /// The values that should be expected by slicing the UBP, or `nil` if the /// test is expected to crash. let expectedValues: [Int]? /// Same as `expectedValues`, but for closed ranges. `nil` if no difference. let expectedClosedValues: [Int]? let loc: SourceLoc static var elementCount = (end - start) % for SelfType in ['UnsafeBufferPointer', 'UnsafeMutableBufferPointer']: /// Create and populate an `${SelfType}` for use with unit tests. /// PRECONDITION: `memory` must be allocated with space for /// `SubscriptGetTest.elementCount` elements. func create${SelfType}(from memory: UnsafeMutablePointer>) -> ${SelfType}> { for i in SubscriptGetTest.start..] let replacementValuesClosed: [OpaqueValue] /// The values that should be expected by slicing the UBP, or `nil` if the /// test is expected to crash. let expectedValues: [Int]? let expectedValuesClosed: [Int]? let loc: SourceLoc static var elementCount = (end - start) /// Create and populate an `UnsafeMutableBufferPointer` for use with unit /// tests. /// PRECONDITION: `memory` must be allocated with space for /// `SubscriptSetTest.elementCount` elements. func createUnsafeMutableBufferPointer( from memory: UnsafeMutablePointer> ) -> UnsafeMutableBufferPointer> { for i in SubscriptSetTest.start..>, replacementValues: [OpaqueValue] ) -> MutableRandomAccessSlice>> { for (i, value) in replacementValues.enumerated() { memory[i] = value } let buffer = UnsafeMutableBufferPointer( start: memory, count: replacementValues.count) let fullRange = RangeSelection.full.range(in: buffer) return buffer[fullRange] } init( rangeSelection: RangeSelection, replacementValues: [Int], replacementValuesClosed: [Int]? = nil, expectedValues: [Int]? = nil, expectedValuesClosed: [Int]? = nil, file: String = #file, line: UInt = #line ) { self.rangeSelection = rangeSelection self.replacementValues = replacementValues.map { OpaqueValue($0) } if let replacements = replacementValuesClosed { self.replacementValuesClosed = replacements.map { OpaqueValue($0) } } else { self.replacementValuesClosed = self.replacementValues } self.expectedValues = expectedValues self.expectedValuesClosed = expectedValuesClosed ?? expectedValues self.loc = SourceLoc(file, line, comment: "test data") } } let subscriptSetTests : [SubscriptSetTest] = [ // Valid, empty. SubscriptSetTest( rangeSelection: .emptyRange, replacementValues: [], expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), // Valid, edges. SubscriptSetTest( rangeSelection: .leftEdge, replacementValues: [], replacementValuesClosed: [9001], expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], expectedValuesClosed: [9001, 1, 2, 3, 4, 5, 6, 7, 8, 9]), SubscriptSetTest( rangeSelection: .rightEdge, replacementValues: [], replacementValuesClosed: [9001], expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], expectedValuesClosed: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9001]), // Valid, internal. SubscriptSetTest( rangeSelection: .leftHalf, replacementValues: [10, 11, 12, 13, 14], expectedValues: [10, 11, 12, 13, 14, 5, 6, 7, 8, 9]), SubscriptSetTest( rangeSelection: .rightHalf, replacementValues: [10, 11, 12, 13, 14], expectedValues: [0, 1, 2, 3, 4, 10, 11, 12, 13, 14]), SubscriptSetTest( rangeSelection: .middle, replacementValues: [10, 11, 12, 13, 14, 15], expectedValues: [0, 1, 10, 11, 12, 13, 14, 15, 8, 9]), SubscriptSetTest( rangeSelection: .full, replacementValues: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], expectedValues: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]), // Invalid, range and replacement count mismatch. SubscriptSetTest( rangeSelection: .leftEdge, replacementValues: [], replacementValuesClosed: [9]), SubscriptSetTest( rangeSelection: .leftEdge, replacementValues: [9, 9], replacementValuesClosed: [9, 9, 9]), SubscriptSetTest( rangeSelection: .offsets(1, 2), replacementValues: [], replacementValuesClosed: [9]), SubscriptSetTest( rangeSelection: .offsets(1, 2), replacementValues: [9, 9], replacementValuesClosed: [9, 9, 9]), SubscriptSetTest( rangeSelection: .offsets(2, 5), replacementValues: [9, 9], replacementValuesClosed: [9, 9, 9]), SubscriptSetTest( rangeSelection: .offsets(2, 5), replacementValues: [9, 9, 9, 9], replacementValuesClosed: [9, 9, 9, 9, 9]), // Invalid, bottom out of bounds. SubscriptSetTest( rangeSelection: .offsets(-1, -1), replacementValues: []), SubscriptSetTest( rangeSelection: .offsets(-1, 0), replacementValues: [9]), SubscriptSetTest( rangeSelection: .offsets(-3, 5), replacementValues: [9, 9, 9, 9, 9, 9, 9, 9]), // Invalid, top out of bounds. SubscriptSetTest( rangeSelection: .offsets(10, 10), replacementValues: []), SubscriptSetTest( rangeSelection: .offsets(9, 10), replacementValues: [9]), SubscriptSetTest( rangeSelection: .offsets(8, 15), replacementValues: [9, 9, 9, 9, 9, 9, 9]), // Invalid, both out of bounds. SubscriptSetTest( rangeSelection: .offsets(-1, 10), replacementValues: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]), SubscriptSetTest( rangeSelection: .offsets(-2, 11), replacementValues: [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]), ] // Test Suites var UnsafeBufferPointerTestSuite = TestSuite("UnsafeBufferPointer") var UnsafeMutableBufferPointerTestSuite = TestSuite("UnsafeMutableBufferPointer") % for (SelfName, IsMutable, SelfType, PointerType) in [ % ('UnsafeBufferPointer', False, 'UnsafeBufferPointer', 'UnsafePointer'), % ('UnsafeMutableBufferPointer', True, 'UnsafeMutableBufferPointer', 'UnsafeMutablePointer') % ]: ${SelfName}TestSuite.test("AssociatedTypes") { typealias Subject = ${SelfName}> expectRandomAccessCollectionAssociatedTypes( collectionType: Subject.self, iteratorType: IndexingIterator.self, subSequenceType: ${'Mutable' if IsMutable else ''}RandomAccessSlice.self, indexType: Int.self, indexDistanceType: Int.self, indicesType: CountableRange.self) expect${'Mutable' if IsMutable else ''}CollectionType(Subject.self) } ${SelfName}TestSuite.test("nilBaseAddress") { let emptyBuffer = ${SelfType}(start: nil, count: 0) expectEmpty(emptyBuffer.baseAddress) expectEqual(0, emptyBuffer.count) expectTrue(emptyBuffer.startIndex == emptyBuffer.endIndex) var iter = emptyBuffer.makeIterator() expectEmpty(iter.next()) expectEqualSequence([], emptyBuffer) } ${SelfName}TestSuite.test("nonNilButEmpty") { let emptyAllocated = UnsafeMutablePointer.allocate(capacity: 0) defer { emptyAllocated.deallocate(capacity: 0) } let emptyBuffer = ${SelfType}(start: ${PointerType}(emptyAllocated), count: 0) expectEqual(emptyAllocated, emptyBuffer.baseAddress) expectEqual(0, emptyBuffer.count) expectTrue(emptyBuffer.startIndex == emptyBuffer.endIndex) var iter = emptyBuffer.makeIterator() expectEmpty(iter.next()) expectEqualSequence([], emptyBuffer) } ${SelfName}TestSuite.test("nonNilNonEmpty") { let count = 4 let allocated = UnsafeMutablePointer.allocate(capacity: count) defer { allocated.deallocate(capacity: count) } allocated.initialize(to: 1.0, count: count) allocated[count - 1] = 2.0 let buffer = ${SelfType}(start: ${PointerType}(allocated), count: count - 1) expectEqual(allocated, buffer.baseAddress) expectEqual(count - 1, buffer.count) expectEqual(count - 1, buffer.endIndex - buffer.startIndex) allocated[1] = 0.0 expectEqual(1.0, buffer[0]) expectEqual(0.0, buffer[1]) expectEqual(1.0, buffer[2]) var iter = buffer.makeIterator() expectEqual(1.0, iter.next()) expectEqual(0.0, iter.next()) expectEqual(1.0, iter.next()) expectEmpty(iter.next()) expectEqualSequence([1.0, 0.0, 1.0], buffer) expectEqual(2.0, allocated[count-1]) } ${SelfName}TestSuite.test("badCount") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { expectCrashLater() let emptyAllocated = UnsafeMutablePointer.allocate(capacity: 0) defer { emptyAllocated.deallocate(capacity: 0) } let buffer = ${SelfType}(start: ${PointerType}(emptyAllocated), count: -1) _ = buffer } ${SelfName}TestSuite.test("badNilCount") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .code { expectCrashLater() let buffer = ${SelfType}(start: nil, count: 1) _ = buffer } % for RangeName in ['range', 'countableRange', 'closedRange', 'countableClosedRange']: ${SelfName}TestSuite.test("subscript/${RangeName}/get").forEach(in: subscriptGetTests) { (test) in let expectedValues: [Int]? % if 'closed' in RangeName.lower(): if test.rangeSelection.isEmpty { return } expectedValues = test.expectedClosedValues % else: expectedValues = test.expectedValues % end let elementCount = SubscriptGetTest.elementCount var memory = UnsafeMutablePointer>.allocate(capacity: elementCount) let buffer = test.create${SelfName}(from: memory) defer { memory.deallocate(capacity: elementCount) } let range = test.rangeSelection.${RangeName}(in: buffer) if expectedValues == nil { expectCrashLater() } let slice = buffer[range] expectEqual( expectedValues!, slice.map { $0.value }, stackTrace: SourceLocStack().with(test.loc) ) } % end % end % for RangeName in ['range', 'countableRange', 'closedRange', 'countableClosedRange']: UnsafeMutableBufferPointerTestSuite.test("subscript/${RangeName}/set") .forEach(in: subscriptSetTests) { (test) in let expectedValues: [Int]? let replacementValues: [OpaqueValue] % if 'closed' in RangeName.lower(): if test.rangeSelection.isEmpty { return } expectedValues = test.expectedValuesClosed replacementValues = test.replacementValuesClosed % else: expectedValues = test.expectedValues replacementValues = test.replacementValues % end let elementCount = SubscriptSetTest.elementCount var memory = UnsafeMutablePointer>.allocate( capacity: elementCount) var sliceMemory = UnsafeMutablePointer>.allocate( capacity: replacementValues.count) var buffer = test.createUnsafeMutableBufferPointer(from: memory) defer { memory.deallocate(capacity: elementCount) sliceMemory.deallocate(capacity: replacementValues.count) } let range = test.rangeSelection.${RangeName}(in: buffer) let replacementSlice = test.replacementValuesSlice( from: sliceMemory, replacementValues: replacementValues) if expectedValues == nil { expectCrashLater() } buffer[range] = replacementSlice expectEqual( expectedValues!, buffer.map { $0.value }, stackTrace: SourceLocStack().with(test.loc) ) } % end UnsafeMutableBufferPointerTestSuite.test("changeElementViaBuffer") { let count = 4 let allocated = UnsafeMutablePointer.allocate(capacity: count) defer { allocated.deallocate(capacity: count) } allocated.initialize(to: 1.0, count: count) allocated[count-1] = -1.0 var buffer = UnsafeMutableBufferPointer(start: allocated, count: count - 1) buffer[1] = 0.0 expectEqual(1.0, buffer[0]) expectEqual(0.0, buffer[1]) expectEqual(1.0, buffer[2]) expectEqual(1.0, allocated[0]) expectEqual(0.0, allocated[1]) expectEqual(1.0, allocated[2]) expectEqual(-1.0, allocated[count-1]) buffer.sort() expectEqual(0.0, buffer[0]) expectEqual(1.0, buffer[1]) expectEqual(1.0, buffer[2]) expectEqual(0.0, allocated[0]) expectEqual(1.0, allocated[1]) expectEqual(1.0, allocated[2]) expectEqual(-1.0, allocated[count-1]) } runAllTests()