mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Update for SE-0107: UnsafeRawPointer This adds a "mutating" initialize to UnsafePointer to make Immutable -> Mutable conversions explicit. These are quick fixes to stdlib, overlays, and test cases that are necessary in order to remove arbitrary UnsafePointer conversions. Many cases can be expressed better up by reworking the surrounding code, but we first need a working starting point.
307 lines
10 KiB
Swift
307 lines
10 KiB
Swift
// RUN: %target-run-simple-swift
|
|
// REQUIRES: executable_test
|
|
|
|
// REQUIRES: objc_interop
|
|
// UNSUPPORTED: OS=watchos
|
|
|
|
import StdlibUnittest
|
|
import StdlibCollectionUnittest
|
|
|
|
|
|
import CoreAudio
|
|
|
|
// Used in tests below.
|
|
extension AudioBuffer : Equatable {}
|
|
|
|
public func == (lhs: AudioBuffer, rhs: AudioBuffer) -> Bool {
|
|
return lhs.mNumberChannels == rhs.mNumberChannels &&
|
|
lhs.mDataByteSize == rhs.mDataByteSize &&
|
|
lhs.mData == rhs.mData
|
|
}
|
|
|
|
var CoreAudioTestSuite = TestSuite("CoreAudio")
|
|
|
|
// The size of the non-flexible part of an AudioBufferList.
|
|
#if arch(i386) || arch(arm)
|
|
let ablHeaderSize = 4
|
|
#elseif arch(x86_64) || arch(arm64)
|
|
let ablHeaderSize = 8
|
|
#endif
|
|
|
|
CoreAudioTestSuite.test("UnsafeBufferPointer.init(_: AudioBuffer)") {
|
|
do {
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: 0, mDataByteSize: 0, mData: nil)
|
|
let result: UnsafeBufferPointer<Float> = UnsafeBufferPointer(audioBuffer)
|
|
expectEqual(nil, result.baseAddress)
|
|
expectEqual(0, result.count)
|
|
}
|
|
|
|
do {
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: 2, mDataByteSize: 1024,
|
|
mData: UnsafeMutableRawPointer(bitPattern: 0x1234_5678))
|
|
let result: UnsafeBufferPointer<Float> = UnsafeBufferPointer(audioBuffer)
|
|
expectEqual(audioBuffer.mData, UnsafeRawPointer(result.baseAddress!))
|
|
expectEqual(256, result.count)
|
|
}
|
|
}
|
|
|
|
CoreAudioTestSuite.test("UnsafeMutableBufferPointer.init(_: AudioBuffer)") {
|
|
do {
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: 0, mDataByteSize: 0, mData: nil)
|
|
let result: UnsafeMutableBufferPointer<Float> =
|
|
UnsafeMutableBufferPointer(audioBuffer)
|
|
expectEqual(nil, result.baseAddress)
|
|
expectEqual(0, result.count)
|
|
}
|
|
|
|
do {
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: 2, mDataByteSize: 1024,
|
|
mData: UnsafeMutableRawPointer(bitPattern: 0x1234_5678))
|
|
let result: UnsafeMutableBufferPointer<Float> =
|
|
UnsafeMutableBufferPointer(audioBuffer)
|
|
expectEqual(audioBuffer.mData!, UnsafeMutableRawPointer(result.baseAddress!))
|
|
expectEqual(256, result.count)
|
|
}
|
|
}
|
|
|
|
CoreAudioTestSuite.test(
|
|
"AudioBuffer.init(_: UnsafeMutableBufferPointer, numberOfChannels: Int)") {
|
|
do {
|
|
// NULL pointer.
|
|
let buffer = UnsafeMutableBufferPointer<Float>(start: nil, count: 0)
|
|
let result = AudioBuffer(buffer, numberOfChannels: 2)
|
|
expectEqual(2, result.mNumberChannels)
|
|
expectEqual(0, result.mDataByteSize)
|
|
expectEqual(nil, result.mData)
|
|
}
|
|
do {
|
|
// Non-NULL pointer.
|
|
let buffer = UnsafeMutableBufferPointer<Float>(
|
|
start: UnsafeMutablePointer<Float>(bitPattern: 0x1234_5678), count: 0)
|
|
let result = AudioBuffer(buffer, numberOfChannels: 2)
|
|
expectEqual(2, result.mNumberChannels)
|
|
expectEqual(0, result.mDataByteSize)
|
|
expectEqual(buffer.baseAddress, result.mData)
|
|
}
|
|
}
|
|
|
|
CoreAudioTestSuite.test(
|
|
"AudioBuffer.init(_: UnsafeMutableBufferPointer, numberOfChannels: Int)/trap") {
|
|
#if arch(i386) || arch(arm)
|
|
let overflowingCount = Int.max
|
|
#elseif arch(x86_64) || arch(arm64)
|
|
let overflowingCount = Int(UInt32.max)
|
|
#endif
|
|
let buffer = UnsafeMutableBufferPointer<Float>(
|
|
start: UnsafeMutablePointer<Float>(bitPattern: 0x1234_5678),
|
|
count: overflowingCount)
|
|
|
|
expectCrashLater()
|
|
// An overflow happens when we try to compute the value for mDataByteSize.
|
|
_ = AudioBuffer(buffer, numberOfChannels: 2)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.sizeInBytes(maximumBuffers: Int)") {
|
|
expectEqual(ablHeaderSize + strideof(AudioBuffer.self),
|
|
AudioBufferList.sizeInBytes(maximumBuffers: 1))
|
|
expectEqual(ablHeaderSize + 16 * strideof(AudioBuffer.self),
|
|
AudioBufferList.sizeInBytes(maximumBuffers: 16))
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.sizeInBytes(maximumBuffers: Int)/trap/count<0") {
|
|
expectCrashLater()
|
|
_ = AudioBufferList.sizeInBytes(maximumBuffers: -1)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.sizeInBytes(maximumBuffers: Int)/trap/count==0") {
|
|
expectCrashLater()
|
|
_ = AudioBufferList.sizeInBytes(maximumBuffers: -1)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.sizeInBytes(maximumBuffers: Int)/trap/overflow") {
|
|
expectCrashLater()
|
|
_ = AudioBufferList.sizeInBytes(maximumBuffers: Int.max)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.allocate(maximumBuffers: Int)") {
|
|
do {
|
|
let ablPtrWrapper = AudioBufferList.allocate(maximumBuffers: 1)
|
|
expectEqual(1, ablPtrWrapper.count)
|
|
free(ablPtrWrapper.unsafeMutablePointer)
|
|
}
|
|
do {
|
|
let ablPtrWrapper = AudioBufferList.allocate(maximumBuffers: 16)
|
|
expectEqual(16, ablPtrWrapper.count)
|
|
free(ablPtrWrapper.unsafeMutablePointer)
|
|
}
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.allocate(maximumBuffers: Int)/trap/count==0") {
|
|
expectCrashLater()
|
|
_ = AudioBufferList.allocate(maximumBuffers: 0)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.allocate(maximumBuffers: Int)/trap/count<0") {
|
|
expectCrashLater()
|
|
_ = AudioBufferList.allocate(maximumBuffers: -1)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("AudioBufferList.allocate(maximumBuffers: Int)/trap/overflow") {
|
|
expectCrashLater()
|
|
_ = AudioBufferList.allocate(maximumBuffers: Int.max)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer/AssociatedTypes") {
|
|
typealias Subject = UnsafeMutableAudioBufferListPointer
|
|
expectRandomAccessCollectionAssociatedTypes(
|
|
collectionType: Subject.self,
|
|
iteratorType: IndexingIterator<Subject>.self,
|
|
subSequenceType: MutableRandomAccessSlice<Subject>.self,
|
|
indexType: Int.self,
|
|
indexDistanceType: Int.self,
|
|
indicesType: CountableRange<Int>.self)
|
|
}
|
|
|
|
CoreAudioTestSuite.test(
|
|
"UnsafeMutableAudioBufferListPointer.init(_: UnsafeMutablePointer<AudioBufferList>)," +
|
|
"UnsafeMutableAudioBufferListPointer.unsafePointer," +
|
|
"UnsafeMutableAudioBufferListPointer.unsafeMutablePointer") {
|
|
do {
|
|
let ablPtrWrapper = UnsafeMutableAudioBufferListPointer(nil)
|
|
expectEmpty(ablPtrWrapper)
|
|
}
|
|
|
|
do {
|
|
let ablPtrWrapper = UnsafeMutableAudioBufferListPointer(
|
|
UnsafeMutablePointer<AudioBufferList>(bitPattern: 0x1234_5678)!)
|
|
expectEqual(
|
|
UnsafePointer<AudioBufferList>(bitPattern: 0x1234_5678),
|
|
ablPtrWrapper.unsafePointer)
|
|
expectEqual(
|
|
UnsafePointer<AudioBufferList>(bitPattern: 0x1234_5678),
|
|
ablPtrWrapper.unsafeMutablePointer)
|
|
}
|
|
|
|
do {
|
|
let ablPtrWrapper = UnsafeMutableAudioBufferListPointer(
|
|
UnsafeMutablePointer<AudioBufferList>(bitPattern: 0x1234_5678))
|
|
expectNotEmpty(ablPtrWrapper)
|
|
expectEqual(
|
|
UnsafePointer<AudioBufferList>(bitPattern: 0x1234_5678),
|
|
ablPtrWrapper!.unsafePointer)
|
|
expectEqual(
|
|
UnsafePointer<AudioBufferList>(bitPattern: 0x1234_5678),
|
|
ablPtrWrapper!.unsafeMutablePointer)
|
|
}
|
|
}
|
|
|
|
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer.count") {
|
|
let sizeInBytes = AudioBufferList.sizeInBytes(maximumBuffers: 16)
|
|
let rawPtr = UnsafeMutableRawPointer.allocate(
|
|
bytes: sizeInBytes, alignedTo: alignof(AudioBufferList.self))
|
|
let ablPtr = rawPtr.bindMemory(to: AudioBufferList.self,
|
|
capacity: sizeInBytes / strideof(AudioBufferList.self))
|
|
|
|
// It is important that 'ablPtrWrapper' is a 'let'. We are verifying that
|
|
// the 'count' property has a nonmutating setter.
|
|
let ablPtrWrapper = UnsafeMutableAudioBufferListPointer(ablPtr)
|
|
|
|
// Test getter.
|
|
rawPtr.storeBytes(of: 0x1234_5678, as: UInt32.self)
|
|
expectEqual(0x1234_5678, ablPtrWrapper.count)
|
|
|
|
// Test setter.
|
|
ablPtrWrapper.count = 0x7765_4321
|
|
expectEqual(0x7765_4321, rawPtr.load(as: UInt32.self))
|
|
|
|
rawPtr.deallocate(
|
|
bytes: sizeInBytes, alignedTo: alignof(AudioBufferList.self))
|
|
}
|
|
|
|
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer.subscript(_: Int)") {
|
|
let sizeInBytes = AudioBufferList.sizeInBytes(maximumBuffers: 16)
|
|
|
|
let rawPtr = UnsafeMutableRawPointer.allocate(
|
|
bytes: sizeInBytes, alignedTo: 1)
|
|
|
|
let ablPtr = rawPtr.bindMemory(
|
|
to: AudioBufferList.self,
|
|
capacity: sizeInBytes / sizeof(AudioBufferList.self))
|
|
|
|
// It is important that 'ablPtrWrapper' is a 'let'. We are verifying that
|
|
// the subscript has a nonmutating setter.
|
|
let ablPtrWrapper = UnsafeMutableAudioBufferListPointer(ablPtr)
|
|
|
|
do {
|
|
// Test getter.
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: 2, mDataByteSize: 1024,
|
|
mData: UnsafeMutableRawPointer(bitPattern: 0x1234_5678))
|
|
|
|
let bufPtr = (rawPtr + ablHeaderSize).assumingMemoryBound(
|
|
to: AudioBuffer.self)
|
|
bufPtr.pointee = audioBuffer
|
|
ablPtrWrapper.count = 1
|
|
|
|
expectEqual(2, ablPtrWrapper[0].mNumberChannels)
|
|
expectEqual(1024, ablPtrWrapper[0].mDataByteSize)
|
|
expectEqual(audioBuffer.mData, ablPtrWrapper[0].mData)
|
|
}
|
|
|
|
do {
|
|
// Test setter.
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: 5, mDataByteSize: 256,
|
|
mData: UnsafeMutableRawPointer(bitPattern: 0x8765_4321 as UInt))
|
|
|
|
ablPtrWrapper.count = 2
|
|
ablPtrWrapper[1] = audioBuffer
|
|
|
|
let audioBufferPtr = (rawPtr + ablHeaderSize).assumingMemoryBound(
|
|
to: AudioBuffer.self) + 1
|
|
expectEqual(5, audioBufferPtr.pointee.mNumberChannels)
|
|
expectEqual(256, audioBufferPtr.pointee.mDataByteSize)
|
|
expectEqual(audioBuffer.mData, audioBufferPtr.pointee.mData)
|
|
}
|
|
|
|
ablPtr.deallocate(capacity: sizeInBytes)
|
|
}
|
|
|
|
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer.subscript(_: Int)/trap") {
|
|
let ablPtrWrapper = AudioBufferList.allocate(maximumBuffers: 4)
|
|
|
|
ablPtrWrapper[0].mNumberChannels = 42
|
|
ablPtrWrapper[1].mNumberChannels = 42
|
|
ablPtrWrapper[2].mNumberChannels = 42
|
|
ablPtrWrapper[3].mNumberChannels = 42
|
|
|
|
expectCrashLater()
|
|
ablPtrWrapper[4].mNumberChannels = 42
|
|
}
|
|
|
|
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer/Collection") {
|
|
var ablPtrWrapper = AudioBufferList.allocate(maximumBuffers: 16)
|
|
expectType(UnsafeMutableAudioBufferListPointer.self, &ablPtrWrapper)
|
|
|
|
var expected: [AudioBuffer] = []
|
|
for i in 0..<16 {
|
|
let audioBuffer = AudioBuffer(
|
|
mNumberChannels: UInt32(2 + i), mDataByteSize: UInt32(1024 * i),
|
|
mData: UnsafeMutableRawPointer(bitPattern: 0x1234_5678 + i * 10))
|
|
|
|
ablPtrWrapper[i] = audioBuffer
|
|
expected.append(audioBuffer)
|
|
}
|
|
|
|
// FIXME: use checkMutableRandomAccessCollection, when we have that function.
|
|
checkRandomAccessCollection(expected, ablPtrWrapper)
|
|
free(ablPtrWrapper.unsafeMutablePointer)
|
|
}
|
|
|
|
runAllTests()
|
|
|