// RUN: %target-run-simple-swift // REQUIRES: executable_test import StdlibUnittest var SubstringTests = TestSuite("SubstringTests") func checkMatch(_ 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(_ 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(_ 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..= 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()