Skip to content

Commit e2734bd

Browse files
committed
Add missing docs/Testing.rst
rdar://problem/23359113
1 parent dcbe84f commit e2734bd

File tree

1 file changed

+365
-0
lines changed

1 file changed

+365
-0
lines changed

docs/Testing.rst

Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
:orphan:
2+
3+
.. @raise litre.TestsAreMissing
4+
5+
=============
6+
Testing Swift
7+
=============
8+
9+
This document describes how we test the Swift compiler, the Swift runtime, and
10+
the Swift standard library.
11+
12+
Testing approaches
13+
==================
14+
15+
We use multiple approaches to test the Swift toolchain.
16+
17+
* LLVM lit-based testsuites for the compiler, runtime and the standard library.
18+
19+
* A selection of open source projects written in Swift.
20+
21+
The LLVM lit-based testsuite
22+
============================
23+
24+
**Purpose**: primary testsuites for the Swift toolchain.
25+
26+
**Contents**: Functional and regression tests for all toolchain components.
27+
28+
**Run by**:
29+
30+
* Engineers and contributors are expected to run tests from these testsuites
31+
locally before commiting. (Usually on a single platform, and not necessarily
32+
all tests.)
33+
34+
* Buildbots run all tests, on all supported platforms.
35+
36+
Running the LLVM lit-based testsuite
37+
------------------------------------
38+
39+
You can run Swift tests using the ``build-script``, or, alternatively, using
40+
these targets in the build directory:
41+
42+
* ``check-swift``
43+
44+
Runs tests from the ``${SWIFT_SOURCE_ROOT}/test`` directory.
45+
46+
* ``check-swift-validation``
47+
48+
Runs tests from the ``${SWIFT_SOURCE_ROOT}/validation-test`` directory.
49+
50+
* ``check-swift-all``
51+
52+
Runs all tests.
53+
54+
For day-to-day work on the Swift compiler, using check-swift should be
55+
sufficient. The buildbot runs validation tests, so if those are accidentally
56+
broken, it should not go unnoticed.
57+
58+
Before commiting a large change to a compiler (especially a language change),
59+
or API changes to the standard library, it is recommended to run validation
60+
test suite.
61+
62+
For every target above, there are variants for different optimizations:
63+
64+
* the target itself (e.g., ``check-swift``) -- runs execution tests in
65+
``-Onone`` mode;
66+
67+
* the target with ``-optimize`` suffix (e.g., ``check-swift-optimize``) -- runs
68+
execution tests in ``-O`` mode; This target will only run tests marked as
69+
``executable_test``.
70+
71+
* the target with ``-optimize-unchecked`` suffix (e.g.,
72+
``check-swift-optimize-unchecked``) -- runs execution tests in
73+
``-Ounchecked`` mode. This target will only run tests marked as
74+
``executable_test``.
75+
76+
If you need to manually run certain tests, you can invoke LLVM's lit.py script
77+
directly. For example::
78+
79+
% ${LLVM_SOURCE_ROOT}/utils/lit/lit.py -sv ${SWIFT_BUILD_ROOT}/test-iphonesimulator-i386/Parse/
80+
81+
This runs the tests in the test/Parse/ directory targeting the 32-bit iOS
82+
Simulator. The ``-sv`` options give you a nice progress bar and only show you
83+
output from the tests that fail.
84+
85+
One downside of using this form is that you're appending relative paths from
86+
the source directory to the test directory in your build directory. (That is,
87+
there may not actually be a directory named 'Parse' in
88+
'test-iphonesimulator-i386/'; the invocation works because there is one in the
89+
source 'test/' directory.) There is a more verbose form that specifies the
90+
testing configuration explicitly, which then allows you to test files
91+
regardless of location.
92+
93+
::
94+
95+
% ${LLVM_SOURCE_ROOT}/utils/lit/lit.py -sv --param swift_site_config=${SWIFT_BUILD_ROOT}/test-iphonesimulator-i386/lit.site.cfg ${SWIFT_SOURCE_ROOT}/test/Parse/
96+
97+
For more complicated configuration, copy the invocation from one of the build
98+
targets mentioned above and modify it as necessary. lit.py also has several
99+
useful features, like timing tests and providing a timeout. Check these features
100+
out with ``lit.py -h``.
101+
102+
Writing tests
103+
-------------
104+
105+
General guidelines
106+
^^^^^^^^^^^^^^^^^^
107+
108+
When adding a new testcase, try to find an existing test file focused on the
109+
same topic rather than starting a new test file. There is a fixed runtime cost
110+
for every test file. On the other hand, avoid dumping new tests in a file that
111+
is only remotely related to the purpose of the new tests.
112+
113+
Don't limit a test to a certain platform or hardware configuration just because
114+
this makes the test slightly easier to write. This sometimes means a little
115+
bit more work when adding the test, but the payoff from the increased testing
116+
is significant. We heavily rely on portable tests to port Swift to other
117+
platforms.
118+
119+
Avoid using unstable language features in tests which test something else (for
120+
example, avoid using an unstable underscored attribute when another
121+
non-underscored attribute would work).
122+
123+
Avoid using arbitrary implementation details of the standard library. Always
124+
prefer to define types locally in the test, if feasible.
125+
126+
Avoid purposefully shadowing names from the standard library, this makes the
127+
test extremely confusing (if nothing else, to understand the intent --- was the
128+
compiler bug triggered by this shadowing?) When reducing a compiler testcase
129+
from the standard library source, rename the types and APIs in the testcase to
130+
differ from the standard library APIs.
131+
132+
In IRGen, SILGen and SIL tests, avoid using platform-dependent implementation
133+
details of the standard library (unless doing so is point of the test).
134+
Platform-dependent details include:
135+
136+
* ``Int`` (use integer types with explicit types instead).
137+
138+
* Layout of ``String``, ``Array``, ``Dictionary``, ``Set``. These differ
139+
between platforms that have Objective-C interop and those that don't.
140+
141+
Unless testing the standard library, avoid using arbitrary standard library
142+
types and APIs, even if it is very convenient for you to do so in your tests.
143+
Using the more common APIs like ``Array`` subscript or ``+`` on ``IntXX`` is
144+
acceptable. This is important because you can't rely on the full standard
145+
library being available. The long-term plan is to introduce a mock, minimal
146+
standard library that only has a very basic set of APIs.
147+
148+
If you write an executable test please add ``REQUIRES: executable_test`` to the
149+
test.
150+
151+
Substitutions in lit tests
152+
^^^^^^^^^^^^^^^^^^^^^^^^^^
153+
154+
Substitutions that start with ``%target`` configure the compiler for building
155+
code for the target that is not the build machine:
156+
157+
* ``%target-parse-verify-swift``: parse and type check the current Swift file
158+
for the target platform and verify diagnostics, like ``swift -parse -verify
159+
%s``.
160+
161+
Use this substitution for testing semantic analysis in the compiler.
162+
163+
* ``%target-swift-frontend``: run ``swift -frontend`` for the target.
164+
165+
Use this substitution (with extra arguments) for tests that don't fit any
166+
other pattern.
167+
168+
* ``%target-swift-frontend(mock-sdk:`` *mock sdk arguments* ``)`` *other
169+
arguments*: like ``%target-swift-frontend``, but allows to specify command
170+
line parameters (typically ``-sdk`` and ``-I``) to use a mock SDK and SDK
171+
overlay that would take precedence over the target SDK.
172+
173+
* ``%target-build-swift``: compile and link a Swift program for the target.
174+
175+
Use this substitution only when you intend to run the program later in the
176+
test.
177+
178+
* ``%target-run-simple-swift``: build a one-file Swift program and run it on
179+
the target machine.
180+
181+
Use this substitution for executable tests that don't require special
182+
compiler arguments.
183+
184+
Add ``REQUIRES: executable_test`` to the test.
185+
186+
* ``%target-run-stdlib-swift``: like ``%target-run-simple-swift`` with
187+
``-parse-stdlib -Xfrontend -disable-access-control``.
188+
189+
This is sometimes useful for testing the Swift standard library.
190+
191+
Add ``REQUIRES: executable_test`` to the test.
192+
193+
* ``%target-repl-run-simple-swift``: run a Swift program in a REPL on the
194+
target machine.
195+
196+
* ``%target-run``: run a command on the target machine.
197+
198+
Add ``REQUIRES: executable_test`` to the test.
199+
200+
* ``%target-jit-run``: run a Swift program on the target machine using a JIT
201+
compiler.
202+
203+
* ``%target-swiftc_driver``: FIXME
204+
205+
* ``%target-sil-opt``: run ``sil-opt`` for the target.
206+
207+
* ``%target-sil-extract``: run ``sil-extract`` for the target.
208+
209+
* ``%target-swift-ide-test``: run ``swift-ide-test`` for the target.
210+
211+
* ``%target-swift-ide-test(mock-sdk:`` *mock sdk arguments* ``)`` *other
212+
arguments*: like ``%target-swift-ide-test``, but allows to specify command
213+
line parameters to use a mock SDK.
214+
215+
* ``%target-swiftc_driver``: FIXME.
216+
217+
* ``%target-swift-autolink-extract``: run ``swift-autolink-extract`` for the
218+
target to extract its autolink flags on platforms that support them (when the
219+
autolink-extract feature flag is set)
220+
221+
* ``%target-clang``: run the system's ``clang++`` for the target.
222+
223+
If you want to run the ``clang`` executable that was built alongside
224+
Swift, use ``%clang`` instead.
225+
226+
* ``%target-ld``: run ``ld`` configured with flags pointing to the standard
227+
library directory for the target.
228+
229+
* ``%target-cc-options``: the clang flags to setup the target with the right
230+
architecture and platform version.
231+
232+
Always use ``%target-*`` substitutions unless you have a good reason. For
233+
example, an exception would be a test that checks how the compiler handles
234+
mixing module files for incompatible platforms (that test would need to compile
235+
Swift code for two different platforms that are known to be incompatible).
236+
237+
When you can't use ``%target-*`` substitutions, you can use:
238+
239+
* ``%swift_driver_plain``: FIXME.
240+
* ``%swiftc_driver_plain``: FIXME.
241+
* ``%swift_driver``: FIXME.
242+
* ``%swiftc_driver``: FIXME.
243+
* ``%sil-opt``: FIXME.
244+
* ``%sil-extract``: FIXME.
245+
* ``%lldb-moduleimport-test``: FIXME.
246+
* ``%swift-ide-test_plain``: FIXME.
247+
* ``%swift-ide-test``: FIXME.
248+
* ``%llvm-opt``: FIXME.
249+
* ``%swift``: FIXME.
250+
* ``%clang-include-dir``: FIXME.
251+
* ``%clang-importer-sdk``: FIXME.
252+
253+
Other substitutions:
254+
255+
* ``%leaks-runner``: FIXME.
256+
* ``%clang_apinotes``: FIXME.
257+
* ``%clang``: FIXME.
258+
* ``%target-triple``: FIXME, possible values.
259+
* ``%target-cpu``: FIXME, possible values.
260+
* ``%target-os``: FIXME, possible values.
261+
* ``%target-object-format``: the platform's object format (elf, macho, coff).
262+
* ``%target-runtime``: the platform's Swift runtime (objc, native).
263+
* ``%target-ptrsize``: the pointer size of the target (32, 64).
264+
* ``%sdk``: FIXME.
265+
* ``%gyb``: FIXME.
266+
267+
* ``%platform-module-dir``: absolute path of the directory where the stdandard
268+
library module file for the target platform is stored. For example,
269+
``/.../lib/swift/macosx``.
270+
271+
* ``%platform-sdk-overlay-dir``: absolute path of the directory where the SDK
272+
overlay module files for the target platform are stored.
273+
274+
* ``%target-swiftmodule-name`` and ``%target-swiftdoc-name``: the basename of
275+
swiftmodule and swiftdoc files for a framework compiled for the target (for
276+
example, ``arm64.swiftmodule`` and ``arm64.swiftdoc``).
277+
278+
* ``%target-sdk-name``: only for Apple platforms: ``xcrun``-style SDK name
279+
(``macosx``, ``iphoneos``, ``iphonesimulator``).
280+
281+
When writing a test where output (or IR, SIL) depends on the bitness of the
282+
target CPU, use this pattern::
283+
284+
// RUN: %target-swift-frontend ... | FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize %s
285+
286+
// CHECK: common line
287+
// CHECK-32: only for 32-bit
288+
// CHECK-64: only for 64-bit
289+
290+
// FileCheck does a single pass for a combined set of CHECK lines, so you can
291+
// do this:
292+
//
293+
// CHECK: define @foo() {
294+
// CHECK-32: integer_literal $Builtin.Int32, 0
295+
// CHECK-64: integer_literal $Builtin.Int64, 0
296+
297+
When writing a test where output (or IR, SIL) depends on the target CPU itself,
298+
use this pattern::
299+
300+
// RUN: %target-swift-frontend ... | FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
301+
302+
// CHECK: common line
303+
// CHECK-i386: only for i386
304+
// CHECK-x86_64: only for x86_64
305+
// CHECK-armv7: only for armv7
306+
// CHECK-arm64: only for arm64
307+
308+
Features for ``REQUIRES`` and ``XFAIL``
309+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
310+
311+
FIXME: list.
312+
313+
When writing a test specific to x86, if possible, prefer ``REQUIRES:
314+
CPU=i386_or_x86_64`` to ``REQUIRES: CPU=x86_64``.
315+
316+
``swift_test_mode_optimize[_unchecked|none]`` and
317+
``swift_test_mode_optimize[_unchecked|none]_<CPUNAME>`` to specify a test mode
318+
plus cpu configuration.
319+
320+
``optimized_stdlib_<CPUNAME>``` to specify a optimized stdlib plus cpu
321+
configuration.
322+
323+
Feature ``REQUIRES: executable_test``
324+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
325+
326+
This feature marks an executable test. The test harness makes this feature
327+
generally available. It can be used to restrict the set of tests to run.
328+
329+
StdlibUnittest
330+
^^^^^^^^^^^^^^
331+
332+
Tests accept command line parameters, run StdlibUnittest-based test binary
333+
with ``--help`` for more information.
334+
335+
Testing memory management in execution tests
336+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
337+
338+
In execution tests, memory management testing should be performed
339+
using local variables enclosed in a closure passed to the standard
340+
library ``autoreleasepool`` function. For example::
341+
342+
// A counter that's decremented by Canary's deinitializer.
343+
var CanaryCount = 0
344+
345+
// A class whose instances increase a counter when they're destroyed.
346+
class Canary {
347+
deinit { ++CanaryCount }
348+
}
349+
350+
// Test that a local variable is correctly released before it goes out of
351+
// scope.
352+
CanaryCount = 0
353+
autoreleasepool {
354+
let canary = Canary()
355+
}
356+
assert(CanaryCount == 1, "canary was not released")
357+
358+
Memory management tests should be performed in a local scope because Swift does
359+
not guarantee the destruction of global variables. Code that needs to
360+
interoperate with Objective-C may put references in the autorelease pool, so
361+
code that uses an ``if true {}`` or similar no-op scope instead of
362+
``autoreleasepool`` may falsely report leaks or fail to catch overrelease bugs.
363+
If you're specifically testing the autoreleasing behavior of code, or do not
364+
expect code to interact with the Objective-C runtime, it may be OK to use ``if
365+
true {}``, but those assumptions should be commented in the test.

0 commit comments

Comments
 (0)