1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// UNSUPPORTED: freestanding
import StdlibUnittest
defer { runAllTests() }
var StringDeconstructTests = TestSuite("StringDeconstructTests")
enum ExpectedDeconstruction {
case scratchIfAvailable
case interiorPointer
case extraAllocation
}
func expectDeconstruct(
_ str: String,
_ expectDeconstruct: ExpectedDeconstruction,
stackTrace: SourceLocStack = SourceLocStack(),
showFrame: Bool = true,
file: String = #file, line: UInt = #line
) {
var stackTrace = stackTrace.pushIf(showFrame, file: file, line: line)
let expectBytes = Array(str.utf8)
_ = Array<UInt8>(unsafeUninitializedCapacity: 16) {
buffer, initializedCount in
// Deconstruct with a provided scratch space
// WS == with scratch, N == nil
let scratch = UnsafeMutableRawBufferPointer(buffer)
let (ownerWS, ptrWS, lengthWS, usedScratchWS, allocatedMemoryWS)
: (AnyObject?, UnsafePointer<UInt8>, Int, Bool, Bool)
= str._deconstructUTF8(scratch: scratch)
let (ownerN, ptrN, lengthN, usedScratchN, allocatedMemoryN)
: (AnyObject?, UnsafePointer<UInt8>, Int, Bool, Bool)
= str._deconstructUTF8(scratch: nil)
let rawBytesWS = UnsafeRawBufferPointer(start: ptrWS, count: lengthWS)
let rawBytesN = UnsafeRawBufferPointer(start: ptrN, count: lengthN)
expectEqualSequence(expectBytes, rawBytesWS, stackTrace: stackTrace)
expectEqualSequence(rawBytesWS, rawBytesN, stackTrace: stackTrace)
switch expectDeconstruct {
case .scratchIfAvailable:
expectNil(ownerWS, stackTrace: stackTrace)
expectNotNil(ownerN, stackTrace: stackTrace)
expectEqual(scratch.baseAddress, rawBytesWS.baseAddress,
stackTrace: stackTrace)
expectNotEqual(scratch.baseAddress, rawBytesN.baseAddress,
stackTrace: stackTrace)
expectTrue(lengthWS < scratch.count, stackTrace: stackTrace)
expectTrue(lengthN < scratch.count, stackTrace: stackTrace)
expectTrue(usedScratchWS, stackTrace: stackTrace)
expectFalse(usedScratchN, stackTrace: stackTrace)
expectFalse(allocatedMemoryWS, stackTrace: stackTrace)
expectTrue(allocatedMemoryN, stackTrace: stackTrace)
case .interiorPointer:
// TODO: owner == (immortal ? nil : StringObject.largeAddress)
expectTrue(str.isContiguousUTF8, stackTrace: stackTrace)
var copy = str
copy.withUTF8 {
expectEqual($0.baseAddress, ptrWS, stackTrace: stackTrace)
expectEqual($0.baseAddress, ptrN, stackTrace: stackTrace)
expectEqual($0.count, lengthWS, stackTrace: stackTrace)
expectEqual($0.count, lengthN, stackTrace: stackTrace)
}
expectFalse(usedScratchWS, stackTrace: stackTrace)
expectFalse(usedScratchN, stackTrace: stackTrace)
expectFalse(allocatedMemoryWS, stackTrace: stackTrace)
expectFalse(allocatedMemoryN, stackTrace: stackTrace)
case .extraAllocation:
expectFalse(str.isContiguousUTF8, stackTrace: stackTrace)
expectNotNil(ownerWS, stackTrace: stackTrace)
expectNotNil(ownerN, stackTrace: stackTrace)
expectFalse(usedScratchWS, stackTrace: stackTrace)
expectFalse(usedScratchN, stackTrace: stackTrace)
expectTrue(allocatedMemoryWS, stackTrace: stackTrace)
expectTrue(allocatedMemoryN, stackTrace: stackTrace)
}
}
}
@inline(never)
func id<T>(_ a: T) -> T { a }
StringDeconstructTests.test("deconstruct") {
let smallASCII = "abcd"
#if _pointerBitWidth(_32)
let smallUTF8 = "ジッパ"
#else
let smallUTF8 = "ジッパー"
#endif
let large = "the quick fox jumped over the lazy brown dog"
var largeMortal = large
largeMortal.append(id("🧟♀️"))
largeMortal.append(id(largeMortal.last!))
expectDeconstruct(smallASCII, .scratchIfAvailable)
expectDeconstruct(smallUTF8, .scratchIfAvailable)
expectDeconstruct(large, .interiorPointer)
expectDeconstruct(largeMortal, .interiorPointer)
}
#if _runtime(_ObjC)
import Foundation
StringDeconstructTests.test("deconstruct cocoa") {
let smallCocoa: NSString = "aaa"
let largeASCIICocoa: NSString = "the quick fox jumped over the lazy brown dog"
let largeCocoa: NSString = "the quick 🧟♀️ ate the slow 🧠"
#if _pointerBitWidth(_32)
expectDeconstruct(smallCocoa as String, .interiorPointer)
#elseif _pointerBitWidth(_64)
expectDeconstruct(smallCocoa as String, .scratchIfAvailable)
#else
#error("Unknown platform")
#endif
expectDeconstruct(largeASCIICocoa as String, .interiorPointer)
expectDeconstruct(largeCocoa as String, .extraAllocation)
}
#endif
|