| .. _tests: |
| |
| Test Producers |
| ============== |
| |
| On the client-side, LNT comes with a number of built-in test data producers. |
| This section focuses on the LLVM test-suite (aka nightly test) generator, since |
| it is the primary test run using the LNT infrastructure, but note that LNT also |
| includes tests for other interesting pieces of data, for example Clang |
| compile-time performance. |
| |
| LNT also makes it easy to add new test data producers and includes examples of |
| custom data importers (e.g., to import buildbot build information into) and |
| dynamic test data generators (e.g., abusing the infrastructure to plot graphs, |
| for example). |
| |
| Running a Local Server |
| ---------------------- |
| |
| It is useful to set up a local LNT server to view the results of tests, either |
| for personal use or to preview results before submitting them to a public |
| server. To set up a one-off server for testing:: |
| |
| # Create a new installation in /tmp/FOO. |
| $ lnt create /tmp/FOO |
| created LNT configuration in '/tmp/FOO' |
| ... |
| |
| # Run a local LNT server. |
| $ lnt runserver /tmp/FOO &> /tmp/FOO/runserver.log & |
| [2] 69694 |
| |
| # Watch the server log. |
| $ tail -f /tmp/FOO/runserver.log |
| * Running on http://localhost:8000/ |
| ... |
| |
| Running Tests |
| ------------- |
| |
| The built-in tests are designed to be run via the ``lnt`` tool. The |
| following tools for working with built-in tests are available: |
| |
| ``lnt showtests`` |
| List the available tests. Tests are defined with an extensible |
| architecture. FIXME: Point at docs on how to add a new test. |
| |
| ``lnt runtest [<run options>] <test name> ... test arguments ...`` |
| Run the named test. The run tool itself accepts a number of options which |
| are common to all tests. The most common option is ``--submit=<url>`` which |
| specifies the server to submit the results to after testing is complete. See |
| ``lnt runtest --help`` for more information on the available options. |
| |
| The remainder of the options are passed to the test tool itself. The options |
| are specific to the test, but well behaved tests should respond to ``lnt |
| runtest <test name> --help``. The following section provides specific |
| documentation on the built-in tests. |
| |
| Built-in Tests |
| -------------- |
| |
| LLVM CMake test-suite |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| The llvm test-suite can be run with the ``test-suite`` built-in test. |
| |
| Running the test-suite via CMake and lit uses a different LNT test:: |
| |
| rm -rf /tmp/BAR |
| lnt runtest test-suite \ |
| --sandbox /tmp/BAR \ |
| --cc ~/llvm.obj.64/Release+Asserts/bin/clang \ |
| --cxx ~/llvm.obj.64/Release+Asserts/bin/clang++ \ |
| --use-cmake=/usr/local/bin/cmake \ |
| --use-lit=~/llvm/utils/lit/lit.py \ |
| --test-suite ~/llvm-test-suite \ |
| --cmake-cache Release |
| |
| Since the CMake test-suite uses lit to run the tests and compare their output, |
| LNT needs to know the path to your LLVM lit installation. The test-suite holds |
| some common configurations in CMake caches. The ``--cmake-cache`` flag |
| and the ``--cmake-define`` flag allow you to change how LNT configures cmake |
| for the test-suite run. |
| |
| |
| LLVM Makefile test-suite (aka LLVM Nightly Test) |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. note:: The Makefile test-suite is deprecated. |
| Consider using the cmake based ``lnt runtest test-suite`` mode instead. |
| It is actively maintained, collects additional metrics such as code size |
| and has extra features such as producing and using PGO data. |
| |
| The ``nt`` built-in test runs the LLVM test-suite execution and performance |
| tests, in the "nightly test" configuration. This test allows running many |
| different applications and benchmarks (e.g., SPEC), with various compile |
| options, and in several different configurations (for example, using an LLVM |
| compiler like ``clang`` or ``llvm-gcc``, running under the LLVM JIT compiler |
| using the LLVM ``lli`` bit-code interpreter, or testing new code generator |
| passes). |
| |
| The ``nt`` test requires that the LLVM test-suite repository, a working LLVM |
| compiler, and a LLVM source and build tree are available. Currently, the LLVM |
| build tree is expected to have been built-in the Release+Asserts configuration. |
| Unlike the prior ``NewNightlyTest.pl``, the ``nt`` tool does not checkout or build |
| any thing, it is expected that users manage their own LLVM source and build |
| trees. Ideally, each of the components should be based on the same LLVM revision |
| (except perhaps the LLVM test-suite), but this is not required. |
| |
| The test runs the LLVM test-suite builds and execution inside a user specificed |
| sandbox directory. By default, each test run will be done in a timestamped |
| directory inside the sandbox, and the results left around for post-mortem |
| analysis. Currently, the user is responsible for cleaning up these directories |
| to manage disk space. |
| |
| The tests are always expected to be run using out-of-tree builds -- this is a |
| more robust model and allow sharing the same source trees across many test |
| runs. One current limitation is that the LLVM test-suite repository will not |
| function correctly if an in-tree build is done, followed by an out-of-tree |
| build. It is very important that the LLVM test-suite repository be left |
| pristine. |
| |
| The following command shows an example of running the ``nt`` test suite on a |
| local build:: |
| |
| $ rm -rf /tmp/BAR |
| $ lnt runtest nt \ |
| --sandbox /tmp/BAR \ |
| --cc ~/llvm.obj.64/Release+Asserts/bin/clang \ |
| --cxx ~/llvm.obj.64/Release+Asserts/bin/clang++ \ |
| --llvm-src ~/llvm \ |
| --llvm-obj ~/llvm.obj.64 \ |
| --test-suite ~/llvm-test-suite \ |
| TESTER_NAME \ |
| -j 16 |
| 2010-04-17 23:46:40: using nickname: 'TESTER_NAME__clang_DEV__i386' |
| 2010-04-17 23:46:40: creating sandbox: '/tmp/BAR' |
| 2010-04-17 23:46:40: starting test in '/private/tmp/BAR/test-2010-04-17_23-46-40' |
| 2010-04-17 23:46:40: configuring... |
| 2010-04-17 23:46:50: testing... |
| 2010-04-17 23:51:04: loading test data... |
| 2010-04-17 23:51:05: generating report: '/private/tmp/BAR/test-2010-04-17_23-46-40/report.json' |
| |
| The first seven arguments are all required -- they specify the sandbox path, the |
| compilers to test, and the paths to the required sources and builds. The |
| ``TESTER_NAME`` argument is used to derive the name for this tester (in |
| conjunction which some inferred information about the compiler under test). This |
| name is used as a short identifier for the test machine; generally it should be |
| the hostname of the machine or the name of the person who is responsible for the |
| tester. The ``-j 16`` argument is optional, in this case it specifies that tests |
| should be run in parallel using up to 16 processes. |
| |
| In this case, we can see from the output that the test created a new sandbox |
| directory, then ran the test in a subdirectory in that sandbox. The test outputs |
| a limited about of summary information as testing is in progress. The full |
| information can be found in .log files within the test build directory (e.g., |
| ``configure.log`` and ``test.log``). |
| |
| The final test step was to generate a test report inside the test |
| directory. This report can now be submitted directly to an LNT server. For |
| example, if we have a local server running as described earlier, we can run:: |
| |
| $ lnt submit http://localhost:8000/submitRun \ |
| /tmp/BAR/test-2010-04-17_23-46-40/report.json |
| STATUS: 0 |
| |
| OUTPUT: |
| IMPORT: /tmp/FOO/lnt_tmp/data-2010-04-17_16-54-35ytpQm_.plist |
| LOAD TIME: 0.34s |
| IMPORT TIME: 5.23s |
| ADDED: 1 machines |
| ADDED: 1 runs |
| ADDED: 1990 tests |
| COMMITTING RESULT: DONE |
| TOTAL IMPORT TIME: 5.57s |
| |
| and view the results on our local server. |
| |
| LNT-based NT test modules |
| +++++++++++++++++++++++++ |
| |
| In order to support more complicated tests, or tests which are not easily |
| integrated into the more strict SingleSource or MultiSource layout of the LLVM |
| test-suite module, the ``nt`` built-in test provides a mechanism for LLVM |
| test-suite tests that just define an extension test module. These tests are |
| passed the user configuration parameters for a test run and expected to return |
| back the test results in the LNT native format. |
| |
| Test modules are defined by providing a ``TestModule`` file in a subdirectory of |
| the ``LNTBased`` root directory inside the LLVM test-suite repository. The |
| ``TestModule`` file is expected to be a well-formed Python module that provides |
| a ``test_class`` global variable which should be a subclass of the |
| ``lnt.tests.nt.TestModule`` abstract base class. |
| |
| The test class should override the ``execute_test`` method which is passed an |
| options dictionary containg the NT user parameters which apply to test |
| execution, and the test should return the test results as a list of |
| ``lnt.testing.TestSamples`` objects. |
| |
| The ``execute_test`` method is passed the following options describing |
| information about the module itself: |
| |
| * ``MODULENAME`` - The name of the module (primarily intended for use in |
| producing well structured test names). |
| |
| * ``SRCROOT`` - The path to the modules source directory. |
| |
| * ``OBJROOT`` - The path to a directory the module should use for temporary |
| output (build products). The directory is guaranteed to exist but is not |
| guaranteed to be clean. |
| |
| The method is passed the following options which apply to how tests should be |
| executed: |
| |
| * ``THREADS`` - The number of parallel processes to run during testing. |
| |
| * ``BUILD_THREADS`` - The number of parallel processes to use while building |
| tests (if applicable). |
| |
| The method is passed the following options which specify how and whether tests |
| should be executed remotely. If any of these parameters are present then all are |
| guaranteed to be present. |
| |
| * ``REMOTE_HOST`` - The host name of the remote machine to execute tests on. |
| |
| * ``REMOTE_USER`` - The user to log in to the remote machine as. |
| |
| * ``REMOTE_PORT`` - The port to connect to the remote machine on. |
| |
| * ``REMOTE_CLIENT`` - The ``rsh`` compatible client to use to connect to the |
| remote machine with. |
| |
| The method is passed the following options which specify how to build the tests: |
| |
| * ``CC`` - The C compiler command to use. |
| |
| * ``CXX`` - The C++ compiler command to use. |
| |
| * ``CFLAGS`` - The compiler flags to use for building C code. |
| |
| * ``CXXFLAGS`` - The compiler flags to use for building C++ code. |
| |
| The method is passed the following optional parameters which specify the |
| environment to use for various commands: |
| |
| * ``COMPILE_ENVIRONMENT_OVERRIDES`` [optional] - If given, a ``env`` style list |
| of environment overrides to use when compiling. |
| |
| * ``LINK_ENVIRONMENT_OVERRIDES`` [optional] - If given, a ``env`` style list of |
| environment overrides to use when linking. |
| |
| * ``EXECUTION_ENVIRONMENT_OVERRIDES`` [optional] - If given, a ``env`` style list of |
| environment overrides to use when executing tests. |
| |
| For more information, see the example tests in the LLVM test-suite repository |
| under the ``LNT/Examples`` directory. |
| |
| |
| |
| Capturing Linux perf profile info |
| +++++++++++++++++++++++++++++++++ |
| |
| When using the CMake driver in the test-suite, LNT can also capture profile |
| information using linux perf. This can then be explored through the LNT webUI |
| as demonstrated at |
| http://blog.llvm.org/2016/06/using-lnt-to-track-performance.html . |
| |
| To capture these profiles, use command line option ``--use-perf=all``. A |
| typical command line using this for evaluating the performance of generated |
| code looks something like the following:: |
| |
| lnt runtest test-suite \ |
| --sandbox SANDBOX \ |
| --cc ~/bin/clang \ |
| --use-cmake=/usr/local/bin/cmake \ |
| --use-lit=~/llvm/utils/lit/lit.py \ |
| --test-suite ~/llvm-test-suite \ |
| --benchmarking-only \ |
| --build-threads 8 \ |
| --threads 1 \ |
| --use-perf=all \ |
| --exec-multisample=5 \ |
| --run-under 'taskset -c 1' |
| |
| |
| Bisecting: ``--single-result`` and ``--single-result-predicate`` |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| The LNT driver for the CMake-based test suite comes with helpers for bisecting conformance and performance changes with ``llvmlab bisect``. |
| |
| ``llvmlab bisect`` is part of the ``zorg`` repository and allows easy bisection of some predicate through a build cache. The key to using ``llvmlab`` effectively is to design a good predicate command - one which exits with zero on 'pass' and nonzero on 'fail'. |
| |
| LNT normally runs one or more tests then produces a test report. It always exits with status zero unless an internal error occurred. The ``--single-result`` argument changes LNT's behaviour - it will only run one specific test and will apply a predicate to the result of that test to determine LNT's exit status. |
| |
| The ``--single-result-predicate`` argument defines the predicate to use. This is a Python expression that is executed in a context containing several pre-set variables: |
| |
| * ``status`` - Boolean passed or failed (True for passed, False for failed). |
| * ``exec_time`` - Execution time (note that ``exec`` is a reserved keyword in Python!) |
| * ``compile`` (or ``compile_time``) - Compilation time |
| |
| Any metrics returned from the test, such as "score" or "hash" are also added to the context. |
| |
| The default predicate is simply ``status`` - so this can be used to debug correctness regressions out of the box. More complex predicates are possible; for example ``exec_time < 3.0`` would bisect assuming that a 'good' result takes less than 3 seconds. |
| |
| Full example using ``llvmlab`` to debug a performance improvement:: |
| |
| llvmlab bisect --min-rev=261265 --max-rev=261369 \ |
| lnt runtest test-suite \ |
| --cc '%(path)s/bin/clang' \ |
| --sandbox SANDBOX \ |
| --test-suite /work/llvm-test-suite \ |
| --use-lit lit \ |
| --run-under 'taskset -c 5' \ |
| --cflags '-O3 -mthumb -mcpu=cortex-a57' \ |
| --single-result MultiSource/Benchmarks/TSVC/Expansion-flt/Expansion-flt \ |
| --single-result-predicate 'exec_time > 8.0' |
| |
| |
| Producing Diagnositic Reports |
| +++++++++++++++++++++++++++++ |
| |
| The test-suite module can produce a diagnostic report which might be useful |
| for figuring out what is going on with a benchmark:: |
| |
| lnt runtest test-suite \ |
| --sandbox /tmp/BAR \ |
| --cc ~/llvm.obj.64/Release+Asserts/bin/clang \ |
| --cxx ~/llvm.obj.64/Release+Asserts/bin/clang++ \ |
| --use-cmake=/usr/local/bin/cmake \ |
| --use-lit=~/llvm/utils/lit/lit.py \ |
| --test-suite ~/llvm-test-suite \ |
| --cmake-cache Release \ |
| --diagnose --only-test SingleSource/Benchmarks/Stanford/Bubblesort |
| |
| This will run the test-suite many times over, collecting useful information |
| in a report directory. The report collects many things like execution profiles, |
| compiler time reports, intermediate files, binary files, and build information. |
| |
| |
| Cross-compiling |
| +++++++++++++++ |
| |
| The best way to run the test-suite in a cross-compiling setup with the |
| cmake driver is to use cmake's built-in support for cross-compiling as much as |
| possible. In practice, the recommended way to cross-compile is to use a cmake |
| toolchain file (see |
| https://cmake.org/cmake/help/v3.0/manual/cmake-toolchains.7.html#cross-compiling) |
| |
| An example command line for cross-compiling on an X86 machine, targeting |
| AArch64 linux, is:: |
| |
| lnt runtest test-suite \ |
| --sandbox SANDBOX \ |
| --test-suite /work/llvm-test-suite \ |
| --use-lit lit \ |
| --cppflags="-O3" \ |
| --run-under=$HOME/dev/aarch64-emu/aarch64-qemu.sh \ |
| --cmake-define=CMAKE_TOOLCHAIN_FILE:FILEPATH=$HOME/clang_aarch64_linux.cmake |
| |
| The key part here is the CMAKE_TOOLCHAIN_FILE define. As you're |
| cross-compiling, you may need a --run-under command as the produced binaries |
| probably won't run natively on your development machine, but something extra |
| needs to be done (e.g. running under a qemu simulator, or transferring the |
| binaries to a development board). This isn't explained further here. |
| |
| In your toolchain file, it's important to specify that the cmake variables |
| defining the toolchain must be cached in CMakeCache.txt, as that's where lnt |
| reads them from to figure out which compiler was used when needing to construct |
| metadata for the json report. An example is below. The important keywords to |
| make the variables appear in the CMakeCache.txt are "CACHE STRING "" FORCE":: |
| |
| $ cat clang_aarch64_linux.cmake |
| set(CMAKE_SYSTEM_NAME Linux ) |
| set(triple aarch64-linux-gnu ) |
| set(CMAKE_C_COMPILER /home/user/build/bin/clang CACHE STRING "" FORCE) |
| set(CMAKE_C_COMPILER_TARGET ${triple} CACHE STRING "" FORCE) |
| set(CMAKE_CXX_COMPILER /home/user/build/bin/clang++ CACHE STRING "" FORCE) |
| set(CMAKE_CXX_COMPILER_TARGET ${triple} CACHE STRING "" FORCE) |
| set(CMAKE_SYSROOT /home/user/aarch64-emu/sysroot-glibc-linaro-2.23-2016.11-aarch64-linux-gnu ) |
| set(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN /home/user/aarch64-emu/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu ) |
| set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN /home/user/aarch64-emu/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu ) |
| |
| |