├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── 01-bug-report.yml │ ├── 02-change-request.yml │ ├── 03-task.yml │ └── config.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .spi.yml ├── .swiftpm ├── Testing.xctestplan └── xcode │ └── xcshareddata │ └── xcschemes │ └── Testing.xcscheme ├── CMakeLists.txt ├── CODEOWNERS ├── CONTRIBUTING.md ├── Dockerfile ├── Documentation ├── ABI │ ├── JSON.md │ └── TestContent.md ├── CMake.md ├── ExpectationCapture.md ├── Porting.md ├── Proposals │ ├── 0001-refactor-bug-inits.md │ ├── 0002-json-abi.md │ ├── 0003-make-serialized-trait-api.md │ ├── 0004-constrain-the-granularity-of-test-time-limit-durations.md │ ├── 0005-ranged-confirmations.md │ ├── 0006-return-errors-from-expect-throws.md │ └── 0007-test-scoping-traits.md ├── README.md ├── SPI.md ├── StyleGuide.md ├── Vision.md └── WASI.md ├── LICENSE.txt ├── NOTICE.txt ├── Package.swift ├── README.md ├── Sources ├── CMakeLists.txt ├── Overlays │ ├── CMakeLists.txt │ ├── _Testing_CoreGraphics │ │ ├── Attachments │ │ │ ├── AttachableAsCGImage.swift │ │ │ ├── Attachment+AttachableAsCGImage.swift │ │ │ ├── CGImage+AttachableAsCGImage.swift │ │ │ ├── ImageAttachmentError.swift │ │ │ └── _AttachableImageWrapper.swift │ │ └── ReexportTesting.swift │ └── _Testing_Foundation │ │ ├── Attachments │ │ ├── Attachable+Encodable+NSSecureCoding.swift │ │ ├── Attachable+Encodable.swift │ │ ├── Attachable+NSSecureCoding.swift │ │ ├── Attachment+URL.swift │ │ ├── Data+Attachable.swift │ │ ├── EncodingFormat.swift │ │ └── _AttachableURLWrapper.swift │ │ ├── CMakeLists.txt │ │ ├── Events │ │ └── Clock+Date.swift │ │ └── ReexportTesting.swift ├── SymbolShowcase │ └── SymbolShowcaseMain.swift ├── Testing │ ├── ABI │ │ ├── ABI.Record+Streaming.swift │ │ ├── ABI.Record.swift │ │ ├── ABI.swift │ │ ├── Encoded │ │ │ ├── ABI.EncodedAttachment.swift │ │ │ ├── ABI.EncodedBacktrace.swift │ │ │ ├── ABI.EncodedError.swift │ │ │ ├── ABI.EncodedEvent.swift │ │ │ ├── ABI.EncodedInstant.swift │ │ │ ├── ABI.EncodedIssue.swift │ │ │ ├── ABI.EncodedMessage.swift │ │ │ └── ABI.EncodedTest.swift │ │ └── EntryPoints │ │ │ ├── ABIEntryPoint.swift │ │ │ ├── EntryPoint.swift │ │ │ └── SwiftPMEntryPoint.swift │ ├── Attachments │ │ ├── Attachable.swift │ │ ├── AttachableWrapper.swift │ │ └── Attachment.swift │ ├── CMakeLists.txt │ ├── Discovery+Macro.swift │ ├── Events │ │ ├── Clock.swift │ │ ├── Event.swift │ │ ├── Recorder │ │ │ ├── Event.ConsoleOutputRecorder.swift │ │ │ ├── Event.HumanReadableOutputRecorder.swift │ │ │ ├── Event.JUnitXMLRecorder.swift │ │ │ └── Event.Symbol.swift │ │ └── TimeValue.swift │ ├── ExitTests │ │ ├── ExitStatus.swift │ │ ├── ExitTest.CapturedValue.swift │ │ ├── ExitTest.Condition.swift │ │ ├── ExitTest.Result.swift │ │ ├── ExitTest.swift │ │ ├── SpawnProcess.swift │ │ └── WaitFor.swift │ ├── Expectations │ │ ├── Expectation+Macro.swift │ │ ├── Expectation.swift │ │ └── ExpectationChecking+Macro.swift │ ├── Issues │ │ ├── Confirmation.swift │ │ ├── ErrorSnapshot.swift │ │ ├── Issue+Recording.swift │ │ ├── Issue.swift │ │ └── KnownIssue.swift │ ├── Parameterization │ │ ├── CustomTestArgumentEncodable.swift │ │ ├── Test.Case.Generator.swift │ │ ├── Test.Case.ID.swift │ │ ├── Test.Case.swift │ │ └── TypeInfo.swift │ ├── Running │ │ ├── Configuration+EventHandling.swift │ │ ├── Configuration.TestFilter.swift │ │ ├── Configuration.swift │ │ ├── Runner.Plan+Dumping.swift │ │ ├── Runner.Plan.swift │ │ ├── Runner.RuntimeState.swift │ │ ├── Runner.swift │ │ └── SkipInfo.swift │ ├── SourceAttribution │ │ ├── Backtrace+Symbolication.swift │ │ ├── Backtrace.swift │ │ ├── CustomTestStringConvertible.swift │ │ ├── Expression+Macro.swift │ │ ├── Expression.swift │ │ ├── SourceContext.swift │ │ ├── SourceLocation+Macro.swift │ │ └── SourceLocation.swift │ ├── Support │ │ ├── Additions │ │ │ ├── ArrayAdditions.swift │ │ │ ├── CollectionDifferenceAdditions.swift │ │ │ ├── CommandLineAdditions.swift │ │ │ ├── NumericAdditions.swift │ │ │ ├── ResultAdditions.swift │ │ │ └── WinSDKAdditions.swift │ │ ├── CError.swift │ │ ├── CartesianProduct.swift │ │ ├── CustomIssueRepresentable.swift │ │ ├── Environment.swift │ │ ├── FileHandle.swift │ │ ├── GetSymbol.swift │ │ ├── Graph.swift │ │ ├── JSON.swift │ │ ├── Locked+Platform.swift │ │ ├── Locked.swift │ │ └── Versions.swift │ ├── Test+Discovery+Legacy.swift │ ├── Test+Discovery.swift │ ├── Test+Macro.swift │ ├── Test.ID.Selection.swift │ ├── Test.ID.swift │ ├── Test.swift │ ├── Testing.docc │ │ ├── AddingComments.md │ │ ├── AddingTags.md │ │ ├── AssociatingBugs.md │ │ ├── Attachments.md │ │ ├── BugIdentifiers.md │ │ ├── DefiningTests.md │ │ ├── Documentation.md │ │ ├── EnablingAndDisabling.md │ │ ├── Expectations.md │ │ ├── Info.plist │ │ ├── LimitingExecutionTime.md │ │ ├── MigratingFromXCTest.md │ │ ├── OrganizingTests.md │ │ ├── Parallelization.md │ │ ├── ParameterizedTesting.md │ │ ├── Traits.md │ │ ├── Traits │ │ │ └── Trait.md │ │ ├── exit-testing.md │ │ ├── known-issues.md │ │ ├── testing-asynchronous-code.md │ │ └── testing-for-errors-in-swift-code.md │ ├── Testing.swiftcrossimport │ │ └── Foundation.swiftoverlay │ └── Traits │ │ ├── Bug.swift │ │ ├── Comment+Macro.swift │ │ ├── Comment.swift │ │ ├── ConditionTrait+Macro.swift │ │ ├── ConditionTrait.swift │ │ ├── HiddenTrait.swift │ │ ├── IssueHandlingTrait.swift │ │ ├── ParallelizationTrait.swift │ │ ├── Tags │ │ ├── Tag+Macro.swift │ │ ├── Tag+Predefined.swift │ │ ├── Tag.Color+Loading.swift │ │ ├── Tag.Color.swift │ │ ├── Tag.List.swift │ │ └── Tag.swift │ │ ├── TimeLimitTrait.swift │ │ └── Trait.swift ├── TestingMacros │ ├── CMakeLists.txt │ ├── ConditionMacro.swift │ ├── PragmaMacro.swift │ ├── SourceLocationMacro.swift │ ├── SuiteDeclarationMacro.swift │ ├── Support │ │ ├── Additions │ │ │ ├── DeclGroupSyntaxAdditions.swift │ │ │ ├── EditorPlaceholderExprSyntaxAdditions.swift │ │ │ ├── FunctionDeclSyntaxAdditions.swift │ │ │ ├── IntegerLiteralExprSyntaxAdditions.swift │ │ │ ├── MacroExpansionContextAdditions.swift │ │ │ ├── TokenSyntaxAdditions.swift │ │ │ ├── TriviaPieceAdditions.swift │ │ │ ├── TypeSyntaxProtocolAdditions.swift │ │ │ ├── VersionTupleSyntaxAdditions.swift │ │ │ └── WithAttributesSyntaxAdditions.swift │ │ ├── Argument.swift │ │ ├── AttributeDiscovery.swift │ │ ├── AvailabilityGuards.swift │ │ ├── ClosureCaptureListParsing.swift │ │ ├── CommentParsing.swift │ │ ├── ConditionArgumentParsing.swift │ │ ├── DiagnosticMessage+Diagnosing.swift │ │ ├── DiagnosticMessage.swift │ │ ├── EffectfulExpressionHandling.swift │ │ ├── SHA256.swift │ │ ├── SourceCodeCapturing.swift │ │ ├── SourceLocationGeneration.swift │ │ └── TestContentGeneration.swift │ ├── TagMacro.swift │ ├── TestDeclarationMacro.swift │ └── TestingMacrosMain.swift ├── _TestDiscovery │ ├── Additions │ │ └── WinSDKAdditions.swift │ ├── CMakeLists.txt │ ├── DiscoverableAsTestContent.swift │ ├── SectionBounds.swift │ ├── TestContentKind.swift │ └── TestContentRecord.swift └── _TestingInternals │ ├── CMakeLists.txt │ ├── Discovery.cpp │ ├── Versions.cpp │ ├── WillThrow.cpp │ └── include │ ├── Defines.h │ ├── Demangle.h │ ├── Discovery.h │ ├── Includes.h │ ├── Stubs.h │ ├── TestSupport.h │ ├── Versions.h │ ├── WillThrow.h │ └── module.modulemap ├── Tests ├── TestingMacrosTests │ ├── ConditionMacroTests.swift │ ├── PragmaMacroTests.swift │ ├── TagMacroTests.swift │ ├── TestDeclarationMacroTests.swift │ ├── TestSupport │ │ ├── FixIts.swift │ │ └── Parse.swift │ └── UniqueIdentifierTests.swift └── TestingTests │ ├── ABIEntryPointTests.swift │ ├── AttachmentTests.swift │ ├── BacktraceTests.swift │ ├── ClockTests.swift │ ├── ConfigurationTests.swift │ ├── ConfirmationTests.swift │ ├── CustomTestStringConvertibleTests.swift │ ├── DiscoveryTests.swift │ ├── DumpTests.swift │ ├── EntryPointTests.swift │ ├── EventRecorderTests.swift │ ├── EventTests.swift │ ├── ExitTestTests.swift │ ├── Expression.ValueTests.swift │ ├── IssueTests.swift │ ├── KnownIssueTests.swift │ ├── MiscellaneousTests.swift │ ├── NonCopyableSuiteTests.swift │ ├── ObjCInteropTests.swift │ ├── PlanIterationTests.swift │ ├── PlanTests.swift │ ├── Runner.Plan.SnapshotTests.swift │ ├── Runner.RuntimeStateTests.swift │ ├── RunnerTests.swift │ ├── SkipInfoTests.swift │ ├── SourceLocationTests.swift │ ├── Support │ ├── CErrorTests.swift │ ├── CartesianProductTests.swift │ ├── EnvironmentTests.swift │ ├── FileHandleTests.swift │ ├── GraphTests.swift │ └── LockTests.swift │ ├── SwiftPMTests.swift │ ├── Test.Case.Argument.IDTests.swift │ ├── Test.Case.ArgumentTests.swift │ ├── Test.Case.GeneratorTests.swift │ ├── Test.CaseTests.swift │ ├── Test.ID.SelectionTests.swift │ ├── Test.SnapshotTests.swift │ ├── TestCaseSelectionTests.swift │ ├── TestSupport │ └── TestingAdditions.swift │ ├── Traits │ ├── BugTests.swift │ ├── CommentTests.swift │ ├── ConditionTraitTests.swift │ ├── CustomTraitTests.swift │ ├── HiddenTraitTests.swift │ ├── IssueHandlingTraitTests.swift │ ├── ParallelizationTraitTests.swift │ ├── TagListTests.swift │ ├── TestScopingTraitTests.swift │ └── TimeLimitTraitTests.swift │ ├── TypeInfoTests.swift │ ├── TypeNameConflictTests.swift │ ├── VariadicGenericTests.swift │ ├── ZipTests.swift │ └── _Testing_Foundation │ └── FoundationTests.swift └── cmake └── modules ├── LibraryVersion.cmake ├── PlatformInfo.cmake ├── SwiftModuleInstallation.cmake ├── TargetTriple.cmake └── shared ├── AvailabilityDefinitions.cmake └── CompilerSettings.cmake /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig documentation: https://editorconfig.org 2 | 3 | root = true 4 | 5 | # Default settings applied to every file type. 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/01-bug-report.yml: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2025 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See https://swift.org/LICENSE.txt for license information 7 | # See https://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | name: 🪲 Report a bug 10 | description: > 11 | Report a deviation from expected or documented behavior. 12 | labels: [bug] 13 | body: 14 | - type: markdown 15 | attributes: 16 | value: > 17 | This repository hosts the Swift Testing library and its documentation. 18 | It does _not_ track feedback for Xcode and other closed source Apple 19 | developer software such as XCTest; please direct that to 20 | [Feedback Assistant](https://developer.apple.com/bug-reporting) instead. 21 | - type: textarea 22 | attributes: 23 | label: Description 24 | description: > 25 | A concise description of what causes the problem, in human language. 26 | Though not required, it may help us to more accurately triage the issue 27 | as well as understand a non-trivial test case. 28 | validations: 29 | required: false 30 | - type: textarea 31 | attributes: 32 | label: Reproduction 33 | description: > 34 | Provide an example, preferably in a Markdown code block, and explain how 35 | to build or run it to reproduce the problem. If the problem is a poor or 36 | unexpected diagnostic, fix-it, or other output, please show this output 37 | as is. For example, paste it from the terminal. Consider reducing the 38 | example to the smallest amount of code possible — a smaller example is 39 | easier to reason about and more appealing to contributors. 40 | value: | 41 | ```swift 42 | 43 | ``` 44 | validations: 45 | required: true 46 | - type: textarea 47 | attributes: 48 | label: Expected behavior 49 | description: Describe the behavior you expected. 50 | validations: 51 | required: true 52 | - type: textarea 53 | attributes: 54 | label: Environment 55 | description: > 56 | Provide details about the environment in which this problem occurs. 57 | Include the versions of Swift Testing and the Swift toolchain. If you 58 | suspect the problem might be specific to a particular platform, please 59 | specify the platform and OS version as well. 60 | placeholder: | 61 | Swift Testing version: (shown in `swift test` output) 62 | $ swift --version 63 | $ uname -a 64 | validations: 65 | required: true 66 | - type: textarea 67 | attributes: 68 | label: Additional information 69 | description: > 70 | Any complementary information that could help others to work around the 71 | problem, and us to better understand the problem and its impact. For 72 | example, a link to a discussion or post that motivated this report. 73 | validations: 74 | required: false 75 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/02-change-request.yml: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2025 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See https://swift.org/LICENSE.txt for license information 7 | # See https://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | name: 🌟 Request a change 10 | description: > 11 | Request a feature, API, improvement, or other change. 12 | labels: [enhancement] 13 | body: 14 | - type: markdown 15 | attributes: 16 | value: > 17 | This repository hosts the Swift Testing library and its documentation. 18 | It does _not_ track feedback for Xcode and other closed source Apple 19 | developer software such as XCTest; please direct that to 20 | [Feedback Assistant](https://developer.apple.com/bug-reporting) instead. 21 | 22 | ___ 23 | 24 | Swift Testing is guided by a community-driven evolution process. 25 | Submitting this form is not a guarantee that the request will be 26 | considered or implemented. If the request implies an addition, removal, 27 | or change to the features of Swift Testing or its public interfaces, 28 | please consider socializing it on the 29 | [Swift forums](https://forums.swift.org/c/related-projects/swift-testing) 30 | instead. The Swift forums are the preferred space for sharing ideas and 31 | discussing them with the Swift community. 32 | - type: textarea 33 | attributes: 34 | label: Motivation 35 | description: > 36 | Describe the problems that this idea seeks to address. If the problem is 37 | that some common pattern is currently hard to express, show how one can 38 | currently get a similar effect and describe its drawbacks. If it's 39 | completely new functionality that cannot be emulated, motivate why this 40 | new functionality would help create better Swift tests. 41 | validations: 42 | required: true 43 | - type: textarea 44 | attributes: 45 | label: Proposed solution 46 | description: > 47 | Describe the proposed solution to the problem. Provide examples and 48 | describe how they work. Show how this solution is better than current 49 | workarounds: is it cleaner, safer, or more efficient? 50 | validations: 51 | required: true 52 | - type: textarea 53 | attributes: 54 | label: Alternatives considered 55 | description: > 56 | Any alternative approaches that were considered, and why the _proposed 57 | solution_ was chosen instead. 58 | validations: 59 | required: false 60 | - type: textarea 61 | attributes: 62 | label: Additional information 63 | description: > 64 | Any complementary information that could be valuable to an author of a 65 | formal proposal, an implementor, or future discussions. For example, a 66 | link to a discussion or post that motivated this request. 67 | validations: 68 | required: false 69 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/03-task.yml: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2025 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See https://swift.org/LICENSE.txt for license information 7 | # See https://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | name: ⚙️ Track a task 10 | description: > 11 | Tasks can be used to track internal work, extract individual subtasks from a 12 | larger issue, or can serve as umbrella issues themselves. 13 | labels: [] 14 | body: 15 | - type: markdown 16 | attributes: 17 | value: > 18 | This repository hosts the Swift Testing library and its documentation. 19 | It does _not_ track feedback for Xcode and other closed source Apple 20 | developer software such as XCTest; please direct that to 21 | [Feedback Assistant](https://developer.apple.com/bug-reporting) instead. 22 | - type: textarea 23 | attributes: 24 | label: Description 25 | description: > 26 | A comprehensive description of the task, in human language. 27 | validations: 28 | required: true 29 | - type: textarea 30 | attributes: 31 | label: Additional information 32 | description: > 33 | Any complementary information that could be valuable to an implementor. 34 | For example, a link to a discussion or post that motivated this task. 35 | validations: 36 | required: false 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2025 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See https://swift.org/LICENSE.txt for license information 7 | # See https://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | blank_issues_enabled: true 10 | contact_links: 11 | - name: 🌐 Discuss an idea 12 | url: https://forums.swift.org/c/related-projects/swift-testing 13 | about: > 14 | Share an idea with the Swift Testing community. 15 | - name: 📄 Formally propose a change 16 | url: https://github.com/swiftlang/swift-testing/blob/main/Documentation/Proposals/0000-proposal-template.md 17 | about: > 18 | Formally propose an addition, removal, or change to the APIs or features 19 | of Swift Testing. 20 | - name: 🙋 Ask a question 21 | url: https://forums.swift.org/c/related-projects/swift-testing 22 | about: > 23 | Ask a question about or get help with Swift Testing. Beginner questions 24 | welcome! 25 | - name: 🪲 Report an issue with Swift Package Manager 26 | url: https://github.com/swiftlang/swift-package-manager/issues/new/choose 27 | about: > 28 | Report an issue with Swift Package Manager, which includes the 29 | "swift test" CLI tool. 30 | - name: 🪲 Report an issue with Apple software using Feedback Assistant 31 | url: https://developer.apple.com/bug-reporting 32 | about: > 33 | Report an issue with Xcode or other closed source Apple developer 34 | software such as XCTest. 35 | - name: 🪲 Report an issue with the VS Code Swift plugin 36 | url: https://github.com/swiftlang/vscode-swift/issues/new/choose 37 | about: > 38 | Report an issue with the Swift plugin for VS Code, which integrates with 39 | Swift Testing. 40 | - name: 📖 Learn about Swift Testing 41 | url: https://swiftpackageindex.com/swiftlang/swift-testing/main/documentation/testing 42 | about: > 43 | Read the official Swift Testing documentation. 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | _[One line description of your change]_ 2 | 3 | ### Motivation: 4 | 5 | _[Explain here the context, and why you're making that change. What is the problem you're trying to solve.]_ 6 | 7 | ### Modifications: 8 | 9 | _[Describe the modifications you've done.]_ 10 | 11 | ### Checklist: 12 | 13 | - [ ] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). 14 | - [ ] If public symbols are renamed or modified, DocC references should be updated. 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /.index-build 4 | /build 5 | /Packages 6 | /*.xcodeproj 7 | xcuserdata/ 8 | DerivedData/ 9 | .swiftpm/config/registries.json 10 | .swiftpm/xcode/package.xcworkspace/ 11 | .swiftpm/xcode/xcuserdata/ 12 | .netrc 13 | .vs 14 | .docc-build/ 15 | Package.resolved 16 | *.profraw 17 | .*.sw? 18 | /.vscode 19 | -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | metadata: 3 | authors: Apple Inc. 4 | builder: 5 | configs: 6 | - documentation_targets: [Testing] 7 | scheme: Testing 8 | -------------------------------------------------------------------------------- /.swiftpm/Testing.xctestplan: -------------------------------------------------------------------------------- 1 | { 2 | "configurations" : [ 3 | { 4 | "id" : "BF6DCB8A-163C-4014-93D6-96B417187A12", 5 | "name" : "Test Scheme Action", 6 | "options" : { 7 | 8 | } 9 | } 10 | ], 11 | "defaultOptions" : { 12 | "codeCoverage" : false 13 | }, 14 | "testTargets" : [ 15 | { 16 | "target" : { 17 | "containerPath" : "container:", 18 | "identifier" : "TestingTests", 19 | "name" : "TestingTests" 20 | } 21 | }, 22 | { 23 | "target" : { 24 | "containerPath" : "container:", 25 | "identifier" : "TestingMacrosTests", 26 | "name" : "TestingMacrosTests" 27 | } 28 | } 29 | ], 30 | "version" : 1 31 | } 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | cmake_minimum_required(VERSION 3.19.6...3.29) 10 | 11 | if(POLICY CMP0157) 12 | if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows AND CMAKE_SYSTEM_NAME STREQUAL Android) 13 | # CMP0157 causes builds to fail when targetting Android with the Windows 14 | # toolchain, because the early swift-driver isn't (yet) available. Disable 15 | # it for now. 16 | cmake_policy(SET CMP0157 OLD) 17 | else() 18 | cmake_policy(SET CMP0157 NEW) 19 | endif() 20 | endif() 21 | 22 | project(SwiftTesting 23 | LANGUAGES CXX Swift) 24 | 25 | if(NOT APPLE) 26 | if(NOT CMAKE_SYSTEM_NAME STREQUAL WASI) 27 | find_package(dispatch CONFIG) 28 | endif() 29 | find_package(Foundation CONFIG) 30 | endif() 31 | 32 | include(GNUInstallDirs) 33 | 34 | list(APPEND CMAKE_MODULE_PATH 35 | ${PROJECT_SOURCE_DIR}/cmake/modules 36 | ${PROJECT_SOURCE_DIR}/cmake/modules/shared) 37 | 38 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 39 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 40 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 41 | 42 | set(CMAKE_INSTALL_RPATH "$,@loader_path/..,$ORIGIN>") 43 | set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH YES) 44 | 45 | set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL) 46 | set(CMAKE_CXX_STANDARD 20) 47 | set(CMAKE_Swift_LANGUAGE_VERSION 6) 48 | set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) 49 | 50 | include(PlatformInfo) 51 | include(SwiftModuleInstallation) 52 | 53 | option(SwiftTesting_INSTALL_NESTED_SUBDIR "Install libraries under a platform and architecture subdirectory" NO) 54 | set(SwiftTesting_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>/${SwiftTesting_PLATFORM_SUBDIR}$<$,$>>:/testing>$<$:/${SwiftTesting_ARCH_SUBDIR}>") 55 | set(SwiftTesting_INSTALL_SWIFTMODULEDIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>/${SwiftTesting_PLATFORM_SUBDIR}$<$,$>>:/testing>") 56 | 57 | add_compile_options($<$:-no-toolchain-stdlib-rpath>) 58 | 59 | add_subdirectory(Sources) 60 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the Swift.org open source project 3 | # 4 | # Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | # Licensed under Apache License v2.0 with Runtime Library Exception 6 | # 7 | # See https://swift.org/LICENSE.txt for license information 8 | # See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | # 10 | 11 | * @stmontgomery @grynspan @briancroom @suzannaratcliff 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2023 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See https://swift.org/LICENSE.txt for license information 7 | # See https://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | FROM swiftlang/swift:nightly-main-jammy 10 | 11 | # Set up the current build user in the same way done in the Swift.org CI system: 12 | # https://github.com/swiftlang/swift-docker/blob/main/swift-ci/master/ubuntu/22.04/Dockerfile 13 | 14 | RUN groupadd -g 998 build-user && \ 15 | useradd -m -r -u 998 -g build-user build-user 16 | 17 | USER build-user 18 | 19 | WORKDIR /home/build-user 20 | -------------------------------------------------------------------------------- /Documentation/Proposals/0001-refactor-bug-inits.md: -------------------------------------------------------------------------------- 1 | # Dedicated `.bug()` functions for URLs and IDs 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0001 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0001: Dedicated `.bug()` functions for URLs and IDs](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0001-refactor-bug-inits.md). 11 | -------------------------------------------------------------------------------- /Documentation/Proposals/0002-json-abi.md: -------------------------------------------------------------------------------- 1 | # A stable JSON-based ABI for tools integration 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0002 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0002: A stable JSON-based ABI for tools integration](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0002-json-abi.md). 11 | -------------------------------------------------------------------------------- /Documentation/Proposals/0003-make-serialized-trait-api.md: -------------------------------------------------------------------------------- 1 | # Make .serialized trait API 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0003 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0003: Make .serialized trait API](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0003-make-serialized-trait-api.md). 11 | -------------------------------------------------------------------------------- /Documentation/Proposals/0004-constrain-the-granularity-of-test-time-limit-durations.md: -------------------------------------------------------------------------------- 1 | # Constrain the granularity of test time limit durations 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0004 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0004: Constrain the granularity of test time limit durations](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0004-constrain-the-granularity-of-test-time-limit-durations.md). 11 | -------------------------------------------------------------------------------- /Documentation/Proposals/0005-ranged-confirmations.md: -------------------------------------------------------------------------------- 1 | # Range-based confirmations 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0005 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0005: Range-based confirmations](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0005-ranged-confirmations.md). 11 | -------------------------------------------------------------------------------- /Documentation/Proposals/0006-return-errors-from-expect-throws.md: -------------------------------------------------------------------------------- 1 | # Return errors from `#expect(throws:)` 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0006 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0006: Return errors from `#expect(throws:)`](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0006-return-errors-from-expect-throws.md). 11 | -------------------------------------------------------------------------------- /Documentation/Proposals/0007-test-scoping-traits.md: -------------------------------------------------------------------------------- 1 | # Test Scoping Traits 2 | 3 | > [!NOTE] 4 | > This proposal was accepted before Swift Testing began using the Swift 5 | > evolution review process. Its original identifier was SWT-0007 but its prefix 6 | > has been changed to "ST" and it has been relocated to the 7 | > [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 8 | 9 | To view this proposal, see 10 | [ST-0007: Test Scoping Traits](https://github.com/swiftlang/swift-evolution/blob/main/proposals/testing/0007-test-scoping-traits.md). 11 | -------------------------------------------------------------------------------- /Documentation/SPI.md: -------------------------------------------------------------------------------- 1 | # SPI groups in Swift Testing 2 | 3 | 12 | 13 | 15 | 16 | This post describes the set of SPI groups used in Swift Testing. In general, 17 | three groups of SPI exist in the testing library: 18 | 19 | 1. Interfaces that aren't needed by test authors, but which may be needed by 20 | tools that use the testing library such as Swift Package Manager; 21 | 1. Interfaces that are available for test authors to use, but which are 22 | experimental or under active development and which may be modified or removed 23 | in the future; and 24 | 1. Interfaces that are private to the testing library but need to be shared 25 | across targets, but which for technical reasons cannot use `package`. 26 | 27 | For interfaces used to integrate with external tools, the SPI group 28 | `@_spi(ForToolsIntegrationOnly)` is used. The name is a hint to adopters that 29 | they should not be using such SPI if they aren't building tooling around the 30 | testing library. 31 | 32 | For interfaces that are experimental or under active development, the SPI group 33 | `@_spi(Experimental)` is used. Such interfaces are intended to eventually become 34 | public, stable API, so test authors are encouraged to hold off adopting them 35 | until that happens. 36 | 37 | For interfaces that are experimental _and_ that are used to integrate with 38 | external tools, _both_ groups are specified. Such SPI is not generally meant to 39 | be promoted to public API, but is still experimental until tools authors have a 40 | chance to evaluate it. 41 | 42 | ## SPI stability 43 | 44 | The testing library does **not** guarantee SPI stability for either group of 45 | SPI. 46 | 47 | For SPI marked `@_spi(ForToolsIntegrationOnly)`, breaking changes will be 48 | preceded by deprecation (where possible) to allow tool authors time to migrate 49 | to newer interfaces. 50 | 51 | SPI marked `@_spi(Experimental)` should be assumed to be unstable. It may be 52 | modified or removed at any time. 53 | 54 | ## API and ABI stability 55 | 56 | When Swift Testing reaches its 1.0 release, API changes will follow the same 57 | general rules as those in the Swift standard library: removal will be a last 58 | resort and will always be preceded by deprecation to allow tool and test authors 59 | time to migrate to newer interfaces. 60 | 61 | As a general rule, ABI stability is not guaranteed by the testing library. 62 | -------------------------------------------------------------------------------- /Documentation/Vision.md: -------------------------------------------------------------------------------- 1 | # A New Direction for Testing in Swift 2 | 3 | 12 | 13 | ## Introduction 14 | 15 | A key requirement for the success of any developer platform is a way to use 16 | automated testing to identify software defects. Better APIs and tools for 17 | testing can greatly improve a platform’s quality. Below, we propose a new API 18 | direction for testing in Swift. 19 | 20 | Click [here](https://github.com/swiftlang/swift-evolution/blob/main/visions/swift-testing.md) 21 | to view the complete vision document for Swift Testing, which has been accepted 22 | by the Swift Language Steering Group and is now hosted in the 23 | [swift-evolution](https://github.com/swiftlang/swift-evolution) repository. 24 | -------------------------------------------------------------------------------- /Documentation/WASI.md: -------------------------------------------------------------------------------- 1 | # Running tests for WebAssembly 2 | 3 | 12 | 13 | 15 | 16 | To run tests for WebAssembly, install a Swift SDK for WebAssembly by following 17 | [these instructions](https://book.swiftwasm.org/getting-started/setup.html). 18 | 19 | Because `swift test` doesn't know what WebAssembly environment you'd like to use 20 | to run your tests, building tests and running them are two separate steps. To 21 | build tests for WebAssembly, use the following command: 22 | 23 | ```sh 24 | swift build --swift-sdk wasm32-unknown-wasi --build-tests 25 | ``` 26 | 27 | After building tests, you can run them using a [WASI](https://wasi.dev/)-compliant 28 | WebAssembly runtime such as [Wasmtime](https://wasmtime.dev/) or 29 | [WasmKit](https://github.com/swiftwasm/WasmKit). For example, to run tests using 30 | Wasmtime, use the following command (replace `{YOURPACKAGE}` with your package's 31 | name): 32 | 33 | ```sh 34 | wasmtime .build/debug/{YOURPACKAGE}PackageTests.wasm --testing-library swift-testing 35 | ``` 36 | 37 | Most WebAssembly runtimes forward trailing arguments to the WebAssembly program, 38 | so you can pass command-line options of the testing library. For example, to list 39 | all tests and filter them by name, use the following commands: 40 | 41 | ```sh 42 | wasmtime .build/debug/{YOURPACKAGE}PackageTests.wasm list --testing-library swift-testing 43 | wasmtime .build/debug/{YOURPACKAGE}PackageTests.wasm --testing-library swift-testing --filter "FoodTruckTests.foodTruckExists" 44 | ``` 45 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | 2 | The Swift Testing Project 3 | ========================= 4 | 5 | Please visit the Swift Testing web site for more information: 6 | 7 | * https://github.com/swiftlang/swift-testing 8 | 9 | Copyright (c) 2023 Apple Inc. and the Swift project authors 10 | 11 | The Swift Project licenses this file to you under the Apache License, 12 | version 2.0 (the "License"); you may not use this file except in compliance 13 | with the License. You may obtain a copy of the License at: 14 | 15 | https://www.apache.org/licenses/LICENSE-2.0 16 | 17 | Unless required by applicable law or agreed to in writing, software 18 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 20 | License for the specific language governing permissions and limitations 21 | under the License. 22 | 23 | ------------------------------------------------------------------------------- 24 | -------------------------------------------------------------------------------- /Sources/Overlays/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | add_subdirectory(_Testing_Foundation) 10 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_CoreGraphics/Attachments/CGImage+AttachableAsCGImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if SWT_TARGET_OS_APPLE && canImport(CoreGraphics) 12 | public import CoreGraphics 13 | 14 | @_spi(Experimental) 15 | extension CGImage: AttachableAsCGImage { 16 | public var attachableCGImage: CGImage { 17 | self 18 | } 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_CoreGraphics/Attachments/ImageAttachmentError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if SWT_TARGET_OS_APPLE && canImport(CoreGraphics) 12 | /// A type representing an error that can occur when attaching an image. 13 | package enum ImageAttachmentError: Error, CustomStringConvertible { 14 | /// The image could not be converted to an instance of `CGImage`. 15 | case couldNotCreateCGImage 16 | 17 | /// The image destination could not be created. 18 | case couldNotCreateImageDestination 19 | 20 | /// The image could not be converted. 21 | case couldNotConvertImage 22 | 23 | public var description: String { 24 | switch self { 25 | case .couldNotCreateCGImage: 26 | "Could not create the corresponding Core Graphics image." 27 | case .couldNotCreateImageDestination: 28 | "Could not create the Core Graphics image destination to encode this image." 29 | case .couldNotConvertImage: 30 | "Could not convert the image to the specified format." 31 | } 32 | } 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_CoreGraphics/ReexportTesting.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @_exported @_spi(Experimental) @_spi(ForToolsIntegrationOnly) public import Testing 12 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/Attachments/Attachable+Encodable+NSSecureCoding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) 12 | public import Testing 13 | public import Foundation 14 | 15 | // This implementation is necessary to let the compiler disambiguate when a type 16 | // conforms to both Encodable and NSSecureCoding. It is hidden from the DocC 17 | // compiler because it appears redundant next to the other two implementations 18 | // (which explicitly document what happens when a type conforms to both 19 | // protocols.) 20 | 21 | /// @Metadata { 22 | /// @Available(Swift, introduced: 6.2) 23 | /// } 24 | extension Attachable where Self: Encodable & NSSecureCoding { 25 | @_documentation(visibility: private) 26 | public func withUnsafeBytes(for attachment: borrowing Attachment, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R { 27 | try _Testing_Foundation.withUnsafeBytes(encoding: self, for: attachment, body) 28 | } 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/Attachments/Data+Attachable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) 12 | public import Testing 13 | public import Foundation 14 | 15 | /// @Metadata { 16 | /// @Available(Swift, introduced: 6.2) 17 | /// } 18 | extension Data: Attachable { 19 | /// @Metadata { 20 | /// @Available(Swift, introduced: 6.2) 21 | /// } 22 | public func withUnsafeBytes(for attachment: borrowing Attachment, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R { 23 | try withUnsafeBytes(body) 24 | } 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/Attachments/EncodingFormat.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) 12 | import Testing 13 | import Foundation 14 | 15 | /// An enumeration describing the encoding formats we support for `Encodable` 16 | /// and `NSSecureCoding` types that conform to `Attachable`. 17 | enum EncodingFormat { 18 | /// The encoding format to use by default. 19 | /// 20 | /// The specific format this case corresponds to depends on if we are encoding 21 | /// an `Encodable` value or an `NSSecureCoding` value. 22 | case `default` 23 | 24 | /// A property list format. 25 | /// 26 | /// - Parameters: 27 | /// - format: The corresponding property list format. 28 | case propertyListFormat(_ format: PropertyListSerialization.PropertyListFormat) 29 | 30 | /// The JSON format. 31 | case json 32 | 33 | /// Initialize an instance of this type representing the content type or media 34 | /// type of the specified attachment. 35 | /// 36 | /// - Parameters: 37 | /// - attachment: The attachment that will be encoded. 38 | /// 39 | /// - Throws: If the attachment's content type or media type is unsupported. 40 | init(for attachment: borrowing Attachment) throws { 41 | let ext = (attachment.preferredName as NSString).pathExtension 42 | if ext.isEmpty { 43 | // No path extension? No problem! Default data. 44 | self = .default 45 | } else if ext.caseInsensitiveCompare("plist") == .orderedSame { 46 | self = .propertyListFormat(.binary) 47 | } else if ext.caseInsensitiveCompare("xml") == .orderedSame { 48 | self = .propertyListFormat(.xml) 49 | } else if ext.caseInsensitiveCompare("json") == .orderedSame { 50 | self = .json 51 | } else { 52 | throw CocoaError(.propertyListWriteInvalid, userInfo: [NSLocalizedDescriptionKey: "The path extension '.\(ext)' cannot be used to attach an instance of \(type(of: self)) to a test."]) 53 | } 54 | } 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/Attachments/_AttachableURLWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) 12 | public import Testing 13 | public import Foundation 14 | 15 | /// A wrapper type representing file system objects and URLs that can be 16 | /// attached indirectly. 17 | /// 18 | /// You do not need to use this type directly. Instead, initialize an instance 19 | /// of ``Attachment`` using a file URL. 20 | public struct _AttachableURLWrapper: Sendable { 21 | /// The underlying URL. 22 | var url: URL 23 | 24 | /// The data contained at ``url``. 25 | var data: Data 26 | 27 | /// Whether or not this instance represents a compressed directory. 28 | var isCompressedDirectory: Bool 29 | } 30 | 31 | // MARK: - 32 | 33 | extension _AttachableURLWrapper: AttachableWrapper { 34 | public var wrappedValue: URL { 35 | url 36 | } 37 | 38 | public func withUnsafeBytes(for attachment: borrowing Attachment, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R { 39 | try data.withUnsafeBytes(body) 40 | } 41 | 42 | public borrowing func preferredName(for attachment: borrowing Attachment, basedOn suggestedName: String) -> String { 43 | // What extension should we have on the filename so that it has the same 44 | // type as the original file (or, in the case of a compressed directory, is 45 | // a zip file?) 46 | let preferredPathExtension = if isCompressedDirectory { 47 | "zip" 48 | } else { 49 | url.pathExtension 50 | } 51 | 52 | // What path extension is on the suggested name already? 53 | let nsSuggestedName = suggestedName as NSString 54 | let suggestedPathExtension = nsSuggestedName.pathExtension 55 | 56 | // If the suggested name's extension isn't what we would prefer, append the 57 | // preferred extension. 58 | if !preferredPathExtension.isEmpty, 59 | suggestedPathExtension.caseInsensitiveCompare(preferredPathExtension) != .orderedSame, 60 | let result = nsSuggestedName.appendingPathExtension(preferredPathExtension) { 61 | return result 62 | } 63 | 64 | return suggestedName 65 | } 66 | } 67 | #endif 68 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | add_library(_Testing_Foundation 10 | Attachments/_AttachableURLWrapper.swift 11 | Attachments/EncodingFormat.swift 12 | Attachments/Attachment+URL.swift 13 | Attachments/Attachable+NSSecureCoding.swift 14 | Attachments/Data+Attachable.swift 15 | Attachments/Attachable+Encodable+NSSecureCoding.swift 16 | Attachments/Attachable+Encodable.swift 17 | Events/Clock+Date.swift 18 | ReexportTesting.swift) 19 | 20 | target_link_libraries(_Testing_Foundation PUBLIC 21 | Testing) 22 | 23 | # Although this library links Foundation on all platforms, it only does so using 24 | # `target_link_libraries()` when building for non-Apple platforms. This is 25 | # because that command uses the `-lFoundation` linker flag, but on Apple 26 | # platforms Foundation is a .framework and requires a different flag. However, 27 | # we don't need to explicitly pass any linker flag since it's handled 28 | # automatically on Apple platforms via auto-linking. 29 | if(NOT APPLE) 30 | target_link_libraries(_Testing_Foundation PUBLIC 31 | Foundation) 32 | endif() 33 | 34 | # Note: This does not enable Library Evolution, despite emitting a module 35 | # interface, because Foundation does not have Library Evolution enabled for all 36 | # platforms. 37 | target_compile_options(_Testing_Foundation PRIVATE 38 | -emit-module-interface -emit-module-interface-path $/_Testing_Foundation.swiftinterface) 39 | 40 | _swift_testing_install_target(_Testing_Foundation) 41 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/Events/Clock+Date.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) && !SWT_NO_UTC_CLOCK 12 | @_spi(Experimental) @_spi(ForToolsIntegrationOnly) public import Testing 13 | public import Foundation 14 | 15 | extension Date { 16 | /// Initialize this date to the equivalent of the same date on the testing 17 | /// library's clock. 18 | /// 19 | /// - Parameters: 20 | /// - testClockInstant: The equivalent instant on ``Test/Clock``. 21 | /// 22 | /// The resulting instance is equivalent to the wall-clock time represented by 23 | /// `testClockInstant`. For precise date/time calculations, convert instances 24 | /// of ``Test/Clock/Instant`` to `SuspendingClock.Instant` instead of `Date`. 25 | @_spi(Experimental) @_spi(ForToolsIntegrationOnly) 26 | public init(_ testClockInstant: Test.Clock.Instant) { 27 | let components = testClockInstant.timeComponentsSince1970 28 | let secondsSince1970 = TimeInterval(components.seconds) + (TimeInterval(components.attoseconds) / TimeInterval(1_000_000_000_000_000_000)) 29 | self.init(timeIntervalSince1970: secondsSince1970) 30 | } 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /Sources/Overlays/_Testing_Foundation/ReexportTesting.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @_exported @_spi(Experimental) @_spi(ForToolsIntegrationOnly) public import Testing 12 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/ABI.Record+Streaming.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) && (!SWT_NO_FILE_IO || !SWT_NO_ABI_ENTRY_POINT) 12 | private import Foundation 13 | 14 | extension ABI.Version { 15 | static func eventHandler( 16 | encodeAsJSONLines: Bool, 17 | forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void 18 | ) -> Event.Handler { 19 | // Encode as JSON Lines if requested. 20 | var eventHandlerCopy = eventHandler 21 | if encodeAsJSONLines { 22 | eventHandlerCopy = { @Sendable in JSON.asJSONLine($0, eventHandler) } 23 | } 24 | 25 | let humanReadableOutputRecorder = Event.HumanReadableOutputRecorder() 26 | return { [eventHandler = eventHandlerCopy] event, context in 27 | if case .testDiscovered = event.kind, let test = context.test { 28 | try? JSON.withEncoding(of: ABI.Record(encoding: test)) { testJSON in 29 | eventHandler(testJSON) 30 | } 31 | } else { 32 | let messages = humanReadableOutputRecorder.record(event, in: context, verbosity: 0) 33 | if let eventRecord = ABI.Record(encoding: event, in: context, messages: messages) { 34 | try? JSON.withEncoding(of: eventRecord, eventHandler) 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | #if !SWT_NO_SNAPSHOT_TYPES 42 | // MARK: - Xcode 16 compatibility 43 | 44 | extension ABI.Xcode16 { 45 | static func eventHandler( 46 | encodeAsJSONLines: Bool, 47 | forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void 48 | ) -> Event.Handler { 49 | return { event, context in 50 | if case .testDiscovered = event.kind { 51 | // Discard events of this kind rather than forwarding them to avoid a 52 | // crash in Xcode 16 (which does not expect any events to occur before 53 | // .runStarted.) 54 | return 55 | } 56 | 57 | struct EventAndContextSnapshot: Codable { 58 | var event: Event.Snapshot 59 | var eventContext: Event.Context.Snapshot 60 | } 61 | let snapshot = EventAndContextSnapshot( 62 | event: Event.Snapshot(snapshotting: event), 63 | eventContext: Event.Context.Snapshot(snapshotting: context) 64 | ) 65 | try? JSON.withEncoding(of: snapshot) { eventAndContextJSON in 66 | eventAndContextJSON.withUnsafeBytes { eventAndContextJSON in 67 | eventHandler(eventAndContextJSON) 68 | } 69 | } 70 | } 71 | } 72 | } 73 | #endif 74 | #endif 75 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/ABI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024–2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A namespace for ABI symbols. 12 | @_spi(ForToolsIntegrationOnly) 13 | public enum ABI: Sendable {} 14 | 15 | // MARK: - ABI version abstraction 16 | 17 | extension ABI { 18 | /// A protocol describing the types that represent different ABI versions. 19 | protocol Version: Sendable { 20 | /// The numeric representation of this ABI version. 21 | static var versionNumber: Int { get } 22 | 23 | #if canImport(Foundation) && (!SWT_NO_FILE_IO || !SWT_NO_ABI_ENTRY_POINT) 24 | /// Create an event handler that encodes events as JSON and forwards them to 25 | /// an ABI-friendly event handler. 26 | /// 27 | /// - Parameters: 28 | /// - encodeAsJSONLines: Whether or not to ensure JSON passed to 29 | /// `eventHandler` is encoded as JSON Lines (i.e. that it does not 30 | /// contain extra newlines.) 31 | /// - eventHandler: The event handler to forward events to. 32 | /// 33 | /// - Returns: An event handler. 34 | /// 35 | /// The resulting event handler outputs data as JSON. For each event handled 36 | /// by the resulting event handler, a JSON object representing it and its 37 | /// associated context is created and is passed to `eventHandler`. 38 | static func eventHandler( 39 | encodeAsJSONLines: Bool, 40 | forwardingTo eventHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void 41 | ) -> Event.Handler 42 | #endif 43 | } 44 | 45 | /// The current supported ABI version (ignoring any experimental versions.) 46 | typealias CurrentVersion = v0 47 | } 48 | 49 | // MARK: - Concrete ABI versions 50 | 51 | extension ABI { 52 | #if !SWT_NO_SNAPSHOT_TYPES 53 | /// A namespace and version type for Xcode 16 compatibility. 54 | /// 55 | /// - Warning: This type will be removed in a future update. 56 | enum Xcode16: Sendable, Version { 57 | static var versionNumber: Int { 58 | -1 59 | } 60 | } 61 | #endif 62 | 63 | /// A namespace and type for ABI version 0 symbols. 64 | public enum v0: Sendable, Version { 65 | static var versionNumber: Int { 66 | 0 67 | } 68 | } 69 | 70 | /// A namespace and type for ABI version 1 symbols. 71 | /// 72 | /// @Metadata { 73 | /// @Available("Swift Testing ABI", introduced: 1) 74 | /// } 75 | @_spi(Experimental) 76 | public enum v1: Sendable, Version { 77 | static var versionNumber: Int { 78 | 1 79 | } 80 | } 81 | } 82 | 83 | /// A namespace for ABI version 0 symbols. 84 | @_spi(ForToolsIntegrationOnly) 85 | @available(*, deprecated, renamed: "ABI.v0") 86 | public typealias ABIv0 = ABI.v0 87 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/Encoded/ABI.EncodedAttachment.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension ABI { 12 | /// A type implementing the JSON encoding of ``Attachment`` for the ABI entry 13 | /// point and event stream output. 14 | /// 15 | /// This type is not part of the public interface of the testing library. It 16 | /// assists in converting values to JSON; clients that consume this JSON are 17 | /// expected to write their own decoders. 18 | /// 19 | /// - Warning: Attachments are not yet part of the JSON schema. 20 | struct EncodedAttachment: Sendable where V: ABI.Version { 21 | /// The path where the attachment was written. 22 | var path: String? 23 | 24 | init(encoding attachment: borrowing Attachment, in eventContext: borrowing Event.Context) { 25 | path = attachment.fileSystemPath 26 | } 27 | } 28 | } 29 | 30 | // MARK: - Codable 31 | 32 | extension ABI.EncodedAttachment: Codable {} 33 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/Encoded/ABI.EncodedBacktrace.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension ABI { 12 | /// A type implementing the JSON encoding of ``Backtrace`` for the ABI entry 13 | /// point and event stream output. 14 | /// 15 | /// This type is not part of the public interface of the testing library. It 16 | /// assists in converting values to JSON; clients that consume this JSON are 17 | /// expected to write their own decoders. 18 | /// 19 | /// - Warning: Backtraces are not yet part of the JSON schema. 20 | struct EncodedBacktrace: Sendable where V: ABI.Version { 21 | /// The frames in the backtrace. 22 | var symbolicatedAddresses: [Backtrace.SymbolicatedAddress] 23 | 24 | init(encoding backtrace: borrowing Backtrace, in eventContext: borrowing Event.Context) { 25 | if let symbolicationMode = eventContext.configuration?.backtraceSymbolicationMode { 26 | symbolicatedAddresses = backtrace.symbolicate(symbolicationMode) 27 | } else { 28 | symbolicatedAddresses = backtrace.addresses.map { Backtrace.SymbolicatedAddress(address: $0) } 29 | } 30 | } 31 | } 32 | } 33 | 34 | // MARK: - Codable 35 | 36 | extension ABI.EncodedBacktrace: Codable { 37 | func encode(to encoder: any Encoder) throws { 38 | try symbolicatedAddresses.encode(to: encoder) 39 | } 40 | 41 | init(from decoder: any Decoder) throws { 42 | self.symbolicatedAddresses = try [Backtrace.SymbolicatedAddress](from: decoder) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/Encoded/ABI.EncodedError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension ABI { 12 | /// A type implementing the JSON encoding of ``Error`` for the ABI entry point 13 | /// and event stream output. 14 | /// 15 | /// This type is not part of the public interface of the testing library. It 16 | /// assists in converting values to JSON; clients that consume this JSON are 17 | /// expected to write their own decoders. 18 | /// 19 | /// - Warning: Errors are not yet part of the JSON schema. 20 | struct EncodedError: Sendable where V: ABI.Version { 21 | /// The error's description 22 | var description: String 23 | 24 | /// The domain of the error. 25 | var domain: String 26 | 27 | /// The code of the error. 28 | var code: Int 29 | 30 | // TODO: userInfo (partial) encoding 31 | 32 | init(encoding error: some Error, in eventContext: borrowing Event.Context) { 33 | description = String(describingForTest: error) 34 | domain = error._domain 35 | code = error._code 36 | } 37 | } 38 | } 39 | 40 | // MARK: - Error 41 | 42 | extension ABI.EncodedError: Error { 43 | var _domain: String { 44 | domain 45 | } 46 | 47 | var _code: Int { 48 | code 49 | } 50 | 51 | var _userInfo: AnyObject? { 52 | // TODO: userInfo (partial) encoding 53 | nil 54 | } 55 | } 56 | 57 | // MARK: - Codable 58 | 59 | extension ABI.EncodedError: Codable {} 60 | 61 | // MARK: - CustomTestStringConvertible 62 | 63 | extension ABI.EncodedError: CustomTestStringConvertible { 64 | var testDescription: String { 65 | description 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/Encoded/ABI.EncodedInstant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension ABI { 12 | /// A type implementing the JSON encoding of ``Test/Clock/Instant`` for the 13 | /// ABI entry point and event stream output. 14 | /// 15 | /// This type is not part of the public interface of the testing library. It 16 | /// assists in converting values to JSON; clients that consume this JSON are 17 | /// expected to write their own decoders. 18 | struct EncodedInstant: Sendable where V: ABI.Version { 19 | /// The number of seconds since the system-defined suspending epoch. 20 | /// 21 | /// For more information, see [`SuspendingClock`](https://developer.apple.com/documentation/swift/suspendingclock). 22 | var absolute: Double 23 | 24 | /// The number of seconds since the UNIX epoch (1970-01-01 00:00:00 UT). 25 | var since1970: Double 26 | 27 | init(encoding instant: borrowing Test.Clock.Instant) { 28 | absolute = Double(instant.suspending) 29 | #if !SWT_NO_UTC_CLOCK 30 | since1970 = Double(instant.wall) 31 | #else 32 | since1970 = 0 33 | #endif 34 | } 35 | } 36 | } 37 | 38 | // MARK: - Codable 39 | 40 | extension ABI.EncodedInstant: Codable {} 41 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/Encoded/ABI.EncodedIssue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension ABI { 12 | /// A type implementing the JSON encoding of ``Issue`` for the ABI entry point 13 | /// and event stream output. 14 | /// 15 | /// This type is not part of the public interface of the testing library. It 16 | /// assists in converting values to JSON; clients that consume this JSON are 17 | /// expected to write their own decoders. 18 | struct EncodedIssue: Sendable where V: ABI.Version { 19 | /// An enumeration representing the level of severity of a recorded issue. 20 | /// 21 | /// For descriptions of individual cases, see ``Issue/Severity-swift.enum``. 22 | enum Severity: String, Sendable { 23 | case warning 24 | case error 25 | } 26 | 27 | /// The severity of this issue. 28 | /// 29 | /// - Warning: Severity is not yet part of the JSON schema. 30 | var _severity: Severity 31 | 32 | /// Whether or not this issue is known to occur. 33 | var isKnown: Bool 34 | 35 | /// The location in source where this issue occurred, if available. 36 | var sourceLocation: SourceLocation? 37 | 38 | /// The backtrace where this issue occurred, if available. 39 | /// 40 | /// - Warning: Backtraces are not yet part of the JSON schema. 41 | var _backtrace: EncodedBacktrace? 42 | 43 | /// The error associated with this issue, if applicable. 44 | /// 45 | /// - Warning: Errors are not yet part of the JSON schema. 46 | var _error: EncodedError? 47 | 48 | init(encoding issue: borrowing Issue, in eventContext: borrowing Event.Context) { 49 | _severity = switch issue.severity { 50 | case .warning: .warning 51 | case .error: .error 52 | } 53 | isKnown = issue.isKnown 54 | sourceLocation = issue.sourceLocation 55 | if let backtrace = issue.sourceContext.backtrace { 56 | _backtrace = EncodedBacktrace(encoding: backtrace, in: eventContext) 57 | } 58 | if let error = issue.error { 59 | _error = EncodedError(encoding: error, in: eventContext) 60 | } 61 | } 62 | } 63 | } 64 | 65 | // MARK: - Codable 66 | 67 | extension ABI.EncodedIssue: Codable {} 68 | extension ABI.EncodedIssue.Severity: Codable {} 69 | -------------------------------------------------------------------------------- /Sources/Testing/ABI/Encoded/ABI.EncodedMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension ABI { 12 | /// A type implementing the JSON encoding of 13 | /// ``Event/HumanReadableOutputRecorder/Message`` for the ABI entry point and 14 | /// event stream output. 15 | /// 16 | /// This type is not part of the public interface of the testing library. It 17 | /// assists in converting values to JSON; clients that consume this JSON are 18 | /// expected to write their own decoders. 19 | struct EncodedMessage: Sendable where V: ABI.Version { 20 | /// A type implementing the JSON encoding of ``Event/Symbol`` for the ABI 21 | /// entry point and event stream output. 22 | /// 23 | /// For descriptions of individual cases, see ``Event/Symbol``. 24 | enum Symbol: String, Sendable { 25 | case `default` 26 | case skip 27 | case pass 28 | case passWithWarnings = "_passWithWarnings" 29 | case passWithKnownIssue 30 | case fail 31 | case difference 32 | case warning 33 | case details 34 | case attachment = "_attachment" 35 | 36 | init(encoding symbol: Event.Symbol) { 37 | self = switch symbol { 38 | case .default: 39 | .default 40 | case .skip: 41 | .skip 42 | case let .pass(knownIssueCount): 43 | if knownIssueCount > 0 { 44 | .passWithKnownIssue 45 | } else { 46 | .pass 47 | } 48 | case .passWithWarnings: 49 | .passWithWarnings 50 | case .fail: 51 | .fail 52 | case .difference: 53 | .difference 54 | case .warning: 55 | .warning 56 | case .details: 57 | .details 58 | case .attachment: 59 | .attachment 60 | } 61 | } 62 | } 63 | 64 | /// The symbol associated with this message. 65 | var symbol: Symbol 66 | 67 | /// The human-readable, unformatted text associated with this message. 68 | var text: String 69 | 70 | init(encoding message: borrowing Event.HumanReadableOutputRecorder.Message) { 71 | symbol = Symbol(encoding: message.symbol ?? .default) 72 | text = message.conciseStringValue ?? message.stringValue 73 | } 74 | } 75 | } 76 | 77 | // MARK: - Codable 78 | 79 | extension ABI.EncodedMessage: Codable {} 80 | extension ABI.EncodedMessage.Symbol: Codable {} 81 | -------------------------------------------------------------------------------- /Sources/Testing/Attachments/AttachableWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A protocol describing a type that can be attached to a test report or 12 | /// written to disk when a test is run and which contains another value that it 13 | /// stands in for. 14 | /// 15 | /// To attach an attachable value to a test, pass it to ``Attachment/record(_:named:sourceLocation:)``. 16 | /// To further configure an attachable value before you attach it, use it to 17 | /// initialize an instance of ``Attachment`` and set its properties before 18 | /// passing it to ``Attachment/record(_:sourceLocation:)``. An attachable 19 | /// value can only be attached to a test once. 20 | /// 21 | /// A type can conform to this protocol if it represents another type that 22 | /// cannot directly conform to ``Attachable``, such as a non-final class or a 23 | /// type declared in a third-party module. 24 | /// 25 | /// @Metadata { 26 | /// @Available(Swift, introduced: 6.2) 27 | /// } 28 | public protocol AttachableWrapper: Attachable, ~Copyable { 29 | /// The type of the underlying value represented by this type. 30 | /// 31 | /// @Metadata { 32 | /// @Available(Swift, introduced: 6.2) 33 | /// } 34 | associatedtype Wrapped 35 | 36 | /// The underlying value represented by this instance. 37 | /// 38 | /// @Metadata { 39 | /// @Available(Swift, introduced: 6.2) 40 | /// } 41 | var wrappedValue: Wrapped { get } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/Testing/Discovery+Macro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023–2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// The type of the accessor function used to access a test content record. 12 | /// 13 | /// The signature of this function type must match that of the corresponding 14 | /// type in the `_TestDiscovery` module. For more information, see 15 | /// `ABI/TestContent.md`. 16 | /// 17 | /// - Warning: This type is used to implement the `@Test` macro. Do not use it 18 | /// directly. 19 | public typealias __TestContentRecordAccessor = @convention(c) ( 20 | _ outValue: UnsafeMutableRawPointer, 21 | _ type: UnsafeRawPointer, 22 | _ hint: UnsafeRawPointer?, 23 | _ reserved: UInt 24 | ) -> CBool 25 | 26 | /// The content of a test content record. 27 | /// 28 | /// The layout of this type must match that of the corresponding type 29 | /// in the `_TestDiscovery` module. For more information, see 30 | /// `ABI/TestContent.md`. 31 | /// 32 | /// - Warning: This type is used to implement the `@Test` macro. Do not use it 33 | /// directly. 34 | public typealias __TestContentRecord = ( 35 | kind: UInt32, 36 | reserved1: UInt32, 37 | accessor: __TestContentRecordAccessor?, 38 | context: UInt, 39 | reserved2: UInt 40 | ) 41 | -------------------------------------------------------------------------------- /Sources/Testing/Issues/ErrorSnapshot.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !SWT_NO_SNAPSHOT_TYPES 12 | /// A serializable snapshot of an `Error` value. 13 | /// 14 | /// This type conforms to `Error` as well, meaning it can be thrown and treated 15 | /// as an error, however it is not considered equal to the underlying error it 16 | /// is a snapshot of. 17 | @_spi(ForToolsIntegrationOnly) 18 | public struct ErrorSnapshot: Error { 19 | /// A description of this instance's underlying error, formatted using 20 | /// ``Swift/String/init(describingForTest:)``. 21 | public var description: String 22 | 23 | /// Information about the type of this instance's underlying error. 24 | public var typeInfo: TypeInfo 25 | 26 | /// Initialize an instance of this type by taking a snapshot of the specified 27 | /// error. 28 | /// 29 | /// - Parameters: 30 | /// - error: The underlying error to snapshot. 31 | public init(snapshotting error: any Error) { 32 | description = String(describingForTest: error) 33 | typeInfo = TypeInfo(describingTypeOf: error) 34 | } 35 | } 36 | 37 | // MARK: - CustomStringConvertible 38 | 39 | extension ErrorSnapshot: CustomStringConvertible {} 40 | 41 | // MARK: - Codable 42 | 43 | extension ErrorSnapshot: Codable {} 44 | #endif 45 | -------------------------------------------------------------------------------- /Sources/Testing/Running/Configuration+EventHandling.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Configuration { 12 | /// Handle the specified event. 13 | /// 14 | /// - Parameters: 15 | /// - event: The event to handle. 16 | /// - context: The context associated with the event. 17 | /// 18 | /// This method is used to handle events which are generated by the testing 19 | /// library. Typically this only involves passing the event to this instance's 20 | /// `eventHandler` but this method may also be used as a customization point 21 | /// to change how the event is passed to the event handler. 22 | func handleEvent(_ event: borrowing Event, in context: borrowing Event.Context) { 23 | var contextCopy = copy context 24 | contextCopy.configuration = self 25 | contextCopy.configuration?.eventHandler = { _, _ in } 26 | 27 | #if !SWT_NO_FILE_IO 28 | if case .valueAttached = event.kind { 29 | var eventCopy = copy event 30 | guard handleValueAttachedEvent(&eventCopy, in: contextCopy) else { 31 | // The attachment could not be handled, so suppress this event. 32 | return 33 | } 34 | return eventHandler(eventCopy, contextCopy) 35 | } 36 | #endif 37 | 38 | return eventHandler(event, contextCopy) 39 | } 40 | } 41 | 42 | extension Configuration.EventHandlingOptions { 43 | /// Determine whether the specified event should be handled according to the 44 | /// options in this instance. 45 | /// 46 | /// - Parameters: 47 | /// - event: The event to consider handling. 48 | /// 49 | /// - Returns: Whether or not the event should be handled or suppressed. 50 | func shouldHandleEvent(_ event: borrowing Event) -> Bool { 51 | switch event.kind { 52 | case let .issueRecorded(issue): 53 | issue.severity > .warning || isWarningIssueRecordedEventEnabled 54 | case .expectationChecked: 55 | isExpectationCheckedEventEnabled 56 | default: 57 | true 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/Testing/Running/SkipInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A type representing the details of a skipped test. 12 | @_spi(ForToolsIntegrationOnly) 13 | public struct SkipInfo: Sendable { 14 | /// A user-specified comment describing this skip, if any. 15 | public var comment: Comment? 16 | 17 | /// A source context indicating where this skip occurred. 18 | public var sourceContext: SourceContext 19 | 20 | /// The location in source where this skip occurred, if available. 21 | public var sourceLocation: SourceLocation? { 22 | get { 23 | sourceContext.sourceLocation 24 | } 25 | set { 26 | sourceContext.sourceLocation = newValue 27 | } 28 | } 29 | 30 | /// Initialize an instance of this type with the specified details. 31 | /// 32 | /// - Parameters: 33 | /// - comment: A user-specified comment describing this skip, if any. 34 | /// Defaults to `nil`. 35 | /// - sourceContext: A source context indicating where this skip occurred. 36 | public init( 37 | comment: Comment? = nil, 38 | sourceContext: SourceContext 39 | ) { 40 | self.comment = comment 41 | self.sourceContext = sourceContext 42 | } 43 | } 44 | 45 | // This conforms to `Error` because throwing an instance of this type is how a 46 | // custom trait can signal that the test it is attached to should be skipped. 47 | extension SkipInfo: Error {} 48 | 49 | // MARK: - Equatable, Hashable 50 | 51 | extension SkipInfo: Equatable, Hashable {} 52 | 53 | // MARK: - Codable 54 | 55 | extension SkipInfo: Codable {} 56 | 57 | // MARK: - Deprecated 58 | 59 | extension SkipInfo { 60 | @available(*, deprecated, message: "Use init(comment:sourceContext:) and pass an explicit SourceContext.") 61 | public init(comment: Comment? = nil) { 62 | self.init(comment: comment, sourceContext: .init(backtrace: .current(), sourceLocation: nil)) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Sources/Testing/SourceAttribution/SourceContext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A type representing the call stack backtrace and source location of a 12 | /// particular call. 13 | /// 14 | /// Most commonly used when recording a failure, in order to indicate the source 15 | /// location where the failure occurred as well as the backtrace of the failing 16 | /// call, since the latter may be useful to understand how it was invoked. 17 | @_spi(ForToolsIntegrationOnly) 18 | public struct SourceContext: Sendable { 19 | /// The backtrace associated with this instance, if available. 20 | public var backtrace: Backtrace? 21 | 22 | /// The location in source code associated with this instance, if available. 23 | public var sourceLocation: SourceLocation? 24 | 25 | /// Initialize an instance of this type with the specified backtrace and 26 | /// source location. 27 | /// 28 | /// - Parameters: 29 | /// - backtrace: The backtrace associated with the new instance. 30 | /// - sourceLocation: The source location associated with the new instance, 31 | /// if available. 32 | public init(backtrace: Backtrace?, sourceLocation: SourceLocation?) { 33 | self.backtrace = backtrace 34 | self.sourceLocation = sourceLocation 35 | } 36 | } 37 | 38 | extension SourceContext: Equatable, Hashable {} 39 | 40 | // MARK: - Codable 41 | 42 | extension SourceContext: Codable {} 43 | 44 | // MARK: - Deprecated 45 | 46 | extension SourceContext { 47 | @available(*, deprecated, message: "Use init(backtrace:sourceLocation:) and pass both arguments explicitly instead.") 48 | public init(backtrace: Backtrace?) { 49 | self.init(backtrace: backtrace, sourceLocation: nil) 50 | } 51 | 52 | @available(*, deprecated, message: "Use init(backtrace:sourceLocation:) and pass both arguments explicitly instead.") 53 | public init(sourceLocation: SourceLocation? = nil) { 54 | self.init(backtrace: nil, sourceLocation: sourceLocation) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Testing/SourceAttribution/SourceLocation+Macro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// Get the current source location as a compile-time constant. 12 | /// 13 | /// - Returns: The source location at which this macro is applied. 14 | /// 15 | /// This macro can be used in place of `#fileID`, `#line`, and `#column` as a 16 | /// default argument to a function. It expands to an instance of 17 | /// ``SourceLocation`` referring to the location of the macro invocation itself 18 | /// (similar to how `#fileID` expands to the ID of the file containing the 19 | /// `#fileID` invocation.) 20 | @freestanding(expression) public macro _sourceLocation() -> SourceLocation = #externalMacro(module: "TestingMacros", type: "SourceLocationMacro") 21 | 22 | extension SourceLocation { 23 | /// Get the current source location as an instance of ``SourceLocation``. 24 | /// 25 | /// - Warning: This function is used to implement the `#_sourceLocation` 26 | /// macro. Do not call it directly. 27 | public static func __here( 28 | fileID: String = #fileID, 29 | filePath: String = #filePath, 30 | line: Int = #line, 31 | column: Int = #column 32 | ) -> Self { 33 | Self(fileID: fileID, filePath: filePath, line: line, column: column) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Testing/Support/Additions/ArrayAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Array { 12 | /// Initialize an array from a single optional value. 13 | /// 14 | /// - Parameters: 15 | /// - optionalValue: The value to place in the array. 16 | /// 17 | /// If `optionalValue` is not `nil`, it is unwrapped and the resulting array 18 | /// contains a single element equal to its value. If `optionalValue` is `nil`, 19 | /// the resulting array is empty. 20 | init(_ optionalValue: Element?) { 21 | self = optionalValue.map { [$0] } ?? [] 22 | } 23 | } 24 | 25 | /// Get the number of elements in a parameter pack. 26 | /// 27 | /// - Parameters: 28 | /// - pack: The parameter pack. 29 | /// 30 | /// - Returns: The number of elements in `pack`. 31 | /// 32 | /// - Complexity: O(_n_) where _n_ is the number of elements in `pack`. The 33 | /// compiler may be able to optimize this operation when the types of `pack` 34 | /// are statically known. 35 | func parameterPackCount(_ pack: repeat each T) -> Int { 36 | var result = 0 37 | for _ in repeat each pack { 38 | result += 1 39 | } 40 | return result 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Testing/Support/Additions/CollectionDifferenceAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension CollectionDifference.Change { 12 | /// The element that was changed. 13 | var element: ChangeElement { 14 | switch self { 15 | case let .insert(offset: _, element: result, associatedWith: _), let .remove(offset: _, element: result, associatedWith: _): 16 | return result 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Testing/Support/Additions/NumericAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Numeric { 12 | /// Form an English noun phrase describing this number of values. 13 | /// 14 | /// - Parameters: 15 | /// - noun: A singular noun describing the kind of values being counted, 16 | /// such as `"issue"` or `"test"`. 17 | /// 18 | /// - Returns: An English-language string composed of `self` and `noun`, with 19 | /// `noun` being pluralized if `self` does not equal `1`. For example, 20 | /// `5.counting("duck")` produces `"5 ducks"`. 21 | func counting(_ noun: String) -> String { 22 | if self == 1 { 23 | return "1 \(noun)" 24 | } 25 | return "\(self) \(noun)s" 26 | } 27 | } 28 | 29 | // MARK: - 30 | 31 | extension UInt8 { 32 | /// Whether or not this instance is an ASCII newline character (`\n` or `\r`). 33 | var isASCIINewline: Bool { 34 | self == UInt8(ascii: "\r") || self == UInt8(ascii: "\n") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Testing/Support/Additions/ResultAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Result { 12 | /// Handle this instance as if it were returned from a call to `#expect()`. 13 | /// 14 | /// - Warning: This function is used to implement the `#expect()` and 15 | /// `#require()` macros. Do not call it directly. 16 | @inlinable public func __expected() where Success == Void {} 17 | 18 | /// Handle this instance as if it were returned from a call to `#require()`. 19 | /// 20 | /// - Warning: This function is used to implement the `#expect()` and 21 | /// `#require()` macros. Do not call it directly. 22 | @inlinable public func __required() throws -> Success { 23 | try get() 24 | } 25 | } 26 | 27 | // MARK: - Optional success values 28 | 29 | extension Result { 30 | /// Handle this instance as if it were returned from a call to `#expect()`. 31 | /// 32 | /// - Warning: This function is used to implement the `#expect()` and 33 | /// `#require()` macros. Do not call it directly. 34 | @discardableResult @inlinable public func __expected() -> Success where Success == T? { 35 | try? get() 36 | } 37 | 38 | /// Handle this instance as if it were returned from a call to `#require()`. 39 | /// 40 | /// This overload of `__require()` assumes that the result cannot actually be 41 | /// `nil` on success. The optionality is part of our ABI contract for the 42 | /// `__check()` function family so that we can support uninhabited types and 43 | /// "soft" failures. 44 | /// 45 | /// If the value really is `nil` (e.g. we're dealing with `Never`), the 46 | /// testing library throws an error representing an issue of kind 47 | /// ``Issue/Kind-swift.enum/apiMisused``. 48 | /// 49 | /// - Warning: This function is used to implement the `#expect()` and 50 | /// `#require()` macros. Do not call it directly. 51 | @discardableResult public func __required() throws -> T where Success == T? { 52 | guard let result = try get() else { 53 | throw APIMisuseError(description: "Could not unwrap 'nil' value of type Optional<\(T.self)>. Consider using #expect() instead of #require() here.") 54 | } 55 | return result 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/Testing/Support/Additions/WinSDKAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | internal import _TestingInternals 12 | 13 | #if os(Windows) 14 | /// A bitmask that can be applied to an `HRESULT` or `NTSTATUS` value to get the 15 | /// underlying status code. 16 | /// 17 | /// The type of this value is `CInt` rather than `HRESULT` or `NTSTATUS` for 18 | /// consistency between 32-bit and 64-bit Windows. 19 | let STATUS_CODE_MASK = CInt(0xFFFF) 20 | 21 | /// The severity and facility bits to mask against a caught signal value before 22 | /// terminating a child process. 23 | /// 24 | /// The type of this value is `CInt` rather than `HRESULT` or `NTSTATUS` for 25 | /// consistency between 32-bit and 64-bit Windows. For more information about 26 | /// the `NTSTATUS` type including its bitwise layout, see 27 | /// [Microsoft's documentation](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781). 28 | let STATUS_SIGNAL_CAUGHT_BITS = { 29 | var result = CInt(0) 30 | 31 | // Set the severity and status bits. 32 | result |= CInt(STATUS_SEVERITY_ERROR) << 30 33 | result |= 1 << 29 // "Customer" bit 34 | 35 | // We only have 12 facility bits, but we'll pretend they spell out "s6", short 36 | // for "Swift 6" of course. 37 | // 38 | // We're camping on a specific "facility" code here that we don't think is 39 | // otherwise in use; if it conflicts with an exit test, we can add an 40 | // environment variable lookup so callers can override us. 41 | let FACILITY_SWIFT6 = ((CInt(UInt8(ascii: "s")) << 4) | 6) 42 | result |= FACILITY_SWIFT6 << 16 43 | 44 | #if DEBUG 45 | assert( 46 | (result & STATUS_CODE_MASK) == 0, 47 | "Constructed NTSTATUS mask \(String(result, radix: 16)) encroached on code bits. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new" 48 | ) 49 | #endif 50 | 51 | return result 52 | }() 53 | #endif 54 | -------------------------------------------------------------------------------- /Sources/Testing/Support/CartesianProduct.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A type describing the [Cartesian product](https://en.wikipedia.org/wiki/Cartesian_product) 12 | /// of two collections. 13 | /// 14 | /// A Cartesian product of two sets is the ordered set containing each pair of 15 | /// elements in those two sets. For example, if the inputs are `[1, 2, 3]` 16 | /// and `["a", "b", "c"]`, the Cartesian product is the set 17 | /// `[(1, "a"), (1, "b"), (1, "c"), (2, "a"), (2, "b"), ... (3, "c")]`. 18 | /// 19 | /// This type is not part of the public interface of the testing library. 20 | /// 21 | /// @Comment { 22 | /// - Bug: The testing library should support variadic generics. 23 | /// ([103416861](rdar://103416861)) 24 | /// } 25 | struct CartesianProduct: LazySequenceProtocol where C1: Collection, C2: Collection { 26 | fileprivate var collection1: C1 27 | fileprivate var collection2: C2 28 | 29 | // MARK: - Sequence 30 | 31 | typealias Element = (C1.Element, C2.Element) 32 | 33 | func makeIterator() -> some IteratorProtocol { 34 | collection1.lazy.flatMap { e1 in 35 | collection2.lazy.map { e2 in 36 | (e1, e2) 37 | } 38 | }.makeIterator() 39 | } 40 | 41 | var underestimatedCount: Int { 42 | let (result, overflowed) = collection1.underestimatedCount 43 | .multipliedReportingOverflow(by: collection2.underestimatedCount) 44 | if overflowed { 45 | return .max 46 | } 47 | return result 48 | } 49 | } 50 | 51 | extension CartesianProduct: Sendable where C1: Sendable, C2: Sendable {} 52 | 53 | /// Creates the Cartesian product of two collections. 54 | /// 55 | /// - Parameters: 56 | /// - collection1: The first collection in the Cartesian product. 57 | /// - collection2: The second collection in the Cartesian product. 58 | /// 59 | /// - Returns: A sequence of tuples of type `(C1.Element, C2.Element)` derived 60 | /// from the input collections. The sequence can be iterated multiple times. 61 | /// 62 | /// When iterating the resulting sequence, `collection1` is iterated only once, 63 | /// while `collection2` is iterated `collection1.count` times. 64 | /// 65 | /// For more information on Cartesian products, see ``CartesianProduct``. 66 | /// 67 | /// @Comment { 68 | /// - Bug: The testing library should support variadic generics. 69 | /// ([103416861](rdar://103416861)) 70 | /// } 71 | func cartesianProduct(_ collection1: C1, _ collection2: C2) -> CartesianProduct where C1: Collection, C2: Collection { 72 | CartesianProduct(collection1: collection1, collection2: collection2) 73 | } 74 | -------------------------------------------------------------------------------- /Sources/Testing/Support/Locked+Platform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023–2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | internal import _TestingInternals 12 | 13 | extension Never: Lockable { 14 | static func initializeLock(at lock: UnsafeMutablePointer) {} 15 | static func deinitializeLock(at lock: UnsafeMutablePointer) {} 16 | static func unsafelyAcquireLock(at lock: UnsafeMutablePointer) {} 17 | static func unsafelyRelinquishLock(at lock: UnsafeMutablePointer) {} 18 | } 19 | 20 | #if SWT_TARGET_OS_APPLE && !SWT_NO_OS_UNFAIR_LOCK 21 | extension os_unfair_lock_s: Lockable { 22 | static func initializeLock(at lock: UnsafeMutablePointer) { 23 | lock.initialize(to: .init()) 24 | } 25 | 26 | static func deinitializeLock(at lock: UnsafeMutablePointer) { 27 | // No deinitialization needed. 28 | } 29 | 30 | static func unsafelyAcquireLock(at lock: UnsafeMutablePointer) { 31 | os_unfair_lock_lock(lock) 32 | } 33 | 34 | static func unsafelyRelinquishLock(at lock: UnsafeMutablePointer) { 35 | os_unfair_lock_unlock(lock) 36 | } 37 | } 38 | #endif 39 | 40 | #if os(FreeBSD) || os(OpenBSD) 41 | typealias pthread_mutex_t = _TestingInternals.pthread_mutex_t? 42 | #endif 43 | 44 | #if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) || os(FreeBSD) || os(OpenBSD) 45 | extension pthread_mutex_t: Lockable { 46 | static func initializeLock(at lock: UnsafeMutablePointer) { 47 | _ = pthread_mutex_init(lock, nil) 48 | } 49 | 50 | static func deinitializeLock(at lock: UnsafeMutablePointer) { 51 | _ = pthread_mutex_destroy(lock) 52 | } 53 | 54 | static func unsafelyAcquireLock(at lock: UnsafeMutablePointer) { 55 | _ = pthread_mutex_lock(lock) 56 | } 57 | 58 | static func unsafelyRelinquishLock(at lock: UnsafeMutablePointer) { 59 | _ = pthread_mutex_unlock(lock) 60 | } 61 | } 62 | #endif 63 | 64 | #if os(Windows) 65 | extension SRWLOCK: Lockable { 66 | static func initializeLock(at lock: UnsafeMutablePointer) { 67 | InitializeSRWLock(lock) 68 | } 69 | 70 | static func deinitializeLock(at lock: UnsafeMutablePointer) { 71 | // No deinitialization needed. 72 | } 73 | 74 | static func unsafelyAcquireLock(at lock: UnsafeMutablePointer) { 75 | AcquireSRWLockExclusive(lock) 76 | } 77 | 78 | static func unsafelyRelinquishLock(at lock: UnsafeMutablePointer) { 79 | ReleaseSRWLockExclusive(lock) 80 | } 81 | } 82 | #endif 83 | 84 | #if SWT_TARGET_OS_APPLE && !SWT_NO_OS_UNFAIR_LOCK 85 | typealias DefaultLock = os_unfair_lock 86 | #elseif SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded)) || os(FreeBSD) || os(OpenBSD) 87 | typealias DefaultLock = pthread_mutex_t 88 | #elseif os(Windows) 89 | typealias DefaultLock = SRWLOCK 90 | #elseif os(WASI) 91 | // No locks on WASI without multithreaded runtime. 92 | typealias DefaultLock = Never 93 | #else 94 | #warning("Platform-specific implementation missing: locking unavailable") 95 | typealias DefaultLock = Never 96 | #endif 97 | -------------------------------------------------------------------------------- /Sources/Testing/Test+Discovery+Legacy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !SWT_NO_LEGACY_TEST_DISCOVERY 12 | @_spi(Experimental) @_spi(ForToolsIntegrationOnly) internal import _TestDiscovery 13 | 14 | /// A protocol describing a type that contains tests. 15 | /// 16 | /// - Warning: This protocol is used to implement the `@Test` macro. Do not use 17 | /// it directly. 18 | @_alwaysEmitConformanceMetadata 19 | public protocol __TestContentRecordContainer { 20 | /// The test content record associated with this container. 21 | /// 22 | /// - Warning: This property is used to implement the `@Test` macro. Do not 23 | /// use it directly. 24 | nonisolated static var __testContentRecord: __TestContentRecord { get } 25 | } 26 | 27 | extension DiscoverableAsTestContent where Self: ~Copyable { 28 | /// Get all test content of this type known to Swift and found in the current 29 | /// process using the legacy discovery mechanism. 30 | /// 31 | /// - Returns: A sequence of instances of ``TestContentRecord``. Only test 32 | /// content records matching this ``TestContent`` type's requirements are 33 | /// included in the sequence. 34 | static func allTypeMetadataBasedTestContentRecords() -> AnySequence> { 35 | return allTypeMetadataBasedTestContentRecords { type, buffer in 36 | guard let type = type as? any __TestContentRecordContainer.Type else { 37 | return false 38 | } 39 | 40 | buffer.withMemoryRebound(to: __TestContentRecord.self) { buffer in 41 | buffer.baseAddress!.initialize(to: type.__testContentRecord) 42 | } 43 | return true 44 | } 45 | } 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/AssociatingBugs.md: -------------------------------------------------------------------------------- 1 | # Associating bugs with tests 2 | 3 | 12 | 13 | Associate bugs uncovered or verified by tests. 14 | 15 | ## Overview 16 | 17 | Tests allow developers to prove that the code they write is working as expected. 18 | If code isn't working correctly, bug trackers are often used to track the work 19 | necessary to fix the underlying problem. It's often useful to associate 20 | specific bugs with tests that reproduce them or verify they are fixed. 21 | 22 | - Note: "Bugs" as described in this document may also be referred to as 23 | "issues." To avoid confusion with the ``Issue`` type in the testing library, 24 | this document consistently refers to them as "bugs." 25 | 26 | ## Associate a bug with a test 27 | 28 | To associate a bug with a test, use one of these functions: 29 | - ``Trait/bug(_:_:)`` 30 | - ``Trait/bug(_:id:_:)-10yf5`` 31 | - ``Trait/bug(_:id:_:)-3vtpl`` 32 | 33 | The first argument to these functions is a URL representing the bug in its 34 | bug-tracking system: 35 | 36 | ```swift 37 | @Test("Food truck engine works", .bug("https://www.example.com/issues/12345")) 38 | func engineWorks() async { 39 | var foodTruck = FoodTruck() 40 | await foodTruck.engine.start() 41 | #expect(foodTruck.engine.isRunning) 42 | } 43 | ``` 44 | 45 | You can also specify the bug's _unique identifier_ in its bug-tracking system in 46 | addition to, or instead of, its URL: 47 | 48 | ```swift 49 | @Test( 50 | "Food truck engine works", 51 | .bug(id: "12345"), 52 | .bug("https://www.example.com/issues/67890", id: 67890) 53 | ) 54 | func engineWorks() async { 55 | var foodTruck = FoodTruck() 56 | await foodTruck.engine.start() 57 | #expect(foodTruck.engine.isRunning) 58 | } 59 | ``` 60 | 61 | A bug's URL is passed as a string and must be parseable according to 62 | [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt). A bug's unique identifier 63 | can be passed as an integer or as a string. For more information on the formats 64 | recognized by the testing library, see . 65 | 66 | ## Add titles to associated bugs 67 | 68 | A bug's unique identifier or URL may be insufficient to uniquely and clearly 69 | identify a bug associated with a test. Bug trackers universally provide a 70 | "title" field for bugs that is not visible to the testing library. To add a 71 | bug's title to a test, include it after the bug's unique identifier or URL: 72 | 73 | ```swift 74 | @Test( 75 | "Food truck has napkins", 76 | .bug(id: "12345", "Forgot to buy more napkins") 77 | ) 78 | func hasNapkins() async { 79 | ... 80 | } 81 | ``` 82 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/Attachments.md: -------------------------------------------------------------------------------- 1 | # Attachments 2 | 3 | 12 | 13 | Attach values to tests to help diagnose issues and gather feedback. 14 | 15 | ## Overview 16 | 17 | Attach values such as strings and files to tests. Implement the ``Attachable`` 18 | protocol to create your own attachable types. 19 | 20 | ## Topics 21 | 22 | ### Attaching values to tests 23 | 24 | - ``Attachment`` 25 | - ``Attachable`` 26 | - ``AttachableWrapper`` 27 | 28 | 33 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/BugIdentifiers.md: -------------------------------------------------------------------------------- 1 | # Interpreting bug identifiers 2 | 3 | 12 | 13 | Examine how the testing library interprets bug identifiers provided by developers. 14 | 15 | ## Overview 16 | 17 | The testing library supports two distinct ways to identify a bug: 18 | 19 | 1. A URL linking to more information about the bug; and 20 | 2. A unique identifier in the bug's associated bug-tracking system. 21 | 22 | - Note: "Bugs" as described in this document may also be referred to as 23 | "issues." To avoid confusion with the ``Issue`` type in the testing library, 24 | this document consistently refers to them as "bugs." 25 | 26 | A bug may have both an associated URL _and_ an associated unique identifier. It 27 | must have at least one or the other in order for the testing library to be able 28 | to interpret it correctly. 29 | 30 | To create an instance of ``Bug`` with a URL, use the ``Trait/bug(_:_:)`` trait. 31 | At compile time, the testing library will validate that the given string can be 32 | parsed as a URL according to [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt). 33 | 34 | To create an instance of ``Bug`` with a bug's unique identifier, use the 35 | ``Trait/bug(_:id:_:)-10yf5`` trait. The testing library does not require that a 36 | bug's unique identifier match any particular format, but will interpret unique 37 | identifiers starting with `"FB"` as referring to bugs tracked with the 38 | [Apple Feedback Assistant](https://feedbackassistant.apple.com). For 39 | convenience, you can also directly pass an integer as a bug's identifier using 40 | ``Trait/bug(_:id:_:)-3vtpl``. 41 | 42 | ### Examples 43 | 44 | | Trait Function | Inferred Bug-Tracking System | 45 | |-|-| 46 | | `.bug(id: 12345)` | None | 47 | | `.bug(id: "12345")` | None | 48 | | `.bug("https://www.example.com?id=12345", id: "12345")` | None | 49 | | `.bug("https://github.com/swiftlang/swift/pull/12345")` | [GitHub Issues for the Swift project](https://github.com/swiftlang/swift/issues) | 50 | | `.bug("https://bugs.webkit.org/show_bug.cgi?id=12345")` | [WebKit Bugzilla](https://bugs.webkit.org/) | 51 | | `.bug(id: "FB12345")` | Apple Feedback Assistant | 52 | 55 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/DefiningTests.md: -------------------------------------------------------------------------------- 1 | # Defining test functions 2 | 3 | 12 | 13 | Define a test function to validate that code is working correctly. 14 | 15 | ## Overview 16 | 17 | Defining a test function for a Swift package or project is straightforward. 18 | 19 | ### Import the testing library 20 | 21 | To import the testing library, add the following to the Swift source file that 22 | contains the test: 23 | 24 | ```swift 25 | import Testing 26 | ``` 27 | 28 | - Note: Only import the testing library into a test target. Importing the 29 | testing library into an application, library, or binary target isn't 30 | supported or recommended. Test functions aren't stripped from binaries when 31 | building for release, so logic and fixtures of a test may be visible to anyone 32 | who inspects a build product that contains a test function. 33 | 34 | ### Declare a test function 35 | 36 | To declare a test function, write a Swift function declaration that doesn't 37 | take any arguments, then prefix its name with the `@Test` attribute: 38 | 39 | ```swift 40 | @Test func foodTruckExists() { 41 | // Test logic goes here. 42 | } 43 | ``` 44 | 45 | This test function can be present at file scope or within a type. A type 46 | containing test functions is automatically a _test suite_ and can be optionally 47 | annotated with the `@Suite` attribute. For more information about suites, see 48 | . 49 | 50 | Note that, while this function is a valid test function, it doesn't actually 51 | perform any action or test any code. To check for expected values and outcomes 52 | in test functions, add [expectations](doc:Expectations) to the test function. 53 | 54 | ### Customize a test's name 55 | 56 | To customize a test function's name as presented in an IDE or at the command 57 | line, supply a string literal as an argument to the `@Test` attribute: 58 | 59 | ```swift 60 | @Test("Food truck exists") func foodTruckExists() { ... } 61 | ``` 62 | 63 | To further customize the appearance and behavior of a test function, use 64 | [traits](doc:Traits) such as ``Trait/tags(_:)``. 65 | 66 | ### Write concurrent or throwing tests 67 | 68 | As with other Swift functions, test functions can be marked `async` and `throws` 69 | to annotate them as concurrent or throwing, respectively. If a test is only safe 70 | to run in the main actor's execution context (that is, from the main thread of 71 | the process), it can be annotated `@MainActor`: 72 | 73 | ```swift 74 | @Test @MainActor func foodTruckExists() async throws { ... } 75 | ``` 76 | 77 | ### Limit the availability of a test 78 | 79 | If a test function can only run on newer versions of an operating system or of 80 | the Swift language, use the `@available` attribute when declaring it. Use the 81 | `message` argument of the `@available` attribute to specify a message to log if 82 | a test is unable to run due to limited availability: 83 | 84 | ```swift 85 | @available(macOS 11.0, *) 86 | @available(swift, introduced: 8.0, message: "Requires Swift 8.0 features to run") 87 | @Test func foodTruckExists() { ... } 88 | ``` 89 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/Documentation.md: -------------------------------------------------------------------------------- 1 | # ``Testing`` 2 | 3 | 4 | 5 | 14 | 15 | Create and run tests for your Swift packages and Xcode projects. 16 | 17 | ## Overview 18 | 19 | With Swift Testing you leverage powerful and expressive capabilities of 20 | the Swift programming language to develop tests with more confidence and less 21 | code. The library integrates seamlessly with Swift Package Manager testing 22 | workflow, supports flexible test organization, customizable metadata, and 23 | scalable test execution. 24 | 25 | - Define test functions almost anywhere with a single attribute. 26 | - Group related tests into hierarchies using Swift's type system. 27 | - Integrate seamlessly with Swift concurrency. 28 | - Parameterize test functions across wide ranges of inputs. 29 | - Enable tests dynamically depending 30 | on runtime conditions. 31 | - Parallelize tests in-process. 32 | - Categorize tests using tags. 33 | - Associate bugs directly with the tests that verify their fixes or reproduce 34 | their problems. 35 | 36 | #### Related videos 37 | 38 | @Links(visualStyle: compactGrid) { 39 | - 40 | - 41 | } 42 | 43 | ## Topics 44 | 45 | ### Essentials 46 | 47 | - 48 | - 49 | - 50 | - ``Test(_:_:)`` 51 | - ``Test`` 52 | - ``Suite(_:_:)`` 53 | 54 | ### Test parameterization 55 | 56 | - 57 | - ``Test(_:_:arguments:)-8kn7a`` 58 | - ``Test(_:_:arguments:_:)`` 59 | - ``Test(_:_:arguments:)-3rzok`` 60 | - ``CustomTestArgumentEncodable`` 61 | 62 | - ``Test/Case`` 63 | 64 | ### Behavior validation 65 | 66 | - 67 | - 68 | 69 | ### Test customization 70 | 71 | - 72 | 73 | ### Data collection 74 | 75 | - 76 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | Testing 7 | CFBundleDisplayName 8 | Testing 9 | CFBundleIdentifier 10 | org.swift.testing 11 | CFBundleDevelopmentRegion 12 | en 13 | CFBundleIconFile 14 | DocumentationIcon 15 | CFBundleIconName 16 | DocumentationIcon 17 | CFBundlePackageType 18 | DOCS 19 | CFBundleShortVersionString 20 | 0.1.0 21 | CFBundleVersion 22 | 0.1.0 23 | CDAppleDefaultAvailability 24 | 25 | Testing 26 | 27 | 28 | name 29 | Xcode 30 | version 31 | 16.0 32 | 33 | 34 | name 35 | Swift 36 | version 37 | 6.0 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/LimitingExecutionTime.md: -------------------------------------------------------------------------------- 1 | # Limiting the running time of tests 2 | 3 | 12 | 13 | Set limits on how long a test can run for until it fails. 14 | 15 | ## Overview 16 | 17 | Some tests may naturally run slowly: they may require significant system 18 | resources to complete, may rely on downloaded data from a server, or may 19 | otherwise be dependent on external factors. 20 | 21 | If a test may hang indefinitely or may consume too many system resources to 22 | complete effectively, consider setting a time limit for it so that it's marked 23 | as failing if it runs for an excessive amount of time. Use the 24 | ``Trait/timeLimit(_:)-4kzjp`` trait as an upper bound: 25 | 26 | ```swift 27 | @Test(.timeLimit(.minutes(60)) 28 | func serve100CustomersInOneHour() async { 29 | for _ in 0 ..< 100 { 30 | let customer = await Customer.next() 31 | await customer.order() 32 | ... 33 | } 34 | } 35 | ``` 36 | 37 | If the above test function takes longer than an 38 | hour (60 x 60 seconds) to execute, the task in which it's running is 39 | [cancelled](https://developer.apple.com/documentation/swift/task/cancel()) 40 | and the test fails with an issue of kind 41 | ``Issue/Kind-swift.enum/timeLimitExceeded(timeLimitComponents:)``. 42 | 43 | - Note: If multiple time limit traits apply to a test, the shortest time limit 44 | is used. 45 | 46 | The testing library may adjust the specified time limit for performance reasons 47 | or to ensure tests have enough time to run. In particular, a granularity of (by 48 | default) one minute is applied to tests. The testing library can also be 49 | configured with a maximum time limit per test that overrides any applied time 50 | limit traits. 51 | 52 | ### Time limits applied to test suites 53 | 54 | When a time limit is applied to a test suite, it's recursively applied to all 55 | test functions and child test suites within that suite. 56 | 57 | ### Time limits applied to parameterized tests 58 | 59 | When a time limit is applied to a parameterized test function, it's applied to 60 | each invocation _separately_ so that if only some arguments cause failures, then 61 | successful arguments aren't incorrectly marked as failing too. 62 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/Parallelization.md: -------------------------------------------------------------------------------- 1 | # Running tests serially or in parallel 2 | 3 | 12 | 13 | Control whether tests run serially or in parallel. 14 | 15 | ## Overview 16 | 17 | By default, tests run in parallel with respect to each other. Parallelization is 18 | accomplished by the testing library using task groups, and tests generally all 19 | run in the same process. The number of tests that run concurrently is controlled 20 | by the Swift runtime. 21 | 22 | ## Disabling parallelization 23 | 24 | Parallelization can be disabled on a per-function or per-suite basis using the 25 | ``Trait/serialized`` trait: 26 | 27 | ```swift 28 | @Test(.serialized, arguments: Food.allCases) func prepare(food: Food) { 29 | // This function will be invoked serially, once per food, because it has the 30 | // .serialized trait. 31 | } 32 | 33 | @Suite(.serialized) struct FoodTruckTests { 34 | @Test(arguments: Condiment.allCases) func refill(condiment: Condiment) { 35 | // This function will be invoked serially, once per condiment, because the 36 | // containing suite has the .serialized trait. 37 | } 38 | 39 | @Test func startEngine() async throws { 40 | // This function will not run while refill(condiment:) is running. One test 41 | // must end before the other will start. 42 | } 43 | } 44 | ``` 45 | 46 | When added to a parameterized test function, this trait causes that test to run 47 | its cases serially instead of in parallel. When applied to a non-parameterized 48 | test function, this trait has no effect. When applied to a test suite, this 49 | trait causes that suite to run its contained test functions and sub-suites 50 | serially instead of in parallel. 51 | 52 | This trait is recursively applied: if it is applied to a suite, any 53 | parameterized tests or test suites contained in that suite are also serialized 54 | (as are any tests contained in those suites, and so on.) 55 | 56 | This trait doesn't affect the execution of a test relative to its peers or to 57 | unrelated tests. This trait has no effect if test parallelization is globally 58 | disabled (by, for example, passing `--no-parallel` to the `swift test` command.) 59 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/Traits.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 | 12 | 13 | Annotate test functions and suites, and customize their behavior. 14 | 15 | ## Overview 16 | 17 | Pass built-in traits to test functions or suite types to comment, categorize, 18 | classify, and modify the runtime behavior of test suites and test functions. 19 | Implement the ``TestTrait``, and ``SuiteTrait`` protocols to create your own 20 | types that customize the behavior of your tests. 21 | 22 | ## Topics 23 | 24 | ### Customizing runtime behaviors 25 | 26 | - 27 | - 28 | - ``Trait/enabled(if:_:sourceLocation:)`` 29 | - ``Trait/enabled(_:sourceLocation:_:)`` 30 | - ``Trait/disabled(_:sourceLocation:)`` 31 | - ``Trait/disabled(if:_:sourceLocation:)`` 32 | - ``Trait/disabled(_:sourceLocation:_:)`` 33 | - ``Trait/timeLimit(_:)-4kzjp`` 34 | 35 | ### Running tests serially or in parallel 36 | 37 | - 38 | - ``Trait/serialized`` 39 | 40 | ### Annotating tests 41 | 42 | - 43 | - 44 | - 45 | - 46 | - ``Tag()`` 47 | - ``Trait/bug(_:_:)`` 48 | - ``Trait/bug(_:id:_:)-10yf5`` 49 | - ``Trait/bug(_:id:_:)-3vtpl`` 50 | 51 | 57 | 58 | ### Creating custom traits 59 | 60 | - ``Trait`` 61 | - ``TestTrait`` 62 | - ``SuiteTrait`` 63 | - ``TestScoping`` 64 | 65 | ### Supporting types 66 | 67 | - ``Bug`` 68 | - ``Comment`` 69 | - ``ConditionTrait`` 70 | - ``ParallelizationTrait`` 71 | - ``Tag`` 72 | - ``Tag/List`` 73 | - ``TimeLimitTrait`` 74 | 75 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.docc/Traits/Trait.md: -------------------------------------------------------------------------------- 1 | # ``Trait`` 2 | 3 | 12 | 13 | ## Topics 14 | 15 | ### Enabling and disabling tests 16 | 17 | - ``Trait/enabled(if:_:sourceLocation:)`` 18 | - ``Trait/enabled(_:sourceLocation:_:)`` 19 | - ``Trait/disabled(_:sourceLocation:)`` 20 | - ``Trait/disabled(if:_:sourceLocation:)`` 21 | - ``Trait/disabled(_:sourceLocation:_:)`` 22 | 23 | ### Controlling how tests are run 24 | 25 | - ``Trait/timeLimit(_:)-4kzjp`` 26 | - ``Trait/serialized`` 27 | 28 | ### Categorizing tests and adding information 29 | 30 | - ``Trait/tags(_:)`` 31 | - ``Trait/comments`` 32 | 33 | ### Associating bugs 34 | 35 | - ``Trait/bug(_:_:)`` 36 | - ``Trait/bug(_:id:_:)-10yf5`` 37 | - ``Trait/bug(_:id:_:)-3vtpl`` 38 | 39 | ### Running code before and after a test or suite 40 | 41 | - ``TestScoping`` 42 | - ``Trait/scopeProvider(for:testCase:)-cjmg`` 43 | - ``Trait/TestScopeProvider`` 44 | - ``Trait/prepare(for:)-3s3zo`` 45 | -------------------------------------------------------------------------------- /Sources/Testing/Testing.swiftcrossimport/Foundation.swiftoverlay: -------------------------------------------------------------------------------- 1 | version: 1 2 | modules: 3 | - name: _Testing_Foundation 4 | -------------------------------------------------------------------------------- /Sources/Testing/Traits/Comment+Macro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Trait where Self == Comment { 12 | /// Construct a comment related to a test from a single-line source code 13 | /// comment near it. 14 | /// 15 | /// - Parameters: 16 | /// - comment: The comment about the test. 17 | /// 18 | /// - Returns: An instance of ``Comment`` containing the specified comment. 19 | /// 20 | /// - Warning: This function is used to implement the `@Test` macro. Do not 21 | /// call it directly. 22 | public static func __line(_ comment: String) -> Self { 23 | Self(rawValue: comment, kind: .line) 24 | } 25 | 26 | /// Construct a comment related to a test from a source code block comment 27 | /// near it. 28 | /// 29 | /// - Parameters: 30 | /// - comment: The comment about the test. 31 | /// 32 | /// - Returns: An instance of ``Comment`` containing the specified comment. 33 | /// 34 | /// - Warning: This function is used to implement the `@Test` macro. Do not 35 | /// call it directly. 36 | public static func __block(_ comment: String) -> Self { 37 | Self(rawValue: comment, kind: .block) 38 | } 39 | 40 | /// Construct a comment related to a test from a single-line 41 | /// [Markup](https://github.com/swiftlang/swift/blob/main/docs/DocumentationComments.md) 42 | /// comment near it. 43 | /// 44 | /// - Parameters: 45 | /// - comment: The comment about the test. 46 | /// 47 | /// - Returns: An instance of ``Comment`` containing the specified comment. 48 | /// 49 | /// - Warning: This function is used to implement the `@Test` macro. Do not 50 | /// call it directly. 51 | public static func __documentationLine(_ comment: String) -> Self { 52 | Self(rawValue: comment, kind: .documentationLine) 53 | } 54 | 55 | /// Construct a comment related to a test from a 56 | /// [Markup](https://github.com/swiftlang/swift/blob/main/docs/DocumentationComments.md) 57 | /// block comment near it. 58 | /// 59 | /// - Parameters: 60 | /// - comment: The comment about the test. 61 | /// 62 | /// - Returns: An instance of ``Comment`` containing the specified comment. 63 | /// 64 | /// - Warning: This function is used to implement the `@Test` macro. Do not 65 | /// call it directly. 66 | public static func __documentationBlock(_ comment: String) -> Self { 67 | Self(rawValue: comment, kind: .documentationBlock) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/Testing/Traits/HiddenTrait.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A type that indicates that a test should be hidden from automatic discovery 12 | /// and only run if explicitly requested. 13 | /// 14 | /// This is different from disabled or skipped, and is primarily meant to be 15 | /// used on tests defined in this project's own test suite, so that example 16 | /// tests can be defined using the `@Test` attribute but not run by default 17 | /// except by the specific unit test(s) which have requested to run them. 18 | /// 19 | /// This type is not part of the public interface of the testing library. 20 | struct HiddenTrait: TestTrait, SuiteTrait { 21 | var isRecursive: Bool { 22 | true 23 | } 24 | } 25 | 26 | extension Trait where Self == HiddenTrait { 27 | static var hidden: Self { 28 | HiddenTrait() 29 | } 30 | } 31 | 32 | extension Test { 33 | /// Whether this test is hidden, whether directly or via a trait inherited 34 | /// from a parent test. 35 | var isHidden: Bool { 36 | traits.contains { $0 is HiddenTrait } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Testing/Traits/ParallelizationTrait.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A type that defines whether the testing library runs this test serially 12 | /// or in parallel. 13 | /// 14 | /// When you add this trait to a parameterized test function, that test runs its 15 | /// cases serially instead of in parallel. This trait has no effect when you 16 | /// apply it to a non-parameterized test function. 17 | /// 18 | /// When you add this trait to a test suite, that suite runs its 19 | /// contained test functions (including their cases, when parameterized) and 20 | /// sub-suites serially instead of in parallel. If the sub-suites have children, 21 | /// they also run serially. 22 | /// 23 | /// This trait does not affect the execution of a test relative to its peers or 24 | /// to unrelated tests. This trait has no effect if you disable test 25 | /// parallelization globally (for example, by passing `--no-parallel` to the 26 | /// `swift test` command.) 27 | /// 28 | /// To add this trait to a test, use ``Trait/serialized``. 29 | public struct ParallelizationTrait: TestTrait, SuiteTrait {} 30 | 31 | // MARK: - TestScoping 32 | 33 | extension ParallelizationTrait: TestScoping { 34 | public func provideScope(for test: Test, testCase: Test.Case?, performing function: @Sendable () async throws -> Void) async throws { 35 | guard var configuration = Configuration.current else { 36 | throw SystemError(description: "There is no current Configuration when attempting to provide scope for test '\(test.name)'. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new") 37 | } 38 | 39 | configuration.isParallelizationEnabled = false 40 | try await Configuration.withCurrent(configuration, perform: function) 41 | } 42 | } 43 | 44 | // MARK: - 45 | 46 | extension Trait where Self == ParallelizationTrait { 47 | /// A trait that serializes the test to which it is applied. 48 | /// 49 | /// ## See Also 50 | /// 51 | /// - ``ParallelizationTrait`` 52 | public static var serialized: Self { 53 | Self() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Testing/Traits/Tags/Tag+Macro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Tag { 12 | /// Create a tag representing a static member of ``Tag`` such as ``Tag/red``. 13 | /// 14 | /// - Parameters: 15 | /// - type: The type in which the tag is declared. This type must either be 16 | /// ``Tag`` or a type nested within it. 17 | /// - name: The name of the declared variable, not including its parent 18 | /// type, module name, or a leading period. 19 | /// 20 | /// - Returns: An instance of ``Tag``. 21 | /// 22 | /// - Warning: This function is used to implement the `@Tag` macro. Do not 23 | /// call it directly. 24 | public static func __fromStaticMember(of type: Any.Type, _ name: _const String) -> Self { 25 | // Split up the supplied type name into its fully-qualified components. We 26 | // will use this string array to reconstruct the fully-qualified name of the 27 | // described static member. 28 | var fullyQualifiedMemberNameComponents = TypeInfo(describing: type).fullyQualifiedNameComponents 29 | 30 | // Strip off the "Testing" and "Tag" components of the fully-qualified name 31 | // since they're redundant. Macro expansion will have already checked that 32 | // the type is nested inside `Tag`. 33 | fullyQualifiedMemberNameComponents = Array(fullyQualifiedMemberNameComponents.dropFirst(2)) 34 | 35 | // Add the specified tag name to the fully-qualified name and reconstruct 36 | // its string representation. 37 | fullyQualifiedMemberNameComponents += CollectionOfOne(name) 38 | let fullyQualifiedMemberName = fullyQualifiedMemberNameComponents.joined(separator: ".") 39 | 40 | return Self(kind: .staticMember(fullyQualifiedMemberName)) 41 | } 42 | } 43 | 44 | /// Declare a tag that can be applied to a test function or test suite. 45 | /// 46 | /// Use this tag with members of the ``Tag`` type declared in an extension to 47 | /// mark them as usable with tests. For more information on declaring tags, see 48 | /// . 49 | @attached(accessor) @attached(peer) public macro Tag() = #externalMacro(module: "TestingMacros", type: "TagMacro") 50 | -------------------------------------------------------------------------------- /Sources/Testing/Traits/Tags/Tag.List.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | extension Tag { 12 | /// A type representing one or more tags applied to a test. 13 | /// 14 | /// To add this trait to a test, use the ``Trait/tags(_:)`` function. 15 | public struct List { 16 | /// The list of tags contained in this instance. 17 | /// 18 | /// This preserves the list of the tags exactly as they were originally 19 | /// specified, in their original order, including duplicate entries. To 20 | /// access the complete, unique set of tags applied to a ``Test``, see 21 | /// ``Test/tags``. 22 | public var tags: [Tag] 23 | 24 | /// Initialize an instance of this type with the specified tags. 25 | /// 26 | /// - Parameters: 27 | /// - tags: The tags to include in the new instance. See ``tags``. 28 | init(tags: some Sequence) { 29 | self.tags = Array(tags) 30 | } 31 | } 32 | } 33 | 34 | // MARK: - Equatable, Hashable, Comparable 35 | 36 | extension Tag.List: Equatable, Hashable {} 37 | 38 | // MARK: - CustomStringConvertible 39 | 40 | extension Tag.List: CustomStringConvertible { 41 | public var description: String { 42 | tags.lazy 43 | .map(String.init(describing:)) 44 | .joined(separator: ", ") 45 | } 46 | } 47 | 48 | // MARK: - Trait, TestTrait, SuiteTrait 49 | 50 | extension Tag.List: TestTrait, SuiteTrait { 51 | public var isRecursive: Bool { 52 | true 53 | } 54 | } 55 | 56 | extension Trait where Self == Tag.List { 57 | /// Construct a list of tags to apply to a test. 58 | /// 59 | /// - Parameters: 60 | /// - tags: The list of tags to apply to the test. 61 | /// 62 | /// - Returns: An instance of ``Tag/List`` containing the specified tags. 63 | public static func tags(_ tags: Tag...) -> Self { 64 | Self(tags: tags) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/TestingMacros/SourceLocationMacro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | public import SwiftSyntax 12 | public import SwiftSyntaxMacros 13 | 14 | /// A type describing the expansion of the `#_sourceLocation` macro. 15 | /// 16 | /// This type is used to implement the `#_sourceLocation` attribute macro. 17 | /// Do not use it directly. 18 | public struct SourceLocationMacro: ExpressionMacro, Sendable { 19 | public static func expansion( 20 | of macro: some FreestandingMacroExpansionSyntax, 21 | in context: some MacroExpansionContext 22 | ) throws -> ExprSyntax { 23 | createSourceLocationExpr(of: macro, context: context) 24 | } 25 | 26 | public static var formatMode: FormatMode { 27 | .disabled 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/DeclGroupSyntaxAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | 13 | extension DeclGroupSyntax { 14 | /// The type declared or extended by this instance. 15 | var type: TypeSyntax { 16 | if let namedDecl = asProtocol((any NamedDeclSyntax).self) { 17 | return TypeSyntax(IdentifierTypeSyntax(name: namedDecl.name)) 18 | } else if let extensionDecl = `as`(ExtensionDeclSyntax.self) { 19 | return extensionDecl.extendedType 20 | } 21 | fatalError("Unexpected DeclGroupSyntax type \(Swift.type(of: self)). Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new") 22 | } 23 | 24 | /// Check whether or not this instance includes a given type name in its 25 | /// inheritance clause. 26 | /// 27 | /// - Parameters: 28 | /// - typeName: The name of the possible parent type. 29 | /// - moduleName: The name of the module the specified type is declared in. 30 | /// 31 | /// - Returns: Whether or not the represented type inherits from the specified 32 | /// type. If the represented type inherits _indirectly_ from that type, or 33 | /// inherits via another declaration group (such as an `extension`), this 34 | /// function is unable to detect it and will return `false.` 35 | func inherits(fromTypeNamed typeName: String, inModuleNamed moduleName: String) -> Bool { 36 | if let inherited = inheritanceClause?.inheritedTypes { 37 | return inherited.lazy 38 | .map(\.type) 39 | .contains { $0.isNamed(typeName, inModuleNamed: moduleName) } 40 | } 41 | return false 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/EditorPlaceholderExprSyntaxAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | 13 | extension EditorPlaceholderExprSyntax { 14 | /// Initialize an instance of this type with the given placeholder string and 15 | /// optional type. 16 | /// 17 | /// - Parameters: 18 | /// - placeholder: The placeholder string, not including surrounding angle 19 | /// brackets or pound characters. 20 | /// - type: The type which this placeholder have, if any. When non-`nil`, 21 | /// the expression will use typed placeholder syntax. 22 | init(_ placeholder: String, type: String? = nil) { 23 | let placeholderContent = if let type { 24 | // These use typed placeholder syntax, which allows the compiler to 25 | // type-check the expression successfully. The resulting code still does 26 | // not compile due to the placeholder, but it makes the diagnostic more 27 | // clear. See 28 | // https://developer.apple.com/documentation/swift-playgrounds/specifying-editable-regions-in-a-playground-page#Mark-Editable-Areas-with-Placeholder-Tokens 29 | if placeholder == type { 30 | // When the placeholder string is exactly the same as the type string, 31 | // use the shorter typed placeholder format. 32 | "T##\(placeholder)" 33 | } else { 34 | "T##\(placeholder)##\(type)" 35 | } 36 | } else { 37 | placeholder 38 | } 39 | 40 | // Manually concatenate the string to avoid it being interpreted as a 41 | // placeholder when editing this file. 42 | self.init(placeholder: .identifier("<#\(placeholderContent)#" + ">")) 43 | } 44 | 45 | /// Initialize an instance of this type with the given type, using that as the 46 | /// placeholder string. 47 | /// 48 | /// - Parameters: 49 | /// - type: The type to use both as the placeholder text and as the 50 | /// expression's type. 51 | init(type: String) { 52 | self.init(type, type: type) 53 | } 54 | } 55 | 56 | extension TypeSyntax { 57 | /// Construct a type syntax node containing a placeholder string. 58 | /// 59 | /// - Parameters: 60 | /// - placeholder: The placeholder string, not including surrounding angle 61 | /// brackets or pound characters. 62 | /// 63 | /// - Returns: A new `TypeSyntax` instance representing a placeholder. 64 | static func placeholder(_ placeholder: String) -> Self { 65 | return Self(IdentifierTypeSyntax(name: .identifier("<#\(placeholder)#" + ">"))) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/IntegerLiteralExprSyntaxAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | 13 | extension IntegerLiteralExprSyntax { 14 | init(_ value: some BinaryInteger, radix: IntegerLiteralExprSyntax.Radix = .decimal) { 15 | let stringValue = "\(radix.literalPrefix)\(String(value, radix: radix.size))" 16 | self.init(literal: .integerLiteral(stringValue)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/TokenSyntaxAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftParser 12 | import SwiftSyntax 13 | 14 | extension TokenSyntax { 15 | /// A tuple containing the text of this instance with enclosing backticks 16 | /// removed and whether or not they were removed. 17 | private var _textWithoutBackticks: (String, backticksRemoved: Bool) { 18 | let text = text 19 | if case .identifier = tokenKind, text.first == "`" && text.last == "`" && text.count >= 2 { 20 | return (String(text.dropFirst().dropLast()), true) 21 | } 22 | 23 | return (text, false) 24 | } 25 | 26 | /// The text of this instance with all backticks removed. 27 | /// 28 | /// - Bug: This property works around the presence of backticks in `text.` 29 | /// ([swift-syntax-#1936](https://github.com/swiftlang/swift-syntax/issues/1936)) 30 | var textWithoutBackticks: String { 31 | _textWithoutBackticks.0 32 | } 33 | 34 | /// The raw identifier, not including enclosing backticks, represented by this 35 | /// token, or `nil` if it does not represent one. 36 | var rawIdentifier: String? { 37 | let (textWithoutBackticks, backticksRemoved) = _textWithoutBackticks 38 | if backticksRemoved, !textWithoutBackticks.isValidSwiftIdentifier(for: .memberAccess) { 39 | return textWithoutBackticks 40 | } 41 | 42 | // TODO: remove this mock path once the toolchain fully supports raw IDs. 43 | let mockPrefix = "__raw__$" 44 | if backticksRemoved, textWithoutBackticks.starts(with: mockPrefix) { 45 | return String(textWithoutBackticks.dropFirst(mockPrefix.count)) 46 | } 47 | 48 | return nil 49 | } 50 | } 51 | 52 | /// The `static` keyword, if `typeName` is not `nil`. 53 | /// 54 | /// - Parameters: 55 | /// - typeName: The name of the type containing the macro being expanded. 56 | /// 57 | /// - Returns: A token representing the `static` keyword, or one representing 58 | /// nothing if `typeName` is `nil`. 59 | func staticKeyword(for typeName: TypeSyntax?) -> TokenSyntax { 60 | (typeName != nil) ? .keyword(.static) : .unknown("") 61 | } 62 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/TriviaPieceAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | 13 | extension TriviaPiece { 14 | /// The number of newline characters represented by this trivia piece. 15 | /// 16 | /// If this trivia piece contains text (such as a comment), the value of this 17 | /// property is `nil`. 18 | var newlineCount: Int? { 19 | switch self { 20 | case let .carriageReturns(count), 21 | let .carriageReturnLineFeeds(count), let .formfeeds(count), 22 | let .newlines(count), let .verticalTabs(count): 23 | return count 24 | default: 25 | return nil 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/TypeSyntaxProtocolAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | 13 | extension TypeSyntaxProtocol { 14 | /// Whether or not this type is an optional type (`T?`, `Optional`, etc.) 15 | var isOptional: Bool { 16 | if `is`(OptionalTypeSyntax.self) { 17 | return true 18 | } else if `is`(ImplicitlyUnwrappedOptionalTypeSyntax.self) { 19 | return true 20 | } 21 | return isNamed("Optional", inModuleNamed: "Swift") 22 | } 23 | 24 | /// Whether or not this type is equivalent to `Void`. 25 | var isVoid: Bool { 26 | if let tuple = `as`(TupleTypeSyntax.self) { 27 | return tuple.elements.isEmpty 28 | } 29 | return isNamed("Void", inModuleNamed: "Swift") 30 | } 31 | 32 | /// Whether or not this type is `some T` or a type derived from such a type. 33 | var isSome: Bool { 34 | tokens(viewMode: .fixedUp).lazy 35 | .map(\.tokenKind) 36 | .contains(.keyword(.some)) 37 | } 38 | 39 | /// Check whether or not this type is named with the specified name and 40 | /// module. 41 | /// 42 | /// The type name is checked both without and with the specified module name 43 | /// as a prefix to allow for either syntax. When comparing the type name, 44 | /// generic type parameters are ignored. 45 | /// 46 | /// - Parameters: 47 | /// - name: The `"."`-separated type name to compare against. 48 | /// - moduleName: The module the specified type is declared in. 49 | /// 50 | /// - Returns: Whether or not this type has the given name. 51 | func isNamed(_ name: String, inModuleNamed moduleName: String) -> Bool { 52 | // Form a string of the fixed-up tokens representing the type name, 53 | // omitting any generic type parameters. 54 | let nameWithoutGenericParameters = tokens(viewMode: .fixedUp) 55 | .prefix { $0.tokenKind != .leftAngle } 56 | .filter { $0.tokenKind != .period } 57 | .filter { $0.tokenKind != .leftParen && $0.tokenKind != .rightParen } 58 | .map(\.textWithoutBackticks) 59 | .joined(separator: ".") 60 | 61 | return nameWithoutGenericParameters == name || nameWithoutGenericParameters == "\(moduleName).\(name)" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/Additions/VersionTupleSyntaxAdditions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | 13 | extension VersionTupleSyntax { 14 | /// A type describing the major, minor, and patch components of a version 15 | /// tuple. 16 | struct ComponentValues: Comparable, CustomStringConvertible { 17 | /// The major component. 18 | var major: UInt64 19 | 20 | /// The minor component. 21 | var minor: UInt64? 22 | 23 | /// The patch component. 24 | var patch: UInt64? 25 | 26 | static func <(lhs: Self, rhs: Self) -> Bool { 27 | if lhs.major < rhs.major { 28 | return true 29 | } else if lhs.major == rhs.major { 30 | if lhs.minor ?? 0 < rhs.minor ?? 0 { 31 | return true 32 | } else if lhs.minor ?? 0 == rhs.minor ?? 0 { 33 | return lhs.patch ?? 0 < rhs.patch ?? 0 34 | } 35 | } 36 | return false 37 | } 38 | 39 | var description: String { 40 | if let minor { 41 | if let patch { 42 | return "\(major).\(minor).\(patch)" 43 | } 44 | return "\(major).\(minor)" 45 | } 46 | return "\(major)" 47 | } 48 | } 49 | 50 | /// The numeric values of the major, minor, and patch components. 51 | var componentValues: ComponentValues { 52 | let components = components 53 | let startIndex = components.startIndex 54 | 55 | let major = UInt64(major.text) ?? 0 56 | let minor: UInt64? = if components.count > 0 { 57 | UInt64(components[startIndex].number.text) 58 | } else { 59 | nil 60 | } 61 | let patch: UInt64? = if components.count > 1 { 62 | UInt64(components[components.index(after: startIndex)].number.text) 63 | } else { 64 | nil 65 | } 66 | 67 | return ComponentValues(major: major, minor: minor, patch: patch) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/TestingMacros/Support/SourceLocationGeneration.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import SwiftSyntax 12 | import SwiftSyntaxBuilder 13 | import SwiftSyntaxMacros 14 | 15 | /// Get an expression initializing an instance of ``SourceLocation`` from an 16 | /// arbitrary expression value. 17 | /// 18 | /// - Parameters: 19 | /// - expr: The expression value for which an instance of ``SourceLocation`` 20 | /// is needed. 21 | /// - context: The macro context in which the expression is being parsed. 22 | /// 23 | /// - Returns: An expression value that initializes an instance of 24 | /// ``SourceLocation`` for `expr`. 25 | func createSourceLocationExpr(of expr: some SyntaxProtocol, context: some MacroExpansionContext) -> ExprSyntax { 26 | if expr.isProtocol((any FreestandingMacroExpansionSyntax).self) { 27 | // Freestanding macro expressions can just use __here() 28 | // directly and do not need to talk to the macro context to get source 29 | // location info. 30 | return "Testing.SourceLocation.__here()" 31 | } 32 | 33 | // Get the equivalent source location in both `#fileID` and `#filePath` modes. 34 | guard let fileIDSourceLoc: AbstractSourceLocation = context.location(of: expr), 35 | let filePathSourceLoc: AbstractSourceLocation = context.location(of: expr, at: .afterLeadingTrivia, filePathMode: .filePath) 36 | else { 37 | return "Testing.SourceLocation.__here()" 38 | } 39 | 40 | return "Testing.SourceLocation(fileID: \(fileIDSourceLoc.file), filePath: \(filePathSourceLoc.file), line: \(fileIDSourceLoc.line), column: \(fileIDSourceLoc.column))" 41 | } 42 | -------------------------------------------------------------------------------- /Sources/TestingMacros/TestingMacrosMain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if SWT_NO_LIBRARY_MACRO_PLUGINS 12 | import SwiftCompilerPlugin 13 | import SwiftSyntaxMacros 14 | 15 | /// The main entry point for the compiler plugin executable that implements 16 | /// macros declared in the `Testing` module. 17 | @main 18 | struct TestingMacrosMain: CompilerPlugin { 19 | var providingMacros: [any Macro.Type] { 20 | [ 21 | SuiteDeclarationMacro.self, 22 | TestDeclarationMacro.self, 23 | ExpectMacro.self, 24 | RequireMacro.self, 25 | AmbiguousRequireMacro.self, 26 | NonOptionalRequireMacro.self, 27 | RequireThrowsMacro.self, 28 | RequireThrowsNeverMacro.self, 29 | ExitTestExpectMacro.self, 30 | ExitTestRequireMacro.self, 31 | TagMacro.self, 32 | SourceLocationMacro.self, 33 | PragmaMacro.self, 34 | ] 35 | } 36 | } 37 | #endif 38 | -------------------------------------------------------------------------------- /Sources/_TestDiscovery/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2023–2025 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | add_library(_TestDiscovery STATIC 10 | Additions/WinSDKAdditions.swift 11 | DiscoverableAsTestContent.swift 12 | SectionBounds.swift 13 | TestContentKind.swift 14 | TestContentRecord.swift) 15 | 16 | target_link_libraries(_TestDiscovery PRIVATE 17 | _TestingInternals) 18 | 19 | target_compile_options(_TestDiscovery PRIVATE 20 | -enable-library-evolution 21 | -emit-module-interface -emit-module-interface-path $/_TestDiscovery.swiftinterface) 22 | set(CMAKE_STATIC_LIBRARY_PREFIX_Swift "lib") 23 | 24 | _swift_testing_install_target(_TestDiscovery) 25 | 26 | if(NOT BUILD_SHARED_LIBS) 27 | # When building a static library, install the internal library archive 28 | # alongside the main library. In shared library builds, the internal library 29 | # is linked into the main library and does not need to be installed separately. 30 | install(TARGETS _TestDiscovery 31 | ARCHIVE DESTINATION "${SwiftTesting_INSTALL_LIBDIR}") 32 | endif() 33 | -------------------------------------------------------------------------------- /Sources/_TestDiscovery/DiscoverableAsTestContent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023–2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A protocol describing a type that can be represented by a test content 12 | /// record, stored in the test content section of a Swift binary at compile 13 | /// time, and dynamically discovered at runtime. 14 | /// 15 | /// Types conforming to this protocol must also conform to [`Sendable`](https://developer.apple.com/documentation/swift/sendable) 16 | /// because they may be discovered within any isolation context or within 17 | /// multiple isolation contexts running concurrently. 18 | @_spi(Experimental) @_spi(ForToolsIntegrationOnly) 19 | public protocol DiscoverableAsTestContent: Sendable, ~Copyable { 20 | /// The value of the `kind` field in test content records associated with this 21 | /// type. 22 | /// 23 | /// The value of this property is reserved for each test content type. See 24 | /// `ABI/TestContent.md` for a list of values and corresponding types. 25 | static var testContentKind: TestContentKind { get } 26 | 27 | /// The type of the `context` field in test content records associated with 28 | /// this type. 29 | /// 30 | /// By default, this type equals `UInt`. This type can be set to some other 31 | /// type with the same stride and alignment as `UInt`. Using a type with 32 | /// different stride or alignment will result in a failure when trying to 33 | /// discover test content records associated with this type. 34 | associatedtype TestContentContext: BitwiseCopyable = UInt 35 | 36 | /// A type of "hint" passed to ``allTestContentRecords()`` to help the testing 37 | /// library find the correct result. 38 | /// 39 | /// By default, this type equals `Never`, indicating that this type of test 40 | /// content does not support hinting during discovery. 41 | associatedtype TestContentAccessorHint = Never 42 | 43 | #if !SWT_NO_LEGACY_TEST_DISCOVERY 44 | /// A string present in the names of types containing test content records 45 | /// associated with this type. 46 | @available(swift, deprecated: 100000.0, message: "Do not adopt this functionality in new code. It will be removed in a future release.") 47 | static var _testContentTypeNameHint: String { get } 48 | #endif 49 | } 50 | 51 | #if !SWT_NO_LEGACY_TEST_DISCOVERY 52 | extension DiscoverableAsTestContent where Self: ~Copyable { 53 | public static var _testContentTypeNameHint: String { 54 | "__🟡$" 55 | } 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | set(CMAKE_CXX_SCAN_FOR_MODULES 0) 10 | 11 | include(LibraryVersion) 12 | include(TargetTriple) 13 | add_library(_TestingInternals STATIC 14 | Discovery.cpp 15 | Versions.cpp 16 | WillThrow.cpp) 17 | target_include_directories(_TestingInternals PUBLIC 18 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 19 | if("${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "MSVC" OR 20 | "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 21 | target_compile_options(_TestingInternals PRIVATE 22 | /EHa-c) 23 | elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") 24 | target_compile_options(_TestingInternals PRIVATE 25 | -fno-exceptions -fPIC) 26 | else() 27 | target_compile_options(_TestingInternals PRIVATE 28 | -fno-exceptions) 29 | endif() 30 | 31 | if(NOT BUILD_SHARED_LIBS) 32 | # When building a static library, install the internal library archive 33 | # alongside the main library. In shared library builds, the internal library 34 | # is linked into the main library and does not need to be installed separately. 35 | install(TARGETS _TestingInternals 36 | ARCHIVE DESTINATION "${SwiftTesting_INSTALL_LIBDIR}") 37 | endif() 38 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/Versions.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #include "Versions.h" 12 | 13 | const char *swt_getTestingLibraryVersion(void) { 14 | #if defined(SWT_TESTING_LIBRARY_VERSION) 15 | return SWT_TESTING_LIBRARY_VERSION; 16 | #else 17 | #warning SWT_TESTING_LIBRARY_VERSION not defined: testing library version is unavailable 18 | return nullptr; 19 | #endif 20 | } 21 | 22 | const char *swt_getTargetTriple(void) { 23 | #if defined(SWT_TARGET_TRIPLE) 24 | return SWT_TARGET_TRIPLE; 25 | #else 26 | // If we're here, we're presumably building as a package. Swift Package 27 | // Manager does not provide a way to get the target triple from within the 28 | // package manifest. SEE: swift-package-manager-#7929 29 | // 30 | // clang has __is_target_*() intrinsics, but we don't want to play a game of 31 | // Twenty Questions in order to synthesize the triple (and still potentially 32 | // get it wrong.) SEE: rdar://134933385 33 | return nullptr; 34 | #endif 35 | } 36 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/WillThrow.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #include "WillThrow.h" 12 | 13 | #include 14 | 15 | /// The Swift runtime error-handling hook. 16 | SWT_IMPORT_FROM_STDLIB std::atomic _swift_willThrow; 17 | 18 | SWTWillThrowHandler swt_setWillThrowHandler(SWTWillThrowHandler handler) { 19 | return _swift_willThrow.exchange(handler, std::memory_order_acq_rel); 20 | } 21 | 22 | /// The Swift runtime typed-error-handling hook. 23 | SWT_IMPORT_FROM_STDLIB __attribute__((weak_import)) std::atomic _swift_willThrowTypedImpl; 24 | 25 | SWTWillThrowTypedHandler swt_setWillThrowTypedHandler(SWTWillThrowTypedHandler handler) { 26 | #if defined(__APPLE__) 27 | if (&_swift_willThrowTypedImpl == nullptr) { 28 | return nullptr; 29 | } 30 | #endif 31 | return _swift_willThrowTypedImpl.exchange(handler, std::memory_order_acq_rel); 32 | } 33 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/include/Defines.h: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !defined(SWT_DEFINES_H) 12 | #define SWT_DEFINES_H 13 | 14 | #define SWT_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") 15 | #define SWT_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") 16 | 17 | #if defined(__cplusplus) 18 | #define SWT_EXTERN extern "C" 19 | #else 20 | #define SWT_EXTERN extern 21 | #endif 22 | 23 | #if defined(_WIN32) 24 | #define SWT_IMPORT_FROM_STDLIB SWT_EXTERN __declspec(dllimport) 25 | #else 26 | #define SWT_IMPORT_FROM_STDLIB SWT_EXTERN 27 | #endif 28 | 29 | /// An attribute that marks some value as being `Sendable` in Swift. 30 | #define SWT_SENDABLE __attribute__((swift_attr("@Sendable"))) 31 | 32 | /// An attribute that renames a C symbol in Swift. 33 | #define SWT_SWIFT_NAME(name) __attribute__((swift_name(#name))) 34 | 35 | #endif // SWT_DEFINES_H 36 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/include/Demangle.h: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !defined(SWT_DEMANGLE_H) 12 | #define SWT_DEMANGLE_H 13 | 14 | #include "Defines.h" 15 | #include "Includes.h" 16 | 17 | SWT_ASSUME_NONNULL_BEGIN 18 | 19 | /// Demangle a Swift symbol name. 20 | /// 21 | /// - Parameters: 22 | /// - mangledName: A pointer to the mangled symbol name to demangle. 23 | /// - mangledNameLength: The length of `mangledName` in bytes, not including 24 | /// any trailing null byte. 25 | /// - outputBuffer: Unused by the testing library. Pass `nullptr`. 26 | /// - outputBufferSize: Unused by the testing library. Pass `nullptr`. 27 | /// - flags: Unused by the testing library. Pass `0`. 28 | /// 29 | /// - Returns: The demangled form of `mangledName`, or `nullptr` if demangling 30 | /// failed. The caller is responsible for freeing this string with `free()` 31 | /// when done. 32 | SWT_IMPORT_FROM_STDLIB char *_Nullable swift_demangle( 33 | const char *mangledName, 34 | size_t mangledNameLength, 35 | char *_Nullable outputBuffer, 36 | size_t *_Nullable outputBufferSize, 37 | uint32_t flags 38 | ); 39 | 40 | #if defined(_WIN32) 41 | /// Configure the environment to allow calling into the Debug Help library. 42 | /// 43 | /// - Parameters: 44 | /// - body: A function to invoke. A process handle valid for use with Debug 45 | /// Help functions is passed in, or `nullptr` if the Debug Help library 46 | /// could not be initialized. 47 | /// - context: An arbitrary pointer to pass to `body`. 48 | /// 49 | /// On Windows, the Debug Help library (DbgHelp.lib) is not thread-safe. All 50 | /// calls into it from the Swift runtime and stdlib should route through this 51 | /// function. 52 | SWT_IMPORT_FROM_STDLIB void _swift_win32_withDbgHelpLibrary( 53 | void (* body)(HANDLE _Nullable hProcess, void *_Null_unspecified context), 54 | void *_Null_unspecified context 55 | ); 56 | #endif 57 | 58 | SWT_ASSUME_NONNULL_END 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/include/Discovery.h: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023–2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !defined(SWT_DISCOVERY_H) 12 | #define SWT_DISCOVERY_H 13 | 14 | #include "Defines.h" 15 | #include "Includes.h" 16 | 17 | SWT_ASSUME_NONNULL_BEGIN 18 | 19 | #if defined(__ELF__) && defined(__swift__) 20 | #pragma mark - ELF image enumeration 21 | 22 | /// A function exported by the Swift runtime that enumerates all metadata 23 | /// sections loaded into the current process. 24 | /// 25 | /// This function is needed on ELF-based platforms because they do not preserve 26 | /// section information that we can discover at runtime. 27 | SWT_IMPORT_FROM_STDLIB void swift_enumerateAllMetadataSections( 28 | bool (* body)(const void *sections, void *context), 29 | void *context 30 | ); 31 | #endif 32 | 33 | #pragma mark - Legacy test discovery 34 | 35 | /// The size, in bytes, of a Swift type metadata record. 36 | SWT_EXTERN const size_t SWTTypeMetadataRecordByteCount; 37 | 38 | /// Get the type represented by the type metadata record at the given address if 39 | /// its name contains the given string. 40 | /// 41 | /// - Parameters: 42 | /// - recordAddress: The address of the Swift type metadata record. 43 | /// - nameSubstring: A string which the names of matching types contain. 44 | /// 45 | /// - Returns: A Swift metatype (as `const void *`) or `nullptr` if it wasn't a 46 | /// usable type metadata record or its name did not contain `nameSubstring`. 47 | SWT_EXTERN const void *_Nullable swt_getTypeFromTypeMetadataRecord( 48 | const void *recordAddress, 49 | const char *nameSubstring 50 | ) SWT_SWIFT_NAME(swt_getType(fromTypeMetadataRecord:ifNameContains:)); 51 | 52 | SWT_ASSUME_NONNULL_END 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/include/TestSupport.h: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !defined(SWT_TESTSUPPORT_H) 12 | #define SWT_TESTSUPPORT_H 13 | 14 | /// This header includes symbols that are used by the testing library's own test 15 | /// targets. These symbols are not used by other clients of the testing library. 16 | 17 | #include "Defines.h" 18 | #include "Includes.h" 19 | 20 | SWT_ASSUME_NONNULL_BEGIN 21 | 22 | /// A type used by the testing library's own tests to validate how C 23 | /// enumerations are presented in test output. 24 | enum __attribute__((enum_extensibility(open))) SWTTestEnumeration { 25 | SWTTestEnumerationA, SWTTestEnumerationB 26 | }; 27 | 28 | static inline bool swt_pointersNotEqual2(const char *a, const char *b) { 29 | return a != b; 30 | } 31 | 32 | static inline bool swt_pointersNotEqual3(const char *a, const char *b, const char *c) { 33 | return a != b && b != c; 34 | } 35 | 36 | static inline bool swt_pointersNotEqual4(const char *a, const char *b, const char *c, const char *d) { 37 | return a != b && b != c && c != d; 38 | } 39 | 40 | SWT_ASSUME_NONNULL_END 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/include/Versions.h: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !defined(SWT_VERSIONS_H) 12 | #define SWT_VERSIONS_H 13 | 14 | #include "Defines.h" 15 | #include "Includes.h" 16 | 17 | SWT_ASSUME_NONNULL_BEGIN 18 | 19 | /// Get the human-readable version of the testing library. 20 | /// 21 | /// - Returns: A human-readable string describing the version of the testing 22 | /// library, or `nullptr` if no version information is available. This 23 | /// string's value and format may vary between platforms, releases, or any 24 | /// other conditions. Do not attempt to parse it. 25 | SWT_EXTERN const char *_Nullable swt_getTestingLibraryVersion(void); 26 | 27 | /// Get the LLVM target triple used to build the testing library. 28 | /// 29 | /// - Returns: A string containing the LLVM target triple used to build the 30 | /// testing library, or `nullptr` if that information is not available. 31 | SWT_EXTERN const char *_Nullable swt_getTargetTriple(void); 32 | 33 | #if defined(__wasi__) 34 | /// Get the version of the C standard library and runtime used by WASI, if 35 | /// available. 36 | /// 37 | /// This function is provided because `WASI_SDK_VERSION` may or may not be 38 | /// defined and may or may not be a complex macro. 39 | /// 40 | /// For more information about the `WASI_SDK_VERSION` macro, see 41 | /// [wasi-libc-#490](https://github.com/WebAssembly/wasi-libc/issues/490). 42 | static const char *_Nullable swt_getWASIVersion(void) { 43 | #if defined(WASI_SDK_VERSION) 44 | return WASI_SDK_VERSION; 45 | #else 46 | return 0; 47 | #endif 48 | } 49 | #endif 50 | 51 | SWT_ASSUME_NONNULL_END 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Sources/_TestingInternals/include/module.modulemap: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | module _TestingInternals { 12 | umbrella "." 13 | export * 14 | } 15 | -------------------------------------------------------------------------------- /Tests/TestingMacrosTests/PragmaMacroTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import Testing 12 | @testable import TestingMacros 13 | 14 | import SwiftDiagnostics 15 | import SwiftParser 16 | import SwiftSyntax 17 | import SwiftSyntaxBuilder 18 | 19 | @Suite("PragmaMacro Tests") 20 | struct PragmaMacroTests { 21 | @Test func findSemantics() throws { 22 | let node = """ 23 | @Testing.__testing(semantics: "abc123") 24 | @__testing(semantics: "def456") 25 | @UnrelatedModule.__testing(semantics: "xyz789") 26 | let x = 0 27 | """ as DeclSyntax 28 | let nodeWithAttributes = try #require(node.asProtocol((any WithAttributesSyntax).self)) 29 | let semantics = semantics(of: nodeWithAttributes) 30 | #expect(semantics == ["abc123", "def456"]) 31 | } 32 | 33 | @Test func warningGenerated() throws { 34 | let sourceCode = """ 35 | @__testing(warning: "abc123") 36 | let x = 0 37 | """ 38 | 39 | let (_, diagnostics) = try parse(sourceCode) 40 | #expect(diagnostics.count == 1) 41 | #expect(diagnostics[0].message == "abc123") 42 | #expect(diagnostics[0].diagMessage.severity == .warning) 43 | #expect(diagnostics[0].node.is(VariableDeclSyntax.self)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Tests/TestingMacrosTests/TagMacroTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import Testing 12 | @testable import TestingMacros 13 | 14 | import SwiftDiagnostics 15 | import SwiftParser 16 | import SwiftSyntax 17 | import SwiftSyntaxBuilder 18 | import SwiftSyntaxMacros 19 | 20 | @Suite("TagMacro Tests") 21 | struct TagMacroTests { 22 | @Test("@Tag macro", 23 | arguments: [ 24 | ("extension Tag { @Tag static var x: Tag }", "Tag"), 25 | ("extension Tag { @Tag static var x: Self }", "Tag"), 26 | ("extension Testing.Tag { @Tag static var x: Testing.Tag }", "Testing.Tag"), 27 | ("extension Tag.A.B { @Tag static var x: Tag }", "Tag.A.B"), 28 | ("extension Testing.Tag.A.B { @Tag static var x: Tag }", "Testing.Tag.A.B"), 29 | ("extension Tag { struct S { @Tag static var x: Tag } }", "Tag.S"), 30 | ("extension Testing.Tag { enum E { @Tag static var x: Tag } }", "Testing.Tag.E"), 31 | ] 32 | ) 33 | func tagMacro(input: String, typeName: String) throws { 34 | let (output, diagnostics) = try parse(input) 35 | #expect(diagnostics.count == 0) 36 | #expect(output.contains("__fromStaticMember(of: \(typeName).self,")) 37 | #expect(output.contains(#""x")"#)) 38 | } 39 | 40 | @Test("Error diagnostics emitted on API misuse", 41 | arguments: [ 42 | "@Tag struct S {}": 43 | "Attribute 'Tag' cannot be applied to a structure", 44 | "@Tag var x: Tag": 45 | "Attribute 'Tag' cannot be applied to a global variable", 46 | "@Tag nonisolated var x: Tag": 47 | "Attribute 'Tag' cannot be applied to a global variable", 48 | "@Tag static var x: Tag": 49 | "Attribute 'Tag' cannot be applied to a global variable", 50 | 51 | "extension Tag { @Tag var x: Tag }": 52 | "Attribute 'Tag' cannot be applied to an instance property", 53 | "extension Tag { @Tag nonisolated var x: Tag }": 54 | "Attribute 'Tag' cannot be applied to an instance property", 55 | "struct S { @Tag static var x: Tag }": 56 | "Attribute 'Tag' cannot be applied to a property except in an extension to 'Tag'", 57 | "extension Tag { @Tag static var x: String }": 58 | "Attribute 'Tag' cannot be applied to a property of type 'String'", 59 | "extension Tag.A.B { @Tag static var x: Self }": 60 | "Attribute 'Tag' cannot be applied to a property of type 'Tag.A.B'", 61 | ] 62 | ) 63 | func apiMisuseErrors(input: String, expectedMessage: String) throws { 64 | let (_, diagnostics) = try parse(input) 65 | 66 | #expect(diagnostics.count > 0) 67 | for diagnostic in diagnostics { 68 | #expect(diagnostic.diagMessage.severity == .error) 69 | #expect(diagnostic.message == expectedMessage) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Tests/TestingMacrosTests/TestSupport/FixIts.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | /// A type representing a fix-it which is expected to be included in a 12 | /// diagnostic from a macro. 13 | struct ExpectedFixIt { 14 | /// A description of what this expected fix-it performs. 15 | var message: String 16 | 17 | /// An enumeration describing a change to be performed by a fix-it. 18 | /// 19 | /// - Note: Not all changes in the real `FixIt` type are currently supported 20 | /// and included in this list. 21 | enum Change { 22 | /// Replace `oldSourceCode` by `newSourceCode`. 23 | case replace(oldSourceCode: String, newSourceCode: String) 24 | } 25 | 26 | /// The changes that would be performed when this expected fix-it is applied. 27 | var changes: [Change] = [] 28 | } 29 | -------------------------------------------------------------------------------- /Tests/TestingMacrosTests/TestSupport/Parse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import TestingMacros 12 | 13 | import SwiftBasicFormat 14 | import SwiftDiagnostics 15 | import SwiftOperators 16 | import SwiftParser 17 | import SwiftSyntax 18 | import SwiftSyntaxBuilder 19 | import SwiftSyntaxMacros 20 | import SwiftSyntaxMacroExpansion 21 | 22 | fileprivate let allMacros: [String: any (Macro & Sendable).Type] = [ 23 | "expect": ExpectMacro.self, 24 | "require": RequireMacro.self, 25 | "requireAmbiguous": AmbiguousRequireMacro.self, // different name needed only for unit testing 26 | "requireNonOptional": NonOptionalRequireMacro.self, // different name needed only for unit testing 27 | "requireThrows": RequireThrowsMacro.self, // different name needed only for unit testing 28 | "requireThrowsNever": RequireThrowsNeverMacro.self, // different name needed only for unit testing 29 | "expectExitTest": ExitTestRequireMacro.self, // different name needed only for unit testing 30 | "requireExitTest": ExitTestRequireMacro.self, // different name needed only for unit testing 31 | "Suite": SuiteDeclarationMacro.self, 32 | "Test": TestDeclarationMacro.self, 33 | "Tag": TagMacro.self, 34 | "__testing": PragmaMacro.self, 35 | ] 36 | 37 | func parse(_ sourceCode: String, activeMacros activeMacroNames: [String] = [], removeWhitespace: Bool = false) throws -> (sourceCode: String, diagnostics: [Diagnostic]) { 38 | let activeMacros: [String: any Macro.Type] 39 | if activeMacroNames.isEmpty { 40 | activeMacros = allMacros 41 | } else { 42 | activeMacros = allMacros.filter { activeMacroNames.contains($0.key) } 43 | } 44 | let operatorTable = OperatorTable.standardOperators 45 | let originalSyntax = try operatorTable.foldAll(Parser.parse(source: sourceCode)) 46 | let context = BasicMacroExpansionContext(lexicalContext: [], expansionDiscriminator: "", sourceFiles: [:]) 47 | let syntax = try operatorTable.foldAll( 48 | originalSyntax.expand(macros: activeMacros) { syntax in 49 | BasicMacroExpansionContext(sharingWith: context, lexicalContext: syntax.allMacroLexicalContexts()) 50 | } 51 | ) 52 | var sourceCode = String(describing: syntax.formatted().trimmed) 53 | if removeWhitespace { 54 | sourceCode = sourceCode.filter { !$0.isWhitespace } 55 | } 56 | return (sourceCode, context.diagnostics) 57 | } 58 | -------------------------------------------------------------------------------- /Tests/TestingTests/ConfigurationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | @Suite("Configuration Tests") 14 | struct ConfigurationTests { 15 | @Test 16 | @available(*, deprecated, message: "Testing a deprecated SPI.") 17 | func deliverExpectationCheckedEventsProperty() throws { 18 | var configuration = Configuration() 19 | #expect(!configuration.deliverExpectationCheckedEvents) 20 | #expect(!configuration.eventHandlingOptions.isExpectationCheckedEventEnabled) 21 | 22 | configuration.deliverExpectationCheckedEvents = true 23 | #expect(configuration.eventHandlingOptions.isExpectationCheckedEventEnabled) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/TestingTests/CustomTestStringConvertibleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | private import _TestingInternals 14 | 15 | @Suite("CustomTestStringConvertible Tests") 16 | struct CustomTestStringConvertibleTests { 17 | @Test func optionals() { 18 | #expect(String(describingForTest: 0 as Int?) == "0") 19 | #expect(String(describingForTest: "abc" as String?) == #""abc""#) 20 | #expect(String(describingForTest: nil as Int?) == "nil") 21 | #expect(String(describingForTest: nil as String?) == "nil") 22 | #expect(String(describingForTest: nil as _OptionalNilComparisonType) == "nil") 23 | } 24 | 25 | @Test func strings() { 26 | #expect(String(describingForTest: "abc") == #""abc""#) 27 | #expect(String(describingForTest: "abc"[...] as Substring) == #""abc""#) 28 | } 29 | 30 | @Test func ranges() { 31 | #expect(String(describingForTest: 0 ... 1) == "0 ... 1") 32 | #expect(String(describingForTest: 0...) == "0...") 33 | #expect(String(describingForTest: ...1) == "...1") 34 | #expect(String(describingForTest: ..<1) == "..<1") 35 | #expect(String(describingForTest: 0 ..< 1) == "0 ..< 1") 36 | } 37 | 38 | @Test func types() { 39 | #expect(String(describingForTest: Self.self) == "CustomTestStringConvertibleTests") 40 | #expect(String(describingForTest: NonCopyableType.self) == "NonCopyableType") 41 | } 42 | 43 | @Test func enumerations() { 44 | #expect(String(describingForTest: SWTTestEnumeration.A) == "SWTTestEnumeration(rawValue: \(SWTTestEnumeration.A.rawValue))") 45 | #expect(String(describingForTest: SomeEnum.elitSedDoEiusmod) == ".elitSedDoEiusmod") 46 | } 47 | 48 | @Test func otherProtocols() { 49 | #expect(String(describingForTest: CustomStringConvertibleType()) == "Lorem ipsum") 50 | #expect(String(describingForTest: TextOutputStreamableType()) == "Dolor sit amet") 51 | #expect(String(describingForTest: CustomDebugStringConvertibleType()) == "Consectetur adipiscing") 52 | } 53 | } 54 | 55 | // MARK: - Fixtures 56 | 57 | private struct NonCopyableType: ~Copyable {} 58 | 59 | private struct CustomStringConvertibleType: CustomStringConvertible { 60 | var description: String { 61 | "Lorem ipsum" 62 | } 63 | } 64 | 65 | private struct TextOutputStreamableType: TextOutputStreamable { 66 | func write(to target: inout some TextOutputStream) { 67 | target.write("Dolor sit amet") 68 | } 69 | } 70 | 71 | private struct CustomDebugStringConvertibleType: CustomDebugStringConvertible { 72 | var debugDescription: String { 73 | "Consectetur adipiscing" 74 | } 75 | } 76 | 77 | private enum SomeEnum { 78 | case elitSedDoEiusmod 79 | } 80 | -------------------------------------------------------------------------------- /Tests/TestingTests/DumpTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(ForToolsIntegrationOnly) import Testing 12 | private import _TestingInternals 13 | 14 | // NOTE: The tests in this file are here to exercise Plan.dump(), but they are 15 | // not intended to actually test that the output is in a particular format since 16 | // the format is meant to be human-readable and is subject to change over time. 17 | 18 | @Suite("Runner.Plan-dumping Tests") 19 | struct DumpTests { 20 | @Test("Dumping a Runner.Plan", .enabled(if: testsWithSignificantIOAreEnabled), arguments: [true, false]) 21 | func dumpPlan(verbose: Bool) async throws { 22 | let plan = await Runner.Plan(selecting: DumpedTests.self) 23 | 24 | var buffer = "" 25 | plan.dump(to: &buffer, verbose: verbose) 26 | print(buffer) 27 | } 28 | } 29 | 30 | // MARK: - Fixtures 31 | 32 | @Suite(.hidden) 33 | struct DumpedTests { 34 | @Test(.hidden) 35 | func noop() {} 36 | 37 | @Test(.hidden, arguments: 0 ..< 10) 38 | func noop(i: Int) {} 39 | 40 | @Test(.hidden, arguments: 0 ..< 10) 41 | func noop(j: Int) {} 42 | 43 | @Test(.hidden, arguments: 0 ..< 10) 44 | func noop(i: Int64) {} 45 | } 46 | -------------------------------------------------------------------------------- /Tests/TestingTests/EntryPointTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing 12 | private import _TestingInternals 13 | 14 | @Suite("Entry point tests") 15 | struct EntryPointTests { 16 | @Test("Entry point filter with filtering of hidden tests enabled") 17 | func hiddenTests() async throws { 18 | var arguments = __CommandLineArguments_v0() 19 | arguments.filter = ["_someHiddenTest"] 20 | arguments.includeHiddenTests = true 21 | arguments.eventStreamVersion = 0 22 | arguments.verbosity = .min 23 | 24 | await confirmation("Test event started", expectedCount: 1) { testMatched in 25 | _ = await entryPoint(passing: arguments) { event, context in 26 | if case .testStarted = event.kind { 27 | testMatched() 28 | } 29 | } 30 | } 31 | } 32 | 33 | @Test("Entry point with WarningIssues feature enabled exits with success if all issues have severity < .error") 34 | func warningIssues() async throws { 35 | var arguments = __CommandLineArguments_v0() 36 | arguments.filter = ["_recordWarningIssue"] 37 | arguments.includeHiddenTests = true 38 | arguments.eventStreamVersion = 0 39 | arguments.verbosity = .min 40 | 41 | let exitCode = await confirmation("Test matched", expectedCount: 1) { testMatched in 42 | await entryPoint(passing: arguments) { event, context in 43 | if case .testStarted = event.kind { 44 | testMatched() 45 | } else if case let .issueRecorded(issue) = event.kind { 46 | Issue.record("Unexpected issue \(issue) was recorded.") 47 | } 48 | } 49 | } 50 | #expect(exitCode == EXIT_SUCCESS) 51 | } 52 | 53 | @Test("Entry point with WarningIssues feature enabled propagates warning issues and exits with success if all issues have severity < .error") 54 | func warningIssuesEnabled() async throws { 55 | var arguments = __CommandLineArguments_v0() 56 | arguments.filter = ["_recordWarningIssue"] 57 | arguments.includeHiddenTests = true 58 | arguments.eventStreamVersion = 0 59 | arguments.isWarningIssueRecordedEventEnabled = true 60 | arguments.verbosity = .min 61 | 62 | let exitCode = await confirmation("Warning issue recorded", expectedCount: 1) { issueRecorded in 63 | await entryPoint(passing: arguments) { event, context in 64 | if case let .issueRecorded(issue) = event.kind { 65 | #expect(issue.severity == .warning) 66 | issueRecorded() 67 | } 68 | } 69 | } 70 | #expect(exitCode == EXIT_SUCCESS) 71 | } 72 | } 73 | 74 | // MARK: - Fixtures 75 | 76 | @Test(.hidden) private func _someHiddenTest() {} 77 | 78 | @Test(.hidden) private func _recordWarningIssue() { 79 | // Intentionally _only_ record issues with warning (or lower) severity. 80 | Issue(kind: .unconditional, severity: .warning, comments: [], sourceContext: .init()).record() 81 | } 82 | -------------------------------------------------------------------------------- /Tests/TestingTests/EventTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !SWT_NO_SNAPSHOT_TYPES 12 | @testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing 13 | private import _TestingInternals 14 | 15 | @Suite("Event Tests") 16 | struct EventTests { 17 | #if canImport(Foundation) 18 | @Test("Event's and Event.Kinds's Codable Conformances", 19 | arguments: [ 20 | Event.Kind.expectationChecked( 21 | Expectation( 22 | evaluatedExpression: __Expression("SyntaxNode"), 23 | mismatchedErrorDescription: "Mismatched Error Description", 24 | differenceDescription: "Difference Description", 25 | isPassing: false, 26 | isRequired: true, 27 | sourceLocation: SourceLocation(fileID: "M/f.swift", filePath: "/f.swift", line: 1, column: 1) 28 | ) 29 | ), 30 | Event.Kind.testSkipped( 31 | SkipInfo( 32 | comment: "Comment", 33 | sourceContext: SourceContext( 34 | backtrace: Backtrace.current(), 35 | sourceLocation: SourceLocation(fileID: "M/f.swift", filePath: "/f.swift", line: 1, column: 1) 36 | ) 37 | ) 38 | ), 39 | Event.Kind.issueRecorded( 40 | Issue( 41 | kind: .system, 42 | comments: ["Comment"], 43 | sourceContext: SourceContext( 44 | backtrace: nil, 45 | sourceLocation: nil) 46 | ) 47 | ), 48 | Event.Kind.runStarted, 49 | Event.Kind.runEnded, 50 | Event.Kind.testCaseStarted, 51 | Event.Kind.testCaseEnded, 52 | Event.Kind.testStarted, 53 | Event.Kind.testEnded, 54 | ] 55 | ) 56 | func codable(kind: Event.Kind) async throws { 57 | let testID = Test.ID(moduleName: "ModuleName", 58 | nameComponents: ["NameComponent1", "NameComponent2"], 59 | sourceLocation: #_sourceLocation) 60 | let testCaseID = Test.Case.ID(argumentIDs: nil, discriminator: nil, isStable: true) 61 | let event = Event(kind, testID: testID, testCaseID: testCaseID, instant: .now) 62 | let eventSnapshot = Event.Snapshot(snapshotting: event) 63 | let decoded = try JSON.encodeAndDecode(eventSnapshot) 64 | 65 | #expect(String(describing: decoded) == String(describing: eventSnapshot)) 66 | } 67 | 68 | @Test("Event.Contexts's Codable Conformances") 69 | func codable() async throws { 70 | let eventContext = Event.Context(test: .current, testCase: .current, configuration: .current) 71 | let snapshot = Event.Context.Snapshot(snapshotting: eventContext) 72 | 73 | let decoded = try JSON.encodeAndDecode(snapshot) 74 | 75 | #expect(String(describing: decoded.test) == String(describing: eventContext.test.map(Test.Snapshot.init(snapshotting:)))) 76 | #expect(String(describing: decoded.testCase) == String(describing: eventContext.testCase.map(Test.Case.Snapshot.init(snapshotting:)))) 77 | } 78 | #endif 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /Tests/TestingTests/NonCopyableSuiteTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | @Suite("Non-Copyable Tests") 14 | struct NonCopyableTests: ~Copyable { 15 | @Test static func staticMe() {} 16 | @Test borrowing func borrowMe() {} 17 | @Test consuming func consumeMe() {} 18 | @Test mutating func mutateMe() {} 19 | @Test borrowing func testNotAnXCTestCaseMethod() {} 20 | 21 | @Test borrowing func typeComparison() { 22 | let lhs = TypeInfo(describing: Self.self) 23 | let rhs = TypeInfo(describing: Self.self) 24 | 25 | #expect(lhs == rhs) 26 | #expect(lhs.hashValue == rhs.hashValue) 27 | } 28 | 29 | @available(_mangledTypeNameAPI, *) 30 | @Test borrowing func mangledTypeName() { 31 | #expect(TypeInfo(describing: Self.self).mangledName != nil) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/TestingTests/Runner.Plan.SnapshotTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if !SWT_NO_SNAPSHOT_TYPES 12 | @testable @_spi(ForToolsIntegrationOnly) import Testing 13 | 14 | @Suite("Runner.Plan.Snapshot tests") 15 | struct Runner_Plan_SnapshotTests { 16 | #if canImport(Foundation) 17 | @Test("Codable") 18 | func codable() async throws { 19 | let suite = try #require(await test(for: Runner_Plan_SnapshotFixtures.self)) 20 | 21 | var configuration = Configuration() 22 | configuration.setTestFilter(toInclude: [suite.id], includeHiddenTests: true) 23 | 24 | let plan = await Runner.Plan(configuration: configuration) 25 | let snapshot = Runner.Plan.Snapshot(snapshotting: plan) 26 | let decoded = try JSON.encodeAndDecode(snapshot) 27 | 28 | try #require(decoded.steps.count == snapshot.steps.count) 29 | 30 | func sort(_ lhs: Runner.Plan.Step.Snapshot, _ rhs: Runner.Plan.Step.Snapshot) -> Bool { 31 | String(describing: lhs.test.id) < String(describing: rhs.test.id) 32 | } 33 | 34 | for (decodedStep, snapshotStep) in zip(decoded.steps.sorted(by: sort), snapshot.steps.sorted(by: sort)) { 35 | #expect(decodedStep.test.id == snapshotStep.test.id) 36 | 37 | switch (decodedStep.action, snapshotStep.action) { 38 | case (.run, .run): 39 | break 40 | case let (.skip(decodedSkipInfo), .skip(snapshotSkipInfo)): 41 | #expect(decodedSkipInfo == snapshotSkipInfo) 42 | case let (.recordIssue(decodedIssue), .recordIssue(snapshotIssue)): 43 | #expect(String(describing: decodedIssue) == String(describing: snapshotIssue)) 44 | default: 45 | Issue.record("Decoded step does not match the original snapshotted step: decodedStep: \(decodedStep), snapshotStep: \(snapshotStep)") 46 | } 47 | } 48 | } 49 | #endif 50 | } 51 | 52 | // MARK: - Fixture tests 53 | 54 | @Suite(.hidden) 55 | private struct Runner_Plan_SnapshotFixtures { 56 | @Test(.hidden) 57 | func basicTest() {} 58 | 59 | @Test(.hidden, .disabled("To validate skip action")) 60 | func disabledTest() {} 61 | 62 | private static func _erroneousCondition() throws -> Bool { 63 | struct ContrivedError: Error {} 64 | throw ContrivedError() 65 | } 66 | 67 | @Test(.hidden, .enabled(if: try _erroneousCondition(), "To demonstrate recordIssue action")) 68 | func erroneousTest() {} 69 | } 70 | #endif 71 | -------------------------------------------------------------------------------- /Tests/TestingTests/Runner.RuntimeStateTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | @Suite("Runner.RuntimeState Tests") 14 | struct Runner_RuntimeStateTests { 15 | // This confirms that the `eventHandler` of a nested runner's configuration 16 | // has the runtime state of the "outer" runner, so that task local data is 17 | // handled appropriately. 18 | @Test func runnerStateScopedEventHandler() async { 19 | var configuration = Configuration() 20 | configuration.eventHandler = { _, _ in 21 | // Inside this event handler, the current Test should be the outer `@Test` 22 | // function, not the temporary `Test` created below. 23 | #expect(Test.current?.name == "runnerStateScopedEventHandler()") 24 | } 25 | 26 | await Test(name: "foo") {}.run(configuration: configuration) 27 | } 28 | 29 | // This confirms that an event posted within the closure of `withTaskGroup` 30 | // (and similar APIs) in regular tests (those which are not testing the 31 | // testing library itself) are handled appropriately and do not crash. 32 | @Test func eventPostingInTaskGroup() async { 33 | // Enable delivery of "expectation checked" events, merely as a way to allow 34 | // an event to be posted during the test below without causing any real 35 | // issues to be recorded or otherwise confuse the testing harness. 36 | var configuration = Configuration.current ?? .init() 37 | configuration.eventHandlingOptions.isExpectationCheckedEventEnabled = true 38 | 39 | await Configuration.withCurrent(configuration) { 40 | await withTaskGroup(of: Void.self) { group in 41 | #expect(Bool(true)) 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Tests/TestingTests/SkipInfoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | @Suite("SkipInfo Tests") 14 | struct SkipInfoTests { 15 | @Test("comment property") func comment() { 16 | var skipInfo = SkipInfo(comment: "abc123", sourceContext: .init()) 17 | #expect(skipInfo.comment == "abc123") 18 | skipInfo.comment = .__line("// Foo") 19 | #expect(skipInfo.comment == .__line("// Foo")) 20 | } 21 | 22 | @Test("sourceLocation property") func sourceLocation() { 23 | let sourceLocation1 = #_sourceLocation 24 | var skipInfo = SkipInfo(sourceContext: .init(sourceLocation: sourceLocation1)) 25 | #expect(skipInfo.sourceLocation == sourceLocation1) 26 | 27 | let sourceLocation2 = #_sourceLocation 28 | skipInfo.sourceLocation = sourceLocation2 29 | #expect(skipInfo.sourceLocation == sourceLocation2) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/TestingTests/Support/CErrorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | private import _TestingInternals 13 | 14 | @Suite("CError Tests") 15 | struct CErrorTests { 16 | @Test("CError.description property", arguments: 1 ..< 100) 17 | func errorDescription(errorCode: CInt) { 18 | let description = String(describing: CError(rawValue: errorCode)) 19 | #expect(!description.isEmpty) 20 | #expect(strerror(errorCode) == description) 21 | } 22 | } 23 | 24 | #if os(Windows) 25 | @Suite("Win32Error Tests") 26 | struct Win32ErrorTests { 27 | @Test("Win32Error.description property", 28 | arguments: [ 29 | (DWORD(ERROR_OUTOFMEMORY), "Not enough memory resources are available to complete this operation."), 30 | (DWORD(ERROR_INVALID_ACCESS), "The access code is invalid."), 31 | (DWORD(ERROR_ARITHMETIC_OVERFLOW), "Arithmetic result exceeded 32 bits."), 32 | (999_999_999, "An unknown error occurred (999999999)."), 33 | ] 34 | ) 35 | fileprivate func errorDescription(errorCode: DWORD, expectedMessage: String) { 36 | let description = String(describing: Win32Error(rawValue: errorCode)) 37 | #expect(!description.isEmpty) 38 | #expect(expectedMessage == description) 39 | } 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /Tests/TestingTests/Support/EnvironmentTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(Experimental) import Testing 12 | private import _TestingInternals 13 | 14 | @Suite("Environment Tests", .serialized) 15 | struct EnvironmentTests { 16 | var name = "SWT_ENVIRONMENT_VARIABLE_FOR_TESTING" 17 | 18 | @Test("Get whole environment block") 19 | func getWholeEnvironment() throws { 20 | let value = "\(UInt64.random(in: 0 ... .max))" 21 | try #require(Environment.setVariable(value, named: name)) 22 | defer { 23 | Environment.setVariable(nil, named: name) 24 | } 25 | let env = Environment.get() 26 | #expect(env[name] == value) 27 | } 28 | 29 | @Test("Read environment variable") 30 | func readEnvironmentVariable() throws { 31 | let value = "\(UInt64.random(in: 0 ... .max))" 32 | try #require(nil == Environment.variable(named: name)) 33 | defer { 34 | Environment.setVariable(nil, named: name) 35 | } 36 | try #require(Environment.setVariable(value, named: name)) 37 | #expect(Environment.variable(named: name) == value) 38 | } 39 | 40 | @Test("Read true environment flags", 41 | arguments: [ 42 | "1", String(describing: UInt64.max), String(describing: Int64.min), 43 | String(describing: UInt64.random(in: 1 ... .max)), String(describing: Int64.random(in: .min ..< 0)), 44 | "YES", "yes", "yEs", "TRUE", "true", "tRuE", 45 | ] 46 | ) 47 | func readTrueFlag(value: String) throws { 48 | try #require(nil == Environment.variable(named: name)) 49 | defer { 50 | Environment.setVariable(nil, named: name) 51 | } 52 | try #require(Environment.setVariable(value, named: name)) 53 | #expect(Environment.variable(named: name) == value) 54 | #expect(Environment.flag(named: name) == true) 55 | } 56 | 57 | @Test("Read false environment flags", 58 | arguments: [ 59 | "0", "", " ", "\t", 60 | "NO", "no", "nO", "FALSE", "false", "fAlSe", 61 | "alphabetical", "ümlaut", "😀", 62 | ] 63 | ) 64 | func readFalseFlag(value: String) throws { 65 | try #require(nil == Environment.variable(named: name)) 66 | defer { 67 | Environment.setVariable(nil, named: name) 68 | } 69 | try #require(Environment.setVariable(value, named: name)) 70 | #expect(Environment.variable(named: name) == value) 71 | #expect(Environment.flag(named: name) == false) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Tests/TestingTests/Support/LockTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | private import _TestingInternals 13 | 14 | @Suite("Locked Tests") 15 | struct LockTests { 16 | func testLock(_ lock: LockedWith) { 17 | #expect(lock.rawValue == 0) 18 | lock.withLock { value in 19 | value = 1 20 | } 21 | #expect(lock.rawValue == 1) 22 | } 23 | 24 | @Test("Platform-default lock") 25 | func locking() { 26 | testLock(Locked(rawValue: 0)) 27 | } 28 | 29 | #if SWT_TARGET_OS_APPLE && !SWT_NO_OS_UNFAIR_LOCK 30 | @Test("pthread_mutex_t (Darwin alternate)") 31 | func lockingWith_pthread_mutex_t() { 32 | testLock(LockedWith(rawValue: 0)) 33 | } 34 | #endif 35 | 36 | @Test("No lock") 37 | func noLock() async { 38 | let lock = LockedWith(rawValue: 0) 39 | await withTaskGroup { taskGroup in 40 | for _ in 0 ..< 100_000 { 41 | taskGroup.addTask { 42 | lock.increment() 43 | } 44 | } 45 | } 46 | #expect(lock.rawValue != 100_000) 47 | } 48 | 49 | @Test("Get the underlying lock") 50 | func underlyingLock() { 51 | let lock = Locked(rawValue: 0) 52 | testLock(lock) 53 | lock.withUnsafeUnderlyingLock { underlyingLock, _ in 54 | DefaultLock.unsafelyRelinquishLock(at: underlyingLock) 55 | lock.withLock { value in 56 | value += 1000 57 | } 58 | DefaultLock.unsafelyAcquireLock(at: underlyingLock) 59 | } 60 | #expect(lock.rawValue == 1001) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Tests/TestingTests/Test.Case.GeneratorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | @Suite("Test.Case.Generator Tests") 14 | struct Test_Case_GeneratorTests { 15 | @Test func uniqueDiscriminators() throws { 16 | let generator = Test.Case.Generator( 17 | arguments: [1, 1, 1], 18 | parameters: [Test.Parameter(index: 0, firstName: "x", type: Int.self)], 19 | testFunction: { _ in } 20 | ) 21 | 22 | let testCases = Array(generator) 23 | #expect(testCases.count == 3) 24 | 25 | let firstCase = try #require(testCases.first) 26 | #expect(firstCase.id.discriminator == 0) 27 | 28 | let discriminators = Set(testCases.map(\.id.discriminator)) 29 | #expect(discriminators.count == 3) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Tests/TestingTests/Traits/BugTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | 13 | @Suite("Bug Tests", .tags(.traitRelated)) 14 | struct BugTests { 15 | @Test(".bug() with URL string") 16 | func bugFactoryMethodWithURLString() throws { 17 | let trait = Bug.bug("https://www.example.com/12345", "Lorem ipsum") 18 | #expect((trait as Any) is Bug) 19 | #expect(trait.url == "https://www.example.com/12345") 20 | #expect(trait.title == "Lorem ipsum") 21 | #expect(trait.comments == ["Lorem ipsum"]) 22 | } 23 | 24 | @Test(".bug() with String") 25 | func bugFactoryMethodWithString() throws { 26 | let trait = Bug.bug(id: "12345", "Lorem ipsum") 27 | #expect((trait as Any) is Bug) 28 | #expect(trait.id == "12345") 29 | #expect(trait.title == "Lorem ipsum") 30 | #expect(trait.comments == ["Lorem ipsum"]) 31 | } 32 | 33 | @Test(".bug() with SignedInteger") 34 | func bugFactoryMethodWithSignedInteger() throws { 35 | let trait = Bug.bug(id: 12345) 36 | #expect((trait as Any) is Bug) 37 | #expect(trait.id == "12345") 38 | #expect(trait.title == nil) 39 | #expect(trait.comments.isEmpty) 40 | } 41 | 42 | @Test(".bug() with UnsignedInteger") 43 | func bugFactoryMethodWithUnsignedInteger() throws { 44 | let trait = Bug.bug(id: UInt32(12345), "Lorem ipsum") 45 | #expect((trait as Any) is Bug) 46 | #expect(trait.id == "12345") 47 | #expect(trait.title == "Lorem ipsum") 48 | #expect(trait.comments == ["Lorem ipsum"]) 49 | } 50 | 51 | @Test("Comparing Bug instances", 52 | arguments: [ 53 | Bug.bug(id: 12345), 54 | .bug("https://www.example.com/67890"), 55 | ], [ 56 | Bug.bug("67890"), 57 | .bug("https://www.example.com/12345"), 58 | ] 59 | ) 60 | func bugComparison(lhs: Bug, rhs: Bug) throws { 61 | #expect(lhs != rhs) 62 | } 63 | 64 | @Test(".bug() is not recursively applied") 65 | func bugIsNotRecursive() async throws { 66 | let trait = Bug.bug(id: 12345) 67 | #expect(!trait.isRecursive) 68 | } 69 | 70 | @Test("Test.associatedBugs property") 71 | func testAssociatedBugsProperty() { 72 | let test = Test(.bug(id: 12345), .disabled(), .bug(id: 67890), .bug(id: 24680), .bug(id: 54321)) {} 73 | let bugIdentifiers = test.associatedBugs 74 | #expect(bugIdentifiers.count == 4) 75 | #expect(bugIdentifiers[0].id == "12345") 76 | #expect(bugIdentifiers[1].id == "67890") 77 | #expect(bugIdentifiers[2].id == "24680") 78 | #expect(bugIdentifiers[3].id == "54321") 79 | } 80 | 81 | @Test("Bug hashing") 82 | func hashing() { 83 | let traits: Set = [.bug(id: 12345), .bug(id: "12345"), .bug(id: 12345), .bug(id: "67890"), .bug("https://www.example.com/12345")] 84 | #expect(traits.count == 3) 85 | } 86 | 87 | #if canImport(Foundation) 88 | @Test("Encoding/decoding") 89 | func encodingAndDecoding() throws { 90 | let original = Bug.bug(id: 12345, "Lorem ipsum") 91 | let copy = try JSON.encodeAndDecode(original) 92 | #expect(original == copy) 93 | } 94 | #endif 95 | } 96 | -------------------------------------------------------------------------------- /Tests/TestingTests/Traits/ConditionTraitTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2025 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | 13 | @Suite("Condition Trait Tests", .tags(.traitRelated)) 14 | struct ConditionTraitTests { 15 | #if compiler(>=6.1) 16 | @Test( 17 | ".enabled trait", 18 | .enabled { true }, 19 | .bug("https://github.com/swiftlang/swift/issues/76409", "Verify the custom trait with closure causes @Test macro to fail is fixed") 20 | ) 21 | func enabledTraitClosure() throws {} 22 | #endif 23 | 24 | @Test( 25 | ".enabled if trait", 26 | .enabled(if: true) 27 | ) 28 | func enabledTraitIf() throws {} 29 | 30 | #if compiler(>=6.1) 31 | @Test( 32 | ".disabled trait", 33 | .disabled { false }, 34 | .bug("https://github.com/swiftlang/swift/issues/76409", "Verify the custom trait with closure causes @Test macro to fail is fixed") 35 | ) 36 | func disabledTraitClosure() throws {} 37 | #endif 38 | 39 | @Test( 40 | ".disabled if trait", 41 | .disabled(if: false) 42 | ) 43 | func disabledTraitIf() throws {} 44 | 45 | @Test 46 | func evaluateCondition() async throws { 47 | let trueUnconditional = ConditionTrait(kind: .unconditional(true), comments: [], sourceLocation: #_sourceLocation) 48 | let falseUnconditional = ConditionTrait.disabled() 49 | let enabledTrue = ConditionTrait.enabled(if: true) 50 | let enabledFalse = ConditionTrait.enabled(if: false) 51 | var result: Bool 52 | 53 | result = try await trueUnconditional.evaluate() 54 | #expect(result) 55 | result = try await falseUnconditional.evaluate() 56 | #expect(!result) 57 | result = try await enabledTrue.evaluate() 58 | #expect(result) 59 | result = try await enabledFalse.evaluate() 60 | #expect(!result) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Tests/TestingTests/Traits/CustomTraitTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | // Note: Do NOT include `@_spi` on this import. The contents of this file are 12 | // specifically intended to validate that a type conforming to `TestTrait` can 13 | // be declared without importing anything except the base. 14 | import Testing 15 | 16 | // This is a "build-only" test which simply validates that we can successfully 17 | // declare a type conforming to `TestTrait` and use its default implementations. 18 | struct MyCustomTrait: TestTrait {} 19 | -------------------------------------------------------------------------------- /Tests/TestingTests/Traits/HiddenTraitTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | 13 | @Suite("Hidden Trait Tests", .tags(.traitRelated)) 14 | struct HiddenTraitTests { 15 | @Test(".hidden trait") 16 | func hiddenTrait() throws { 17 | let test = Test(.hidden) {} 18 | #expect(test.isHidden) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Tests/TestingTests/Traits/ParallelizationTraitTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing 12 | 13 | @Suite("Parallelization Trait Tests", .tags(.traitRelated)) 14 | struct ParallelizationTraitTests { 15 | @Test(".serialized trait serializes parameterized test") 16 | func serializesParameterizedTestFunction() async { 17 | var configuration = Configuration() 18 | configuration.isParallelizationEnabled = true 19 | 20 | let indicesRecorded = Locked<[Int]>() 21 | configuration.eventHandler = { event, _ in 22 | if case let .issueRecorded(issue) = event.kind, 23 | let comment = issue.comments.first, 24 | comment.rawValue.hasPrefix("PARAMETERIZED") { 25 | // Silly hack: only letters before the index, so just scrape off all 26 | // leading letters and what's left will be the index as a string. No 27 | // need for sscanf() or similar. 28 | if let index = Int(String(comment.rawValue.drop(while: \.isLetter))) { 29 | indicesRecorded.withLock { indicesRecorded in 30 | indicesRecorded.append(index) 31 | } 32 | } 33 | } 34 | } 35 | 36 | let plan = await Runner.Plan(selecting: OuterSuite.self, configuration: configuration) 37 | let runner = Runner(plan: plan, configuration: configuration) 38 | await runner.run() 39 | 40 | let indicesRecordedValue = indicesRecorded.rawValue 41 | #expect(indicesRecordedValue.count == 10_000) 42 | let isSorted = indicesRecordedValue == indicesRecordedValue.sorted() 43 | #expect(isSorted) 44 | } 45 | } 46 | 47 | // MARK: - Fixtures 48 | 49 | @Suite(.hidden, .serialized) 50 | private struct OuterSuite { 51 | /* This @Suite intentionally left blank */ struct IntermediateSuite { 52 | @Suite(.hidden) 53 | struct InnerSuite { 54 | @Test(.hidden) func example() {} 55 | 56 | @Test(.hidden, arguments: 0 ..< 10_000) func parameterized(i: Int) async throws { 57 | Issue.record("PARAMETERIZED\(i)") 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Tests/TestingTests/TypeNameConflictTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | 13 | @Suite("Type Name Conflict Tests") 14 | struct TypeNameConflictTests { 15 | @Test("Test function does not conflict with local type names") 16 | func someTest() { 17 | #expect(Bool(true)) 18 | } 19 | 20 | @Test("Test function does not conflict with local type names") 21 | @available(*, noasync) 22 | func someNoAsyncTest() { 23 | #expect(Bool(true)) 24 | } 25 | } 26 | 27 | // MARK: - Fixtures 28 | 29 | fileprivate struct SourceLocation {} 30 | fileprivate struct __TestContentRecordContainer {} 31 | fileprivate struct __XCTestCompatibleSelector {} 32 | 33 | fileprivate func __forward(_ value: R) async throws { 34 | Issue.record("Called wrong __forward()") 35 | } 36 | fileprivate func __forwardNoAsync(_ value: @autoclosure () throws -> R) throws { 37 | Issue.record("Called wrong __forwardNoAsync()") 38 | } 39 | 40 | fileprivate func __invokeXCTestCaseMethod( 41 | _ selector: __XCTestCompatibleSelector?, 42 | onInstanceOf xcTestCaseSubclass: T.Type, 43 | sourceLocation: SourceLocation 44 | ) { 45 | Issue.record("Called wrong __invokeXCTestCaseMethod()") 46 | } 47 | 48 | fileprivate func __xcTestCompatibleSelector(_ selector: String) -> __XCTestCompatibleSelector? { 49 | Issue.record("Called wrong __xcTestCompatibleSelector()") 50 | return nil 51 | } 52 | 53 | @Suite(.hidden) 54 | struct tests { 55 | @Test(.hidden) 56 | static func f() {} 57 | } 58 | -------------------------------------------------------------------------------- /Tests/TestingTests/VariadicGenericTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | import Testing 12 | private import _TestingInternals 13 | 14 | @Test func variadicCStringArguments() async throws { 15 | #expect(swt_pointersNotEqual2("abc", "123")) 16 | #expect(swt_pointersNotEqual3("abc", "123", "def")) 17 | #expect(swt_pointersNotEqual4("abc", "123", "def", "456")) 18 | } 19 | -------------------------------------------------------------------------------- /Tests/TestingTests/ZipTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2023 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | @testable import Testing 12 | 13 | @Suite("zip Tests") 14 | struct ZipTests { 15 | @Test("Zipped collections are not combinatoric") 16 | func zippedCollections() async throws { 17 | await confirmation("correct number of iterations", expectedCount: 10) { testCaseStarted in 18 | await Test(arguments: zip("ABCDEFGHIJ", 0 ..< 10)) { _, _ in 19 | testCaseStarted() 20 | }.run() 21 | } 22 | } 23 | 24 | @Test("All elements of two ranges are equal", arguments: zip(0 ..< 10, 0 ..< 10)) 25 | func allElementsEqual(i: Int, j: Int) { 26 | #expect(i == j) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Tests/TestingTests/_Testing_Foundation/FoundationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This source file is part of the Swift.org open source project 3 | // 4 | // Copyright (c) 2024 Apple Inc. and the Swift project authors 5 | // Licensed under Apache License v2.0 with Runtime Library Exception 6 | // 7 | // See https://swift.org/LICENSE.txt for license information 8 | // See https://swift.org/CONTRIBUTORS.txt for Swift project authors 9 | // 10 | 11 | #if canImport(Foundation) && !SWT_NO_UTC_CLOCK 12 | @testable @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import _Testing_Foundation 13 | @_spi(Experimental) @_spi(ForToolsIntegrationOnly) import Testing 14 | import Foundation 15 | 16 | struct FoundationTests { 17 | @Test("Casting Test.Clock.Instant to Date") 18 | func castTestClockInstantToDate() { 19 | let instant = Test.Clock.Instant.now 20 | let date = Date(instant) 21 | #expect(TimeInterval(instant.timeComponentsSince1970.seconds) == date.timeIntervalSince1970.rounded(.down)) 22 | } 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /cmake/modules/LibraryVersion.cmake: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | # The current version of the Swift Testing release. For release branches, 10 | # remember to remove -dev. 11 | set(SWT_TESTING_LIBRARY_VERSION "6.3-dev") 12 | 13 | find_package(Git QUIET) 14 | if(Git_FOUND) 15 | # Get the commit hash corresponding to the current build. Limit length to 15 16 | # to match `swift --version` output format. 17 | execute_process( 18 | COMMAND ${GIT_EXECUTABLE} rev-parse --short=15 --verify HEAD 19 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 20 | OUTPUT_VARIABLE GIT_VERSION 21 | OUTPUT_STRIP_TRAILING_WHITESPACE 22 | ERROR_QUIET) 23 | 24 | # Check if there are local changes. 25 | execute_process( 26 | COMMAND ${GIT_EXECUTABLE} status -s 27 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 28 | OUTPUT_VARIABLE GIT_STATUS 29 | OUTPUT_STRIP_TRAILING_WHITESPACE) 30 | if(GIT_STATUS) 31 | set(GIT_VERSION "${GIT_VERSION} - modified") 32 | endif() 33 | endif() 34 | 35 | # Combine the hard-coded Swift version with available Git information. 36 | if(GIT_VERSION) 37 | set(SWT_TESTING_LIBRARY_VERSION "${SWT_TESTING_LIBRARY_VERSION} (${GIT_VERSION})") 38 | endif() 39 | 40 | # All done! 41 | message(STATUS "Swift Testing version: ${SWT_TESTING_LIBRARY_VERSION}") 42 | add_compile_definitions( 43 | "$<$:SWT_TESTING_LIBRARY_VERSION=\"${SWT_TESTING_LIBRARY_VERSION}\">") 44 | -------------------------------------------------------------------------------- /cmake/modules/PlatformInfo.cmake: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2025 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | set(print_target_info_invocation "${CMAKE_Swift_COMPILER}" -print-target-info) 10 | if(CMAKE_Swift_COMPILER_TARGET) 11 | list(APPEND print_target_info_invocation -target ${CMAKE_Swift_COMPILER_TARGET}) 12 | endif() 13 | execute_process(COMMAND ${print_target_info_invocation} OUTPUT_VARIABLE target_info_json) 14 | message(CONFIGURE_LOG "Swift Target Info: ${print_target_info_invocation}\n" 15 | "${target_info_json}") 16 | 17 | if(NOT SwiftTesting_MODULE_TRIPLE) 18 | string(JSON module_triple GET "${target_info_json}" "target" "moduleTriple") 19 | set(SwiftTesting_MODULE_TRIPLE "${module_triple}" CACHE STRING "Triple used for installed swift{doc,module,interface} files") 20 | mark_as_advanced(SwiftTesting_MODULE_TRIPLE) 21 | 22 | message(CONFIGURE_LOG "Swift Module Triple: ${module_triple}") 23 | endif() 24 | 25 | if(NOT SwiftTesting_PLATFORM_SUBDIR) 26 | string(JSON platform GET "${target_info_json}" "target" "platform") 27 | if(NOT platform) 28 | if(NOT SWIFT_SYSTEM_NAME) 29 | if(CMAKE_SYSTEM_NAME STREQUAL Darwin) 30 | set(platform macosx) 31 | else() 32 | set(platform $) 33 | endif() 34 | endif() 35 | endif() 36 | set(SwiftTesting_PLATFORM_SUBDIR "${platform}" CACHE STRING "Platform name used for installed swift{doc,module,interface} files") 37 | mark_as_advanced(SwiftTesting_PLATFORM_SUBDIR) 38 | 39 | message(CONFIGURE_LOG "Swift Platform: ${platform}") 40 | endif() 41 | 42 | if(NOT SwiftTesting_ARCH_SUBDIR) 43 | string(JSON arch GET "${target_info_json}" "target" "arch") 44 | set(SwiftTesting_ARCH_SUBDIR "${arch}" CACHE STRING "Architecture used for setting the architecture subdirectory") 45 | mark_as_advanced(SwiftTesting_ARCH_SUBDIR) 46 | 47 | message(CONFIGURE_LOG "Swift Architecture: ${arch}") 48 | endif() 49 | -------------------------------------------------------------------------------- /cmake/modules/SwiftModuleInstallation.cmake: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | function(_swift_testing_install_target module) 10 | install(TARGETS ${module} 11 | ARCHIVE DESTINATION "${SwiftTesting_INSTALL_LIBDIR}" 12 | LIBRARY DESTINATION "${SwiftTesting_INSTALL_LIBDIR}" 13 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 14 | 15 | get_target_property(type ${module} TYPE) 16 | if(type STREQUAL EXECUTABLE) 17 | return() 18 | endif() 19 | 20 | get_target_property(module_name ${module} Swift_MODULE_NAME) 21 | if(NOT module_name) 22 | set(module_name ${module}) 23 | endif() 24 | 25 | set(module_dir ${SwiftTesting_INSTALL_SWIFTMODULEDIR}/${module_name}.swiftmodule) 26 | install(FILES $/${module_name}.swiftdoc 27 | DESTINATION "${module_dir}" 28 | RENAME ${SwiftTesting_MODULE_TRIPLE}.swiftdoc) 29 | install(FILES $/${module_name}.swiftinterface 30 | DESTINATION "${module_dir}" 31 | RENAME ${SwiftTesting_MODULE_TRIPLE}.swiftinterface) 32 | endfunction() 33 | 34 | # Install the specified .swiftcrossimport directory for the specified declaring 35 | # module. 36 | # 37 | # Usage: 38 | # _swift_testing_install_swiftcrossimport(module swiftcrossimport_dir) 39 | # 40 | # Arguments: 41 | # module: The name of the declaring module. This is used to determine where 42 | # the .swiftcrossimport directory should be installed, since it must be 43 | # adjacent to the declaring module's .swiftmodule directory. 44 | # swiftcrossimport_dir: The path to the source .swiftcrossimport directory 45 | # which will be installed. 46 | function(_swift_testing_install_swiftcrossimport module swiftcrossimport_dir) 47 | install(DIRECTORY "${swiftcrossimport_dir}" 48 | DESTINATION "${SwiftTesting_INSTALL_SWIFTMODULEDIR}") 49 | endfunction() 50 | -------------------------------------------------------------------------------- /cmake/modules/TargetTriple.cmake: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | # Ask the Swift compiler what target triple it will be compiling with today. 10 | set(SWT_TARGET_INFO_COMMAND "${CMAKE_Swift_COMPILER}" -print-target-info) 11 | if(CMAKE_Swift_COMPILER_TARGET) 12 | list(APPEND SWT_TARGET_INFO_COMMAND -target ${CMAKE_Swift_COMPILER_TARGET}) 13 | endif() 14 | execute_process(COMMAND ${SWT_TARGET_INFO_COMMAND} OUTPUT_VARIABLE SWT_TARGET_INFO_JSON) 15 | string(JSON SWT_TARGET_TRIPLE GET "${SWT_TARGET_INFO_JSON}" "target" "unversionedTriple") 16 | 17 | # All done! 18 | message(STATUS "Swift Testing target triple: ${SWT_TARGET_TRIPLE}") 19 | if(SWT_TARGET_TRIPLE) 20 | add_compile_definitions( 21 | "$<$:SWT_TARGET_TRIPLE=\"${SWT_TARGET_TRIPLE}\">") 22 | endif() 23 | -------------------------------------------------------------------------------- /cmake/modules/shared/AvailabilityDefinitions.cmake: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | # Settings which define commonly-used OS availability macros. 10 | add_compile_options( 11 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_mangledTypeNameAPI:macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0\">" 12 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_uttypesAPI:macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0\">" 13 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_backtraceAsyncAPI:macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0\">" 14 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_clockAPI:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0\">" 15 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_regexAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0\">" 16 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_swiftVersionAPI:macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0\">" 17 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_typedThrowsAPI:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0\">" 18 | "SHELL:$<$:-Xfrontend -define-availability -Xfrontend \"_distantFuture:macOS 99.0, iOS 99.0, watchOS 99.0, tvOS 99.0, visionOS 99.0\">") 19 | -------------------------------------------------------------------------------- /cmake/modules/shared/CompilerSettings.cmake: -------------------------------------------------------------------------------- 1 | # This source file is part of the Swift.org open source project 2 | # 3 | # Copyright (c) 2024 Apple Inc. and the Swift project authors 4 | # Licensed under Apache License v2.0 with Runtime Library Exception 5 | # 6 | # See http://swift.org/LICENSE.txt for license information 7 | # See http://swift.org/CONTRIBUTORS.txt for Swift project authors 8 | 9 | # Settings intended to be applied to every Swift target in this project. 10 | # Analogous to project-level build settings in an Xcode project. 11 | add_compile_options( 12 | "SHELL:$<$:-package-name org.swift.testing>") 13 | add_compile_options( 14 | "SHELL:$<$:-Xfrontend -require-explicit-sendable>") 15 | add_compile_options( 16 | "SHELL:$<$:-Xfrontend -enable-experimental-feature -Xfrontend AccessLevelOnImport>") 17 | add_compile_options( 18 | "SHELL:$<$:-Xfrontend -enable-upcoming-feature -Xfrontend ExistentialAny>" 19 | "SHELL:$<$:-Xfrontend -enable-upcoming-feature -Xfrontend InternalImportsByDefault>" 20 | "SHELL:$<$:-Xfrontend -enable-upcoming-feature -Xfrontend MemberImportVisibility>" 21 | "SHELL:$<$:-Xfrontend -enable-upcoming-feature -Xfrontend InferIsolatedConformances>") 22 | 23 | # Platform-specific definitions. 24 | if(APPLE) 25 | add_compile_definitions("SWT_TARGET_OS_APPLE") 26 | endif() 27 | set(SWT_NO_EXIT_TESTS_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android") 28 | if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_EXIT_TESTS_LIST) 29 | add_compile_definitions("SWT_NO_EXIT_TESTS") 30 | endif() 31 | set(SWT_NO_PROCESS_SPAWNING_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android") 32 | if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_PROCESS_SPAWNING_LIST) 33 | add_compile_definitions("SWT_NO_PROCESS_SPAWNING") 34 | endif() 35 | if(NOT APPLE) 36 | add_compile_definitions("SWT_NO_SNAPSHOT_TYPES") 37 | endif() 38 | if(CMAKE_SYSTEM_NAME STREQUAL "WASI") 39 | add_compile_definitions("SWT_NO_DYNAMIC_LINKING") 40 | add_compile_definitions("SWT_NO_PIPES") 41 | endif() 42 | --------------------------------------------------------------------------------