blob: 2e42bb8ee764df2e25100bd84379be8e288828f7 [file] [log] [blame]
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
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 arch(i386) || arch(arm) || arch(wasm32)
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 arch(i386) || arch(arm) || arch(wasm32)
expectDeconstruct(smallCocoa as String, .interiorPointer)
#else
expectDeconstruct(smallCocoa as String, .scratchIfAvailable)
#endif
expectDeconstruct(largeASCIICocoa as String, .interiorPointer)
expectDeconstruct(largeCocoa as String, .extraAllocation)
}
#endif