// RUN: %target-run-simple-swift // REQUIRES: executable_test // // Tests for the non-Foundation CString-oriented API of String // import StdlibUnittest var CStringTests = TestSuite("CStringTests") func getNullUTF8() -> UnsafeMutablePointer? { return nil } func getASCIIUTF8() -> (UnsafeMutablePointer, dealloc: () -> ()) { let up = UnsafeMutablePointer.allocate(capacity: 100) up[0] = 0x61 up[1] = 0x62 up[2] = 0 return (up, { up.deallocate() }) } func getNonASCIIUTF8() -> (UnsafeMutablePointer, dealloc: () -> ()) { let up = UnsafeMutablePointer.allocate(capacity: 100) up[0] = 0xd0 up[1] = 0xb0 up[2] = 0xd0 up[3] = 0xb1 up[4] = 0 return (UnsafeMutablePointer(up), { up.deallocate() }) } func getIllFormedUTF8String1( ) -> (UnsafeMutablePointer, dealloc: () -> ()) { let up = UnsafeMutablePointer.allocate(capacity: 100) up[0] = 0x41 up[1] = 0xed up[2] = 0xa0 up[3] = 0x80 up[4] = 0x41 up[5] = 0 return (UnsafeMutablePointer(up), { up.deallocate() }) } func getIllFormedUTF8String2( ) -> (UnsafeMutablePointer, dealloc: () -> ()) { let up = UnsafeMutablePointer.allocate(capacity: 100) up[0] = 0x41 up[0] = 0x41 up[1] = 0xed up[2] = 0xa0 up[3] = 0x81 up[4] = 0x41 up[5] = 0 return (UnsafeMutablePointer(up), { up.deallocate() }) } func asCCharArray(_ a: [UInt8]) -> [CChar] { return a.map { CChar(bitPattern: $0) } } func getUTF8Length(_ cString: UnsafePointer) -> Int { var length = 0 while cString[length] != 0 { length += 1 } return length } func bindAsCChar(_ utf8: UnsafePointer) -> UnsafePointer { return UnsafeRawPointer(utf8).bindMemory(to: CChar.self, capacity: getUTF8Length(utf8)) } func expectEqualCString(_ lhs: UnsafePointer, _ rhs: UnsafePointer) { var index = 0 while lhs[index] != 0 { expectEqual(lhs[index], rhs[index]) index += 1 } expectEqual(0, rhs[index]) } func expectEqualCString(_ lhs: UnsafePointer, _ rhs: ContiguousArray) { rhs.withUnsafeBufferPointer { expectEqualCString(lhs, $0.baseAddress!) } } func expectEqualCString(_ lhs: UnsafePointer, _ rhs: ContiguousArray) { rhs.withUnsafeBufferPointer { $0.baseAddress!.withMemoryRebound( to: UInt8.self, capacity: rhs.count) { expectEqualCString(lhs, $0) } } } CStringTests.test("String.init(validatingUTF8:)") { do { let (s, dealloc) = getASCIIUTF8() expectEqual("ab", String(validatingUTF8: bindAsCChar(s))) dealloc() } do { let (s, dealloc) = getNonASCIIUTF8() expectEqual("аб", String(validatingUTF8: bindAsCChar(s))) dealloc() } do { let (s, dealloc) = getIllFormedUTF8String1() expectNil(String(validatingUTF8: bindAsCChar(s))) dealloc() } } CStringTests.test("String(cString:)") { do { let (s, dealloc) = getASCIIUTF8() let result = String(cString: s) expectEqual("ab", result) let su = bindAsCChar(s) expectEqual("ab", String(cString: su)) dealloc() } do { let (s, dealloc) = getNonASCIIUTF8() let result = String(cString: s) expectEqual("аб", result) let su = bindAsCChar(s) expectEqual("аб", String(cString: su)) dealloc() } do { let (s, dealloc) = getIllFormedUTF8String1() let result = String(cString: s) expectEqual("\u{41}\u{fffd}\u{fffd}\u{fffd}\u{41}", result) let su = bindAsCChar(s) expectEqual("\u{41}\u{fffd}\u{fffd}\u{fffd}\u{41}", String(cString: su)) dealloc() } } CStringTests.test("String.decodeCString") { do { let s = getNullUTF8() let result = String.decodeCString(s, as: UTF8.self) expectNil(result) } do { // repairing let (s, dealloc) = getIllFormedUTF8String1() if let (result, repairsMade) = String.decodeCString( s, as: UTF8.self, repairingInvalidCodeUnits: true) { expectEqual("\u{41}\u{fffd}\u{fffd}\u{fffd}\u{41}", result) expectTrue(repairsMade) } else { expectUnreachable("Expected .some()") } dealloc() } do { // non repairing let (s, dealloc) = getIllFormedUTF8String1() let result = String.decodeCString( s, as: UTF8.self, repairingInvalidCodeUnits: false) expectNil(result) dealloc() } } CStringTests.test("String.utf8CString") { do { let (cstr, dealloc) = getASCIIUTF8() defer { dealloc() } let str = String(cString: cstr) expectEqualCString(cstr, str.utf8CString) } do { let (cstr, dealloc) = getNonASCIIUTF8() defer { dealloc() } let str = String(cString: cstr) expectEqualCString(cstr, str.utf8CString) } } CStringTests.test("String.withCString") { do { let (cstr, dealloc) = getASCIIUTF8() defer { dealloc() } let str = String(cString: cstr) str.withCString { expectEqual(str, String(cString: $0)) } } do { let (cstr, dealloc) = getASCIIUTF8() defer { dealloc() } let str = String(cString: cstr) str.withCString { expectEqual(str, String(cString: $0)) } } } CStringTests.test("Substring.withCString") { do { let (cstr, dealloc) = getASCIIUTF8() defer { dealloc() } let str = String(cString: cstr).dropFirst() str.withCString { expectEqual(str, String(cString: $0)) } } do { let (cstr, dealloc) = getASCIIUTF8() defer { dealloc() } let str = String(cString: cstr).dropFirst() str.withCString { expectEqual(str, String(cString: $0)) } } } runAllTests()