LIT(1)

πŸ’… LIT(1) β€” LLVM Integrated Tester πŸŽ€

okay bestie, welcome to the lit manual page, from the LLVM crew. this is LLVM Integrated Tester and she is that girl. let's get into it ✨


🌸 SYNOPSIS 🌸

lit [options] [tests]

✨ DESCRIPTION ✨

so lit is a portable tool for running LLVM- and Clang-style test suites, giving you the rundown on how they went, and pointing at the failures. she's built to be a lightweight testing tool with the simplest user interface possible. no cap. πŸ’…

you run lit with one or more tests specified on the command line, bestie. those tests can be either individual test files or directories to search for tests (peep TEST DISCOVERY for the deets).

every test you specify gets executed β€” potentially concurrently πŸ‘€ β€” and once they've all run, lit prints summary info on how many passed or failed (that's TEST STATUS RESULTS, iykyk). and heads up: if any tests fail, lit exits with a non-zero exit code. periodt.

by default lit keeps it cute with a succinct progress display and only prints summary info for the tests that failed. want to control that? that's what OUTPUT OPTIONS are for 🫢

lit also ships a whole bunch of options for controlling how tests get executed (some specific features depend on the particular test format, ngl). see EXECUTION OPTIONS for more.

and finally, there are extra options for running only a subset of the options you specified on the command line β€” that's SELECTION OPTIONS, go look 🌈

one more thing, and it's important: lit parses options from the environment variable LIT_OPTS after it parses options from the command line. LIT_OPTS is mostly for supplementing or overriding the command-line options that a project's build system passes to lit via check targets. iconic behavior honestly.

if you're the kind of person who's into the lit architecture, or you're designing your own lit testing implementation, go read LIT INFRASTRUCTURE. that one's for you πŸ’œ


🧚 GENERAL OPTIONS 🧚

  • -h, --help β€” show the lit help message. simple as that, bestie.
  • -j N, --workers=N β€” run N tests in parallel. by default this is automatically picked to match the number of detected available CPUs. the machine knows itself fr fr.
  • --config-prefix=NAME β€” when searching for test suites, look for NAME.cfg and NAME.site.cfg instead of lit.cfg and lit.site.cfg.
  • -D NAME[=VALUE], --param NAME[=VALUE] β€” add a user-defined parameter NAME with the given VALUE (or the empty string if you don't give one). what these parameters actually mean and how they're used is entirely up to the test suite. not our business πŸ’…

πŸŽ€ OUTPUT OPTIONS πŸŽ€

  • -q, --quiet β€” suppress any output except for test failures. silence is golden ✨
  • -s, --succinct β€” show less output, like, don't show info on tests that pass. also shows a progress bar, unless --no-progress-bar is specified.
  • -v, --verbose β€” show more info on test failures, e.g. the entire test output instead of just the test result. the receipts, basically.
  • -vv, --echo-all-commands β€” echo all commands to stdout as they're being executed. this is lowkey valuable for debugging test failures, because the last echoed command is the one that failed. lit normally inserts a no-op command (: in the case of bash) with the argument 'RUN: at line N' before each command pipeline, and this option also makes those no-op commands get echoed to stdout to help you locate the source line of the failed command. this option implies --verbose.
  • -a, --show-all β€” show more info about all tests, e.g. the entire test commandline and output. everything everywhere all at once 🫢
  • --no-progress-bar β€” do not use the curses based progress bar.
  • --show-unsupported β€” show the names of unsupported tests.
  • --show-xfail β€” show the names of tests that were expected to fail.

πŸ”₯ EXECUTION OPTIONS πŸ”₯

  • --path=PATH β€” specify an additional PATH to use when searching for executables in tests.
  • --vg β€” run individual tests under valgrind (using the memcheck tool). the --error-exitcode argument for valgrind is used, so that valgrind failures make the program exit with a non-zero status.

when this option is enabled, lit also automatically provides a "valgrind" feature that you can use to conditionally disable certain tests (or expect failure in them).

  • --vg-arg=ARG β€” when --vg is used, specify an additional argument to pass to valgrind itself.
  • --vg-leak β€” when --vg is used, enable memory leak checks. when this option is enabled, lit also automatically provides a "vg_leak" feature that you can use to conditionally disable certain tests (or expect failure in them).
  • --time-tests β€” track the wall time individual tests take to execute and include the results in the summary output. super useful for figuring out which tests in a suite take the longest to run. the slow ones are always the main characters smh 😭
  • --ignore-fail β€” exit with status zero even if some tests fail. we're pretending we didn't see it bestie πŸ™ˆ
  • --no-indirectly-run-check β€” do not error if a test would not have been run had you specified the containing directory instead of naming the test directly.

πŸ‘‘ SELECTION OPTIONS πŸ‘‘

by default, lit runs failing tests first, then runs tests in descending execution time order to optimize concurrency. you can change the execution order with the --order option.

the timing data lives in the test_exec_root in a file named .lit_test_times.txt. if that file doesn't exist, lit checks the test_source_root for the file, so it can optionally accelerate clean builds. cute ✨

  • --shuffle β€” run the tests in a random order, not failing/slowest first. deprecated, use --order instead.
  • --max-failures N β€” stop execution after the given number N of failures. you pass an integer argument on the command line prior to execution.
  • --max-tests=N β€” run at most N tests and then terminate.
  • --max-time=N β€” spend at most N seconds (approximately) running tests and then terminate. note that this is not an alias for --timeout β€” the two are different kinds of maximums, okay?
  • --num-shards=M β€” divide the set of selected tests into M equal-sized subsets or "shards", and run only one of them. must be used with the --run-shard=N option, which selects the shard to run. the environment variable LIT_NUM_SHARDS can also be used in place of this option. these two options give you a coarse mechanism for partitioning large testsuites, for parallel execution on separate machines (say, in a big testing farm πŸ‘©β€πŸ’»).
  • --order={lexical,random,smart} β€” define the order in which tests are run. the supported values are:
    • lexical β€” tests will be run in lexical order according to the test file path. useful when you want a predictable test order.
    • random β€” tests will be run in random order.
    • smart β€” tests that failed previously will be run first, then the remaining tests, all in descending execution time order. this is the default because it optimizes concurrency.
  • --run-shard=N β€” select which shard to run, assuming the --num-shards=M option was provided. the two options must be used together, and the value of N must be in the range 1..M. the environment variable LIT_RUN_SHARD can also be used in place of this option.
  • --timeout=N β€” spend at most N seconds (approximately) running each individual test. 0 means no time limit, and 0 is the default. note that this is not an alias for --max-time β€” the two are different kinds of maximums, fr fr.
  • --filter=REGEXP β€” run only those tests whose name matches the regular expression specified in REGEXP. the environment variable LIT_FILTER can also be used in place of this option, which is especially useful in environments where the call to lit is issued indirectly.
  • --filter-out=REGEXP β€” filter out those tests whose name matches the regular expression specified in REGEXP. the environment variable LIT_FILTER_OUT can also be used in place of this option, which is especially useful in environments where the call to lit is issued indirectly.
  • --xfail=LIST β€” treat those tests whose name is in the semicolon separated list LIST as XFAIL. helpful when you don't want to modify the test suite. the environment variable LIT_XFAIL can also be used in place of this option, which is especially useful in environments where the call to lit is issued indirectly.

a test name can be specified as a file name relative to the test suite directory. for example:

LIT_XFAIL="affinity/kmp-hw-subset.c;offloading/memory_manager.cpp"

in this case, all of the following tests are treated as XFAIL:

libomp :: affinity/kmp-hw-subset.c
libomptarget :: nvptx64-nvidia-cuda :: offloading/memory_manager.cpp
libomptarget :: x86_64-pc-linux-gnu :: offloading/memory_manager.cpp

alternatively, a test name can be specified as the full test name reported in lit output. for example, we can adjust the previous example so the nvptx64-nvidia-cuda version of offloading/memory_manager.cpp is not treated as XFAIL:

LIT_XFAIL="affinity/kmp-hw-subset.c;libomptarget :: x86_64-pc-linux-gnu :: offloading/memory_manager.cpp"
  • --xfail-not=LIST β€” do not treat the specified tests as XFAIL. the environment variable LIT_XFAIL_NOT can also be used in place of this option. the syntax is the same as for --xfail and LIT_XFAIL. --xfail-not and LIT_XFAIL_NOT always override all other XFAIL specifications, including an --xfail that appears later on the command line. the main purpose is to suppress an XPASS result without having to modify a test case that uses the XFAIL directive. so powerful honestly πŸ’…

πŸ¦‹ ADDITIONAL OPTIONS πŸ¦‹

  • --debug β€” run lit in debug mode, for debugging configuration issues and lit itself.
  • --show-suites β€” list the discovered test suites and exit.
  • --show-tests β€” list all of the discovered tests and exit.

πŸ’€ EXIT STATUS πŸ’€

lit exits with an exit code of 1 if there are any FAIL or XPASS results. otherwise, it exits with status 0. other exit codes get used for non-test related failures (like a user error, or an internal program error πŸ‘€).


more to come bestie, don't go anywhere πŸ’–

πŸ” TEST DISCOVERY πŸ”

okay so bestie, when you hand lit some stuff to run, those inputs can be individual tests, or whole directories, or even entire hierarchies of tests. And the very first thing lit does when it wakes up? It converts all of those inputs into one complete list of tests to run. That whole process is literally called test discovery. ✨

In the lit model, every test has to exist inside some test suite β€” no exceptions, no cap. So lit takes the inputs you gave it on the command line and resolves them to test suites by searching upwards from the input path until it finds a lit.cfg or lit.site.cfg file. πŸ¦‹ Those files are doing double duty fr fr β€” they're the marker that says "yep, this is a test suite" and they're the configuration files lit loads so it knows how to find and run the tests inside that suite.

Once lit has mapped your inputs onto test suites, it walks the list of inputs, adding tests for individual files and recursively searching directories for more tests. πŸ”₯

And like, that's the whole point: it makes it super easy to specify just a subset of tests to run, while the test suite configuration still gets to control exactly how those tests are interpreted. Also β€” and this is the iconic part β€” lit always identifies tests by the test suite they're in, plus their relative path inside that test suite. For projects that are configured the right way, that's what gives lit its convenient and flexible support for out-of-tree builds. πŸ’…


πŸ’– TEST STATUS RESULTS πŸ’–

Every single test ends up with exactly one of these eight results. Eight of them! Count 'em:

  • PASS β€” the test succeeded. slay. πŸ‘‘
  • FLAKYPASS β€” the test succeeded, but only after being re-run more than once. This one only applies to tests that contain an ALLOW_RETRIES: annotation. she needed a second chance and she took it. πŸŽ€
  • XFAIL β€” the test failed, but that's expected. This is used for test formats that let you specify a test doesn't currently work, but you still wanna leave it sitting in the test suite. it's fine. it's fine.
  • XPASS β€” the test succeeded, but it was expected to fail. This is for tests that were marked as expected-to-fail but are now passing (usually because the feature they test was broken and someone fixed it). glow-up behavior honestly. ✨
  • FAIL β€” the test failed. πŸ’€
  • UNRESOLVED β€” the test result could not be determined at all. For example, this happens when the test couldn't be run, or the test itself is invalid, or the test got interrupted. it's giving mystery. πŸ™ˆ
  • UNSUPPORTED β€” the test is not supported in this environment. Used by test formats that can report unsupported tests.
  • TIMEOUT β€” the test ran, but it timed out before it could finish. And heads up: this counts as a failure. ⏰

Depending on the test format, tests may produce extra info about their status (generally only for failures). Peep the OUTPUT OPTIONS section for more on that. πŸ‘€


✨ LIT INFRASTRUCTURE ✨

This section is for the girlies who wanna know how lit is actually built β€” whether you're creating a brand new lit testing implementation or extending one that already exists. πŸ› οΈ

Here's the vibe: lit proper is primarily an infrastructure for discovering and running arbitrary tests, and for exposing a single convenient interface to those tests. lit itself does not know how to run tests β€” that logic is defined by test suites. periodt.

πŸŽ€ TEST SUITES πŸŽ€

As we said back in TEST DISCOVERY, tests always live inside a test suite. Test suites are the ones that define the format of the tests they contain, the logic for finding those tests, and any additional info needed to run them. πŸ’–

lit identifies test suites as directories containing lit.cfg or lit.site.cfg files (see also --config-prefix). Test suites get discovered initially by recursively searching up the directory hierarchy for all the input files you passed on the command line. And you can use --show-suites to display the discovered test suites at startup. cute, right? 🌸

Once a test suite is discovered, its config file gets loaded. Config files are themselves Python modules that will be executed. When the config file runs, two important global variables are predefined for you:

  • lit_config β€” the global lit configuration object (a LitConfig instance), which defines the builtin test formats, global configuration parameters, and other helper routines for implementing test configurations.
  • config β€” the config object (a TestingConfig instance) for the test suite, which the config file is expected to populate. The following variables are also available on the config object β€” some of them must be set by the config, and the rest are optional or predefined:
    • name [required] β€” the name of the test suite, for use in reports and diagnostics.
    • test_format [required] β€” the test format object that will be used to discover and run tests in the test suite. Generally this will be a builtin test format available from the lit.formats module.
    • test_source_root β€” the filesystem path to the test suite root. For out-of-dir builds, this is the directory that will be scanned for tests.
    • test_exec_root β€” for out-of-dir builds, the path to the test suite root inside the object directory. This is where tests will be run and temporary output files placed.
    • environment β€” a dictionary representing the environment to use when executing tests in the suite.
    • standalone_tests β€” when true, marks a directory with tests expected to be run standalone. Test discovery is disabled for that directory and –no-indirectly-run-check is in effect. lit.suffixes and lit.excludes must be empty when this variable is true. ⚠️
    • suffixes β€” for lit test formats that scan directories for tests, this variable is a list of suffixes used to identify test files. Used by: ShTest.
    • substitutions β€” for lit test formats that substitute variables into a test script, the list of substitutions to perform. Used by: ShTest.
    • unsupported β€” marks an unsupported directory, and all tests within it will be reported as unsupported. Used by: ShTest.
    • parent β€” the parent configuration, i.e. the config object for the directory containing the test suite, or None.
    • root β€” the root configuration. This is the top-most lit configuration in the project.
    • pipefail β€” normally a test using a shell pipe fails if any of the commands on the pipe fail. If that's not what you want, setting this variable to false makes the test fail only if the last command in the pipe fails.
    • available_features β€” a set of features that can be used in XFAIL, REQUIRES, and UNSUPPORTED directives.

πŸ¦‹ TEST DISCOVERY πŸ¦‹

Once the test suites are located, lit recursively traverses the source directory (following test_source_root) looking for tests. When lit enters a sub-directory, the first thing it checks is whether a nested test suite is defined in that directory. If so, it loads that test suite recursively. If not, it instantiates a local test config for that directory (see LOCAL CONFIGURATION FILES below). 🌈

Tests are identified by the test suite they're contained within, plus the relative path inside that suite. And heads up: that relative path might not refer to an actual file on disk! Some test formats (like GoogleTest) define "virtual tests" whose path contains both the path to the actual test file and a subpath that identifies the virtual test. sneaky but iconic. πŸ’…

🌸 LOCAL CONFIGURATION FILES 🌸

When lit loads a subdirectory inside a test suite, it instantiates a local test configuration by cloning the configuration of the parent directory β€” and the root of this whole configuration chain will always be a test suite. Once the test configuration is cloned, lit checks for a lit.local.cfg file in that subdirectory. If it's there, that file gets loaded and can be used to specialize the configuration for each individual directory. πŸŽ€

This whole facility is perfect for defining subdirectories of optional tests, or for changing other configuration parameters β€” for example, changing the test format, or changing the suffixes that identify test files. chef's kiss. 😘

✨ SUBSTITUTIONS ✨

okay so here's the tea bestie: lit lets you substitute patterns inside RUN commands. and it also hands you this whole base set of substitutions for free, all defined in TestRunner.py 🫢

  • %s β€” source path (the path to the file that's currently being run, iykyk)
  • %S β€” source dir (the directory of the file currently being run)
  • %p β€” literally the same thing as %S
  • %{pathsep} β€” the path separator
  • %t β€” a temporary file name that's unique to the test ✨
  • %basename_t β€” the last path component of %t, but with the .tmp extension stripped off
  • %T β€” the parent directory of %t (⚠️ not unique, deprecated, do not use, bestie I'm begging)
  • %% β€” a literal %
  • %/s β€” %s but every \ gets replaced by /
  • %/S β€” %S but every \ gets replaced by /
  • %/p β€” %p but every \ gets replaced by /
  • %/t β€” %t but every \ gets replaced by /
  • %/T β€” %T but every \ gets replaced by /
  • %{/s:regex_replacement} β€” %/s but escaped so you can use it in the replacement of a s@@@ command in sed
  • %{/S:regex_replacement} β€” %/S but escaped so you can use it in the replacement of a s@@@ command in sed
  • %{/p:regex_replacement} β€” %/p but escaped so you can use it in the replacement of a s@@@ command in sed
  • %{/t:regex_replacement} β€” %/t but escaped so you can use it in the replacement of a s@@@ command in sed
  • %{/T:regex_replacement} β€” %/T but escaped so you can use it in the replacement of a s@@@ command in sed
  • %:s β€” on Windows, that's %/s but a : gets removed if it's the second character. otherwise, it's %s but with a single leading / removed.
  • %:S β€” on Windows, that's %/S but a : gets removed if it's the second character. otherwise, it's %S but with a single leading / removed.
  • %:p β€” on Windows, that's %/p but a : gets removed if it's the second character. otherwise, it's %p but with a single leading / removed.
  • %:t β€” on Windows, that's %/t but a : gets removed if it's the second character. otherwise, it's %t but with a single leading / removed.
  • %:T β€” on Windows, that's %/T but a : gets removed if it's the second character. otherwise, it's %T but with a single leading / removed.

and there's more, obviously πŸ’… other substitutions are provided that are just variations on this base set, and each test module can define even more substitution patterns of its own. peep the LOCAL CONFIGURATION FILES section for the modules.

now, the important bit, don't skip this 🫢 by default substitutions get expanded exactly once. so like, if a substitution %build is defined on top of another substitution %cxx, then %build expands to the text %cxx, not to whatever %cxx actually expands to. no cap.

but β€” if the recursiveExpansionLimit property of the TestingConfig is set to a non-negative integer, then substitutions get expanded recursively until that limit is hit. and here's the catch: it's an error if the limit is reached and expanding substitutions one more time would give you a different result. so like, know your limits bestie 😭

more detailed info on substitutions lives in the LLVM Testing Infrastructure Guide.


πŸŽ€ TEST RUN OUTPUT FORMAT πŸŽ€

the lit output for a test run follows this schema, in both short and verbose modes (tho in short mode there just won't be any PASS lines shown, sorry bestie). this schema was picked so a machine can reliably parse it (like, say, when you're scraping buildbot logs πŸ‘‘) and so other tools can generate it too.

every test result is expected to show up on a line matching:

<result code>: <test name> (<progress info>)

where <result-code> is a standard test result like PASS, FAIL, XFAIL, XPASS, UNRESOLVED, or UNSUPPORTED. the performance result codes IMPROVED and REGRESSED are also allowed ✨

the <test name> field can be any arbitrary string, just no newlines allowed in it.

the <progress info> field is for reporting progress info like (1/300), or it can be empty β€” but even when it's empty, the parentheses are required. them's the rules πŸ’…

every test result can also include extra (multiline) log info in this format:

<log delineator> TEST '(<test name>)' <trailing delineator>
... log message ...
<log delineator>

where <test name> should be the name of a preceding reported test, <log delineator> is a string of * characters that's at least four characters long (and bestie, the recommended length is 20, so like… go for 20 πŸ’…), and <trailing delineator> is an arbitrary (unparsed) string. She does not read it. She does not care. It's just vibes at the end. πŸ™ˆ

Okay so here's what a run looks like when it's got four tests β€” A, B, C, and D β€” and test C decides to absolutely tank and leaves a log message on its way out:

PASS: A (1 of 4)
PASS: B (2 of 4)
FAIL: C (3 of 4)
******************** TEST 'C' FAILED ********************
Test 'C' failed as a result of exit code 1.
********************
PASS: D (4 of 4)

See how C is out here being the main character of its own tragedy? 😭 A, B and D are just passing through like nothing happened. Iconic behaviour from all four of them honestly.


🌸 LIT EXAMPLE TESTS 🌸

The lit distribution ships with several example implementations of test suites living in the ExampleTests directory. Fr fr, they're right there for you to peek at β€” go look, it's giving free education. ✨


🫢 SEE ALSO 🫢


πŸ‘‘ AUTHOR πŸ‘‘

Maintained by the LLVM Team (https://llvm.org/). Slay, kings. πŸ’œ


2003-2025, LLVM Project


okay that's the whole page bestie, we made it to the end together πŸ₯Ή this was version 14, dated 2025-05-22, and it's the LIT(1) page β€” go forth and run your tests, no cap πŸ’–βœ¨πŸŒΈπŸ¦‹

πŸ“¦ where this page comes from