Compiletest ディレクティブ
ディレクティブは、テストをどのようにビルドし解釈するかを compiletest に伝える特別なコメントです。
rmake.rs の run-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 | チェックするアセンブリ出力の種類 | assembly | emit-asm, bpf-linker, ptx-linker |
補助ビルド
補助クレートのビルドを参照してください
| ディレクティブ | 説明 | 対応するテストスイート | 指定可能な値 |
|---|---|---|---|
aux-bin | 補助バイナリをビルドし、テストディレクトリからの相対パス auxiliary/bin で利用可能にする | run-make/run-make-cargo を除くすべて | 補助 .rs ファイルへのパス |
aux-build | 指定されたソースファイルから別個のクレートをビルドする | run-make/run-make-cargo を除くすべて | 補助 .rs ファイルへのパス |
aux-crate | aux-build と似ているが、extern prelude として利用可能にする | run-make/run-make-cargo を除くすべて | [<extern_modifiers>:]<extern_prelude_name>=<path/to/aux/file.rs> |
aux-codegen-backend | aux-build と似ているが、メインファイルのビルド時にコンパイル済み dylib を -Zcodegen-backend に渡す | ui-fulldeps | codegen backend ファイルへのパス |
proc-macro | aux-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 なし)は成功するべき | ui | N/A |
check-fail | ビルド(codegen なし)は失敗するべき | ui | N/A |
build-pass | ビルドは成功するべき | ui | N/A |
build-fail | ビルドは失敗するべき | ui | N/A |
run-pass | プログラムはコード 0 で終了しなければならない | ui | N/A |
run-fail | プログラムはコード 1..=127 で終了しなければならない | ui | N/A |
run-crash | プログラムはクラッシュしなければならない | ui | N/A |
run-fail-or-crash | プログラムは run-fail または run-crash でなければならない | ui | N/A |
no-pass-override | --pass フラグを無視する | ui | N/A |
dont-check-failure-status | 正確な失敗ステータス(つまり 1)をチェックしない | ui, incremental | N/A |
failure-status | 失敗時、コンパイラはこのステータスコードで終了しなければならない。ICE を期待するには、//@ failure-status: 101 を使用する。 | ui, incremental | 任意の u16 |
should-fail | Compiletest のセルフテスト | すべて | N/A |
出力スナップショットと正規化の制御
詳細については、正規化、出力 比較、および Rustfix テストを参照してください。
| ディレクティブ | 説明 | サポートされるテストスイート | 使用可能な値 |
|---|---|---|---|
check-run-results | テストバイナリ run-{pass,fail} の実行結果の出力スナップショットを確認する | ui, crashes, incremental | N/A |
error-pattern | 出力に特定の文字列が含まれていることを確認する | ui, crashes, incremental | 文字列 |
regex-error-pattern | 出力に正規表現パターンが含まれていることを確認する | ui, crashes, incremental | 正規表現 |
check-stdout | テストバイナリの実行結果の stdout を error-pattern と照合する2 | ui, crashes, incremental | N/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 スナップショットを照合しない | ui | N/A |
dont-check-compiler-stdout | 実際のコンパイラ stdout と stdout スナップショットを照合しない | ui | N/A |
dont-require-annotations | 指定された診断種別(//~ KIND)について、行アノテーションが網羅的であることを要求しない | ui, incremental | ERROR, WARN, NOTE, HELP, SUGGESTION |
run-rustfix | rustfix によってすべての提案を適用し、修正後の出力をスナップショット化し、修正後の出力がビルドできることを確認する | ui | N/A |
rustfix-only-machine-applicable | run-rustfix と同じだが、機械的に適用可能な提案のみを対象とする | ui | N/A |
exec-env | テスト実行時に設定する環境変数 | ui, crashes | <KEY>=<VALUE> |
unset-exec-env | テスト実行時に解除する環境変数 | ui, crashes | 任意の環境変数名 |
stderr-per-bitwidth | 各ビット幅ごとに stderr スナップショットを生成する | ui | N/A |
forbid-output | コンパイル/実行の出力に特定の文字列が含まれていないことを確認する | ui, incremental | 文字列 |
run-flags | テスト実行可能ファイルに渡されるフラグ | ui | 任意のフラグ |
known-bug | 既知のバグのためエラーアノテーションは不要 | ui, crashes, incremental | Issue 番号 #123456 |
compare-output-by-lines | 出力を単一の文字列としてではなく、行単位で比較する | すべて | N/A |
テストを実行するタイミングの制御
これらのディレクティブは、状況によってテストを無視するために使用されます。これは、 そのテストがコンパイルも実行もされないことを意味します。
ignore-Xは、Xがテストを無視する対象の詳細またはその他の条件である場合に使用します(以下を参照)only-Xはignore-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.tomlのbuild.profiler = true)needs-sanitizer-support— サニタイザーサポートがターゲットに対して有効化されていない場合に 無視します(bootstrap.tomlのbuild.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.tomlのrust.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 サポートを持たない場合に無視します。- codegen テストにおける
#![no_std]/#![no_core]と暗黙のneeds-target-stdも 参照してください。
- codegen テストにおける
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テストのサブセットのみを実行します。 このディレクティブを持つ他のテストはまったく実行されませんが、これは通常望ましいことではありません。
- これは2つの CI ジョブ([
デバッガーを無視するためのディレクティブについては、デバッグ情報テスト も参照してください。
[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-env | rustc の実行時に設定する環境変数 | run-make/run-make-cargo を除くすべて | <KEY>=<VALUE> |
unset-rustc-env | rustc の実行時に設定解除する環境変数 | run-make/run-make-cargo を除くすべて | 任意の環境変数名 |
incremental | インクリメンタルテストスイート外のテストに対する適切なインクリメンタルサポート | ui, crashes | N/A |
no-prefer-dynamic | -C prefer-dynamic を使用せず、--crate-type=dylib プリセットフラグによる dylib としてのビルドもしない | ui, crashes | N/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-html、rustdoc-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ツールの実行時に追加のフラグを追加します。- codegen テスト、 assembly テスト、および MIR-opt テストで使用されます。
llvm-cov-flagsは、LLVM のllvm-covツールの実行時に追加のフラグを追加します。coverage-runモードの coverage テストで使用されます。
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テストを想定しています。
- 主に、API 経由でコンパイラを実行する
{{target-linker}}: このテストで-Clinkerに渡されるリンカー。 リンカーのオーバーライドが有効でない場合は空です。- 主に、API 経由でコンパイラを実行する
ui-fulldepsテストを想定しています。
- 主に、API 経由でコンパイラを実行する
{{target}}: テストのコンパイル対象となるターゲット- 例:
x86_64-unknown-linux-gnu
- 例:
この置換を使用するテストの例については、
tests/ui/argfile/commandline-argfile.rs
を参照してください。
ディレクティブの追加
個々のテストごとに何らかのテストプロパティや振る舞いを定義する必要がある場合、 新しいディレクティブを追加します。 ディレクティブプロパティは、実行時にディレクティブのバッキングストア (コマンドの現在の値を保持するもの)として機能します。
新しいディレクティブプロパティを追加するには、次のようにします。
src/tools/compiletest/src/directives.rsでpub struct TestProps宣言を探し、 新しい public プロパティをその宣言の末尾に追加します。- 構造体宣言の直後にある
impl TestProps実装ブロックを探し、 新しいプロパティをデフォルト値で初期化します。
新しいディレクティブパーサーの追加
compiletest がテストファイルに遭遇すると、これも
src/tools/compiletest/src/directives.rs にある Config 構造体の実装ブロックで
定義されているすべてのパーサーを呼び出すことで、ファイルを 1 行ずつ解析します
(Config 構造体の宣言ブロックは src/tools/compiletest/src/common.rs にあることに注意してください)。
TestProps の load_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 に評価されます。
-
詳細については、compiletest の章の 補助 proc-macro セクションを参照してください。 ↩
-
現在 これには奇妙な癖があり、 テストバイナリの stdout と stderr が連結されてから、
error-patternがこの結合された出力に対してマッチされる。これは ??? 控えめに言っても、少し疑問がある。 ↩