Compiletest 지시문
지시문은 compiletest에 테스트를 빌드하고 해석하는 방법을 알려 주는 특수한 주석입니다. 지시문은 rmake.rs run-make 테스트에도 나타날 수 있습니다.
지시문은 보통 이 테스트의 목적을 설명하는 짧은 주석 뒤에 둡니다. Compiletest 테스트 스위트는 //@를 사용하여 주석이 지시문임을 나타냅니다. 예를 들어, 이 테스트는 //@ compile-flags 명령을 사용하여 테스트를 컴파일할 때 rustc에 전달할 사용자 지정 플래그를 지정합니다:
// Test the behavior of `0 - 1` when overflow checks are disabled.
//@ compile-flags: -C overflow-checks=off
fn main() {
let x = 0 - 1;
...
}
지시문은 (//@ run-pass처럼) 단독으로 쓰일 수도 있고 (//@ compile-flags: -C overflow-checks=off처럼) 값을 받을 수도 있습니다.
지시문은 한 줄에 하나씩 작성합니다. 같은 줄에 여러 지시문을 작성할 수 없습니다. 예를 들어, //@ 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 | 코드 생성 백엔드 파일 경로 |
proc-macro | aux-build와 비슷하지만, 보조 크레이트를 호스트용으로 강제 빌드하고 -Cprefer-dynamic1을 사용하지 않습니다. | run-make/run-make-cargo를 제외한 모든 테스트 스위트 | 보조 proc-macro .rs 파일 경로 |
build-aux-docs | 보조 크레이트의 문서도 함께 빌드합니다. 이 기능은 aux-crate가 아닌 aux-build에서만 동작한다는 점에 유의하십시오. | run-make/run-make-cargo를 제외한 모든 테스트 스위트 | 해당 없음 |
결과 기대치 제어하기
통과/실패 기대치 제어하기를 참고하십시오.
| 지시문 | 설명 | 지원되는 테스트 스위트 | 가능한 값 |
|---|---|---|---|
check-pass | 빌드(코드 생성 제외)가 통과해야 합니다 | ui | 해당 없음 |
check-fail | 빌드(코드 생성 제외)가 실패해야 합니다 | ui | 해당 없음 |
build-pass | 빌드가 성공해야 합니다 | ui | 해당 없음 |
build-fail | 빌드가 실패해야 합니다 | ui | 해당 없음 |
run-pass | 프로그램이 코드 0으로 종료되어야 합니다 | ui | 해당 없음 |
run-fail | 프로그램이 코드 1..=127로 종료되어야 합니다 | ui | 해당 없음 |
run-crash | 프로그램이 크래시해야 합니다 | ui | 해당 없음 |
run-fail-or-crash | 프로그램이 run-fail 또는 run-crash에 해당해야 합니다 | ui | 해당 없음 |
no-pass-override | --pass 플래그를 무시합니다 | ui | 해당 없음 |
dont-check-failure-status | 정확한 실패 상태(예: 1)를 검사하지 않습니다 | ui, incremental | 해당 없음 |
failure-status | 실패 시 컴파일러는 이 상태 코드로 종료해야 합니다. ICE를 예상하려면 //@ failure-status: 101을 사용하십시오. | ui, incremental | 임의의 u16 |
should-fail | Compiletest 자체 테스트 | 전체 | 해당 없음 |
출력 스냅숏과 정규화 제어
자세한 내용은 정규화, 출력 비교, Rustfix 테스트를 참고하십시오.
| 지시문 | 설명 | 지원되는 테스트 스위트 | 가능한 값 |
|---|---|---|---|
check-run-results | 실행 테스트 바이너리의 run-{pass,fail} 출력 스냅숏을 검사합니다 | ui, crashes, incremental | 해당 없음 |
error-pattern | 출력에 특정 문자열이 포함되어 있는지 검사합니다 | ui, crashes, incremental | 문자열 |
regex-error-pattern | 출력에 정규식 패턴이 포함되어 있는지 검사합니다 | ui, crashes, incremental | 정규식 |
check-stdout | 테스트 바이너리를 실행한 결과의 stdout을 error-pattern들과 대조하여 검사합니다2 | ui, crashes, incremental | 해당 없음 |
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 | 해당 없음 |
dont-check-compiler-stdout | 실제 컴파일러 stdout을 stdout 스냅숏과 비교하지 않습니다 | ui | 해당 없음 |
dont-require-annotations | 지정한 진단 종류(//~ KIND)의 줄 주석이 빠짐없이 달려 있을 것을 요구하지 않습니다 | ui, incremental | ERROR, WARN, NOTE, HELP, SUGGESTION |
run-rustfix | rustfix로 모든 제안을 적용하고, 수정된 출력의 스냅숏을 만든 뒤, 수정된 출력이 빌드되는지 확인합니다 | ui | 해당 없음 |
rustfix-only-machine-applicable | run-rustfix와 같지만 기계적으로 적용 가능한 제안만 적용합니다 | ui | 해당 없음 |
exec-env | 테스트를 실행할 때 설정할 환경 변수 | ui, crashes | <KEY>=<VALUE> |
unset-exec-env | 테스트를 실행할 때 해제할 환경 변수 | ui, crashes | 임의의 환경 변수 이름 |
stderr-per-bitwidth | 비트 폭마다 stderr 스냅숏을 생성합니다 | ui | 해당 없음 |
forbid-output | 컴파일/실행 출력에 특정 문자열이 포함되지 않는지 확인합니다 | ui, incremental | 문자열 |
run-flags | 테스트 실행 파일에 전달되는 플래그 | ui | 임의의 플래그 |
known-bug | 알려진 버그이므로 오류 주석이 필요하지 않습니다 | ui, crashes, incremental | 이슈 번호 #123456 |
compare-output-by-lines | 출력을 하나의 문자열이 아니라 줄 단위로 비교합니다 | 전체 | 해당 없음 |
테스트 실행 시점 제어
이 지시문들은 특정 상황에서 테스트를 무시하는 데 사용되며, 이 경우 테스트는 컴파일되거나 실행되지 않습니다.
ignore-X:X는 테스트를 무시할 기준이 되는 타깃 세부 사항이나 기타 조건입니다(아래 참조)only-X는ignore-X와 비슷하지만, 해당 타깃이나 스테이지에서만 테스트를 실행합니다ignore-auxiliary는 하나 이상의 다른 주 테스트 파일에 참여하지만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, … - 환경(타깃 트리플의 네 번째 단어):
gnu,msvc,musl - 포인터 너비:
32bit,64bit - 엔디언:
endian-big - 스테이지:
stage1,stage2 - 바이너리 형식:
elf - 채널:
stable,beta - 크로스 컴파일할 때:
cross-compile - 원격 테스트를 사용할 때:
remote - 특정 디버거를 테스트할 때:
cdb,gdb,lldb - 특정 디버거 버전이 일치할 때:
ignore-gdb-version - 병렬 프런트엔드가 활성화된 경우:
ignore-parallel-frontend - 특정 비교 모드:
compare-mode-polonius,compare-mode-next-solver,compare-mode-next-solver-coherence,compare-mode-split-dwarf,compare-mode-split-dwarf-single - 커버리지 테스트에서 사용하는 두 가지 테스트 모드:
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-ret- 대상의 어셈블리 구문에ret명령어가 없으면 무시합니다. 대부분의 대상 아키텍처에는 이 명령어가 있어 이식 가능한 인라인 어셈블리 테스트에 유용하지만, 일부 아키텍처(예: 32비트 ARM)에는 이 명령어가 없습니다.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— 대상 플랫폼이 쉼표로 구분된 목록에 지정된 크레이트 타입 중 하나 이상을 지원하지 않으면 무시합니다. 예를 들어//@ needs-crate-type: cdylib, proc-macro를 지정하면wasm32-unknown-unknown대상은proc-macro크레이트 타입을 지원하지 않으므로 해당 대상에서 테스트가 무시됩니다.needs-target-std— 대상 플랫폼이 std를 지원하지 않으면 무시합니다.ignore-backends— 공백 문자로 구분하여 나열한 백엔드를 무시합니다. 이 지시문은--bypass-ignore-backends=[BACKEND]명령줄 플래그로 재정의할 수 있다는 점에 유의하십시오.needs-backends— 현재 코드 생성 백엔드가 목록에 있는 경우에만 테스트를 실행합니다.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도 빌드합니다- 이 환경 변수는 두 개의 CI 작업(
test-x86_64-gnu-debug와test-aarch64-gnu-debug)에서만 설정되며, 이 작업들은run-make테스트의 일부만 실행합니다. 이 지시문이 있는 다른 테스트는 전혀 실행되지 않으며, 이는 대개 원하는 동작이 아닙니다.
- 이 환경 변수는 두 개의 CI 작업(
디버거를 무시하는 지시문은 debuginfo 테스트도 참고하십시오.
테스트 빌드 방식에 영향을 주는 지시어
| 지시문 | 설명 | 지원되는 테스트 스위트 | 가능한 값 |
|---|---|---|---|
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 | 해당 없음 |
no-prefer-dynamic | -C prefer-dynamic을 사용하지 않으며, --crate-type=dylib 사전 설정 플래그를 통해 dylib로 빌드하지 않음 | ui, crashes | 해당 없음 |
(run-make/run-make-cargo 외부의) 테스트 중 증분 테스트 스위트에 속하지 않으면서 증분 테스트를 사용하려는 테스트는 compile-flags를 통해 -C incremental을 전달해서는 안 되며, 대신 //@ incremental 지시문을 사용해야 합니다.
대신 해당 테스트를 올바른 증분 테스트로 작성하는 것을 고려하십시오.
에디션 지시문
//@ 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 | 테스트 또는 보조 파일을 빌드할 때 rustdoc에 전달되는 플래그 | rustdoc, rustdoc-js, rustdoc-json | 유효한 모든 rustdoc 플래그 |
테스트 스위트별 지시문
테스트 스위트 rustdoc-html, rustdoc-js/rustdoc-js-std, rustdoc-json에는 각각 추가 지시문 집합이 있는 기능이 있으며, 이 지시문들의 기본 구문은 compiletest 지시문과 비슷하지만 최종적으로는 별도의 도구가 읽고 검사합니다. 자세한 내용은 위에 링크된 각 장을 참고하십시오.
예쁜 출력(pretty printing)
Pretty-printer를 참고하십시오.
기타 지시문
no-auto-check-cfg— 자동 check-cfg를 비활성화합니다(--check-cfg테스트에만 해당)revisions— 여러 번 컴파일합니다forbid-output— 출력에 지정한 문자열이 포함되지 않았는지 검사합니다reference— 레퍼런스의 규칙으로 연결되는 주석입니다disable-gdb-pretty-printers— debuginfo 테스트에서 gdb 예쁜 출력기(pretty printer)를 비활성화합니다
도구별 지시문
다음 지시문은 특정 명령줄 도구를 사용하는 테스트 스위트에서 해당 도구를 호출하는 방식에 영향을 줍니다.
skip-filecheck는 원래 LLVM의FileCheck도구를 실행해 출력을 검사하는 테스트에서 이 도구를 실행하지 않게 합니다.- 코드 생성 테스트, 어셈블리 테스트, mir-opt 테스트에서 사용합니다.
filecheck-flags는 LLVM의FileCheck도구를 실행할 때 추가 플래그를 전달합니다.- 코드 생성 테스트, 어셈블리 테스트, MIR-opt 테스트에서 사용합니다.
llvm-cov-flags는 LLVM의llvm-cov도구를 실행할 때 추가 플래그를 전달합니다.coverage-run모드의 커버리지 테스트에서 사용합니다.
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}}: 테스트가 정의된 디렉터리입니다. 이는 출력 정규화의$DIR과 동일합니다.- 예시:
/path/to/rust/tests/ui/error-codes
- 예시:
{{build-base}}: 테스트의 출력이 저장되는 기본 디렉터리입니다. 이는 출력 정규화의$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선언을 찾아 선언의 끝에 새 공개 속성을 추가하십시오.- 구조체 선언 바로 뒤에 있는
impl TestProps구현 블록을 찾아 새 속성을 기본값으로 초기화하십시오.
새 지시문 파서 추가하기
compiletest는 테스트 파일을 만나면, 역시 src/tools/compiletest/src/directives.rs에 있는 Config 구조체의 구현 블록에 정의된 모든 파서를 호출하여 파일을 한 줄씩 파싱합니다(Config 구조체의 선언 블록은 src/tools/compiletest/src/common.rs에 있다는 점에 유의하십시오). TestProps의 load_from() 메서드는 현재 텍스트 줄을 각 파서에 차례로 전달해 보며, 각 파서는 일반적으로 그 줄이 //@ must-compile-successfully나 //@ failure-status와 같은 특정 주석(//@) 지시문으로 시작하는지 확인합니다. 주석 마커 뒤의 공백은 선택 사항입니다.
파서는 지시문에 따라, 테스트 파일에 지시문으로 지정되기만 하거나 테스트 파일에 매개변수 값이 지정되는 것만으로 해당 지시문 속성의 기본값을 재정의합니다.
impl Config에 정의된 파서는 일반적으로 parse_<directive-name>이라는 이름을 가집니다(케밥 케이스 <directive-command>가 스네이크 케이스 <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 {
// 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,
+ }
+ }
동작 변경 구현하기
테스트가 특정 지시문을 호출하면 그 결과로 어떤 동작이 바뀔 것으로 예상됩니다. 물론 어떤 동작이 바뀌는지는 지시문의 목적에 따라 다릅니다. failure-status의 경우, 바뀌는 동작은 compiletest가 기본값 대신 테스트에서 호출한 지시문이 정의한 실패 코드를 기대하게 된다는 것입니다.
이 내용은 failure-status에만 해당하지만(지시문마다 동작 변경을 일으키기 위한 구현이 다르기 때문입니다), 한 가지 사례의 동작 변경 구현을 단순히 예시로 살펴보는 것이 도움이 될 수 있습니다. 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) {
- // 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!();
}
}
지시문 속성에 접근하기 위해 self.props.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들이 매칭된다는 점으로, 이는 ??? 좋게 말해도 다소 의문스럽습니다. ↩