Files
swift-mirror/test/stdlib/subString.swift
Cory Benfield c6dfea6fc4 [stdlib] Re-add withContiguousStorageIfAvailable to SubString.UTF8View
This is a second pass at the original patch, which broke an OS test.

Due to an oversight it seems that we never added a
withContigousStorageIfAvailable implementation to SubString.UTF8View,
which meant that if you sliced a String you lost the ability to get fast
access to the backing storage. There's no good reason for this
functionality to be missing, so this patch adds it in by delegating to
the Slice implementation.

Resolves SR-11999.
2020-01-14 14:01:06 +00:00

292 lines
9.3 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
import StdlibUnittest
var SubstringTests = TestSuite("SubstringTests")
func checkMatch<S: Collection, T: Collection>(_ x: S, _ y: T, _ i: S.Index)
where S.Index == T.Index, S.Iterator.Element == T.Iterator.Element,
S.Iterator.Element: Equatable
{
expectEqual(x[i], y[i])
}
func checkMatchContiguousStorage<S: Collection, T: Collection>(_ x: S, _ y: T, expected: Bool)
where S.Element == T.Element, S.Element: Equatable
{
let xElement = x.withContiguousStorageIfAvailable { $0.first }
let yElement = y.withContiguousStorageIfAvailable { $0.first }
if expected {
expectEqual(xElement, yElement)
} else {
expectNotEqual(xElement, yElement)
}
}
func checkHasContiguousStorage<S: Collection>(_ x: S, expected: Bool) {
let hasStorage = x.withContiguousStorageIfAvailable { _ in true } ?? false
expectEqual(hasStorage, expected)
}
func checkHasContiguousStorageSubstring(_ x: Substring.UTF8View) {
let hasStorage = x.withContiguousStorageIfAvailable { _ in true } ?? false
expectTrue(hasStorage)
}
SubstringTests.test("Equality") {
let s = "abcdefg"
let s1 = s[s.index(s.startIndex, offsetBy: 2) ..<
s.index(s.startIndex, offsetBy: 4)]
let s2 = s1[s1.startIndex..<s1.endIndex]
let s3 = s2[s1.startIndex..<s1.endIndex]
expectEqual(s1, "cd")
expectEqual(s2, "cd")
expectEqual(s3, "cd")
expectTrue("" == s.dropFirst(s.count))
expectTrue(s.dropFirst().dropFirst(s.count) == s.dropFirst(s.count))
expectEqual("ab" as String, s.prefix(2))
expectEqual("fg" as String, s.suffix(2))
#if _runtime(_ObjC)
expectTrue(s == s[...])
expectTrue(s[...] == s)
expectTrue(s.dropFirst(2) != s)
expectTrue(s == s.dropFirst(0))
expectTrue(s != s.dropFirst(1))
expectTrue(s != s.dropLast(1))
expectEqual(s[...], s[...])
expectEqual(s.dropFirst(0), s.dropFirst(0))
expectTrue(s == s.dropFirst(0))
expectTrue(s.dropFirst(2) != s.dropFirst(1))
expectNotEqual(s.dropLast(2), s.dropLast(1))
expectEqual(s.dropFirst(1), s.dropFirst(1))
expectTrue(s != s[...].dropFirst(1))
#endif
// equatable conformance
expectTrue("one,two,three".split(separator: ",").contains("two"))
expectTrue("one,two,three".split(separator: ",") == ["one","two","three"])
}
#if _runtime(_ObjC)
SubstringTests.test("Equality/Emoji")
.xfail(.osxMinor(10, 9, reason: "Mac OS X 10.9 has an old ICU"))
.xfail(.iOSMajor(7, reason: "iOS 7 has an old ICU"))
.code {
let s = "abcdefg"
let emoji: String = s + "😄👍🏽🇫🇷👩‍👩‍👧‍👦🙈" + "😡🇧🇪🇨🇦🇮🇳"
let i = emoji.firstIndex(of: "😄")!
expectEqual("😄👍🏽" as String, emoji[i...].prefix(2))
expectTrue("😄👍🏽🇫🇷👩‍👩‍👧‍👦🙈😡🇧🇪" as String == emoji[i...].dropLast(2))
expectTrue("🇫🇷👩‍👩‍👧‍👦🙈😡🇧🇪" as String == emoji[i...].dropLast(2).dropFirst(2))
expectTrue(s as String != emoji[i...].dropLast(2).dropFirst(2))
expectEqualSequence("😄👍🏽🇫🇷👩‍👩‍👧‍👦🙈😡🇧🇪" as String, emoji[i...].dropLast(2))
expectEqualSequence("🇫🇷👩‍👩‍👧‍👦🙈😡🇧🇪" as String, emoji[i...].dropLast(2).dropFirst(2))
}
#endif
SubstringTests.test("Comparison") {
var s = "abc"
s += "defg"
expectFalse(s < s[...])
expectTrue(s <= s[...])
expectTrue(s >= s[...])
expectFalse(s > s[...])
expectFalse(s[...] < s)
expectTrue(s[...] <= s)
expectTrue(s[...] >= s)
expectFalse(s[...] > s)
expectFalse(s[...] < s[...])
expectTrue(s[...] <= s[...])
expectTrue(s[...] >= s[...])
expectFalse(s[...] > s[...])
expectTrue(s < s.dropFirst())
expectFalse(s > s.dropFirst())
expectFalse(s < s.dropLast())
expectTrue(s > s.dropLast())
expectTrue(s.dropFirst() < s.dropFirst(2))
expectFalse(s.dropFirst() > s.dropFirst(2))
expectFalse(s.dropLast() < s.dropLast(2))
expectTrue(s.dropLast() > s.dropLast(2))
expectFalse(s.dropFirst() < s.dropFirst().dropLast())
expectTrue(s.dropFirst() > s.dropFirst().dropLast())
expectTrue(s.dropFirst() > s)
expectTrue(s.dropFirst() > s[...])
expectTrue(s >= s[...])
expectTrue(s.dropFirst() >= s.dropFirst())
// comparable conformance
expectEqualSequence("pen,pineapple,apple,pen".split(separator: ",").sorted(),
["apple", "pen", "pen", "pineapple"])
}
SubstringTests.test("Filter") {
var name = "😂Edward Woodward".dropFirst()
var filtered = name.filter { $0 != "d" }
expectType(Substring.self, &name)
expectType(String.self, &filtered)
expectEqual("Ewar Woowar", filtered)
}
SubstringTests.test("CharacterView") {
let s = "abcdefg"
var t = s.dropFirst(2)
var u = t.dropFirst(2)
checkMatch(s, t, t.startIndex)
checkMatch(s, t, t.index(after: t.startIndex))
checkMatch(s, t, t.index(before: t.endIndex))
checkMatch(s, t, u.startIndex)
checkMatch(t, u, u.startIndex)
checkMatch(t, u, u.index(after: u.startIndex))
checkMatch(t, u, u.index(before: u.endIndex))
expectEqual("", String(t.dropFirst(10)))
expectEqual("", String(t.dropLast(10)))
expectEqual("", String(u.dropFirst(10)))
expectEqual("", String(u.dropLast(10)))
t.replaceSubrange(t.startIndex...t.startIndex, with: ["C"])
u.replaceSubrange(u.startIndex...u.startIndex, with: ["E"])
expectEqual(String(u), "Efg")
expectEqual(String(t), "Cdefg")
expectEqual(s, "abcdefg")
}
SubstringTests.test("UnicodeScalars") {
let s = "abcdefg"
var t = s.unicodeScalars.dropFirst(2)
var u = t.dropFirst(2)
checkMatch(s.unicodeScalars, t, t.startIndex)
checkMatch(s.unicodeScalars, t, t.index(after: t.startIndex))
checkMatch(s.unicodeScalars, t, t.index(before: t.endIndex))
checkMatch(s.unicodeScalars, t, u.startIndex)
checkMatch(t, u, u.startIndex)
checkMatch(t, u, u.index(after: u.startIndex))
checkMatch(t, u, u.index(before: u.endIndex))
expectEqual("", String(t.dropFirst(10)))
expectEqual("", String(t.dropLast(10)))
expectEqual("", String(u.dropFirst(10)))
expectEqual("", String(u.dropLast(10)))
t.replaceSubrange(t.startIndex...t.startIndex, with: ["C"])
u.replaceSubrange(u.startIndex...u.startIndex, with: ["E"])
expectEqual(String(u), "Efg")
expectEqual(String(t), "Cdefg")
expectEqual(s, "abcdefg")
}
SubstringTests.test("UTF16View") {
let s = "abcdefg"
let t = s.utf16.dropFirst(2)
let u = t.dropFirst(2)
checkMatch(s.utf16, t, t.startIndex)
checkMatch(s.utf16, t, t.index(after: t.startIndex))
checkMatch(s.utf16, t, t.index(before: t.endIndex))
checkMatch(s.utf16, t, u.startIndex)
checkMatch(t, u, u.startIndex)
checkMatch(t, u, u.index(after: u.startIndex))
checkMatch(t, u, u.index(before: u.endIndex))
expectEqual("", String(t.dropFirst(10))!)
expectEqual("", String(t.dropLast(10))!)
expectEqual("", String(u.dropFirst(10))!)
expectEqual("", String(u.dropLast(10))!)
}
SubstringTests.test("Mutate Substring through utf16 view") {
let s = "abcdefg"
var ss = s[...]
expectEqual(s.startIndex, ss.startIndex)
expectEqual(s.count, ss.count)
let first = ss.utf16.removeFirst()
expectEqual(s.index(after: s.startIndex), ss.startIndex)
expectEqual(s.count - 1, ss.count)
}
SubstringTests.test("Mutate Substring through unicodeScalars view") {
let s = "abcdefg"
var ss = s[...]
expectEqual(s.startIndex, ss.startIndex)
expectEqual(s.count, ss.count)
ss.unicodeScalars.append("h")
expectEqual(s.startIndex, ss.startIndex)
expectEqual(s.count + 1, ss.count)
expectEqual(ss.last, "h")
expectEqual(s.last, "g")
}
SubstringTests.test("UTF8View") {
let strs = [
"abcdefg", // Small ASCII
"abéÏ", // Small Unicode
"012345678901234567890", // Large ASCII
"abéÏ012345678901234567890", // Large Unicode
]
for s in strs {
let count = s.count
let t = s.utf8.dropFirst(2)
let u = t.dropFirst(2)
checkMatch(s.utf8, t, t.startIndex)
checkMatch(s.utf8, t, t.index(after: t.startIndex))
checkMatch(s.utf8, t, u.startIndex)
checkMatch(t, u, u.startIndex)
checkMatch(t, u, u.index(after: u.startIndex))
expectEqual("", String(t.dropFirst(100))!)
expectEqual("", String(t.dropLast(100))!)
expectEqual("", String(u.dropFirst(100))!)
expectEqual("", String(u.dropLast(100))!)
let expectSubstringWCSIA: Bool
// This availability guard should refer to a concrete OS version in
// future.
if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) {
expectSubstringWCSIA = true
} else {
expectSubstringWCSIA = false
}
checkHasContiguousStorage(s.utf8, expected: true) // Strings always do
checkHasContiguousStorage(t, expected: expectSubstringWCSIA)
checkHasContiguousStorage(u, expected: expectSubstringWCSIA)
checkHasContiguousStorageSubstring(t)
checkHasContiguousStorageSubstring(u)
checkMatchContiguousStorage(Array(s.utf8), s.utf8, expected: true)
checkMatchContiguousStorage(Array(t), t, expected: expectSubstringWCSIA)
checkMatchContiguousStorage(Array(u), u, expected: expectSubstringWCSIA)
}
}
SubstringTests.test("Persistent Content") {
var str = "abc"
str += "def"
expectEqual("bcdefg", str.dropFirst(1) + "g")
expectEqual("bcdefg", (str.dropFirst(1) + "g") as String)
}
SubstringTests.test("Substring.base") {
let str = "abéÏ01😓🎃👨👨👧👦"
expectEqual(str, str.dropLast().base)
for idx in str.indices {
expectEqual(str, str[idx...].base)
expectEqual(str, str[...idx].base)
}
}
runAllTests()