699 lines
45 KiB
HTML
699 lines
45 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="light sidebar-visible" dir="ltr">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>Test directives - Rust Compiler Development Guide</title>
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
<meta name="description" content="A guide to developing the Rust compiler (rustc)">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
<link rel="icon" href="../favicon.svg">
|
|
<link rel="shortcut icon" href="../favicon.png">
|
|
<link rel="stylesheet" href="../css/variables.css">
|
|
<link rel="stylesheet" href="../css/general.css">
|
|
<link rel="stylesheet" href="../css/chrome.css">
|
|
<link rel="stylesheet" href="../css/print.css" media="print">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
|
|
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
|
|
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
|
|
<!-- Provide site root and default themes to javascript -->
|
|
<script>
|
|
const path_to_root = "../";
|
|
const default_light_theme = "light";
|
|
const default_dark_theme = "navy";
|
|
</script>
|
|
<!-- Start loading toc.js asap -->
|
|
<script src="../toc.js"></script>
|
|
</head>
|
|
<body>
|
|
<div id="body-container">
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script>
|
|
try {
|
|
let theme = localStorage.getItem('mdbook-theme');
|
|
let sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script>
|
|
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
|
let theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
const html = document.documentElement;
|
|
html.classList.remove('light')
|
|
html.classList.add(theme);
|
|
html.classList.add("js");
|
|
</script>
|
|
|
|
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script>
|
|
let sidebar = null;
|
|
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
} else {
|
|
sidebar = 'hidden';
|
|
}
|
|
sidebar_toggle.checked = sidebar === 'visible';
|
|
html.classList.remove('sidebar-visible');
|
|
html.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<!-- populated by js -->
|
|
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
|
<noscript>
|
|
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
|
</noscript>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
|
<div class="sidebar-resize-indicator"></div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky">
|
|
<div class="left-buttons">
|
|
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</label>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<h1 class="menu-title">Rust Compiler Development Guide</h1>
|
|
|
|
<div class="right-buttons">
|
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
<a href="https://github.com/rust-lang/rustc-dev-guide" title="Git repository" aria-label="Git repository">
|
|
<i id="git-repository-button" class="fa fa-github"></i>
|
|
</a>
|
|
<a href="https://github.com/rust-lang/rustc-dev-guide/edit/master/src/tests/directives.md" title="Suggest an edit" aria-label="Suggest an edit">
|
|
<i id="git-edit-button" class="fa fa-edit"></i>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script>
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h1 id="compiletest-directives"><a class="header" href="#compiletest-directives">Compiletest directives</a></h1>
|
|
<ul>
|
|
<li><a href="#listing-of-compiletest-directives">Listing of compiletest directives</a>
|
|
<ul>
|
|
<li><a href="#assembly">Assembly</a></li>
|
|
<li><a href="#auxiliary-builds">Auxiliary builds</a></li>
|
|
<li><a href="#controlling-outcome-expectations">Controlling outcome expectations</a></li>
|
|
<li><a href="#controlling-output-snapshots-and-normalizations">Controlling output snapshots and normalizations</a></li>
|
|
<li><a href="#controlling-when-tests-are-run">Controlling when tests are run</a></li>
|
|
<li><a href="#affecting-how-tests-are-built">Affecting how tests are built</a></li>
|
|
<li><a href="#rustdoc">Rustdoc</a>
|
|
<ul>
|
|
<li><a href="#test-suite-specific-directives">Test-suite-specific directives</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#pretty-printing">Pretty printing</a>
|
|
<ul>
|
|
<li><a href="#misc-directives">Misc directives</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#tool-specific-directives">Tool-specific directives</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#substitutions">Substitutions</a></li>
|
|
<li><a href="#adding-a-directive">Adding a directive</a>
|
|
<ul>
|
|
<li><a href="#adding-a-new-directive-parser">Adding a new directive parser</a></li>
|
|
<li><a href="#implementing-the-behavior-change">Implementing the behavior change</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<!--
|
|
FIXME(jieyouxu) completely revise this chapter.
|
|
-->
|
|
<p>Directives are special comments that tell compiletest how to build and interpret a test.
|
|
They may also appear in <code>rmake.rs</code> <a href="compiletest.html#run-make-tests">run-make tests</a>.</p>
|
|
<p>They are normally put after the short comment that explains the point of this
|
|
test. Compiletest test suites use <code>//@</code> to signal that a comment is a directive.
|
|
For example, this test uses the <code>//@ compile-flags</code> command to specify a custom
|
|
flag to give to rustc when the test is compiled:</p>
|
|
<pre><code class="language-rust ignore">// Test the behavior of `0 - 1` when overflow checks are disabled.
|
|
|
|
//@ compile-flags: -C overflow-checks=off
|
|
|
|
fn main() {
|
|
let x = 0 - 1;
|
|
...
|
|
}</code></pre>
|
|
<p>Directives can be standalone (like <code>//@ run-pass</code>) or take a value (like <code>//@ compile-flags: -C overflow-checks=off</code>).</p>
|
|
<p>Directives are written one directive per line: you cannot write multiple
|
|
directives on the same line. For example, if you write <code>//@ only-x86 only-windows</code> then <code>only-windows</code> is interpreted as a comment, not a separate
|
|
directive.</p>
|
|
<h2 id="listing-of-compiletest-directives"><a class="header" href="#listing-of-compiletest-directives">Listing of compiletest directives</a></h2>
|
|
<p>The following is a list of compiletest directives. Directives are linked to
|
|
sections that describe the command in more detail if available. This list may
|
|
not be exhaustive. Directives can generally be found by browsing the
|
|
<code>TestProps</code> structure found in <a href="https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs"><code>header.rs</code></a> from the compiletest source.</p>
|
|
<h3 id="assembly"><a class="header" href="#assembly">Assembly</a></h3>
|
|
<!-- date-check: Oct 2024 -->
|
|
<div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Explanation</th><th>Supported test suites</th><th>Possible values</th></tr></thead><tbody>
|
|
<tr><td><code>assembly-output</code></td><td>Assembly output kind to check</td><td><code>assembly</code></td><td><code>emit-asm</code>, <code>bpf-linker</code>, <code>ptx-linker</code></td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
<h3 id="auxiliary-builds"><a class="header" href="#auxiliary-builds">Auxiliary builds</a></h3>
|
|
<div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Explanation</th><th>Supported test suites</th><th>Possible values</th></tr></thead><tbody>
|
|
<tr><td><code>aux-bin</code></td><td>Build a aux binary, made available in <code>auxiliary/bin</code> relative to test directory</td><td>All except <code>run-make</code></td><td>Path to auxiliary <code>.rs</code> file</td></tr>
|
|
<tr><td><code>aux-build</code></td><td>Build a separate crate from the named source file</td><td>All except <code>run-make</code></td><td>Path to auxiliary <code>.rs</code> file</td></tr>
|
|
<tr><td><code>aux-crate</code></td><td>Like <code>aux-build</code> but makes available as extern prelude</td><td>All except <code>run-make</code></td><td><code><extern_prelude_name>=<path/to/aux/file.rs></code></td></tr>
|
|
<tr><td><code>aux-codegen-backend</code></td><td>Similar to <code>aux-build</code> but pass the compiled dylib to <code>-Zcodegen-backend</code> when building the main file</td><td><code>ui-fulldeps</code></td><td>Path to codegen backend file</td></tr>
|
|
<tr><td><code>proc-macro</code></td><td>Similar to <code>aux-build</code>, but for aux forces host and don't use <code>-Cprefer-dynamic</code><sup class="footnote-reference" id="fr-pm-1"><a href="#footnote-pm">1</a></sup>.</td><td>All except <code>run-make</code></td><td>Path to auxiliary proc-macro <code>.rs</code> file</td></tr>
|
|
<tr><td><code>build-aux-docs</code></td><td>Build docs for auxiliaries as well</td><td>All except <code>run-make</code></td><td>N/A</td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
<h3 id="controlling-outcome-expectations"><a class="header" href="#controlling-outcome-expectations">Controlling outcome expectations</a></h3>
|
|
<p>See <a href="ui.html#controlling-passfail-expectations">Controlling pass/fail
|
|
expectations</a>.</p>
|
|
<div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Explanation</th><th>Supported test suites</th><th>Possible values</th></tr></thead><tbody>
|
|
<tr><td><code>check-pass</code></td><td>Building (no codegen) should pass</td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>check-fail</code></td><td>Building (no codegen) should fail</td><td><code>ui</code>, <code>crashes</code></td><td>N/A</td></tr>
|
|
<tr><td><code>build-pass</code></td><td>Building should pass</td><td><code>ui</code>, <code>crashes</code>, <code>codegen</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>build-fail</code></td><td>Building should fail</td><td><code>ui</code>, <code>crashes</code></td><td>N/A</td></tr>
|
|
<tr><td><code>run-pass</code></td><td>Running the test binary should pass</td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>run-fail</code></td><td>Running the test binary should fail</td><td><code>ui</code>, <code>crashes</code></td><td>N/A</td></tr>
|
|
<tr><td><code>ignore-pass</code></td><td>Ignore <code>--pass</code> flag</td><td><code>ui</code>, <code>crashes</code>, <code>codegen</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>dont-check-failure-status</code></td><td>Don't check exact failure status (i.e. <code>1</code>)</td><td><code>ui</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>failure-status</code></td><td>Check</td><td><code>ui</code>, <code>crashes</code></td><td>Any <code>u16</code></td></tr>
|
|
<tr><td><code>should-ice</code></td><td>Check failure status is <code>101</code></td><td><code>coverage</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>should-fail</code></td><td>Compiletest self-test</td><td>All</td><td>N/A</td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
<h3 id="controlling-output-snapshots-and-normalizations"><a class="header" href="#controlling-output-snapshots-and-normalizations">Controlling output snapshots and normalizations</a></h3>
|
|
<p>See <a href="ui.html#normalization">Normalization</a>, <a href="ui.html#output-comparison">Output
|
|
comparison</a> and <a href="ui.html#rustfix-tests">Rustfix tests</a>
|
|
for more details.</p>
|
|
<div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Explanation</th><th>Supported test suites</th><th>Possible values</th></tr></thead><tbody>
|
|
<tr><td><code>check-run-results</code></td><td>Check run test binary <code>run-{pass,fail}</code> output snapshot</td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code> if <code>run-pass</code></td><td>N/A</td></tr>
|
|
<tr><td><code>error-pattern</code></td><td>Check that output contains a specific string</td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code> if <code>run-pass</code></td><td>String</td></tr>
|
|
<tr><td><code>regex-error-pattern</code></td><td>Check that output contains a regex pattern</td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code> if <code>run-pass</code></td><td>Regex</td></tr>
|
|
<tr><td><code>check-stdout</code></td><td>Check <code>stdout</code> against <code>error-pattern</code>s from running test binary<sup class="footnote-reference" id="fr-check_stdout-1"><a href="#footnote-check_stdout">2</a></sup></td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code></td><td>N/A</td></tr>
|
|
<tr><td><code>normalize-stderr-32bit</code></td><td>Normalize actual stderr (for 32-bit platforms) with a rule <code>"<raw>" -> "<normalized>"</code> before comparing against snapshot</td><td><code>ui</code>, <code>incremental</code></td><td><code>"<RAW>" -> "<NORMALIZED>"</code>, <code><RAW></code>/<code><NORMALIZED></code> is regex capture and replace syntax</td></tr>
|
|
<tr><td><code>normalize-stderr-64bit</code></td><td>Normalize actual stderr (for 64-bit platforms) with a rule <code>"<raw>" -> "<normalized>"</code> before comparing against snapshot</td><td><code>ui</code>, <code>incremental</code></td><td><code>"<RAW>" -> "<NORMALIZED>"</code>, <code><RAW></code>/<code><NORMALIZED></code> is regex capture and replace syntax</td></tr>
|
|
<tr><td><code>normalize-stderr</code></td><td>Normalize actual stderr with a rule <code>"<raw>" -> "<normalized>"</code> before comparing against snapshot</td><td><code>ui</code>, <code>incremental</code></td><td><code>"<RAW>" -> "<NORMALIZED>"</code>, <code><RAW></code>/<code><NORMALIZED></code> is regex capture and replace syntax</td></tr>
|
|
<tr><td><code>normalize-stdout</code></td><td>Normalize actual stdout with a rule <code>"<raw>" -> "<normalized>"</code> before comparing against snapshot</td><td><code>ui</code>, <code>incremental</code></td><td><code>"<RAW>" -> "<NORMALIZED>"</code>, <code><RAW></code>/<code><NORMALIZED></code> is regex capture and replace syntax</td></tr>
|
|
<tr><td><code>dont-check-compiler-stderr</code></td><td>Don't check actual compiler stderr vs stderr snapshot</td><td><code>ui</code></td><td>N/A</td></tr>
|
|
<tr><td><code>dont-check-compiler-stdout</code></td><td>Don't check actual compiler stdout vs stdout snapshot</td><td><code>ui</code></td><td>N/A</td></tr>
|
|
<tr><td><code>dont-require-annotations</code></td><td>Don't require line annotations for the given diagnostic kind (<code>//~ KIND</code>) to be exhaustive</td><td><code>ui</code>, <code>incremental</code></td><td><code>ERROR</code>, <code>WARN</code>, <code>NOTE</code>, <code>HELP</code>, <code>SUGGESTION</code></td></tr>
|
|
<tr><td><code>run-rustfix</code></td><td>Apply all suggestions via <code>rustfix</code>, snapshot fixed output, and check fixed output builds</td><td><code>ui</code></td><td>N/A</td></tr>
|
|
<tr><td><code>rustfix-only-machine-applicable</code></td><td><code>run-rustfix</code> but only machine-applicable suggestions</td><td><code>ui</code></td><td>N/A</td></tr>
|
|
<tr><td><code>exec-env</code></td><td>Env var to set when executing a test</td><td><code>ui</code>, <code>crashes</code></td><td><code><KEY>=<VALUE></code></td></tr>
|
|
<tr><td><code>unset-exec-env</code></td><td>Env var to unset when executing a test</td><td><code>ui</code>, <code>crashes</code></td><td>Any env var name</td></tr>
|
|
<tr><td><code>stderr-per-bitwidth</code></td><td>Generate a stderr snapshot for each bitwidth</td><td><code>ui</code></td><td>N/A</td></tr>
|
|
<tr><td><code>forbid-output</code></td><td>A pattern which must not appear in stderr/<code>cfail</code> output</td><td><code>ui</code>, <code>incremental</code></td><td>Regex pattern</td></tr>
|
|
<tr><td><code>run-flags</code></td><td>Flags passed to the test executable</td><td><code>ui</code></td><td>Arbitrary flags</td></tr>
|
|
<tr><td><code>known-bug</code></td><td>No error annotation needed due to known bug</td><td><code>ui</code>, <code>crashes</code>, <code>incremental</code></td><td>Issue number <code>#123456</code></td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
<h3 id="controlling-when-tests-are-run"><a class="header" href="#controlling-when-tests-are-run">Controlling when tests are run</a></h3>
|
|
<p>These directives are used to ignore the test in some situations, which
|
|
means the test won't be compiled or run.</p>
|
|
<ul>
|
|
<li><code>ignore-X</code> where <code>X</code> is a target detail or other criteria on which to ignore the test (see below)</li>
|
|
<li><code>only-X</code> is like <code>ignore-X</code>, but will <em>only</em> run the test on that target or
|
|
stage</li>
|
|
<li><code>ignore-auxiliary</code> is intended for files that <em>participate</em> in one or more other
|
|
main test files but that <code>compiletest</code> should not try to build the file itself.
|
|
Please backlink to which main test is actually using the auxiliary file.</li>
|
|
<li><code>ignore-test</code> always ignores the test. This can be used to temporarily disable
|
|
a test if it is currently not working, but you want to keep it in tree to
|
|
re-enable it later.</li>
|
|
</ul>
|
|
<p>Some examples of <code>X</code> in <code>ignore-X</code> or <code>only-X</code>:</p>
|
|
<ul>
|
|
<li>A full target triple: <code>aarch64-apple-ios</code></li>
|
|
<li>Architecture: <code>aarch64</code>, <code>arm</code>, <code>mips</code>, <code>wasm32</code>, <code>x86_64</code>, <code>x86</code>,
|
|
...</li>
|
|
<li>OS: <code>android</code>, <code>emscripten</code>, <code>freebsd</code>, <code>ios</code>, <code>linux</code>, <code>macos</code>, <code>windows</code>,
|
|
...</li>
|
|
<li>Environment (fourth word of the target triple): <code>gnu</code>, <code>msvc</code>, <code>musl</code></li>
|
|
<li>WASM: <code>wasm32-bare</code> matches <code>wasm32-unknown-unknown</code>. <code>emscripten</code> also
|
|
matches that target as well as the emscripten targets.</li>
|
|
<li>Pointer width: <code>32bit</code>, <code>64bit</code></li>
|
|
<li>Endianness: <code>endian-big</code></li>
|
|
<li>Stage: <code>stage1</code>, <code>stage2</code></li>
|
|
<li>Binary format: <code>elf</code></li>
|
|
<li>Channel: <code>stable</code>, <code>beta</code></li>
|
|
<li>When cross compiling: <code>cross-compile</code></li>
|
|
<li>When <a href="running.html#running-tests-on-a-remote-machine">remote testing</a> is used: <code>remote</code></li>
|
|
<li>When particular debuggers are being tested: <code>cdb</code>, <code>gdb</code>, <code>lldb</code></li>
|
|
<li>When particular debugger versions are matched: <code>ignore-gdb-version</code></li>
|
|
<li>Specific <a href="ui.html#compare-modes">compare modes</a>: <code>compare-mode-polonius</code>, <code>compare-mode-chalk</code>,
|
|
<code>compare-mode-split-dwarf</code>, <code>compare-mode-split-dwarf-single</code></li>
|
|
<li>The two different test modes used by coverage tests:
|
|
<code>ignore-coverage-map</code>, <code>ignore-coverage-run</code></li>
|
|
<li>When testing a dist toolchain: <code>dist</code>
|
|
<ul>
|
|
<li>This needs to be enabled with <code>COMPILETEST_ENABLE_DIST_TESTS=1</code></li>
|
|
</ul>
|
|
</li>
|
|
<li>The <code>rustc_abi</code> of the target: e.g. <code>rustc_abi-x86_64-sse2</code></li>
|
|
</ul>
|
|
<p>The following directives will check rustc build settings and target
|
|
settings:</p>
|
|
<ul>
|
|
<li><code>needs-asm-support</code> — ignores if it is running on a target that doesn't have
|
|
stable support for <code>asm!</code></li>
|
|
<li><code>needs-profiler-runtime</code> — ignores the test if the profiler runtime was not
|
|
enabled for the target
|
|
(<code>build.profiler = true</code> in rustc's <code>bootstrap.toml</code>)</li>
|
|
<li><code>needs-sanitizer-support</code> — ignores if the sanitizer support was not enabled
|
|
for the target (<code>sanitizers = true</code> in rustc's <code>bootstrap.toml</code>)</li>
|
|
<li><code>needs-sanitizer-{address,hwaddress,leak,memory,thread}</code> — ignores if the
|
|
corresponding sanitizer is not enabled for the target (AddressSanitizer,
|
|
hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or
|
|
ThreadSanitizer respectively)</li>
|
|
<li><code>needs-run-enabled</code> — ignores if it is a test that gets executed, and running
|
|
has been disabled. Running tests can be disabled with the <code>x test --run=never</code>
|
|
flag, or running on fuchsia.</li>
|
|
<li><code>needs-unwind</code> — ignores if the target does not support unwinding</li>
|
|
<li><code>needs-rust-lld</code> — ignores if the rust lld support is not enabled (<code>rust.lld = true</code> in <code>bootstrap.toml</code>)</li>
|
|
<li><code>needs-threads</code> — ignores if the target does not have threading support</li>
|
|
<li><code>needs-subprocess</code> — ignores if the target does not have subprocess support</li>
|
|
<li><code>needs-symlink</code> — ignores if the target does not support symlinks. This can be
|
|
the case on Windows if the developer did not enable privileged symlink
|
|
permissions.</li>
|
|
<li><code>ignore-std-debug-assertions</code> — ignores if std was built with debug
|
|
assertions.</li>
|
|
<li><code>needs-std-debug-assertions</code> — ignores if std was not built with debug
|
|
assertions.</li>
|
|
<li><code>ignore-rustc-debug-assertions</code> — ignores if rustc was built with debug
|
|
assertions.</li>
|
|
<li><code>needs-rustc-debug-assertions</code> — ignores if rustc was not built with debug
|
|
assertions.</li>
|
|
<li><code>needs-target-has-atomic</code> — ignores if target does not have support for all
|
|
specified atomic widths, e.g. the test with <code>//@ needs-target-has-atomic: 8, 16, ptr</code> will only run if it supports the comma-separated list of atomic
|
|
widths.</li>
|
|
<li><code>needs-dynamic-linking</code> — ignores if target does not support dynamic linking
|
|
(which is orthogonal to it being unable to create <code>dylib</code> and <code>cdylib</code> crate types)</li>
|
|
<li><code>needs-crate-type</code> — ignores if target platform does not support one or more
|
|
of the comma-delimited list of specified crate types. For example,
|
|
<code>//@ needs-crate-type: cdylib, proc-macro</code> will cause the test to be ignored
|
|
on <code>wasm32-unknown-unknown</code> target because the target does not support the
|
|
<code>proc-macro</code> crate type.</li>
|
|
<li><code>needs-target-std</code> — ignores if target platform does not have std support.</li>
|
|
</ul>
|
|
<p>The following directives will check LLVM support:</p>
|
|
<ul>
|
|
<li><code>exact-llvm-major-version: 19</code> — ignores if the llvm major version does not
|
|
match the specified llvm major version.</li>
|
|
<li><code>min-llvm-version: 13.0</code> — ignored if the LLVM version is less than the given
|
|
value</li>
|
|
<li><code>min-system-llvm-version: 12.0</code> — ignored if using a system LLVM and its
|
|
version is less than the given value</li>
|
|
<li><code>max-llvm-major-version: 19</code> — ignored if the LLVM major version is higher
|
|
than the given major version</li>
|
|
<li><code>ignore-llvm-version: 9.0</code> — ignores a specific LLVM version</li>
|
|
<li><code>ignore-llvm-version: 7.0 - 9.9.9</code> — ignores LLVM versions in a range
|
|
(inclusive)</li>
|
|
<li><code>needs-llvm-components: powerpc</code> — ignores if the specific LLVM component was
|
|
not built. Note: The test will fail on CI (when
|
|
<code>COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS</code> is set) if the component does not
|
|
exist.</li>
|
|
<li><code>needs-forced-clang-based-tests</code> — test is ignored unless the environment
|
|
variable <code>RUSTBUILD_FORCE_CLANG_BASED_TESTS</code> is set, which enables building
|
|
clang alongside LLVM
|
|
<ul>
|
|
<li>This is only set in two CI jobs (<a href="https://github.com/rust-lang/rust/blob/ab3dba92db355b8d97db915a2dca161a117e959c/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile#L32"><code>x86_64-gnu-debug</code></a> and
|
|
<a href="https://github.com/rust-lang/rust/blob/20c909ff9cdd88d33768a4ddb8952927a675b0ad/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile#L32"><code>aarch64-gnu-debug</code></a>), which only runs a
|
|
subset of <code>run-make</code> tests. Other tests with this directive will not
|
|
run at all, which is usually not what you want.</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<p>See also <a href="compiletest.html#debuginfo-tests">Debuginfo tests</a> for directives for
|
|
ignoring debuggers.</p>
|
|
<h3 id="affecting-how-tests-are-built"><a class="header" href="#affecting-how-tests-are-built">Affecting how tests are built</a></h3>
|
|
<div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Explanation</th><th>Supported test suites</th><th>Possible values</th></tr></thead><tbody>
|
|
<tr><td><code>compile-flags</code></td><td>Flags passed to <code>rustc</code> when building the test or aux file</td><td>All except for <code>run-make</code></td><td>Any valid <code>rustc</code> flags, e.g. <code>-Awarnings -Dfoo</code>. Cannot be <code>-Cincremental</code> or <code>--edition</code></td></tr>
|
|
<tr><td><code>edition</code></td><td>The edition used to build the test</td><td>All except for <code>run-make</code></td><td>Any valid <code>--edition</code> value</td></tr>
|
|
<tr><td><code>rustc-env</code></td><td>Env var to set when running <code>rustc</code></td><td>All except for <code>run-make</code></td><td><code><KEY>=<VALUE></code></td></tr>
|
|
<tr><td><code>unset-rustc-env</code></td><td>Env var to unset when running <code>rustc</code></td><td>All except for <code>run-make</code></td><td>Any env var name</td></tr>
|
|
<tr><td><code>incremental</code></td><td>Proper incremental support for tests outside of incremental test suite</td><td><code>ui</code>, <code>crashes</code></td><td>N/A</td></tr>
|
|
<tr><td><code>no-prefer-dynamic</code></td><td>Don't use <code>-C prefer-dynamic</code>, don't build as a dylib via a <code>--crate-type=dylib</code> preset flag</td><td><code>ui</code>, <code>crashes</code></td><td>N/A</td></tr>
|
|
</tbody></table>
|
|
</div><div class="warning">
|
|
<p>Tests (outside of <code>run-make</code>) that want to use incremental tests not in the
|
|
incremental test-suite must not pass <code>-C incremental</code> via <code>compile-flags</code>, and
|
|
must instead use the <code>//@ incremental</code> directive.</p>
|
|
<p>Consider writing the test as a proper incremental test instead.</p>
|
|
</div>
|
|
<h3 id="rustdoc"><a class="header" href="#rustdoc">Rustdoc</a></h3>
|
|
<div class="table-wrapper"><table><thead><tr><th>Directive</th><th>Explanation</th><th>Supported test suites</th><th>Possible values</th></tr></thead><tbody>
|
|
<tr><td><code>doc-flags</code></td><td>Flags passed to <code>rustdoc</code> when building the test or aux file</td><td><code>rustdoc</code>, <code>rustdoc-js</code>, <code>rustdoc-json</code></td><td>Any valid <code>rustdoc</code> flags</td></tr>
|
|
</tbody></table>
|
|
</div><!--
|
|
**FIXME(rustdoc)**: what does `check-test-line-numbers-match` do?
|
|
Asked in
|
|
<https://rust-lang.zulipchat.com/#narrow/stream/266220-t-rustdoc/topic/What.20is.20the.20.60check-test-line-numbers-match.60.20directive.3F>.
|
|
-->
|
|
<h4 id="test-suite-specific-directives"><a class="header" href="#test-suite-specific-directives">Test-suite-specific directives</a></h4>
|
|
<p>The test suites <a href="../rustdoc-internals/rustdoc-test-suite.html"><code>rustdoc</code></a>, <a href="../rustdoc-internals/search.html#testing-the-search-engine"><code>rustdoc-js</code>/<code>rustdoc-js-std</code></a>
|
|
and <a href="../rustdoc-internals/rustdoc-json-test-suite.html"><code>rustdoc-json</code></a> each feature an additional set of directives whose basic
|
|
syntax resembles the one of compiletest directives but which are ultimately read and checked by
|
|
separate tools. For more information, please read their respective chapters as linked above.</p>
|
|
<h3 id="pretty-printing"><a class="header" href="#pretty-printing">Pretty printing</a></h3>
|
|
<p>See <a href="compiletest.html#pretty-printer-tests">Pretty-printer</a>.</p>
|
|
<h4 id="misc-directives"><a class="header" href="#misc-directives">Misc directives</a></h4>
|
|
<ul>
|
|
<li><code>no-auto-check-cfg</code> — disable auto check-cfg (only for <code>--check-cfg</code> tests)</li>
|
|
<li><a href="compiletest.html#revisions"><code>revisions</code></a> — compile multiple times</li>
|
|
<li><a href="compiletest.html#ignoring-unused-revision-names"><code>unused-revision-names</code></a> -
|
|
suppress tidy checks for mentioning unknown revision names
|
|
-<a href="compiletest.html#incremental-tests"><code>forbid-output</code></a> — incremental cfail rejects
|
|
output pattern</li>
|
|
<li><a href="compiletest.html#incremental-tests"><code>should-ice</code></a> — incremental cfail should
|
|
ICE</li>
|
|
<li><a href="https://github.com/rust-lang/reference/blob/master/docs/authoring.md#test-rule-annotations"><code>reference</code></a> — an annotation linking to a rule in the reference</li>
|
|
</ul>
|
|
<h3 id="tool-specific-directives"><a class="header" href="#tool-specific-directives">Tool-specific directives</a></h3>
|
|
<p>The following directives affect how certain command-line tools are invoked, in
|
|
test suites that use those tools:</p>
|
|
<ul>
|
|
<li><code>filecheck-flags</code> adds extra flags when running LLVM's <code>FileCheck</code> tool.
|
|
<ul>
|
|
<li>Used by <a href="compiletest.html#codegen-tests">codegen tests</a>,
|
|
<a href="compiletest.html#assembly-tests">assembly tests</a>, and
|
|
<a href="compiletest.html#mir-opt-tests">MIR-opt tests</a>.</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>llvm-cov-flags</code> adds extra flags when running LLVM's <code>llvm-cov</code> tool.
|
|
<ul>
|
|
<li>Used by <a href="compiletest.html#coverage-tests">coverage tests</a> in <code>coverage-run</code> mode.</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<h2 id="substitutions"><a class="header" href="#substitutions">Substitutions</a></h2>
|
|
<p>Directive values support substituting a few variables which will be replaced
|
|
with their corresponding value. For example, if you need to pass a compiler flag
|
|
with a path to a specific file, something like the following could work:</p>
|
|
<pre><code class="language-rust ignore">//@ compile-flags: --remap-path-prefix={{src-base}}=/the/src</code></pre>
|
|
<p>Where the sentinel <code>{{src-base}}</code> will be replaced with the appropriate path
|
|
described below:</p>
|
|
<ul>
|
|
<li><code>{{cwd}}</code>: The directory where compiletest is run from. This may not be the
|
|
root of the checkout, so you should avoid using it where possible.
|
|
<ul>
|
|
<li>Examples: <code>/path/to/rust</code>, <code>/path/to/build/root</code></li>
|
|
</ul>
|
|
</li>
|
|
<li><code>{{src-base}}</code>: The directory where the test is defined. This is equivalent to
|
|
<code>$DIR</code> for <a href="ui.html#normalization">output normalization</a>.
|
|
<ul>
|
|
<li>Example: <code>/path/to/rust/tests/ui/error-codes</code></li>
|
|
</ul>
|
|
</li>
|
|
<li><code>{{build-base}}</code>: The base directory where the test's output goes. This is
|
|
equivalent to <code>$TEST_BUILD_DIR</code> for <a href="ui.html#normalization">output normalization</a>.
|
|
<ul>
|
|
<li>Example: <code>/path/to/rust/build/x86_64-unknown-linux-gnu/test/ui</code></li>
|
|
</ul>
|
|
</li>
|
|
<li><code>{{rust-src-base}}</code>: The sysroot directory where libstd/libcore/... are
|
|
located</li>
|
|
<li><code>{{sysroot-base}}</code>: Path of the sysroot directory used to build the test.
|
|
<ul>
|
|
<li>Mainly intended for <code>ui-fulldeps</code> tests that run the compiler via API.</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>{{target-linker}}</code>: Linker that would be passed to <code>-Clinker</code> for this test,
|
|
or blank if no linker override is active.
|
|
<ul>
|
|
<li>Mainly intended for <code>ui-fulldeps</code> tests that run the compiler via API.</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>{{target}}</code>: The target the test is compiling for
|
|
<ul>
|
|
<li>Example: <code>x86_64-unknown-linux-gnu</code></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<p>See
|
|
<a href="https://github.com/rust-lang/rust/blob/master/tests/ui/argfile/commandline-argfile.rs"><code>tests/ui/commandline-argfile.rs</code></a>
|
|
for an example of a test that uses this substitution.</p>
|
|
<h2 id="adding-a-directive"><a class="header" href="#adding-a-directive">Adding a directive</a></h2>
|
|
<p>One would add a new directive if there is a need to define some test property or
|
|
behavior on an individual, test-by-test basis. A directive property serves as
|
|
the directive's backing store (holds the command's current value) at runtime.</p>
|
|
<p>To add a new directive property:</p>
|
|
<ol>
|
|
<li>Look for the <code>pub struct TestProps</code> declaration in
|
|
<a href="https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs"><code>src/tools/compiletest/src/header.rs</code></a> and add the new public property to
|
|
the end of the declaration.</li>
|
|
<li>Look for the <code>impl TestProps</code> implementation block immediately following the
|
|
struct declaration and initialize the new property to its default value.</li>
|
|
</ol>
|
|
<h3 id="adding-a-new-directive-parser"><a class="header" href="#adding-a-new-directive-parser">Adding a new directive parser</a></h3>
|
|
<p>When <code>compiletest</code> encounters a test file, it parses the file a line at a time
|
|
by calling every parser defined in the <code>Config</code> struct's implementation block,
|
|
also in <a href="https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs"><code>src/tools/compiletest/src/header.rs</code></a> (note that the <code>Config</code> struct's
|
|
declaration block is found in <a href="https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/common.rs"><code>src/tools/compiletest/src/common.rs</code></a>).
|
|
<code>TestProps</code>'s <code>load_from()</code> method will try passing the current line of text to
|
|
each parser, which, in turn typically checks to see if the line begins with a
|
|
particular commented (<code>//@</code>) directive such as <code>//@ must-compile-successfully</code>
|
|
or <code>//@ failure-status</code>. Whitespace after the comment marker is optional.</p>
|
|
<p>Parsers will override a given directive property's default value merely by being
|
|
specified in the test file as a directive or by having a parameter value
|
|
specified in the test file, depending on the directive.</p>
|
|
<p>Parsers defined in <code>impl Config</code> are typically named <code>parse_<directive-name></code>
|
|
(note kebab-case <code><directive-command></code> transformed to snake-case
|
|
<code><directive_command></code>). <code>impl Config</code> also defines several 'low-level' parsers
|
|
which make it simple to parse common patterns like simple presence or not
|
|
(<code>parse_name_directive()</code>), <code>directive:parameter(s)</code>
|
|
(<code>parse_name_value_directive()</code>), optional parsing only if a particular <code>cfg</code>
|
|
attribute is defined (<code>has_cfg_prefix()</code>) and many more. The low-level parsers
|
|
are found near the end of the <code>impl Config</code> block; be sure to look through them
|
|
and their associated parsers immediately above to see how they are used to avoid
|
|
writing additional parsing code unnecessarily.</p>
|
|
<p>As a concrete example, here is the implementation for the
|
|
<code>parse_failure_status()</code> parser, in <a href="https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs"><code>src/tools/compiletest/src/header.rs</code></a>:</p>
|
|
<pre><code class="language-diff">@@ -232,6 +232,7 @@ pub struct TestProps {
|
|
// customized normalization rules
|
|
pub normalize_stdout: Vec<(String, String)>,
|
|
pub normalize_stderr: Vec<(String, String)>,
|
|
+ pub failure_status: i32,
|
|
}
|
|
|
|
impl TestProps {
|
|
@@ -260,6 +261,7 @@ impl TestProps {
|
|
run_pass: false,
|
|
normalize_stdout: vec![],
|
|
normalize_stderr: vec![],
|
|
+ failure_status: 101,
|
|
}
|
|
}
|
|
|
|
@@ -383,6 +385,10 @@ impl TestProps {
|
|
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
|
|
self.normalize_stderr.push(rule);
|
|
}
|
|
+
|
|
+ if let Some(code) = config.parse_failure_status(ln) {
|
|
+ self.failure_status = code;
|
|
+ }
|
|
});
|
|
|
|
for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
|
|
@@ -488,6 +494,13 @@ impl Config {
|
|
self.parse_name_directive(line, "pretty-compare-only")
|
|
}
|
|
|
|
+ fn parse_failure_status(&self, line: &str) -> Option<i32> {
|
|
+ match self.parse_name_value_directive(line, "failure-status") {
|
|
+ Some(code) => code.trim().parse::<i32>().ok(),
|
|
+ _ => None,
|
|
+ }
|
|
+ }
|
|
</code></pre>
|
|
<h3 id="implementing-the-behavior-change"><a class="header" href="#implementing-the-behavior-change">Implementing the behavior change</a></h3>
|
|
<p>When a test invokes a particular directive, it is expected that some behavior
|
|
will change as a result. What behavior, obviously, will depend on the purpose of
|
|
the directive. In the case of <code>failure-status</code>, the behavior that changes is
|
|
that <code>compiletest</code> expects the failure code defined by the directive invoked in
|
|
the test, rather than the default value.</p>
|
|
<p>Although specific to <code>failure-status</code> (as every directive will have a different
|
|
implementation in order to invoke behavior change) perhaps it is helpful to see
|
|
the behavior change implementation of one case, simply as an example. To
|
|
implement <code>failure-status</code>, the <code>check_correct_failure_status()</code> function found
|
|
in the <code>TestCx</code> implementation block, located in
|
|
<a href="https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/runtest.rs"><code>src/tools/compiletest/src/runtest.rs</code></a>, was modified as per below:</p>
|
|
<pre><code class="language-diff">@@ -295,11 +295,14 @@ impl<'test> TestCx<'test> {
|
|
}
|
|
|
|
fn check_correct_failure_status(&self, proc_res: &ProcRes) {
|
|
- // The value the Rust runtime returns on failure
|
|
- const RUST_ERR: i32 = 101;
|
|
- if proc_res.status.code() != Some(RUST_ERR) {
|
|
+ let expected_status = Some(self.props.failure_status);
|
|
+ let received_status = proc_res.status.code();
|
|
+
|
|
+ if expected_status != received_status {
|
|
self.fatal_proc_rec(
|
|
- &format!("failure produced the wrong error: {}", proc_res.status),
|
|
+ &format!("Error: expected failure status ({:?}) but received status {:?}.",
|
|
+ expected_status,
|
|
+ received_status),
|
|
proc_res,
|
|
);
|
|
}
|
|
@@ -320,7 +323,6 @@ impl<'test> TestCx<'test> {
|
|
);
|
|
|
|
let proc_res = self.exec_compiled_test();
|
|
-
|
|
if !proc_res.status.success() {
|
|
self.fatal_proc_rec("test run failed!", &proc_res);
|
|
}
|
|
@@ -499,7 +501,6 @@ impl<'test> TestCx<'test> {
|
|
expected,
|
|
actual
|
|
);
|
|
- panic!();
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>Note the use of <code>self.props.failure_status</code> to access the directive property. In
|
|
tests which do not specify the failure status directive,
|
|
<code>self.props.failure_status</code> will evaluate to the default value of 101 at the
|
|
time of this writing. But for a test which specifies a directive of, for
|
|
example, <code>//@ failure-status: 1</code>, <code>self.props.failure_status</code> will evaluate to
|
|
1, as <code>parse_failure_status()</code> will have overridden the <code>TestProps</code> default
|
|
value, for that test specifically.</p>
|
|
<hr>
|
|
<ol class="footnote-definition"><li id="footnote-pm">
|
|
<p>please see the Auxiliary proc-macro section in the
|
|
<a href="./compiletest.html">compiletest</a> chapter for specifics. <a href="#fr-pm-1">↩</a></p>
|
|
</li>
|
|
<li id="footnote-check_stdout">
|
|
<p>presently <!-- date-check: Oct 2024 --> this has a weird quirk
|
|
where the test binary's stdout and stderr gets concatenated and then
|
|
<code>error-pattern</code>s are matched on this combined output, which is ??? slightly
|
|
questionable to say the least. <a href="#fr-check_stdout-1">↩</a></p>
|
|
</li>
|
|
</ol>
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
<a rel="prev" href="../tests/ui.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../tests/minicore.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
<a rel="prev" href="../tests/ui.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../tests/minicore.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
<script src="../elasticlunr.min.js"></script>
|
|
<script src="../mark.min.js"></script>
|
|
<script src="../searcher.js"></script>
|
|
|
|
<script src="../clipboard.min.js"></script>
|
|
<script src="../highlight.js"></script>
|
|
<script src="../book.js"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
<script src="../mermaid.min.js"></script>
|
|
<script src="../mermaid-init.js"></script>
|
|
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|