Files
swift-mirror/test/stdlib/UnsafePointer.swift.gyb
Max Desiatov 1f99204897 test: disable crashing tests on WASI (#67531)
WASI doesn't support spawning a subprocess, so crash tests crashes the test harness itself. Those should be skipped until proper subprocess support is available.
2023-07-26 18:43:02 +01:00

567 lines
17 KiB
Swift

// RUN: %target-run-simple-swiftgyb
// REQUIRES: executable_test
// REQUIRES: reflection
import StdlibUnittest
protocol TestProtocol1 {}
// Check that the generic parameter is called 'Pointee'.
#if _runtime(_ObjC)
extension AutoreleasingUnsafeMutablePointer where Pointee : TestProtocol1 {
var _memoryIsTestProtocol1: Bool {
fatalError("not implemented")
}
}
#endif
extension UnsafePointer where Pointee : TestProtocol1 {
var _memoryIsTestProtocol1: Bool {
fatalError("not implemented")
}
}
extension UnsafeMutablePointer where Pointee : TestProtocol1 {
var _memoryIsTestProtocol1: Bool {
fatalError("not implemented")
}
}
// Check that the generic parameter is called 'Element'.
extension UnsafeBufferPointer.Iterator where Element : TestProtocol1 {
var _elementIsTestProtocol1: Bool {
fatalError("not implemented")
}
}
extension UnsafeBufferPointer where Element : TestProtocol1 {
var _elementIsTestProtocol1: Bool {
fatalError("not implemented")
}
}
extension UnsafeMutableBufferPointer where Element : TestProtocol1 {
var _elementIsTestProtocol1: Bool {
fatalError("not implemented")
}
}
var UnsafePointerTestSuite = TestSuite("UnsafePointer")
var UnsafeMutablePointerTestSuite = TestSuite("UnsafeMutablePointer")
var UnsafeRawPointerTestSuite = TestSuite("UnsafeRawPointer")
var UnsafeMutableRawPointerTestSuite = TestSuite("UnsafeMutableRawPointer")
var OpaquePointerTestSuite = TestSuite("OpaquePointer")
% for (SelfName, SelfType) in [
% ('UnsafePointer', 'UnsafePointer<Float>'),
% ('UnsafeMutablePointer', 'UnsafeMutablePointer<Float>'),
% ('UnsafeRawPointer', 'UnsafeRawPointer'),
% ('UnsafeMutableRawPointer', 'UnsafeMutableRawPointer')]:
${SelfName}TestSuite.test("initFromOpaquePointer") {
let other = OpaquePointer(bitPattern: 0x12345678)!
let ptr = ${SelfType}(other)
expectEqual(0x12345678, unsafeBitCast(ptr, to: Int.self))
let optionalOther: Optional = other
let optionalPointer = ${SelfType}(optionalOther)
expectNotNil(optionalPointer)
expectEqual(0x12345678, unsafeBitCast(optionalPointer, to: Int.self))
let nilOther: Optional<OpaquePointer> = nil
let nilPointer = ${SelfType}(nilOther)
expectNil(nilPointer)
}
% end
% for (SelfName, SelfType) in [
% ('UnsafeRawPointer', 'UnsafeRawPointer'),
% ('UnsafeMutableRawPointer', 'UnsafeMutableRawPointer')]:
UnsafeMutableRawPointerTestSuite.test("initFromMutating") {
let other = UnsafeRawPointer(bitPattern: 0x12345678)!
let ptr = UnsafeMutableRawPointer(mutating: other)
expectEqual(0x12345678, unsafeBitCast(ptr, to: Int.self))
let optionalOther: Optional = other
let optionalPointer = UnsafeMutableRawPointer(mutating: optionalOther)
expectNotNil(optionalPointer)
expectEqual(0x12345678, unsafeBitCast(optionalPointer, to: Int.self))
let nilOther: Optional<UnsafeRawPointer> = nil
let nilPointer = UnsafeMutableRawPointer(mutating: nilOther)
expectNil(nilPointer)
}
% end
% for (SelfName, SelfType) in [
% ('UnsafePointer', 'UnsafePointer<Float>'),
% ('UnsafeMutablePointer', 'UnsafeMutablePointer<Float>'),
% ('UnsafeRawPointer', 'UnsafeRawPointer'),
% ('UnsafeMutableRawPointer', 'UnsafeMutableRawPointer'),
% ('OpaquePointer', 'OpaquePointer')]:
${SelfName}TestSuite.test("convertFromNil") {
let ptr: ${SelfType}? = nil
expectEqual(0, unsafeBitCast(ptr, to: Int.self))
}
${SelfName}TestSuite.test("initFromInteger") {
do {
let word: Int = 0x12345678
let ptr = ${SelfType}(bitPattern: word)
expectNotNil(ptr)
expectEqual(word, unsafeBitCast(ptr, to: Int.self))
}
do {
let uword: UInt = 0x12345678
let ptr = ${SelfType}(bitPattern: uword)
expectNotNil(ptr)
expectEqual(uword, unsafeBitCast(ptr, to: UInt.self))
}
}
${SelfName}TestSuite.test("initFromNilBitPattern") {
do {
let word = unsafeBitCast(nil as ${SelfType}?, to: Int.self)
let ptr = ${SelfType}(bitPattern: word)
expectNil(ptr)
expectEqual(word, unsafeBitCast(ptr, to: Int.self))
}
do {
let uword = unsafeBitCast(nil as ${SelfType}?, to: UInt.self)
let ptr = ${SelfType}(bitPattern: uword)
expectNil(ptr)
expectEqual(uword, unsafeBitCast(ptr, to: UInt.self))
}
}
${SelfName}TestSuite.test("Hashable") {
let ptrs = [
${SelfType}(bitPattern: 0x12345678)!,
${SelfType}(bitPattern: 0x87654321 as UInt)!,
]
checkHashable(ptrs, equalityOracle: { $0 == $1 })
}
${SelfName}TestSuite.test("toInteger") {
do {
let word: Int = 0x12345678
let ptr = ${SelfType}(bitPattern: word)
expectEqual(word, Int(bitPattern: ptr))
}
do {
let ptr: ${SelfType}? = nil
expectEqual(Int(0), Int(bitPattern: ptr))
}
do {
let uword: UInt = 0x12345678
let ptr = ${SelfType}(bitPattern: uword)
expectEqual(uword, UInt(bitPattern: ptr))
}
do {
let ptr: ${SelfType}? = nil
expectEqual(UInt(0), UInt(bitPattern: ptr))
}
}
% end
% for (SelfName, SelfType) in [
% ('UnsafePointer', 'UnsafePointer<Float>'),
% ('UnsafeRawPointer', 'UnsafeRawPointer'),
% ('UnsafeMutableRawPointer', 'UnsafeMutableRawPointer')]:
${SelfName}TestSuite.test("initFromUnsafeMutablePointer") {
let other = UnsafeMutablePointer<Float>(bitPattern: 0x12345678)!
let ptr = ${SelfType}(other)
expectEqual(0x12345678, unsafeBitCast(ptr, to: Int.self))
let optionalOther: Optional = other
let optionalPointer = ${SelfType}(optionalOther)
expectNotNil(optionalPointer)
expectEqual(0x12345678, unsafeBitCast(optionalPointer, to: Int.self))
let nilOther: Optional<UnsafeMutablePointer<Float>> = nil
let nilPointer = ${SelfType}(nilOther)
expectNil(nilPointer)
}
% end
% for (SelfName, SelfType) in [
% ('UnsafePointer', 'UnsafePointer<Float>'),
% ('UnsafeRawPointer', 'UnsafeRawPointer')]:
${SelfName}TestSuite.test("initFromUnsafePointer") {
let other = UnsafePointer<Float>(bitPattern: 0x12345678)!
let ptr = ${SelfType}(other)
expectEqual(0x12345678, unsafeBitCast(ptr, to: Int.self))
let optionalOther: Optional = other
let optionalPointer = ${SelfType}(optionalOther)
expectNotNil(optionalPointer)
expectEqual(0x12345678, unsafeBitCast(optionalPointer, to: Int.self))
let nilOther: Optional<UnsafePointer<Float>> = nil
let nilPointer = ${SelfType}(nilOther)
expectNil(nilPointer)
}
% end
UnsafeRawPointerTestSuite.test("initFromUnsafeMutableRawPointer") {
let other = UnsafeMutableRawPointer(bitPattern: 0x12345678)!
let ptr = UnsafeRawPointer(other)
expectEqual(0x12345678, unsafeBitCast(ptr, to: Int.self))
let optionalOther: Optional = other
let optionalPointer = UnsafeRawPointer(optionalOther)
expectNotNil(optionalPointer)
expectEqual(0x12345678, unsafeBitCast(optionalPointer, to: Int.self))
let nilOther: Optional<UnsafeMutableRawPointer> = nil
let nilPointer = UnsafeRawPointer(nilOther)
expectNil(nilPointer)
}
enum Check {
case LeftOverlap
case RightOverlap
case Disjoint
}
class Missile {
static var missilesLaunched = 0
let number: Int
init(_ number: Int) { self.number = number }
deinit { Missile.missilesLaunched += 1 }
}
func checkPointerCorrectness(_ check: Check,
_ withMissiles: Bool = false,
_ f: (UnsafeMutablePointer<Missile>) ->
(UnsafeMutablePointer<Missile>, _ count: Int) -> Void) {
let ptr = UnsafeMutablePointer<Missile>.allocate(capacity: 4)
switch check {
case .RightOverlap:
ptr.initialize(to: Missile(1))
(ptr + 1).initialize(to: Missile(2))
if withMissiles {
(ptr + 2).initialize(to: Missile(3))
}
f(ptr + 1)(ptr, 2)
expectEqual(1, ptr[1].number)
expectEqual(2, ptr[2].number)
case .LeftOverlap:
if withMissiles {
ptr.initialize(to: Missile(1))
}
(ptr + 1).initialize(to: Missile(2))
(ptr + 2).initialize(to: Missile(3))
f(ptr)(ptr + 1, 2)
expectEqual(2, ptr[0].number)
expectEqual(3, ptr[1].number)
case .Disjoint:
if withMissiles {
ptr.initialize(to: Missile(0))
(ptr + 1).initialize(to: Missile(1))
}
(ptr + 2).initialize(to: Missile(2))
(ptr + 3).initialize(to: Missile(3))
f(ptr)(ptr + 2, 2)
expectEqual(2, ptr[0].number)
expectEqual(3, ptr[1].number)
// backwards
let ptr2 = UnsafeMutablePointer<Missile>.allocate(capacity: 4)
ptr2.initialize(to: Missile(0))
(ptr2 + 1).initialize(to: Missile(1))
if withMissiles {
(ptr2 + 2).initialize(to: Missile(2))
(ptr2 + 3).initialize(to: Missile(3))
}
f(ptr2 + 2)(ptr2, 2)
expectEqual(0, ptr2[2].number)
expectEqual(1, ptr2[3].number)
}
}
func checkPtr(
_ f: @escaping ((UnsafeMutablePointer<Missile>) -> (UnsafeMutablePointer<Missile>, _ count: Int) -> Void),
_ m: Bool
) -> (Check) -> Void {
return { checkPointerCorrectness($0, m, f) }
}
func checkPtr(
_ f: @escaping ((UnsafeMutablePointer<Missile>) -> (UnsafePointer<Missile>, _ count: Int) -> Void),
_ m: Bool
) -> (Check) -> Void {
return {
checkPointerCorrectness($0, m) { destPtr in
return { f(destPtr)(UnsafeMutablePointer($0), $1) }
}
}
}
#if !os(WASI)
// Trap tests aren't available on WASI.
UnsafeMutablePointerTestSuite.test("moveAssign:from:") {
let check = checkPtr(UnsafeMutablePointer.moveAssign, true)
check(Check.Disjoint)
// This check relies on _debugPrecondition() so will only trigger in -Onone mode.
if _isDebugAssertConfiguration() {
expectCrashLater()
check(Check.LeftOverlap)
}
}
UnsafeMutablePointerTestSuite.test("moveAssign:from:.Right") {
let check = checkPtr(UnsafeMutablePointer.moveAssign, true)
// This check relies on _debugPrecondition() so will only trigger in -Onone mode.
if _isDebugAssertConfiguration() {
expectCrashLater()
check(Check.RightOverlap)
}
}
#endif
UnsafeMutablePointerTestSuite.test("assign:from:") {
let check = checkPtr(UnsafeMutablePointer.assign, true)
check(Check.LeftOverlap)
check(Check.Disjoint)
check(Check.RightOverlap)
}
UnsafeMutablePointerTestSuite.test("moveInitialize:from:") {
let check = checkPtr(UnsafeMutablePointer.moveInitialize, false)
check(Check.LeftOverlap)
check(Check.Disjoint)
check(Check.RightOverlap)
}
#if !os(WASI)
// Trap tests aren't available on WASI.
UnsafeMutablePointerTestSuite.test("initialize:from:") {
let check = checkPtr(UnsafeMutablePointer.initialize(from:count:), false)
check(Check.Disjoint)
// This check relies on _debugPrecondition() so will only trigger in -Onone mode.
if _isDebugAssertConfiguration() {
expectCrashLater()
check(Check.LeftOverlap)
}
}
UnsafeMutablePointerTestSuite.test("initialize:from:.Right") {
let check = checkPtr(UnsafeMutablePointer.initialize(from:count:), false)
// This check relies on _debugPrecondition() so will only trigger in -Onone mode.
if _isDebugAssertConfiguration() {
expectCrashLater()
check(Check.RightOverlap)
}
}
#endif
UnsafeMutablePointerTestSuite.test("initialize:from:/immutable") {
let ptr = UnsafeMutablePointer<Missile>.allocate(capacity: 3)
defer {
ptr.deinitialize(count: 3)
ptr.deallocate()
}
let source = (0..<3).map(Missile.init)
source.withUnsafeBufferPointer { bufferPtr in
ptr.initialize(from: bufferPtr.baseAddress!, count: 3)
expectEqual(0, ptr[0].number)
expectEqual(1, ptr[1].number)
expectEqual(2, ptr[2].number)
}
}
UnsafeMutablePointerTestSuite.test("assign/immutable") {
let ptr = UnsafeMutablePointer<Missile>.allocate(capacity: 2)
defer {
ptr.deinitialize(count: 2)
ptr.deallocate()
}
ptr.initialize(to: Missile(1))
(ptr + 1).initialize(to: Missile(2))
let source = (3..<5).map(Missile.init)
source.withUnsafeBufferPointer { bufferPtr in
ptr.assign(from: bufferPtr.baseAddress!, count: 2)
expectEqual(3, ptr[0].number)
expectEqual(4, ptr[1].number)
}
}
% for (SelfName, SelfType) in [
% ('UnsafePointer', 'UnsafePointer<Float>'),
% ('UnsafeMutablePointer', 'UnsafeMutablePointer<Float>'),
% ('UnsafeRawPointer', 'UnsafeRawPointer'),
% ('UnsafeMutableRawPointer', 'UnsafeMutableRawPointer')]:
${SelfName}TestSuite.test("customMirror") {
// Ensure that the custom mirror works properly, including when the raw value
// is greater than Int.max
let reallyBigInt: UInt = UInt(Int.max) + 1
let ptr = ${SelfType}(bitPattern: reallyBigInt)!
let mirror = ptr.customMirror
expectEqual(1, mirror.children.count)
#if _pointerBitWidth(_32)
expectEqual("18446744071562067968", String(describing: mirror.children.first!.1))
#elseif _pointerBitWidth(_64)
expectEqual("9223372036854775808", String(describing: mirror.children.first!.1))
#else
fatalError("Unimplemented")
#endif
}
${SelfName}TestSuite.test("customPlaygroundQuickLook") {
// Ensure that the custom playground quicklook works properly, including when
// the raw value is greater than Int.max
let reallyBigInt: UInt = UInt(Int.max) + 1
let ptr = ${SelfType}(bitPattern: reallyBigInt)!
if case let .text(desc) = ptr.customPlaygroundQuickLook {
#if _pointerBitWidth(_32)
expectEqual("${SelfName}(0xFFFFFFFF80000000)", desc)
#elseif _pointerBitWidth(_64)
expectEqual("${SelfName}(0x8000000000000000)", desc)
#else
fatalError("Unimplemented")
#endif
} else {
expectTrue(false)
}
}
${SelfName}TestSuite.test("Comparable") {
var addresses: [UInt] = [
0x00000001,
0xFF00FF00,
0x00001111,
0x00000002,
0xFFFFFFFF,
0x00001111
]
#if arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le)
addresses += [
0xFFFFFFFF80000000,
0x8000000000000000
]
#endif
let instances = addresses.map { ($0, ${SelfType}(bitPattern: $0)!) }
func comparisonOracle(i: Int, j: Int) -> ExpectedComparisonResult {
return instances[i].0 <=> instances[j].0
}
checkComparable(instances.map { $0.1 }, oracle: comparisonOracle)
}
% end
% for SelfName in ['UnsafePointer', 'UnsafeMutablePointer']:
${SelfName}TestSuite.test("withMemoryRebound") {
let mutablePtrI = UnsafeMutablePointer<Int>.allocate(capacity: 4)
defer { mutablePtrI.deallocate() }
let ptrI = ${SelfName}<Int>(mutablePtrI)
ptrI.withMemoryRebound(to: UInt.self, capacity: 4) {
// Make sure the closure argument isa $SelfName
let ptrU: ${SelfName}<UInt> = $0
// and that the element type is UInt.
let mutablePtrU = UnsafeMutablePointer(mutating: ptrU)
expectType(UInt.self, &mutablePtrU.pointee)
}
}
${SelfName}TestSuite.test("withMemoryReboundSE0333") {
let mutablePtrI = UnsafeMutablePointer<Int>.allocate(capacity: 4)
defer { mutablePtrI.deallocate() }
let ptrI = ${SelfName}<Int>(mutablePtrI)
// test rebinding to a wider type with the same alignment
ptrI.withMemoryRebound(to: (Int, Int).self, capacity: 2) {
// Make sure the closure argument isa $SelfName
let ptrT: ${SelfName}<(Int, Int)> = $0
// and that the element type is (Int, Int).
let mutablePtrT = UnsafeMutablePointer(mutating: ptrT)
expectType((Int, Int).self, &mutablePtrT.pointee)
// test rebinding to a narrower type
ptrT.withMemoryRebound(to: UInt.self, capacity: 4) {
// Make sure the closure argument isa $SelfName
let ptrU: ${SelfName}<UInt> = $0
// and that the element type is UInt.
let mutablePtrU = UnsafeMutablePointer(mutating: ptrU)
expectType(UInt.self, &mutablePtrU.pointee)
}
}
}
${SelfName}TestSuite.test("withMemoryReboundSE0333.capacity1") {
let mutablePtr = UnsafeMutablePointer<(Int,Bool,Int64)>.allocate(capacity: 1)
let i = Int.random(in: 0 ... .max)
mutablePtr.initialize(to: (i, i.isMultiple(of: 2), Int64(0xff & i)))
defer { mutablePtr.deallocate() }
let ptr = ${SelfName}<(Int, Bool, Int64)>(mutablePtr)
// test rebinding to a shorter type with the same alignment
ptr.withMemoryRebound(to: (Int, Bool).self, capacity: 1) {
// Make sure the closure argument is a ${SelfName}
let ptrT: ${SelfName}<(Int, Bool)> = $0
// and that the element is (Int, Bool).
let mutablePtrT = UnsafeMutablePointer(mutating: ptrT)
expectType((Int, Bool).self, &mutablePtrT.pointee)
expectEqual($0.pointee.0, i)
expectEqual($0.pointee.1, i.isMultiple(of: 2))
}
}
${SelfName}TestSuite.test("pointer(to:)") {
struct Example {
var a = false
var b = 0
var c: String { "\(a),\(b)" }
}
let allocated = UnsafeMutablePointer<Example>.allocate(capacity: 1)
allocated.pointee = Example()
defer { allocated.deallocate() }
let p = ${SelfName}(allocated)
expectEqual(p.pointer(to: \.a)!.pointee, false)
expectEqual(p.pointer(to: \.b)!.pointee, 0)
expectNil(p.pointer(to: \.c))
% if SelfName == 'UnsafeMutablePointer':
p.pointer(to: \.a)!.pointee = true
p.pointer(to: \.b)!.pointee += 1
expectEqual(p.pointer(to: \.a as KeyPath)!.pointee, true)
expectEqual(p.pointer(to: \.b as KeyPath)!.pointee, 1)
% end
}
#if !os(WASI)
${SelfName}TestSuite.test("pointer(to:).overflow") {
struct Example {
var a = false
var b = 0
var c: String { "\(a),\(b)" }
var d = 0.0
}
let o = MemoryLayout<Example>.offset(of: \.b)!
let p = UnsafePointer<Example>(bitPattern: -o)
expectNotNil(p)
guard let p else { fatalError() }
if _isDebugAssertConfiguration() {
expectCrashLater()
}
let intPointer = p.pointer(to: \.b)
expectNil(intPointer) // nil because of overflow
let stringPointer = p.pointer(to: \.c)
expectNil(stringPointer) // nil because c is a computed property
let doublePointer = p.pointer(to: \.d)
expectNotNil(doublePointer)
}
#endif
% end
runAllTests()