diff --git a/.github/workflows/build-toolchain.yml b/.github/workflows/build-toolchain.yml index 04888782..f8950e7e 100644 --- a/.github/workflows/build-toolchain.yml +++ b/.github/workflows/build-toolchain.yml @@ -303,7 +303,13 @@ jobs: if: ${{ matrix.run_stdlib_test && matrix.container != null }} run: | docker exec swiftwasm-ci-buildbot /bin/bash -lc \ - "./swiftwasm-build/schemes/${{ matrix.scheme }}/build/run-test.sh && rm -rf build" + "./swiftwasm-build/schemes/${{ matrix.scheme }}/build/run-test.sh" + + # We need this step to save disk space for the next steps when building toolchain + - name: Cleanup build directory + if: ${{ matrix.run_stdlib_test && matrix.container != null && !matrix.only_swift_sdk }} + run: docker exec swiftwasm-ci-buildbot /bin/bash -lc "rm -rf build" + - name: Run stdlib tests for wasi-wasm32 if: ${{ matrix.run_stdlib_test && matrix.container == null }} run: ./swiftwasm-build/schemes/${{ matrix.scheme }}/build/run-test.sh @@ -319,6 +325,15 @@ jobs: name: ${{ matrix.target }}-test-results path: ./swift-test-results.tar.gz + - name: Run integration tests (Swift SDK) + if: ${{ matrix.run_e2e_test && matrix.only_swift_sdk }} + run: | + docker exec swiftwasm-ci-buildbot /bin/bash -lc \ + "./llvm-project/llvm/utils/lit/lit.py \ + --param swift-sdk=wasm32-unknown-wasi \ + --param swift-sdks-path=./swiftwasm-build/tools/swift-sdk-generator/Bundles \ + --param scheme=${{ matrix.scheme }} ./swiftwasm-build/test -vv" + - name: Cleanup docker volume if: ${{ matrix.container != null }} run: | diff --git a/test/lit.cfg b/test/lit.cfg index eb8f4aac..605abc13 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -23,6 +23,7 @@ config.test_exec_root = lit_config.params.get( config.available_features.add("platform="+platform.system()) config.available_features.add("scheme="+lit_config.params.get("scheme", "main")) +# --param package-path=PATH package_path = lit_config.params.get("package-path") if package_path: package_path = os.path.abspath(package_path) @@ -31,6 +32,30 @@ else: lit_config.warning("'--param package-path=PATH' is not set, skipping toolchain tests") config.swift_package_path = package_path +# --param swift-sdk= +swift_sdk = lit_config.params.get("swift-sdk") +if swift_sdk: + lit_config.note(f"testing Swift SDK: {swift_sdk}") +else: + lit_config.warning("'--param swift-sdk=' is not set, skipping Swift SDK tests") +config.swift_sdk = swift_sdk + +# --param swift-sdks-path= +config.swift_sdks_path = lit_config.params.get("swift-sdks-path") +if config.swift_sdks_path: + config.swift_sdks_path = os.path.abspath(config.swift_sdks_path) + lit_config.note(f"using Swift SDKs path: {config.swift_sdks_path}") + +# --param base-toolchain-path=PATH +base_toolchain_path = lit_config.params.get("base-toolchain-path") +if base_toolchain_path: + base_toolchain_path = os.path.abspath(base_toolchain_path) + lit_config.note(f"using base toolchain: {base_toolchain_path}") +else: + base_toolchain_path = os.path.abspath(os.path.join(workspace_root, "build", "Packaging", "base-snapshot")) + lit_config.note(f"using default base toolchain: {base_toolchain_path}") +config.base_toolchain_path = base_toolchain_path + def llvm_tool_path(tool): candidates = [] llvm_bin = lit_config.params.get("llvm-bin") diff --git a/test/swift-sdk/Inputs/clang-module-example/Package.swift b/test/swift-sdk/Inputs/clang-module-example/Package.swift new file mode 100644 index 00000000..3f9e9fe3 --- /dev/null +++ b/test/swift-sdk/Inputs/clang-module-example/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version: 5.8 + +import PackageDescription + +let package = Package( + name: "ClangModuleExample", + targets: [ + .executableTarget(name: "Main", dependencies: ["_CModule"]), + .target(name: "_CModule"), + ] +) diff --git a/test/swift-sdk/Inputs/clang-module-example/Sources/Main/ClangModuleExample.swift b/test/swift-sdk/Inputs/clang-module-example/Sources/Main/ClangModuleExample.swift new file mode 100644 index 00000000..ff04306d --- /dev/null +++ b/test/swift-sdk/Inputs/clang-module-example/Sources/Main/ClangModuleExample.swift @@ -0,0 +1 @@ +import _CModule diff --git a/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/_CModule.c b/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/_CModule.c new file mode 100644 index 00000000..1cf4ec8d --- /dev/null +++ b/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/_CModule.c @@ -0,0 +1 @@ +#include "_CModule.h" diff --git a/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/include/_CModule.h b/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/include/_CModule.h new file mode 100644 index 00000000..df556d03 --- /dev/null +++ b/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/include/_CModule.h @@ -0,0 +1,4 @@ +#include // Clang header should be found +#if __wasi__ +# include // wasi-libc header +#endif diff --git a/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/include/module.modulemap b/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/include/module.modulemap new file mode 100644 index 00000000..72fb2c4c --- /dev/null +++ b/test/swift-sdk/Inputs/clang-module-example/Sources/_CModule/include/module.modulemap @@ -0,0 +1,3 @@ +module _CModule { + header "_CModule.h" +} diff --git a/test/swift-sdk/Inputs/imports.swift b/test/swift-sdk/Inputs/imports.swift new file mode 100644 index 00000000..9315ff64 --- /dev/null +++ b/test/swift-sdk/Inputs/imports.swift @@ -0,0 +1,17 @@ +import Foundation +import XCTest +import WASILibc + +#if canImport(FoundationXML) + import FoundationXML +#endif +// FIXME: This should be supported on swiftwasm branch +// #if canImport(FoundationNetworking) +// #error("FoundationNetworking should not be able to import now") +// #endif + +public func main() { + _ = Date() + _ = UUID() + _ = URL(string: "https://example.com")! +} diff --git a/test/swift-sdk/clang-module.swift b/test/swift-sdk/clang-module.swift new file mode 100644 index 00000000..ab2c4c67 --- /dev/null +++ b/test/swift-sdk/clang-module.swift @@ -0,0 +1,6 @@ +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir +// RUN: %{swift} build --package-path %S/Inputs/clang-module-example --scratch-path %t.dir --triple wasm32-unknown-wasi --static-swift-stdlib + +// Skipping this test on main until we include swift-testing in the SDK +// REQUIRES: GH-5587 diff --git a/test/swift-sdk/foundation/Bundle.swift b/test/swift-sdk/foundation/Bundle.swift new file mode 100644 index 00000000..01b30a80 --- /dev/null +++ b/test/swift-sdk/foundation/Bundle.swift @@ -0,0 +1,13 @@ +// RUN: %{target_simple_swift_build} +// RUN: %{wasm_run} --dir %t.dir::/tmp --dir %t.dir::/tmp2 %t.dir/.build/debug/Check.wasm | %{FileCheck} %s +// REQUIRES: FileCheck && scheme=main + +import Foundation + +// Bundle.main is derived from the path of the executable and cwd +// CHECK: bundlePath: /tmp +chdir("/tmp") +print("bundlePath:", Bundle.main.bundlePath) + +// CHECK: Bundle(path:).bundlePath: /tmp2 +print("Bundle(path:).bundlePath:", Bundle(path: "/tmp2")?.bundlePath ?? "nil") diff --git a/test/swift-sdk/foundation/FileManager.swift b/test/swift-sdk/foundation/FileManager.swift new file mode 100644 index 00000000..8cbb3e00 --- /dev/null +++ b/test/swift-sdk/foundation/FileManager.swift @@ -0,0 +1,34 @@ +// RUN: %{target_simple_swift_build} +// RUN: rm -rf %t.mnt +// RUN: mkdir -p %t.mnt +// RUN: %{wasm_run} --dir %t.mnt::/tmp --dir %S/Inputs::/Inputs %t.dir/.build/debug/Check.wasm | %{FileCheck} %s +// REQUIRES: FileCheck && scheme=main + +import Foundation + +// CHECK: cwd: / +print("cwd: \(FileManager.default.currentDirectoryPath)") +// CHECK: chdir: true +let chdirResult = FileManager.default.changeCurrentDirectoryPath("/tmp") +print("chdir: \(chdirResult)") +// CHECK: cwd: /tmp +print("cwd: \(FileManager.default.currentDirectoryPath)") + +// CHECK: homeDirectory: file:///var/empty/ +print("homeDirectory: \(FileManager.default.homeDirectory(forUser: "nobody")?.absoluteString ?? "nil")") + +// CHECK: temporaryDirectory: file:///tmp/ +print("temporaryDirectory: \(FileManager.default.temporaryDirectory)") + +// CHECK: contentsOfDirectory(/Inputs): ["check.dir", "empty.txt", "hello.txt"] +print("contentsOfDirectory(/Inputs): \(try! FileManager.default.contentsOfDirectory(atPath: "/Inputs").sorted())") +// CHECK: contentsOfDirectory(/Inputs/check.dir): ["check0.txt", "check1.txt"] +print("contentsOfDirectory(/Inputs/check.dir): \(try! FileManager.default.contentsOfDirectory(atPath: "/Inputs/check.dir").sorted())") + +// CHECK: Data(contentsOf: /Inputs/hello.txt): 6 bytes +print("Data(contentsOf: /Inputs/hello.txt): \(try! Data(contentsOf: URL(fileURLWithPath: "/Inputs/hello.txt")))") +// CHECK: String(contentsOf: /Inputs/hello.txt): world +print("String(contentsOf: /Inputs/hello.txt): \(try! String(contentsOf: URL(fileURLWithPath: "/Inputs/hello.txt")))") + +// CHECK: mountedVolumeURLs: ["/Inputs", "/tmp"] +print("mountedVolumeURLs: \(FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys:[], options: [])?.map { $0.path }.sorted() ?? [])") diff --git a/test/swift-sdk/foundation/Inputs/check.dir/check0.txt b/test/swift-sdk/foundation/Inputs/check.dir/check0.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/swift-sdk/foundation/Inputs/check.dir/check1.txt b/test/swift-sdk/foundation/Inputs/check.dir/check1.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/swift-sdk/foundation/Inputs/empty.txt b/test/swift-sdk/foundation/Inputs/empty.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/swift-sdk/foundation/Inputs/hello.txt b/test/swift-sdk/foundation/Inputs/hello.txt new file mode 100644 index 00000000..cc628ccd --- /dev/null +++ b/test/swift-sdk/foundation/Inputs/hello.txt @@ -0,0 +1 @@ +world diff --git a/test/swift-sdk/foundation/ProcessInfo.swift b/test/swift-sdk/foundation/ProcessInfo.swift new file mode 100644 index 00000000..1b1ef371 --- /dev/null +++ b/test/swift-sdk/foundation/ProcessInfo.swift @@ -0,0 +1,11 @@ +// RUN: %{target_simple_swift_build} +// RUN: %{wasm_run} --dir %t.dir::/tmp %t.dir/.build/debug/Check.wasm | %{FileCheck} %s +// REQUIRES: FileCheck && scheme=main + +import Foundation + +// CHECK: processName: Check.wasm +print("processName: " + ProcessInfo.processInfo.processName) + +// CHECK: hostname: localhost +print("hostname: " + ProcessInfo.processInfo.hostName) diff --git a/test/swift-sdk/foundation/XML.swift b/test/swift-sdk/foundation/XML.swift new file mode 100644 index 00000000..8704bd0d --- /dev/null +++ b/test/swift-sdk/foundation/XML.swift @@ -0,0 +1,21 @@ +// RUN: %{target_simple_swift_build} +// RUN: %{wasm_run} %t.dir/.build/debug/Check.wasm | %{FileCheck} %s +// REQUIRES: FileCheck + +import FoundationXML + +let xml = """ + + Tove + Jani + Reminder + Don't forget me this weekend! + +""" + +let xmlData = xml.data(using: .utf8)! +let document = try XMLDocument(data: xmlData) + +let to = try document.nodes(forXPath: "/note/to").first?.stringValue +// CHECK: to: Tove +print("to: \(to!)") diff --git a/test/swift-sdk/lit.local.cfg b/test/swift-sdk/lit.local.cfg new file mode 100644 index 00000000..df5019d3 --- /dev/null +++ b/test/swift-sdk/lit.local.cfg @@ -0,0 +1,25 @@ +import os + +if not config.root.swift_sdk: + config.unsupported = True +else: + bin_path = os.path.join(config.root.base_toolchain_path, "usr", "bin") + + swift = os.path.join(bin_path, "swift") + config.substitutions.append(("%{swift}", swift)) + + swift_sdk_options = f"--swift-sdk {config.root.swift_sdk}" + if config.root.swift_sdks_path: + swift_sdk_options += f" --swift-sdks-path {config.root.swift_sdks_path}" + config.substitutions.append(("%{swift_sdk_options}", swift_sdk_options)) + target_swift_build = f"{swift} build {swift_sdk_options}" + config.substitutions.append(("%{target_swift_build}", target_swift_build)) + + simple_swift_build_steps = [ + 'rm -rf %t.dir', + 'mkdir -p %t.dir', + f'{swift} package init --package-path %t.dir --name Check --type executable', + 'cp %s %t.dir/Sources/main.swift', + f'{target_swift_build} --package-path %t.dir', + ] + config.substitutions.append(("%{target_simple_swift_build}", " && ".join(simple_swift_build_steps))) diff --git a/test/swift-sdk/swiftpm-build.swift b/test/swift-sdk/swiftpm-build.swift new file mode 100755 index 00000000..00d62f33 --- /dev/null +++ b/test/swift-sdk/swiftpm-build.swift @@ -0,0 +1,5 @@ +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir +// RUN: %{swift} package init --package-path %t.dir --name Example +// RUN: cp %S/Inputs/imports.swift %t.dir/Sources/Example/Imports.swift +// RUN: %{target_swift_build} --package-path %t.dir diff --git a/test/swift-sdk/swiftpm-test.test b/test/swift-sdk/swiftpm-test.test new file mode 100644 index 00000000..b17a2e22 --- /dev/null +++ b/test/swift-sdk/swiftpm-test.test @@ -0,0 +1,12 @@ +REQUIRES: FileCheck +# Skipping this test on main until we include swift-testing in the SDK +REQUIRES: GH-5587 + +RUN: rm -rf %t.dir +RUN: mkdir -p %t.dir +RUN: %{swift} package init --package-path %t.dir --name Example +RUN: %{target_swift_build} --package-path %t.dir --build-tests +RUN: %{wasm_run} --dir . %t.dir/.build/debug/ExamplePackageTests.wasm | %{FileCheck} %s + +CHECK: Test Suite 'All tests' passed at +CHECK: Executed 1 test, with 0 failures (0 unexpected) in diff --git a/test/toolchain/lit.local.cfg b/test/toolchain/lit.local.cfg index ef765528..4e97f498 100644 --- a/test/toolchain/lit.local.cfg +++ b/test/toolchain/lit.local.cfg @@ -2,10 +2,10 @@ import os if not config.root.swift_package_path: config.unsupported = True +else: + bin_path = os.path.join(config.root.swift_package_path, "usr", "bin") -bin_path = os.path.join(config.root.swift_package_path, "usr", "bin") + for tool in ["swift", "swiftc"]: + config.substitutions.append(("%{" + tool + "}", os.path.join(bin_path, tool))) -for tool in ["swift", "swiftc"]: - config.substitutions.append(("%{" + tool + "}", os.path.join(bin_path, tool))) - -config.substitutions.append(("%{package_path}", config.root.swift_package_path)) + config.substitutions.append(("%{package_path}", config.root.swift_package_path)) diff --git a/tools/swift-sdk-generator b/tools/swift-sdk-generator index 1a5e7c86..26a65a0d 160000 --- a/tools/swift-sdk-generator +++ b/tools/swift-sdk-generator @@ -1 +1 @@ -Subproject commit 1a5e7c86e728a0a40ccf0b7b192b11ca3a4ad4aa +Subproject commit 26a65a0df7ab675c423970de2a9b92f45d60b860