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
|
// RUN: %target-run-stdlib-swift
// REQUIRES: executable_test,optimized_stdlib
// UNSUPPORTED: freestanding
// Some targeted tests for the breadcrumbs path. There is some overlap with
// UTF16View tests for huge strings, but we want a simpler suite that targets
// some corner cases specifically.
import Swift
import StdlibUnittest
let smallASCII = "abcdefg"
let smallUnicode = "abรฉร๐"
let largeASCII = "012345678901234567890"
let largeUnicode = "abรฉร012345678901234567890๐"
let emoji = "๐๐๐คข๐คฎ๐ฉ๐ฟโ๐ค๐ง๐ปโโ๏ธ๐ง๐ปโโ๏ธ๐ฉโ๐ฉโ๐ฆโ๐ฆ"
let chinese = "Swift ๆฏ้ขๅ Apple ๅนณๅฐ็็ผ็จ่ฏญ่จ๏ผๅ่ฝๅผบๅคงไธ็ด่งๆ็จ๏ผ่ๆฌๆฌกๆดๆฐๅฏนๅ
ถ่ฟ่กไบๅ
จ้ขไผๅใ"
let nonBMP = String(repeating: "๐", count: 1 + (64 / 2))
let largeString: String = {
var result = ""
result += smallASCII
result += smallUnicode
result += largeASCII
result += chinese
result += largeUnicode
result += emoji
result += smallASCII
result += result.reversed()
return result
}()
extension FixedWidthInteger {
var hexStr: String { return "0x\(String(self, radix: 16, uppercase: true))" }
}
let StringBreadcrumbsTests = TestSuite("StringBreadcrumbsTests")
func validateBreadcrumbs(_ str: String) {
var utf16CodeUnits = Array(str.utf16)
var outputBuffer = Array<UInt16>(repeating: 0, count: utf16CodeUnits.count)
// Include the endIndex, so we can test end conversions
var utf16Indices = Array(str.utf16.indices) + [str.utf16.endIndex]
for i in 0...utf16CodeUnits.count {
for j in i...utf16CodeUnits.count {
let range = Range(uncheckedBounds: (i, j))
let indexRange = str._toUTF16Indices(range)
// Range<String.Index> <=> Range<Int>
expectEqual(utf16Indices[i], indexRange.lowerBound)
expectEqual(utf16Indices[j], indexRange.upperBound)
expectEqualSequence(
utf16CodeUnits[i..<j], str.utf16[indexRange])
let roundTripOffsets = str._toUTF16Offsets(indexRange)
expectEqualSequence(range, roundTripOffsets)
// Single Int <=> String.Index
expectEqual(indexRange.lowerBound, str._toUTF16Index(i))
expectEqual(indexRange.upperBound, str._toUTF16Index(j))
expectEqual(i, str._toUTF16Offset(indexRange.lowerBound))
expectEqual(j, str._toUTF16Offset(indexRange.upperBound))
// Copy characters
outputBuffer.withUnsafeMutableBufferPointer {
str._copyUTF16CodeUnits(into: $0, range: range)
}
expectEqualSequence(utf16CodeUnits[i..<j], outputBuffer[..<range.count])
}
}
}
StringBreadcrumbsTests.test("uniform strings") {
validateBreadcrumbs(smallASCII)
validateBreadcrumbs(largeASCII)
validateBreadcrumbs(smallUnicode)
validateBreadcrumbs(largeUnicode)
}
StringBreadcrumbsTests.test("largeString") {
validateBreadcrumbs(largeString)
}
// Test various boundary conditions with surrogate pairs aligning or not
// aligning
StringBreadcrumbsTests.test("surrogates-heavy") {
// Mis-align the hieroglyphics by 1,2,3 UTF-8 and UTF-16 code units
validateBreadcrumbs(nonBMP)
validateBreadcrumbs("a" + nonBMP)
validateBreadcrumbs("ab" + nonBMP)
validateBreadcrumbs("abc" + nonBMP)
validateBreadcrumbs("รฉ" + nonBMP)
validateBreadcrumbs("ๆฏ" + nonBMP)
validateBreadcrumbs("aรฉ" + nonBMP)
}
// Test bread-crumb invalidation
StringBreadcrumbsTests.test("stale breadcrumbs") {
var str = nonBMP + "๐"
let oldLen = str.utf16.count
str.removeLast()
expectEqual(oldLen - 2, str.utf16.count)
str += "a"
expectEqual(oldLen - 1, str.utf16.count)
str += "๐"
expectEqual(oldLen + 1, str.utf16.count)
}
runAllTests()
|