// RUN: %target-build-swift -Xfrontend -disable-access-control -module-name a %s -o %t.out -O // RUN: %target-run %t.out // REQUIRES: executable_test // REQUIRES: objc_interop // REQUIRES: CPU=arm64 || CPU=x86_64 // // Tests for small strings // import StdlibUnittest import Foundation var SmallStringTests = TestSuite("SmallStringTests") extension String: Error {} func verifySmallString(_ small: _SmallUTF8String, _ input: String) { expectEqual(_SmallUTF8String.capacity, small.count + small.unusedCapacity) let tiny = Array(input.utf8) expectEqual(tiny.count, small.count) for (lhs, rhs) in zip(tiny, small) { expectEqual(lhs, rhs) } small.withTranscodedUTF16CodeUnits { let codeUnits = Array(input.utf16) expectEqualSequence(codeUnits, $0) } let smallFromUTF16 = _SmallUTF8String(Array(input.utf16)) expectNotNil(smallFromUTF16) expectEqualSequence(small, smallFromUTF16!) // Test slicing // for i in 0..) { guard let smol = codeUnits.withUnsafeBufferPointer({ return _SmallUTF8String($0) }) else { return nil } self = smol } init?(_ codeUnits: Array) { guard let smol = codeUnits.withUnsafeBufferPointer({ return _SmallUTF8String($0) }) else { return nil } self = smol } } SmallStringTests.test("FitsInSmall") { func runTest(_ input: String) throws { let tiny = Array(input.utf8) // Constructed from UTF-8 code units guard let small = _SmallUTF8String(tiny) else { throw "Didn't fit" } verifySmallString(small, input) // Constructed from UTF-16 code units guard let fromUTF16Small = _SmallUTF8String(Array(input.utf16)) else { throw "Failed from utf-16" } verifySmallString(fromUTF16Small, input) } // Pass tests // // TODO(UTF-8 SSO): expectDoesNotThrow({ try runTest("abπŸ˜‡c") }) expectDoesNotThrow({ try runTest("0123456789abcde") }) // TODO(UTF-8 SSO): expectDoesNotThrow({ try runTest("πŸ‘¨β€πŸ‘¦") }) expectDoesNotThrow({ try runTest("") }) // Fail tests // expectThrows("Didn't fit", { try runTest("0123456789abcdef") }) expectThrows("Didn't fit", { try runTest("πŸ‘©β€πŸ‘¦β€πŸ‘¦") }) for cu in (0 as UInt32)...(0x10FFFF as UInt32) { // TODO: Iterate over all scalars when we support UTF-8, and possibly move // this to validation suite. guard let scalar = Unicode.Scalar(cu) else { continue } guard cu <= 0x7F else { break } expectDoesNotThrow({ try runTest(String(scalar)) }) } } SmallStringTests.test("Bridging") { // Test bridging retains small string form func bridge(_ small: _SmallUTF8String) -> String { return _bridgeToCocoa(small) as! String } func runTestSmall(_ input: String) throws { // Constructed through CF guard let fromCocoaSmall = _SmallUTF8String( _cocoaString: input as NSString ) else { throw "Didn't fit" } verifySmallString(fromCocoaSmall, input) verifySmallString(fromCocoaSmall, bridge(fromCocoaSmall)) } // Pass tests // expectDoesNotThrow({ try runTestSmall("abc") }) expectDoesNotThrow({ try runTestSmall("0123456789abcde") }) expectDoesNotThrow({ try runTestSmall("\u{0}") }) // TODO(UTF-8 SSO): expectDoesNotThrow({ try runTestSmall("πŸ‘¨β€πŸ‘¦") }) expectDoesNotThrow({ try runTestSmall("") }) // TODO(UTF-8 SSO): expectDoesNotThrow({ try runTestSmall("πŸ‘¨β€πŸ‘¦abcd") }) // Fail tests // expectThrows("Didn't fit", { try runTestSmall("πŸ‘¨β€πŸ‘©β€πŸ‘¦") }) expectThrows("Didn't fit", { try runTestSmall("πŸ‘¨β€πŸ‘¦abcde") }) } SmallStringTests.test("Append, repeating") { let strings = [ "", "a", "bc", "def", "hijk", "lmnop", "qrstuv", "xyzzzzz", "01234567", "890123456", "7890123456", "78901234567", "890123456789", "0123456789012", "34567890123456", "789012345678901", ] let smallstrings = strings.compactMap { _SmallUTF8String(Array($0.utf8)) } expectEqual(strings.count, smallstrings.count) for (small, str) in zip(smallstrings, strings) { verifySmallString(small, str) } for i in 0.. _SmallUTF8String.capacity { continue } verifySmallString(lhs._appending(rhs)!, (strings[i] + strings[j])) verifySmallString(rhs._appending(lhs)!, (strings[j] + strings[i])) } } for i in 0.. 15) } } } } runAllTests()