diff --git a/Fixtures/Miscellaneous/Unicode/Package.swift b/Fixtures/Miscellaneous/Unicode/Package.swift new file mode 100644 index 00000000000..8060a02c2ba --- /dev/null +++ b/Fixtures/Miscellaneous/Unicode/Package.swift @@ -0,0 +1,44 @@ +// swift-tools-version:5.1 + +import PackageDescription +import Foundation + +/// This string demonstrates as many complications of Unicode as possible. +let complicatedString = "πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄" +// π U+03C0: A simple BMP scalar. +//‎ שּׁ U+FB2C: Changes under both NFC and NFD. +// µ U+00B5: Changes under NFKC and NFKD. +// 𝄞 U+1D11E: Simple non‐BMP scalar. +// 🇺🇳 U+1F1FA U+1F1F3: Multi‐scalar character. +// 🇮🇱 U+1F1EE U+1F1F1: Second consecutive regional indicator. (Complicated grapheme breaking.) +// x̱̱̱̱̱̄̄̄̄̄ U+0078 (U+0331 U+0304) × 5: Extremely long combining sequence. (Also reordrant under normalization.) + +// The following verifies that sources haven’t been normalized, which would reduce the test’s effectiveness. +var verify = "\u{03C0}\u{0FB2C}\u{00B5}\u{1D11E}\u{1F1FA}\u{1F1F3}\u{1F1EE}\u{1F1F1}\u{0078}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}" +assert( + complicatedString.unicodeScalars.elementsEqual(verify.unicodeScalars), + "\(complicatedString) ≠ \(verify)") + +let package = Package( + name: complicatedString, + products: [ + .library( + name: complicatedString, + targets: [complicatedString]), + .executable(name: complicatedString + "‐tool", targets: [complicatedString + "‐tool"]) + ], + dependencies: [ + .package(url: "../UnicodeDependency‐\(complicatedString)", from: "1.0.0") + ], + targets: [ + .target( + name: complicatedString, + dependencies: [.product(name: "UnicodeDependency‐\(complicatedString)")]), + .target( + name: complicatedString + "‐tool", + dependencies: [.target(name: complicatedString)]), + .testTarget( + name: complicatedString + "Tests", + dependencies: [.target(name: complicatedString)]), + ] +) diff --git a/Fixtures/Miscellaneous/Unicode/README.md b/Fixtures/Miscellaneous/Unicode/README.md new file mode 100644 index 00000000000..9722804862a --- /dev/null +++ b/Fixtures/Miscellaneous/Unicode/README.md @@ -0,0 +1,5 @@ +# Unicode + +This fixture makes extensive use of exotic Unicode. While deliberately trying to break a as many common false assumptions as possible, *this is a valid package*, and clients are encouraged to test their functionality with it. A tool that successfully handles this package is unlikely to encounter problems with any real‐world package in any human language. + +The neighbouring package `UnicodeDependency‐πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄` must be placed next this package and tagged with version 1.0.0. (This is necessary to use Unicode in dependency URLs in this package’s manifest.) diff --git "a/Fixtures/Miscellaneous/Unicode/Sources/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204.swift" "b/Fixtures/Miscellaneous/Unicode/Sources/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204.swift" new file mode 100644 index 00000000000..8da325df478 --- /dev/null +++ "b/Fixtures/Miscellaneous/Unicode/Sources/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204.swift" @@ -0,0 +1,4 @@ +public struct πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄ { + public init() {} + public var πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄ = "Hello, World!" +} diff --git "a/Fixtures/Miscellaneous/Unicode/Sources/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204\342\200\220tool/main.swift" "b/Fixtures/Miscellaneous/Unicode/Sources/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204\342\200\220tool/main.swift" new file mode 100644 index 00000000000..9f1f221c672 --- /dev/null +++ "b/Fixtures/Miscellaneous/Unicode/Sources/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204\342\200\220tool/main.swift" @@ -0,0 +1,3 @@ +import π_µ_____x__________ + +print(πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄().πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄) diff --git a/Fixtures/Miscellaneous/Unicode/Tests/LinuxMain.swift b/Fixtures/Miscellaneous/Unicode/Tests/LinuxMain.swift new file mode 100644 index 00000000000..9fa0ebb8942 --- /dev/null +++ b/Fixtures/Miscellaneous/Unicode/Tests/LinuxMain.swift @@ -0,0 +1,8 @@ +import XCTest + +import π_µ_____x__________Tests + +var tests = [XCTestCaseEntry]() +tests += π_µ_____x__________Tests.__allTests() + +XCTMain(tests) diff --git "a/Fixtures/Miscellaneous/Unicode/Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests/XCTestManifests.swift" "b/Fixtures/Miscellaneous/Unicode/Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests/XCTestManifests.swift" new file mode 100644 index 00000000000..4180c254a1e --- /dev/null +++ "b/Fixtures/Miscellaneous/Unicode/Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests/XCTestManifests.swift" @@ -0,0 +1,18 @@ +#if !canImport(ObjectiveC) +import XCTest + +extension πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄Tests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄Tests = [ + ("testπשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄", testπשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄), + ] +} + +public func __allTests() -> [XCTestCaseEntry] { + return [ + testCase(πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄Tests.__allTests__πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄Tests), + ] +} +#endif diff --git "a/Fixtures/Miscellaneous/Unicode/Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests.swift" "b/Fixtures/Miscellaneous/Unicode/Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests.swift" new file mode 100644 index 00000000000..b071411645c --- /dev/null +++ "b/Fixtures/Miscellaneous/Unicode/Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests/\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204Tests.swift" @@ -0,0 +1,13 @@ +import XCTest + +// TODO: - Can imports be made less ugly? (SR‐10839) +//@testable import πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄ +@testable import π_µ_____x__________ +// (These characters all work for identifiers. See below.) + +final class πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄Tests: XCTestCase { + + func testπשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄() { + XCTAssertEqual(πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄().πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄, "Hello, World!") + } +} diff --git a/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/Package.swift b/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/Package.swift new file mode 100644 index 00000000000..4c7950bdcec --- /dev/null +++ b/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/Package.swift @@ -0,0 +1,15 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "SomeOtherPackage", + dependencies: [ + .package(path: "../../"), + ], + targets: [ + .target( + name: "SomeOtherPackage", + dependencies: ["πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄"]), + ] +) diff --git a/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/README.md b/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/README.md new file mode 100644 index 00000000000..47ee364eaa7 --- /dev/null +++ b/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/README.md @@ -0,0 +1,7 @@ +# SomeOtherPackage + +This nested utility package refers back to the main repository as a local dependency. + +If client tools accidently pick this package up as part of the main repository package, dependency resolution could become circular or otherwise problematic. + +(Prior to direct Xcode support for packages, this repository structure was a common way of hiding executable utilities from `generate-xcodeproj`, so that the main package would still be viable for iOS.) diff --git a/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/Sources/SomeOtherPackage/main.swift b/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/Sources/SomeOtherPackage/main.swift new file mode 100644 index 00000000000..f7cf60e14f9 --- /dev/null +++ b/Fixtures/Miscellaneous/Unicode/Utilities/SomeOtherPackage/Sources/SomeOtherPackage/main.swift @@ -0,0 +1 @@ +print("Hello, world!") diff --git "a/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/Package.swift" "b/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/Package.swift" new file mode 100644 index 00000000000..edae9611eaf --- /dev/null +++ "b/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/Package.swift" @@ -0,0 +1,17 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "UnicodeDependency‐πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄", + products: [ + .library( + name: "UnicodeDependency‐πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄", + targets: ["UnicodeDependency‐πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄"]), + ], + targets: [ + .target( + name: "UnicodeDependency‐πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄", + dependencies: []), + ] +) diff --git "a/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/README.md" "b/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/README.md" new file mode 100644 index 00000000000..064051aa3f0 --- /dev/null +++ "b/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/README.md" @@ -0,0 +1,3 @@ +# UnicodeDependency‐πשּׁµ𝄞🇺🇳x̱̱̱̱̱̄̄̄̄̄ + +A description of this package. diff --git "a/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/Sources/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204.swift" "b/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/Sources/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204.swift" new file mode 100644 index 00000000000..f64277de509 --- /dev/null +++ "b/Fixtures/Miscellaneous/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/Sources/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204/UnicodeDependency\342\200\220\317\200\327\251\326\274\327\201\302\265\360\235\204\236\360\237\207\272\360\237\207\263\360\237\207\256\360\237\207\261x\314\261\314\261\314\261\314\261\314\261\314\204\314\204\314\204\314\204\314\204.swift" @@ -0,0 +1,3 @@ +struct UnicodeDependency_UnicodeDependency_πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄ { + var text = "Hello, World!" +} diff --git a/Tests/FunctionalTests/MiscellaneousTests.swift b/Tests/FunctionalTests/MiscellaneousTests.swift index d3ec467a2a7..dbd57169fc6 100644 --- a/Tests/FunctionalTests/MiscellaneousTests.swift +++ b/Tests/FunctionalTests/MiscellaneousTests.swift @@ -16,6 +16,8 @@ import TSCUtility import TSCLibc import class Foundation.ProcessInfo import class Foundation.Thread +import SourceControl +import SPMTestSupport import Workspace typealias ProcessID = TSCBasic.Process.ProcessID @@ -435,4 +437,40 @@ class MiscellaneousTestCase: XCTestCase { } #endif } + + func testUnicode() { + #if !os(Linux) // TODO: - Linux has trouble with this and needs investigation. + fixture(name: "Miscellaneous/Unicode") { prefix in + // See the fixture manifest for an explanation of this string. + let complicatedString = "πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄" + let verify = "\u{03C0}\u{0FB2C}\u{00B5}\u{1D11E}\u{1F1FA}\u{1F1F3}\u{1F1EE}\u{1F1F1}\u{0078}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}\u{0331}\u{0304}" + XCTAssert( + complicatedString.unicodeScalars.elementsEqual(verify.unicodeScalars), + "\(complicatedString) ≠ \(verify)") + + // ••••• Set up dependency. + let dependencyName = "UnicodeDependency‐\(complicatedString)" + let dependencyOrigin = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory + .appending(component: "Fixtures") + .appending(component: "Miscellaneous") + .appending(component: dependencyName) + let dependencyDestination = prefix.parentDirectory.appending(component: dependencyName) + try? FileManager.default.removeItem(atPath: dependencyDestination.pathString) + defer { try? FileManager.default.removeItem(atPath: dependencyDestination.pathString) } + try FileManager.default.copyItem( + atPath: dependencyOrigin.pathString, + toPath: dependencyDestination.pathString) + let dependency = GitRepository(path: dependencyDestination) + try dependency.create() + try dependency.stageEverything() + try dependency.commit() + try dependency.tag(name: "1.0.0") + // ••••• + + // Attempt several operations. + try SwiftPMProduct.SwiftTest.execute([], packagePath: prefix) + try SwiftPMProduct.SwiftRun.execute([complicatedString + "‐tool"], packagePath: prefix) + } + #endif + } } diff --git a/Tests/FunctionalTests/XCTestManifests.swift b/Tests/FunctionalTests/XCTestManifests.swift index 7d09c6f5558..d85fd8e7d2a 100644 --- a/Tests/FunctionalTests/XCTestManifests.swift +++ b/Tests/FunctionalTests/XCTestManifests.swift @@ -50,6 +50,7 @@ extension MiscellaneousTestCase { ("testSwiftTestFilter", testSwiftTestFilter), ("testSwiftTestLinuxMainGeneration", testSwiftTestLinuxMainGeneration), ("testSwiftTestParallel", testSwiftTestParallel), + ("testUnicode", testUnicode), ] }