Skip to content

Commit 66a8ae0

Browse files
committed
[test] Move string test helper methods to StdlibUnittest
This fixes a Windows regression triggered by #41417.
1 parent 9de1a79 commit 66a8ae0

File tree

4 files changed

+141
-141
lines changed

4 files changed

+141
-141
lines changed

stdlib/private/StdlibUnicodeUnittest/StdlibUnicodeUnittest.swift

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -778,143 +778,3 @@ public let utf16Tests = [
778778
[ 0xDC00, 0xD800, 0xD800, 0xDC00 ]),
779779
],
780780
]
781-
782-
extension String {
783-
/// Print out a full list of indices in every view of this string.
784-
/// This is useful while debugging string indexing issues.
785-
public func dumpIndices() {
786-
print("-------------------------------------------------------------------")
787-
print("String: \(String(reflecting: self))")
788-
print("Characters:")
789-
self.indices.forEach { i in
790-
let char = self[i]
791-
print(" \(i) -> \(String(reflecting: char))")
792-
}
793-
print("Scalars:")
794-
self.unicodeScalars.indices.forEach { i in
795-
let scalar = self.unicodeScalars[i]
796-
let value = String(scalar.value, radix: 16, uppercase: true)
797-
let padding = String(repeating: "0", count: max(0, 4 - value.count))
798-
let name = scalar.properties.name ?? "\(scalar.debugDescription)"
799-
print(" \(i) -> U+\(padding)\(value) \(name)")
800-
}
801-
print("UTF-8:")
802-
self.utf8.indices.forEach { i in
803-
let code = self.utf8[i]
804-
let value = String(code, radix: 16, uppercase: true)
805-
let padding = value.count < 2 ? "0" : ""
806-
print(" \(i) -> \(padding)\(value)")
807-
}
808-
print("UTF-16:")
809-
self.utf16.indices.forEach { i in
810-
let code = self.utf16[i]
811-
let value = String(code, radix: 16, uppercase: true)
812-
let padding = String(repeating: "0", count: 4 - value.count)
813-
print(" \(i) -> \(padding)\(value)")
814-
}
815-
}
816-
817-
// Returns a list of every valid index in every string view, optionally
818-
// including end indices. We keep equal indices originating from different
819-
// views because they may have different grapheme size caches or flags etc.
820-
public func allIndices(includingEnd: Bool = true) -> [String.Index] {
821-
var r = Array(self.indices)
822-
if includingEnd { r.append(self.endIndex) }
823-
r += Array(self.unicodeScalars.indices)
824-
if includingEnd { r.append(self.unicodeScalars.endIndex) }
825-
r += Array(self.utf8.indices)
826-
if includingEnd { r.append(self.utf8.endIndex) }
827-
r += Array(self.utf16.indices)
828-
if includingEnd { r.append(self.utf16.endIndex) }
829-
return r
830-
}
831-
}
832-
833-
extension Substring {
834-
// Returns a list of every valid index in every substring view, optionally
835-
// including end indices. We keep equal indices originating from different
836-
// views because they may have different grapheme size caches or flags etc.
837-
public func allIndices(includingEnd: Bool = true) -> [String.Index] {
838-
var r = Array(self.indices)
839-
if includingEnd { r.append(self.endIndex) }
840-
r += Array(self.unicodeScalars.indices)
841-
if includingEnd { r.append(self.unicodeScalars.endIndex) }
842-
r += Array(self.utf8.indices)
843-
if includingEnd { r.append(self.utf8.endIndex) }
844-
r += Array(self.utf16.indices)
845-
if includingEnd { r.append(self.utf16.endIndex) }
846-
return r
847-
}
848-
}
849-
850-
extension Collection {
851-
// Assuming both `self` and `other` use the same index space, call `body` for
852-
// each index `i` in `other`, along with the slice in `self` that begins at
853-
// `i` and ends at the index following it in `other`.
854-
//
855-
// `other` must start with an item that is less than or equal to the first
856-
// item in `self`.
857-
func forEachIndexGroup<G: Collection>(
858-
by other: G,
859-
body: (G.Index, Self.SubSequence, Int) throws -> Void
860-
) rethrows
861-
where G.Index == Self.Index
862-
{
863-
if other.isEmpty {
864-
assert(self.isEmpty)
865-
return
866-
}
867-
var i = other.startIndex
868-
var j = self.startIndex
869-
var offset = 0
870-
while i != other.endIndex {
871-
let current = i
872-
other.formIndex(after: &i)
873-
let start = j
874-
while j < i, j < self.endIndex {
875-
self.formIndex(after: &j)
876-
}
877-
let end = j
878-
try body(current, self[start ..< end], offset)
879-
offset += 1
880-
}
881-
}
882-
}
883-
884-
extension String {
885-
/// Returns a dictionary mapping each valid index to the index that addresses
886-
/// the nearest scalar boundary, rounding down.
887-
public func scalarMap() -> [Index: (index: Index, offset: Int)] {
888-
var map: [Index: (index: Index, offset: Int)] = [:]
889-
890-
utf8.forEachIndexGroup(by: unicodeScalars) { scalar, slice, offset in
891-
for i in slice.indices { map[i] = (scalar, offset) }
892-
}
893-
utf16.forEachIndexGroup(by: unicodeScalars) { scalar, slice, offset in
894-
for i in slice.indices { map[i] = (scalar, offset) }
895-
}
896-
self.forEachIndexGroup(by: unicodeScalars) { scalar, slice, offset in
897-
for i in slice.indices { map[i] = (scalar, offset) }
898-
}
899-
map[endIndex] = (endIndex, unicodeScalars.count)
900-
return map
901-
}
902-
903-
/// Returns a dictionary mapping each valid index to the index that addresses
904-
/// the nearest character boundary, rounding down.
905-
public func characterMap() -> [Index: (index: Index, offset: Int)] {
906-
var map: [Index: (index: Index, offset: Int)] = [:]
907-
utf8.forEachIndexGroup(by: self) { char, slice, offset in
908-
for i in slice.indices { map[i] = (char, offset) }
909-
}
910-
utf16.forEachIndexGroup(by: self) { char, slice, offset in
911-
for i in slice.indices { map[i] = (char, offset) }
912-
}
913-
unicodeScalars.forEachIndexGroup(by: self) { char, slice, offset in
914-
for i in slice.indices { map[i] = (char, offset) }
915-
}
916-
map[endIndex] = (endIndex, count)
917-
return map
918-
}
919-
}
920-

stdlib/private/StdlibUnittest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
4242
Statistics.swift
4343
StdlibCoreExtras.swift
4444
StringConvertible.swift
45+
StringTestHelpers.swift
4546
SymbolLookup.swift
4647
TestHelpers.swift
4748
TypeIndexed.swift
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
extension String {
2+
/// Print out a full list of indices in every view of this string.
3+
/// This is useful while debugging string indexing issues.
4+
public func dumpIndices() {
5+
print("-------------------------------------------------------------------")
6+
print("String: \(String(reflecting: self))")
7+
print("Characters:")
8+
self.indices.forEach { i in
9+
let char = self[i]
10+
print(" \(i) -> \(String(reflecting: char))")
11+
}
12+
print("Scalars:")
13+
self.unicodeScalars.indices.forEach { i in
14+
let scalar = self.unicodeScalars[i]
15+
let value = String(scalar.value, radix: 16, uppercase: true)
16+
let padding = String(repeating: "0", count: max(0, 4 - value.count))
17+
let name = scalar.properties.name ?? "\(scalar.debugDescription)"
18+
print(" \(i) -> U+\(padding)\(value) \(name)")
19+
}
20+
print("UTF-8:")
21+
self.utf8.indices.forEach { i in
22+
let code = self.utf8[i]
23+
let value = String(code, radix: 16, uppercase: true)
24+
let padding = value.count < 2 ? "0" : ""
25+
print(" \(i) -> \(padding)\(value)")
26+
}
27+
print("UTF-16:")
28+
self.utf16.indices.forEach { i in
29+
let code = self.utf16[i]
30+
let value = String(code, radix: 16, uppercase: true)
31+
let padding = String(repeating: "0", count: 4 - value.count)
32+
print(" \(i) -> \(padding)\(value)")
33+
}
34+
}
35+
36+
// Returns a list of every valid index in every string view, optionally
37+
// including end indices. We keep equal indices originating from different
38+
// views because they may have different grapheme size caches or flags etc.
39+
public func allIndices(includingEnd: Bool = true) -> [String.Index] {
40+
var r = Array(self.indices)
41+
if includingEnd { r.append(self.endIndex) }
42+
r += Array(self.unicodeScalars.indices)
43+
if includingEnd { r.append(self.unicodeScalars.endIndex) }
44+
r += Array(self.utf8.indices)
45+
if includingEnd { r.append(self.utf8.endIndex) }
46+
r += Array(self.utf16.indices)
47+
if includingEnd { r.append(self.utf16.endIndex) }
48+
return r
49+
}
50+
}
51+
52+
extension Substring {
53+
// Returns a list of every valid index in every substring view, optionally
54+
// including end indices. We keep equal indices originating from different
55+
// views because they may have different grapheme size caches or flags etc.
56+
public func allIndices(includingEnd: Bool = true) -> [String.Index] {
57+
var r = Array(self.indices)
58+
if includingEnd { r.append(self.endIndex) }
59+
r += Array(self.unicodeScalars.indices)
60+
if includingEnd { r.append(self.unicodeScalars.endIndex) }
61+
r += Array(self.utf8.indices)
62+
if includingEnd { r.append(self.utf8.endIndex) }
63+
r += Array(self.utf16.indices)
64+
if includingEnd { r.append(self.utf16.endIndex) }
65+
return r
66+
}
67+
}
68+
69+
extension Collection {
70+
// Assuming both `self` and `other` use the same index space, call `body` for
71+
// each index `i` in `other`, along with the slice in `self` that begins at
72+
// `i` and ends at the index following it in `other`.
73+
//
74+
// `other` must start with an item that is less than or equal to the first
75+
// item in `self`.
76+
func forEachIndexGroup<G: Collection>(
77+
by other: G,
78+
body: (G.Index, Self.SubSequence, Int) throws -> Void
79+
) rethrows
80+
where G.Index == Self.Index
81+
{
82+
if other.isEmpty {
83+
assert(self.isEmpty)
84+
return
85+
}
86+
var i = other.startIndex
87+
var j = self.startIndex
88+
var offset = 0
89+
while i != other.endIndex {
90+
let current = i
91+
other.formIndex(after: &i)
92+
let start = j
93+
while j < i, j < self.endIndex {
94+
self.formIndex(after: &j)
95+
}
96+
let end = j
97+
try body(current, self[start ..< end], offset)
98+
offset += 1
99+
}
100+
}
101+
}
102+
103+
extension String {
104+
/// Returns a dictionary mapping each valid index to the index that addresses
105+
/// the nearest scalar boundary, rounding down.
106+
public func scalarMap() -> [Index: (index: Index, offset: Int)] {
107+
var map: [Index: (index: Index, offset: Int)] = [:]
108+
109+
utf8.forEachIndexGroup(by: unicodeScalars) { scalar, slice, offset in
110+
for i in slice.indices { map[i] = (scalar, offset) }
111+
}
112+
utf16.forEachIndexGroup(by: unicodeScalars) { scalar, slice, offset in
113+
for i in slice.indices { map[i] = (scalar, offset) }
114+
}
115+
self.forEachIndexGroup(by: unicodeScalars) { scalar, slice, offset in
116+
for i in slice.indices { map[i] = (scalar, offset) }
117+
}
118+
map[endIndex] = (endIndex, unicodeScalars.count)
119+
return map
120+
}
121+
122+
/// Returns a dictionary mapping each valid index to the index that addresses
123+
/// the nearest character boundary, rounding down.
124+
public func characterMap() -> [Index: (index: Index, offset: Int)] {
125+
var map: [Index: (index: Index, offset: Int)] = [:]
126+
utf8.forEachIndexGroup(by: self) { char, slice, offset in
127+
for i in slice.indices { map[i] = (char, offset) }
128+
}
129+
utf16.forEachIndexGroup(by: self) { char, slice, offset in
130+
for i in slice.indices { map[i] = (char, offset) }
131+
}
132+
unicodeScalars.forEachIndexGroup(by: self) { char, slice, offset in
133+
for i in slice.indices { map[i] = (char, offset) }
134+
}
135+
map[endIndex] = (endIndex, count)
136+
return map
137+
}
138+
}
139+

test/stdlib/StringIndex.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import StdlibUnittest
66
#if _runtime(_ObjC)
77
import Foundation
8-
#endif
98
import StdlibUnicodeUnittest
9+
#endif
1010

1111
var suite = TestSuite("StringIndexTests")
1212
defer { runAllTests() }

0 commit comments

Comments
 (0)