mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This fix updates various initializers to handle incoming empty buffers that happen to have a nil base. They should simply create another buffer with nil base rather than crashing! It is valid for an Unsafe[Raw]BufferPointer can have a nil base address. This allows round-tripping with C code that takes a pointer/length pair and uses `0` as the pointer value. The original design wrongly assumed that we would use a sentinel value for empty buffers and was never updated for or tested with the current design. Fixes <rdar://problem/47946984> Regression in Foundation.Data's UnsafeBufferPointer constructor.
544 lines
17 KiB
Swift
544 lines
17 KiB
Swift
// RUN: %target-run-simple-swiftgyb
|
|
// REQUIRES: executable_test
|
|
//
|
|
// Test corner cases specific to UnsafeRawBufferPointer.
|
|
// General Collection behavior tests are in
|
|
// validation-test/stdlib/UnsafeBufferPointer.swift.
|
|
|
|
// FIXME: The optimized-build behavior of UnsafeBufferPointer bounds/overflow
|
|
// checking cannot be tested. The standard library always compiles with debug
|
|
// checking enabled, so the behavior of the optimized test depends on whether
|
|
// the inlining heuristics decide to inline these methods. To fix this, we need
|
|
// a way to force @inlinable UnsafeBufferPointer methods to be emitted inside
|
|
// the client code, and thereby subject the stdlib implementation to the test
|
|
// case's compile options.
|
|
//
|
|
// REQUIRES: swift_test_mode_optimize_none
|
|
|
|
import StdlibUnittest
|
|
|
|
var UnsafeRawBufferPointerTestSuite = TestSuite("UnsafeRawBufferPointer")
|
|
|
|
// View an in-memory value's bytes.
|
|
// Use copyBytes to overwrite the value's bytes.
|
|
UnsafeRawBufferPointerTestSuite.test("initFromValue") {
|
|
var value1: Int32 = -1
|
|
var value2: Int32 = 0
|
|
// Immutable view of value1's bytes.
|
|
withUnsafeBytes(of: &value1) { bytes1 in
|
|
expectEqual(bytes1.count, 4)
|
|
for b in bytes1 {
|
|
expectEqual(b, 0xFF)
|
|
}
|
|
// Mutable view of value2's bytes.
|
|
withUnsafeMutableBytes(of: &value2) { bytes2 in
|
|
expectEqual(bytes1.count, bytes2.count)
|
|
bytes2.copyMemory(from: bytes1)
|
|
}
|
|
}
|
|
expectEqual(value2, value1)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initFromNilBuffer") {
|
|
let urbp1 =
|
|
UnsafeRawBufferPointer(UnsafeBufferPointer<Int>(start: nil, count: 0))
|
|
expectEqual(urbp1.baseAddress, nil)
|
|
|
|
let urbp2 =
|
|
UnsafeRawBufferPointer(UnsafeMutableBufferPointer<Int>(start: nil, count: 0))
|
|
expectEqual(urbp2.baseAddress, nil)
|
|
|
|
let umrbp =
|
|
UnsafeMutableRawBufferPointer(
|
|
UnsafeMutableBufferPointer<Int>(start: nil, count: 0))
|
|
expectEqual(umrbp.baseAddress, nil)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initFromNilSlice") {
|
|
let urbp1 =
|
|
UnsafeRawBufferPointer(
|
|
rebasing: UnsafeRawBufferPointer(start: nil, count: 0)[...])
|
|
expectEqual(urbp1.baseAddress, nil)
|
|
|
|
let urbp2 =
|
|
UnsafeRawBufferPointer(
|
|
rebasing: UnsafeMutableRawBufferPointer(start: nil, count: 0)[...])
|
|
expectEqual(urbp2.baseAddress, nil)
|
|
|
|
let umrbp =
|
|
UnsafeMutableRawBufferPointer(
|
|
rebasing: UnsafeMutableRawBufferPointer(start: nil, count: 0)[...])
|
|
expectEqual(umrbp.baseAddress, nil)
|
|
}
|
|
|
|
// Test mutability and subscript getter/setters.
|
|
UnsafeRawBufferPointerTestSuite.test("nonmutating_subscript_setter") {
|
|
var value1: Int32 = -1
|
|
var value2: Int32 = 0
|
|
|
|
withUnsafeMutableBytes(of: &value1) { bytes1 in
|
|
withUnsafeMutableBytes(of: &value2) { bytes2 in
|
|
bytes2[0..<bytes2.count] = bytes1[0..<bytes1.count]
|
|
}
|
|
}
|
|
expectEqual(value2, value1)
|
|
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 4, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
buffer.copyBytes(from: [0, 1, 2, 3] as [UInt8])
|
|
let leftBytes = buffer[0..<2]
|
|
|
|
// Subscript assign.
|
|
var rightBytes = buffer[2..<4]
|
|
buffer[2..<4] = leftBytes
|
|
expectEqualSequence(leftBytes, rightBytes)
|
|
|
|
// Subscript assign into a `var` mutable slice.
|
|
buffer.copyBytes(from: [0, 1, 2, 3] as [UInt8])
|
|
rightBytes[2..<4] = leftBytes
|
|
expectEqualSequence(leftBytes, rightBytes)
|
|
}
|
|
|
|
// View an array's elements as bytes.
|
|
// Use copyBytes to overwrite the array element's bytes.
|
|
UnsafeRawBufferPointerTestSuite.test("initFromArray") {
|
|
let array1: [Int32] = [0, 1, 2, 3]
|
|
var array2 = [Int32](repeating: 0, count: 4)
|
|
// Immutable view of array1's bytes.
|
|
array1.withUnsafeBytes { bytes1 in
|
|
expectEqual(bytes1.count, 16)
|
|
for (i, b) in bytes1.enumerated() {
|
|
var num = i
|
|
#if _endian(big)
|
|
num = num + 1
|
|
#endif
|
|
if num % 4 == 0 {
|
|
expectEqual(Int(b), i / 4)
|
|
}
|
|
else {
|
|
expectEqual(b, 0)
|
|
}
|
|
}
|
|
// Mutable view of array2's bytes.
|
|
array2.withUnsafeMutableBytes { bytes2 in
|
|
expectEqual(bytes1.count, bytes2.count)
|
|
bytes2.copyMemory(from: bytes1)
|
|
}
|
|
}
|
|
expectEqual(array2, array1)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initializeMemory(as:from:).underflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 30, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
let source = stride(from: 5 as Int64, to: 0, by: -1)
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
var (it, bound) = buffer.initializeMemory(as: Int64.self, from: source)
|
|
let idx = bound.endIndex * MemoryLayout<Int64>.stride
|
|
expectEqual(it.next()!, 2)
|
|
expectEqual(idx, 24)
|
|
let expected: [Int64] = [5,4,3]
|
|
expected.withUnsafeBytes { expectEqualSequence($0,buffer[0..<idx]) }
|
|
expectEqualSequence([5, 4, 3],bound)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initializeMemory(as:from:).overflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 30, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
let source: [Int64] = [5, 4, 3, 2, 1]
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
var (it,bound) = buffer.initializeMemory(as: Int64.self, from: source)
|
|
let idx = bound.endIndex * MemoryLayout<Int64>.stride
|
|
expectEqual(it.next()!, 2)
|
|
expectEqual(idx, 24)
|
|
let expected: [Int64] = [5,4,3]
|
|
expected.withUnsafeBytes { expectEqualSequence($0,buffer[0..<idx]) }
|
|
expectEqualSequence([5, 4, 3],bound)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initializeMemory(as:from:).exact") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 24, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
let source: [Int64] = [5, 4, 3]
|
|
var (it,bound) = buffer.initializeMemory(as: Int64.self, from: source)
|
|
let idx = bound.endIndex * MemoryLayout<Int64>.stride
|
|
expectNil(it.next())
|
|
expectEqual(idx, buffer.endIndex)
|
|
source.withUnsafeBytes { expectEqualSequence($0,buffer) }
|
|
expectEqualSequence([5, 4, 3],bound)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initializeMemory(as:from:).invalidNilPtr") {
|
|
let buffer = UnsafeMutableRawBufferPointer(start: nil, count: 0)
|
|
let source: [Int64] = [5, 4, 3, 2, 1]
|
|
expectCrashLater()
|
|
_ = buffer.initializeMemory(as: Int64.self, from: source)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("initializeMemory(as:from:).validNilPtr") {
|
|
let buffer = UnsafeMutableRawBufferPointer(start: nil, count: 0)
|
|
let source: [Int64] = []
|
|
var (it, bound) = buffer.initializeMemory(as: Int64.self, from: source)
|
|
let idx = bound.endIndex * MemoryLayout<Int64>.stride
|
|
expectNil(it.next())
|
|
expectEqual(idx, source.endIndex)
|
|
}
|
|
|
|
|
|
// Directly test the byte Sequence produced by withUnsafeBytes.
|
|
UnsafeRawBufferPointerTestSuite.test("withUnsafeBytes.Sequence") {
|
|
let array1: [Int32] = [0, 1, 2, 3]
|
|
array1.withUnsafeBytes { bytes1 in
|
|
// Initialize an array from a sequence of bytes.
|
|
let byteArray = [UInt8](bytes1)
|
|
for (b1, b2) in zip(byteArray, bytes1) {
|
|
expectEqual(b1, b2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test the empty buffer.
|
|
UnsafeRawBufferPointerTestSuite.test("empty") {
|
|
let emptyBytes = UnsafeRawBufferPointer(start: nil, count: 0)
|
|
for _ in emptyBytes {
|
|
expectUnreachable()
|
|
}
|
|
let emptyMutableBytes = UnsafeMutableRawBufferPointer.allocate(byteCount: 0, alignment: MemoryLayout<UInt>.alignment)
|
|
for _ in emptyMutableBytes {
|
|
expectUnreachable()
|
|
}
|
|
emptyMutableBytes.deallocate()
|
|
}
|
|
|
|
// Store a sequence of integers to raw memory, and reload them as structs.
|
|
// Store structs to raw memory, and reload them as integers.
|
|
UnsafeRawBufferPointerTestSuite.test("reinterpret") {
|
|
struct Pair {
|
|
var x: Int32
|
|
var y: Int32
|
|
}
|
|
let numPairs = 2
|
|
let bytes = UnsafeMutableRawBufferPointer.allocate(
|
|
byteCount: MemoryLayout<Pair>.stride * numPairs, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { bytes.deallocate() }
|
|
|
|
for i in 0..<(numPairs * 2) {
|
|
bytes.storeBytes(of: Int32(i), toByteOffset: i * MemoryLayout<Int32>.stride,
|
|
as: Int32.self)
|
|
}
|
|
let pair1 = bytes.load(as: Pair.self)
|
|
let pair2 = bytes.load(fromByteOffset: MemoryLayout<Pair>.stride,
|
|
as: Pair.self)
|
|
expectEqual(0, pair1.x)
|
|
expectEqual(1, pair1.y)
|
|
expectEqual(2, pair2.x)
|
|
expectEqual(3, pair2.y)
|
|
|
|
bytes.storeBytes(of: Pair(x: -1, y: 0), as: Pair.self)
|
|
for i in 0..<MemoryLayout<Int32>.stride {
|
|
expectEqual(0xFF, bytes[i])
|
|
}
|
|
let bytes2 = UnsafeMutableRawBufferPointer(
|
|
rebasing: bytes[MemoryLayout<Int32>.stride..<bytes.count])
|
|
for i in 0..<MemoryLayout<Int32>.stride {
|
|
expectEqual(0, bytes2[i])
|
|
}
|
|
}
|
|
|
|
// Store, load, subscript, and slice at all valid byte offsets.
|
|
UnsafeRawBufferPointerTestSuite.test("inBounds") {
|
|
let numInts = 4
|
|
let bytes = UnsafeMutableRawBufferPointer.allocate(
|
|
byteCount: MemoryLayout<Int>.stride * numInts, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { bytes.deallocate() }
|
|
|
|
for i in 0..<numInts {
|
|
bytes.storeBytes(
|
|
of: i, toByteOffset: i * MemoryLayout<Int>.stride, as: Int.self)
|
|
}
|
|
for i in 0..<numInts {
|
|
let x = bytes.load(
|
|
fromByteOffset: i * MemoryLayout<Int>.stride, as: Int.self)
|
|
expectEqual(x, i)
|
|
}
|
|
for i in 0..<numInts {
|
|
var x = i
|
|
withUnsafeBytes(of: &x) {
|
|
for (offset, byte) in $0.enumerated() {
|
|
expectEqual(bytes[i * MemoryLayout<Int>.stride + offset], byte)
|
|
}
|
|
}
|
|
}
|
|
let median = (numInts/2 * MemoryLayout<Int>.stride)
|
|
var firstHalf = bytes[0..<median]
|
|
let secondHalf = bytes[median..<bytes.count]
|
|
firstHalf[0..<firstHalf.count] = secondHalf
|
|
expectEqualSequence(firstHalf, secondHalf)
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.get.underflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytes = UnsafeRawBufferPointer(rebasing: buffer[1..<2])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
_ = bytes[-1]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.get.overflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytes = UnsafeRawBufferPointer(rebasing: buffer[0..<1])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
_ = bytes[1]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.set.underflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[1..<2])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
bytes[-1] = 0
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.set.overflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 2, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[0..<1])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
bytes[1] = 0
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.range.get.underflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytes = UnsafeRawBufferPointer(rebasing: buffer[1..<3])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
_ = bytes[-1..<1]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.range.get.overflow") {
|
|
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytes = UnsafeRawBufferPointer(rebasing: buffer[0..<2])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
_ = bytes[1..<3]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.range.set.underflow") {
|
|
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[1..<3])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Accesses a valid buffer location but triggers a debug bounds check.
|
|
bytes[-1..<1] = bytes[0..<2]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.range.set.overflow") {
|
|
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
var bytes = UnsafeMutableRawBufferPointer(rebasing: buffer[0..<2])
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
|
|
// Performs a valid byte-wise copy but triggers a debug bounds check.
|
|
bytes[1..<3] = bytes[0..<2]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.range.narrow") {
|
|
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Performs a valid byte-wise copy but triggers a debug bounds check.
|
|
buffer[0..<3] = buffer[0..<2]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("subscript.range.wide") {
|
|
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Performs a valid byte-wise copy but triggers a debug bounds check.
|
|
buffer[0..<2] = buffer[0..<3]
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("copyMemory.overflow") {
|
|
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytes = buffer[0..<2]
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Performs a valid byte-wise copy but triggers a debug range size check.
|
|
UnsafeMutableRawBufferPointer(rebasing: bytes).copyMemory(
|
|
from: UnsafeRawBufferPointer(buffer))
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("copyBytes.sequence.overflow") {
|
|
var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<UInt>.alignment)
|
|
defer { buffer.deallocate() }
|
|
|
|
let bytes = buffer[0..<2]
|
|
|
|
if _isDebugAssertConfiguration() {
|
|
expectCrashLater()
|
|
}
|
|
// Performs a valid byte-wise copy but triggers a debug range size check.
|
|
UnsafeMutableRawBufferPointer(rebasing: bytes).copyBytes(
|
|
from: [0, 1, 2] as [UInt8])
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("load.before")
|
|
.skip(.custom(
|
|
{ !_isDebugAssertConfiguration() },
|
|
reason: "This tests a debug precondition."))
|
|
.code {
|
|
expectCrashLater()
|
|
var x: Int32 = 0
|
|
withUnsafeBytes(of: &x) {
|
|
_ = $0.load(fromByteOffset: -1, as: UInt8.self)
|
|
}
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("load.after")
|
|
.skip(.custom(
|
|
{ !_isDebugAssertConfiguration() },
|
|
reason: "This tests a debug precondition.."))
|
|
.code {
|
|
expectCrashLater()
|
|
var x: Int32 = 0
|
|
withUnsafeBytes(of: &x) {
|
|
_ = $0.load(as: UInt64.self)
|
|
}
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("store.before")
|
|
.skip(.custom(
|
|
{ !_isDebugAssertConfiguration() },
|
|
reason: "This tests a debug precondition.."))
|
|
.code {
|
|
expectCrashLater()
|
|
var x: Int32 = 0
|
|
withUnsafeMutableBytes(of: &x) {
|
|
$0.storeBytes(of: UInt8(0), toByteOffset: -1, as: UInt8.self)
|
|
}
|
|
}
|
|
UnsafeRawBufferPointerTestSuite.test("store.after")
|
|
.skip(.custom(
|
|
{ !_isDebugAssertConfiguration() },
|
|
reason: "This tests a debug precondition.."))
|
|
.code {
|
|
expectCrashLater()
|
|
var x: Int32 = 0
|
|
withUnsafeMutableBytes(of: &x) {
|
|
$0.storeBytes(of: UInt64(0), as: UInt64.self)
|
|
}
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("copy.bytes.overflow")
|
|
.skip(.custom(
|
|
{ !_isDebugAssertConfiguration() },
|
|
reason: "This tests a debug precondition.."))
|
|
.code {
|
|
expectCrashLater()
|
|
var x: Int64 = 0
|
|
var y: Int32 = 0
|
|
withUnsafeBytes(of: &x) { srcBytes in
|
|
withUnsafeMutableBytes(of: &y) { destBytes in
|
|
destBytes.copyMemory(
|
|
from: srcBytes)
|
|
}
|
|
}
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("copy.sequence.overflow")
|
|
.skip(.custom(
|
|
{ !_isDebugAssertConfiguration() },
|
|
reason: "This tests a debug precondition.."))
|
|
.code {
|
|
expectCrashLater()
|
|
var x: Int64 = 0
|
|
var y: Int32 = 0
|
|
withUnsafeBytes(of: &x) { srcBytes in
|
|
withUnsafeMutableBytes(of: &y) { destBytes in
|
|
destBytes.copyMemory(from: srcBytes)
|
|
}
|
|
}
|
|
}
|
|
|
|
UnsafeRawBufferPointerTestSuite.test("copy.overlap") {
|
|
let bytes = UnsafeMutableRawBufferPointer.allocate(byteCount: 4, alignment: MemoryLayout<UInt>.alignment)
|
|
// Right Overlap
|
|
bytes[0] = 1
|
|
bytes[1] = 2
|
|
bytes[1..<3] = bytes[0..<2]
|
|
expectEqual(1, bytes[1])
|
|
expectEqual(2, bytes[2])
|
|
// Left Overlap
|
|
bytes[1] = 2
|
|
bytes[2] = 3
|
|
bytes[0..<2] = bytes[1..<3]
|
|
expectEqual(2, bytes[0])
|
|
expectEqual(3, bytes[1])
|
|
// Disjoint
|
|
bytes[2] = 2
|
|
bytes[3] = 3
|
|
bytes[0..<2] = bytes[2..<4]
|
|
expectEqual(2, bytes[0])
|
|
expectEqual(3, bytes[1])
|
|
bytes[0] = 0
|
|
bytes[1] = 1
|
|
bytes[2..<4] = bytes[0..<2]
|
|
expectEqual(0, bytes[2])
|
|
expectEqual(1, bytes[3])
|
|
}
|
|
|
|
runAllTests()
|