File: StringBreadcrumbs.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (115 lines) | stat: -rw-r--r-- 3,650 bytes parent folder | download
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()