Files
swift-mirror/validation-test/stdlib/UnsafeBufferPointer.swift.gyb
Austin Zheng dfcc13dc69 [stdlib] Bounds checks and tests for Unsafe*BufferPointer
Changes:
- Added bounds checks to Unsafe*BufferPointer's subscript getter and setter
- Added tests for Unsafe*BufferPointer's subscript getter for all four range types
2016-06-20 21:41:20 -07:00

244 lines
7.5 KiB
Plaintext

// 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]?
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<OpaqueValue<Int>>)
-> ${SelfType}<OpaqueValue<Int>>
{
for i in SubscriptGetTest.start..<SubscriptGetTest.end {
memory[i] = OpaqueValue(i)
}
return ${SelfType}(start: memory, count: SubscriptGetTest.elementCount)
}
% end
init(
rangeSelection: RangeSelection, expectedValues: [Int]? = nil,
file: String = #file, line: UInt = #line
) {
self.rangeSelection = rangeSelection
self.expectedValues = expectedValues
self.loc = SourceLoc(file, line, comment: "test data")
}
}
let subscriptGetTests : [SubscriptGetTest] = [
// Valid, empty.
SubscriptGetTest(rangeSelection: .emptyRange, expectedValues: []),
// Valid, edges.
SubscriptGetTest(rangeSelection: .leftEdge, expectedValues: [0]),
SubscriptGetTest(rangeSelection: .rightEdge, expectedValues: [19]),
// Valid, internal.
SubscriptGetTest(rangeSelection: .leftHalf,
expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
SubscriptGetTest(rangeSelection: .rightHalf,
expectedValues: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),
SubscriptGetTest(rangeSelection: .middle,
expectedValues: [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
SubscriptGetTest(rangeSelection: .full,
expectedValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),
// Invalid, bottom out of bounds.
SubscriptGetTest(rangeSelection: .offsets(-1, -1)),
SubscriptGetTest(rangeSelection: .offsets(-1, 0)),
SubscriptGetTest(rangeSelection: .offsets(-100, 5)),
// Invalid, top out of bounds.
SubscriptGetTest(rangeSelection: .offsets(20, 20)),
SubscriptGetTest(rangeSelection: .offsets(19, 20)),
SubscriptGetTest(rangeSelection: .offsets(5, 100)),
// Invalid, both out of bounds.
SubscriptGetTest(rangeSelection: .offsets(-1, 20)),
SubscriptGetTest(rangeSelection: .offsets(-100, 100)),
]
// Test Suites
var UnsafeBufferPointerTestSuite = TestSuite("UnsafeBufferPointer")
var UnsafeMutableBufferPointerTestSuite = TestSuite("UnsafeMutableBufferPointer")
% for (SelfName, IsMutable, SelfType, PointerType) in [
% ('UnsafeBufferPointer', False, 'UnsafeBufferPointer<Float>', 'UnsafePointer<Float>'),
% ('UnsafeMutableBufferPointer', True, 'UnsafeMutableBufferPointer<Float>', 'UnsafeMutablePointer<Float>')
% ]:
${SelfName}TestSuite.test("AssociatedTypes") {
typealias Subject = ${SelfName}<OpaqueValue<Int>>
expectRandomAccessCollectionAssociatedTypes(
collectionType: Subject.self,
iteratorType: IndexingIterator<Subject>.self,
subSequenceType: ${'Mutable' if IsMutable else ''}RandomAccessSlice<Subject>.self,
indexType: Int.self,
indexDistanceType: Int.self,
indicesType: CountableRange<Int>.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<Float>(allocatingCapacity: 0)
defer { emptyAllocated.deallocateCapacity(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<Float>(allocatingCapacity: count)
defer { allocated.deallocateCapacity(count) }
allocated.initialize(with: 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<Float>(allocatingCapacity: 0)
defer { emptyAllocated.deallocateCapacity(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/get").forEach(in: subscriptGetTests) {
(test) in
% if 'closed' in RangeName.lower():
if test.rangeSelection.isEmpty {
return
}
% end
let elementCount = SubscriptGetTest.elementCount
var memory = UnsafeMutablePointer<OpaqueValue<Int>>(allocatingCapacity: elementCount)
let buffer = test.create${SelfName}(from: memory)
defer { memory.deallocateCapacity(elementCount) }
let range = test.rangeSelection.${RangeName}(in: buffer)
if test.expectedValues == nil { expectCrashLater() }
let slice = buffer[range]
expectEqual(
test.expectedValues!,
slice.map { $0.value },
stackTrace: SourceLocStack().with(test.loc)
)
}
% end
% end
UnsafeMutableBufferPointerTestSuite.test("changeElementViaBuffer") {
let count = 4
let allocated = UnsafeMutablePointer<Float>(allocatingCapacity: count)
defer { allocated.deallocateCapacity(count) }
allocated.initialize(with: 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()