Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compiletest ディレクティブ

ディレクティブは、テストをどのようにビルドし解釈するかを compiletest に伝える特別なコメントです。 rmake.rsrun-make テストにも現れることがあります。

通常、ディレクティブはこのテストの要点を説明する短いコメントの後に置かれます。 Compiletest のテストスイートでは、コメントがディレクティブであることを示すために //@ を使用します。 たとえば、このテストでは、テストのコンパイル時に rustc に渡すカスタムフラグを指定するために、//@ compile-flags コマンドを使用しています。

// オーバーフローチェックが無効な場合の `0 - 1` の挙動をテストする。

//@ compile-flags: -C overflow-checks=off

fn main() {
    let x = 0 - 1;
    ...
}

ディレクティブは単独で記述することも(例: //@ run-pass)、値を取ることもできます(例: //@ compile-flags: -C overflow-checks=off)。

ディレクティブは 1 行につき 1 つ記述します。同じ行に複数のディレクティブを書くことはできません。 たとえば、//@ only-x86 only-windows と書いた場合、 only-windows は別個のディレクティブではなく、コメントとして解釈されます。

compiletest ディレクティブの一覧

以下は compiletest ディレクティブの一覧です。 利用可能な場合、ディレクティブはそのコマンドをより詳しく説明するセクションにリンクされています。 この一覧は網羅的ではない可能性があります。 ディレクティブは一般に、compiletest ソースの directives.rs にある TestProps 構造体を参照することで見つけられます。

アセンブリ

ディレクティブ説明対応するテストスイート指定可能な値
assembly-outputチェックするアセンブリ出力の種類assemblyemit-asm, bpf-linker, ptx-linker

補助ビルド

補助クレートのビルドを参照してください

ディレクティブ説明対応するテストスイート指定可能な値
aux-bin補助バイナリをビルドし、テストディレクトリからの相対パス auxiliary/bin で利用可能にするrun-make/run-make-cargo を除くすべて補助 .rs ファイルへのパス
aux-build指定されたソースファイルから別個のクレートをビルドするrun-make/run-make-cargo を除くすべて補助 .rs ファイルへのパス
aux-crateaux-build と似ているが、extern prelude として利用可能にするrun-make/run-make-cargo を除くすべて[<extern_modifiers>:]<extern_prelude_name>=<path/to/aux/file.rs>
aux-codegen-backendaux-build と似ているが、メインファイルのビルド時にコンパイル済み dylib を -Zcodegen-backend に渡すui-fulldepscodegen backend ファイルへのパス
proc-macroaux-build と似ているが、aux に対してホストを強制し、-Cprefer-dynamic1 を使用しない。run-make/run-make-cargo を除くすべて補助 proc-macro .rs ファイルへのパス
build-aux-docs補助対象についてもドキュメントをビルドする。これは aux-crate ではなく aux-build でのみ動作することに注意。run-make/run-make-cargo を除くすべてN/A

結果の期待値の制御

pass/fail 期待値の制御を参照してください。

ディレクティブ説明対応するテストスイート指定可能な値
check-passビルド(codegen なし)は成功するべきuiN/A
check-failビルド(codegen なし)は失敗するべきuiN/A
build-passビルドは成功するべきuiN/A
build-failビルドは失敗するべきuiN/A
run-passプログラムはコード 0 で終了しなければならないuiN/A
run-failプログラムはコード 1..=127 で終了しなければならないuiN/A
run-crashプログラムはクラッシュしなければならないuiN/A
run-fail-or-crashプログラムは run-fail または run-crash でなければならないuiN/A
no-pass-override--pass フラグを無視するuiN/A
dont-check-failure-status正確な失敗ステータス(つまり 1)をチェックしないui, incrementalN/A
failure-status失敗時、コンパイラはこのステータスコードで終了しなければならない。ICE を期待するには、//@ failure-status: 101 を使用する。ui, incremental任意の u16
should-failCompiletest のセルフテストすべてN/A

出力スナップショットと正規化の制御

詳細については、正規化出力 比較、および Rustfix テストを参照してください。

ディレクティブ説明サポートされるテストスイート使用可能な値
check-run-resultsテストバイナリ run-{pass,fail} の実行結果の出力スナップショットを確認するui, crashes, incrementalN/A
error-pattern出力に特定の文字列が含まれていることを確認するui, crashes, incremental文字列
regex-error-pattern出力に正規表現パターンが含まれていることを確認するui, crashes, incremental正規表現
check-stdoutテストバイナリの実行結果の stdouterror-pattern と照合する2ui, crashes, incrementalN/A
normalize-stderr-32bitスナップショットと比較する前に、ルール "<raw>" -> "<normalized>" で実際の stderr(32 ビットプラットフォーム向け)を正規化するui, incremental"<RAW>" -> "<NORMALIZED>"<RAW>/<NORMALIZED> は正規表現のキャプチャおよび置換構文
normalize-stderr-64bitスナップショットと比較する前に、ルール "<raw>" -> "<normalized>" で実際の stderr(64 ビットプラットフォーム向け)を正規化するui, incremental"<RAW>" -> "<NORMALIZED>"<RAW>/<NORMALIZED> は正規表現のキャプチャおよび置換構文
normalize-stderrスナップショットと比較する前に、ルール "<raw>" -> "<normalized>" で実際の stderr を正規化するui, incremental"<RAW>" -> "<NORMALIZED>"<RAW>/<NORMALIZED> は正規表現のキャプチャおよび置換構文
normalize-stdoutスナップショットと比較する前に、ルール "<raw>" -> "<normalized>" で実際の stdout を正規化するui, incremental"<RAW>" -> "<NORMALIZED>"<RAW>/<NORMALIZED> は正規表現のキャプチャおよび置換構文
dont-check-compiler-stderr実際のコンパイラ stderr と stderr スナップショットを照合しないuiN/A
dont-check-compiler-stdout実際のコンパイラ stdout と stdout スナップショットを照合しないuiN/A
dont-require-annotations指定された診断種別(//~ KIND)について、行アノテーションが網羅的であることを要求しないui, incrementalERROR, WARN, NOTE, HELP, SUGGESTION
run-rustfixrustfix によってすべての提案を適用し、修正後の出力をスナップショット化し、修正後の出力がビルドできることを確認するuiN/A
rustfix-only-machine-applicablerun-rustfix と同じだが、機械的に適用可能な提案のみを対象とするuiN/A
exec-envテスト実行時に設定する環境変数ui, crashes<KEY>=<VALUE>
unset-exec-envテスト実行時に解除する環境変数ui, crashes任意の環境変数名
stderr-per-bitwidth各ビット幅ごとに stderr スナップショットを生成するuiN/A
forbid-outputコンパイル/実行の出力に特定の文字列が含まれていないことを確認するui, incremental文字列
run-flagsテスト実行可能ファイルに渡されるフラグui任意のフラグ
known-bug既知のバグのためエラーアノテーションは不要ui, crashes, incrementalIssue 番号 #123456
compare-output-by-lines出力を単一の文字列としてではなく、行単位で比較するすべてN/A

テストを実行するタイミングの制御

これらのディレクティブは、状況によってテストを無視するために使用されます。これは、 そのテストがコンパイルも実行もされないことを意味します。

  • ignore-X は、X がテストを無視する対象の詳細またはその他の条件である場合に使用します(以下を参照)
  • only-Xignore-X に似ていますが、そのターゲットまたはステージでのみテストを実行します
  • ignore-auxiliary は、1つ以上の他のメインテストファイルに関与するものの、 compiletest がそのファイル自体をビルドしようとするべきではないファイルを対象としています。 その補助ファイルを実際に使用しているメインテストへのバックリンクを付けてください。
  • ignore-test は常にテストを無視します。 これは、現在動作していないテストを一時的に無効化しつつ、 後で再有効化するためにツリー内に保持したい場合に使用できます。

ignore-X または only-X における X の例をいくつか示します。

  • 完全なターゲットトリプル: aarch64-apple-ios
  • アーキテクチャ: aarch64, arm, csky, mips, mips64, wasm32, x86_64, x86, …
  • OS: android, emscripten, freebsd, ios, linux, macos, windows, …
  • 環境(ターゲットトリプルの4番目の単語): gnu, msvc, musl
  • ポインター幅: 32bit, 64bit
  • エンディアン: endian-big
  • ステージ: stage1, stage2
  • バイナリ形式: elf
  • チャネル: stable, beta
  • クロスコンパイル時: cross-compile
  • [remote testing] が使用される場合: remote
  • 特定のデバッガーがテストされる場合: cdb, gdb, lldb
  • 特定のデバッガーバージョンに一致する場合: ignore-gdb-version
  • [parallel frontend] が有効な場合: ignore-parallel-frontend
  • 特定の [compare modes]: compare-mode-polonius, compare-mode-next-solver, compare-mode-next-solver-coherence, compare-mode-split-dwarf, compare-mode-split-dwarf-single
  • カバレッジテストで使用される2つの異なるテストモード: ignore-coverage-map, ignore-coverage-run
  • dist ツールチェーンをテストする場合: dist
    • これは COMPILETEST_ENABLE_DIST_TESTS=1 で有効にする必要があります
  • ターゲットの rustc_abi: 例: rustc_abi-x86_64-sse2

以下のディレクティブは rustc のビルド設定とターゲット設定をチェックします。

  • needs-asm-supportホストアーキテクチャが asm! の安定サポートを持たない場合に無視します。 明示的なターゲットへクロスコンパイルするテストでは、 --target を介して、 適切なバックエンドが利用可能であることを保証するために、代わりに needs-llvm-components を使用してください。
  • needs-asm-mnemonic: <MNEMONIC> — ターゲットバックエンドが指定されたアセンブリニーモニック(例: RET, NOP)を サポートしていない場合に無視します。 LLVM バックエンドでのみサポートされます。
  • needs-profiler-runtime — プロファイラーランタイムがターゲットに対して有効化されていない場合に テストを無視します(bootstrap.tomlbuild.profiler = true
  • needs-sanitizer-support — サニタイザーサポートがターゲットに対して有効化されていない場合に 無視します(bootstrap.tomlbuild.sanitizers = true
  • needs-sanitizer-{address,hwaddress,leak,memory,thread} — 対応するサニタイザーが ターゲットに対して有効化されていない場合に無視します(それぞれ AddressSanitizer、 ハードウェア支援 AddressSanitizer、LeakSanitizer、MemorySanitizer または ThreadSanitizer)
  • needs-run-enabled — 実行されるテストであり、実行が無効化されている場合に無視します。 テストの実行は、x test --run=never フラグ、または fuchsia 上で実行することによって無効化できます。
  • needs-unwind — ターゲットがアンワインドをサポートしていない場合に無視します
  • needs-rust-lld — rust lld サポートが有効化されていない場合に無視します(bootstrap.tomlrust.lld = true
  • needs-threads — ターゲットがスレッドサポートを持たない場合に無視します
  • needs-subprocess — ターゲットがサブプロセスサポートを持たない場合に無視します
  • needs-symlink — ターゲットがシンボリックリンクをサポートしていない場合に無視します。 開発者が特権付きシンボリックリンク権限を有効にしていない場合、Windows ではこれに該当することがあります。
  • ignore-std-debug-assertions — std がデバッグアサーション付きでビルドされている場合に無視します。
  • needs-std-debug-assertions — std がデバッグアサーション付きでビルドされていない場合に無視します。
  • ignore-std-remap-debuginfo — std がそのソースの再マッピング付きでビルドされている場合に無視します。
  • needs-std-remap-debugino — std がそのソースの再マッピング付きでビルドされていない場合に無視します。
  • ignore-rustc-debug-assertions — rustc がデバッグアサーション付きでビルドされている場合に無視します。
  • needs-rustc-debug-assertions — rustc がデバッグアサーション付きでビルドされていない場合に無視します。
  • needs-target-has-atomic — ターゲットが指定されたすべての アトミック幅のサポートを持たない場合に無視します。たとえば、//@ needs-target-has-atomic: 8, 16, ptr を持つテストは、カンマ区切りリストのアトミック幅をサポートしている場合にのみ実行されます。
  • needs-dynamic-linking — ターゲットが動的リンクをサポートしていない場合に無視します (これは、dylib および cdylib クレートタイプを作成できないこととは直交します)
  • needs-crate-type — ターゲットプラットフォームが、指定されたクレートタイプの カンマ区切りリストのうち1つ以上をサポートしていない場合に無視します。 たとえば、 //@ needs-crate-type: cdylib, proc-macro は、 wasm32-unknown-unknown ターゲットではターゲットが proc-macro クレートタイプをサポートしていないため、テストが無視される原因になります。
  • needs-target-std — ターゲットプラットフォームが std サポートを持たない場合に無視します。
  • ignore-backends — 空白文字で区切られた、列挙されたバックエンドを無視します。 このディレクティブは --bypass-ignore-backends=[BACKEND] コマンドライン フラグで上書きできることに注意してください。
  • needs-backends — 現在の codegen バックエンドが列挙されている場合にのみテストを実行します。
  • needs-offload — LLVM バックエンドがオフロードサポート付きでビルドされていない場合に無視します。
  • needs-enzyme — Enzyme サブモジュールがビルドされていない場合に無視します。

以下のディレクティブは LLVM サポートをチェックします。

  • exact-llvm-major-version: 19 — llvm メジャーバージョンが指定された llvm メジャーバージョンと 一致しない場合に無視します。
  • min-llvm-version: 13.0 — LLVM バージョンが指定された値より小さい場合に無視されます
  • min-system-llvm-version: 12.0 — システム LLVM を使用していて、その バージョンが指定された値より小さい場合に無視されます
  • max-llvm-major-version: 19 — LLVM メジャーバージョンが指定されたメジャーバージョンより高い場合に 無視されます
  • ignore-llvm-version: 9.0 — 特定の LLVM バージョンを無視します
  • ignore-llvm-version: 7.0 - 9.9.9 — 範囲内の LLVM バージョンを無視します(両端を含む)
  • needs-llvm-components: powerpc — 特定の LLVM コンポーネントがビルドされていない場合に無視します。 注: コンポーネントが存在しない場合、CI では(COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS が設定されていると) テストは失敗します。
  • needs-forced-clang-based-tests — 環境変数 RUSTBUILD_FORCE_CLANG_BASED_TESTS が設定されていない限りテストは無視されます。これにより LLVM と並行して clang をビルドできるようになります
    • これは2つの CI ジョブ([x86_64-gnu-debug] と [aarch64-gnu-debug])でのみ設定されており、run-make テストのサブセットのみを実行します。 このディレクティブを持つ他のテストはまったく実行されませんが、これは通常望ましいことではありません。

デバッガーを無視するためのディレクティブについては、デバッグ情報テスト も参照してください。 [remote testing]: running.md#running-tests-on-a-remote-machine [parallel frontend]: compiletest.md#parallel-frontend [compare modes]: ui.md#compare-modes [x86_64-gnu-debug]: https://github.com/rust-lang/rust/blob/ab3dba92db355b8d97db915a2dca161a117e959c/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile#L32 [aarch64-gnu-debug]: https://github.com/rust-lang/rust/blob/20c909ff9cdd88d33768a4ddb8952927a675b0ad/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile#L32

テストのビルド方法に影響するもの

ディレクティブ説明サポートされるテストスイート指定可能な値
compile-flagsテストまたは aux ファイルをビルドするときに rustc に渡されるフラグrun-make/run-make-cargo を除くすべて任意の有効な rustc フラグ(例: -Awarnings -Dfoo)。-Cincremental または --edition は不可
editionテストのビルドに使用されるエディションrun-make/run-make-cargo を除くすべて任意の有効な --edition の値
rustc-envrustc の実行時に設定する環境変数run-make/run-make-cargo を除くすべて<KEY>=<VALUE>
unset-rustc-envrustc の実行時に設定解除する環境変数run-make/run-make-cargo を除くすべて任意の環境変数名
incrementalインクリメンタルテストスイート外のテストに対する適切なインクリメンタルサポートui, crashesN/A
no-prefer-dynamic-C prefer-dynamic を使用せず、--crate-type=dylib プリセットフラグによる dylib としてのビルドもしないui, crashesN/A

インクリメンタルテストスイートに含まれないインクリメンタルテストを使用したいテスト(run-make/run-make-cargo 以外)は、 compile-flags 経由で -C incremental を渡してはならず、 代わりに //@ incremental ディレクティブを使用しなければなりません。

代わりに、そのテストを適切なインクリメンタルテストとして書くことを検討してください。

edition ディレクティブ

//@ edition ディレクティブには、厳密なエディション、エディションの有界範囲、 またはエディションの左有界な半開範囲を指定できます。 これは、./x test がテストを実行するために使用するエディションに影響します。

例:

  • //@ edition: 2018 ディレクティブを持つテストは、2018 エディションでのみ実行されます。
  • //@ edition: 2015..2021 ディレクティブを持つテストは、2015 エディションと 2018 エディションで実行できます。 したがって、上限は Rust の場合と同様に排他的です (上限を包含する Rust の ..= に相当するものはないことに注意してください)。 ただし、CI は範囲内の最も低いエディション(この例では 2015)でのみテストを実行します。
  • //@ edition: 2018.. ディレクティブを持つテストは、2018 エディション以上で実行されます。 ただし、CI は範囲内の最も低いエディション(この例では 2018)でのみテストを実行します。

-- --edition= 引数を渡すことで、./x test に特定のエディションを強制的に使用させることもできます。 ただし、//@ edition ディレクティブを持つテストは、引数に渡された値をクランプします。 たとえば、./x test -- --edition=2015 を実行した場合:

  • //@ edition: 2018 を持つテストは、2018 エディションで実行されます。
  • //@ edition: 2015..2021 を持つテストは、2015 エディションで実行されます。
  • //@ edition: 2018.. を持つテストは、2018 エディションで実行されます。

Rustdoc

ディレクティブ説明サポートされるテストスイート指定可能な値
doc-flagsテストまたは aux ファイルをビルドするときに rustdoc に渡されるフラグrustdoc, rustdoc-js, rustdoc-json任意の有効な rustdoc フラグ

テストスイート固有のディレクティブ

テストスイート rustdoc-htmlrustdoc-js/rustdoc-js-std、 および rustdoc-json には、それぞれ追加のディレクティブ群があります。その基本的な 構文は compiletest ディレクティブのものに似ていますが、最終的には別個のツールによって読み取られ、チェックされます。 詳細については、上にリンクされているそれぞれの章を参照してください。

プリティプリント

Pretty-printer を参照してください。

その他のディレクティブ

  • no-auto-check-cfg — 自動 check-cfg を無効化する(--check-cfg テスト専用)
  • revisions — 複数回コンパイルする
  • forbid-output — 出力に指定された文字列が含まれていないことをチェックする
  • reference — reference 内のルールにリンクする注釈
  • disable-gdb-pretty-printers — debuginfo テスト用の gdb pretty printer を無効化する

ツール固有のディレクティブ

以下のディレクティブは、それらのツールを使用するテストスイートにおいて、 特定のコマンドラインツールがどのように呼び出されるかに影響します。

  • skip-filecheck は、通常であれば出力をチェックするために LLVM の FileCheck ツールを実行するテストで、その実行を回避します。
    • codegen テスト、assembly テスト、および mir-opt テストで使用されます。
  • filecheck-flags は、LLVM の FileCheck ツールの実行時に追加のフラグを追加します。
  • llvm-cov-flags は、LLVM の llvm-cov ツールの実行時に追加のフラグを追加します。

Tidy 固有のディレクティブ

以下のディレクティブは、tidy スクリプトがテストを検証する方法を制御します。

  • ignore-tidy-target-specific-tests は、テストが(compile-flag ディレクティブ内の --target フラグによって) 特定のターゲット向けにコンパイルされる場合に、適切な LLVM コンポーネントが(needs-llvm-components ディレクティブによって) 必要とされていることのチェックを無効にします。
  • unused-revision-names - 未知のリビジョン名への言及に対する tidy チェックを抑制します。

置換

ディレクティブの値では、対応する値に置き換えられるいくつかの変数を 置換として使用できます。 たとえば、特定のファイルへのパスを含むコンパイラフラグを渡す必要がある場合は、 次のようなものが使用できます。

//@ compile-flags: --remap-path-prefix={{src-base}}=/the/src

ここで、センチネル {{src-base}} は、以下で説明する適切なパスに置き換えられます。

  • {{cwd}}: compiletest が実行されるディレクトリ。 これはチェックアウトのルートではない場合があるため、可能な限り使用を避けるべきです。
    • 例: /path/to/rust, /path/to/build/root
  • {{src-base}}: テストが定義されているディレクトリ。 これは output normalization における $DIR と同等です。
    • 例: /path/to/rust/tests/ui/error-codes
  • {{build-base}}: テストの出力先となるベースディレクトリ。 これは output normalization における $TEST_BUILD_DIR と同等です。
    • 例: /path/to/rust/build/x86_64-unknown-linux-gnu/test/ui
  • {{rust-src-base}}: libstd/libcore/… が置かれている sysroot ディレクトリ
  • {{sysroot-base}}: テストのビルドに使用される sysroot ディレクトリのパス。
    • 主に、API 経由でコンパイラを実行する ui-fulldeps テストを想定しています。
  • {{target-linker}}: このテストで -Clinker に渡されるリンカー。 リンカーのオーバーライドが有効でない場合は空です。
    • 主に、API 経由でコンパイラを実行する ui-fulldeps テストを想定しています。
  • {{target}}: テストのコンパイル対象となるターゲット
    • 例: x86_64-unknown-linux-gnu

この置換を使用するテストの例については、 tests/ui/argfile/commandline-argfile.rs を参照してください。

ディレクティブの追加

個々のテストごとに何らかのテストプロパティや振る舞いを定義する必要がある場合、 新しいディレクティブを追加します。 ディレクティブプロパティは、実行時にディレクティブのバッキングストア (コマンドの現在の値を保持するもの)として機能します。

新しいディレクティブプロパティを追加するには、次のようにします。

  1. src/tools/compiletest/src/directives.rspub struct TestProps 宣言を探し、 新しい public プロパティをその宣言の末尾に追加します。
  2. 構造体宣言の直後にある impl TestProps 実装ブロックを探し、 新しいプロパティをデフォルト値で初期化します。

新しいディレクティブパーサーの追加

compiletest がテストファイルに遭遇すると、これも src/tools/compiletest/src/directives.rs にある Config 構造体の実装ブロックで 定義されているすべてのパーサーを呼び出すことで、ファイルを 1 行ずつ解析します (Config 構造体の宣言ブロックは src/tools/compiletest/src/common.rs にあることに注意してください)。 TestPropsload_from() メソッドは、現在のテキスト行を 各パーサーに渡そうとします。各パーサーは通常、その行が //@ must-compile-successfully//@ failure-status のような 特定のコメント付き(//@)ディレクティブで始まるかどうかをチェックします。 コメントマーカーの後の空白は任意です。

パーサーは、ディレクティブに応じて、テストファイル内でディレクティブとして 指定されているだけで、またはテストファイル内でパラメータ値が指定されていることで、 指定されたディレクティブプロパティのデフォルト値を上書きします。

impl Config で定義されるパーサーは通常、parse_<directive-name> という名前です (kebab-case の <directive-command> が snake-case の <directive_command> に変換されることに注意してください)。 impl Config は、単純な有無(parse_name_directive())や directive:parameter(s)parse_name_value_directive())、 特定の cfg 属性が定義されている場合にのみ任意で解析するもの(has_cfg_prefix())など、 一般的なパターンを簡単に解析できるいくつかの「低レベル」パーサーも定義しています。 低レベルパーサーは impl Config ブロックの末尾付近にあります。不要な追加の解析コードを書かないように、 それらと、そのすぐ上にある関連パーサーに目を通して、どのように使用されているかを必ず確認してください。

具体例として、src/tools/compiletest/src/directives.rs にある parse_failure_status() パーサーの実装を次に示します。

@@ -232,6 +232,7 @@ pub struct TestProps {
     // カスタマイズされた正規化ルール
     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,
+        }
+    }

振る舞いの変更の実装

テストが特定のディレクティブを呼び出すと、その結果として何らかの振る舞いが 変更されることが期待されます。 どのような振る舞いかは、当然ながらディレクティブの目的によって異なります。 failure-status の場合、変更される振る舞いは、 compiletest がデフォルト値ではなく、テスト内で呼び出されたディレクティブによって 定義された失敗コードを期待するようになることです。

これは failure-status に固有のものですが(振る舞いの変更を呼び出すための実装は ディレクティブごとに異なるため)、単なる例として、1 つのケースにおける 振る舞いの変更の実装を見ると役に立つかもしれません。 failure-status を実装するために、src/tools/compiletest/src/runtest.rs にある TestCx 実装ブロック内の check_correct_failure_status() 関数は、以下のように変更されました。

@@ -295,11 +295,14 @@ impl<'test> TestCx<'test> {
     }

     fn check_correct_failure_status(&self, proc_res: &ProcRes) {
-        // Rustランタイムが失敗時に返す値
-        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!("エラー: 期待される失敗ステータス ({:?}) に対して、受け取ったステータスは {:?} でした。",
+                         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);
+            self.fatal_proc_rec("テストの実行に失敗しました!", &proc_res);
         }
@@ -499,7 +501,6 @@ impl<'test> TestCx<'test> {
                 expected,
                 actual
             );
-            panic!();
         }
     }

ディレクティブプロパティにアクセスするために self.props.failure_status を使用していることに注目してください。 failure status ディレクティブを指定していないテストでは、 本稿執筆時点で self.props.failure_status はデフォルト値の 101 に評価されます。 しかし、たとえば //@ failure-status: 1 のようなディレクティブを 指定したテストでは、そのテストに限って、parse_failure_status()TestProps の デフォルト値を上書きするため、self.props.failure_status は 1 に評価されます。


  1. 詳細については、compiletest の章の 補助 proc-macro セクションを参照してください。

  2. 現在 これには奇妙な癖があり、 テストバイナリの stdout と stderr が連結されてから、 error-pattern がこの結合された出力に対してマッチされる。これは ??? 控えめに言っても、少し疑問がある。