菜单

代码生成测试

相关源文件

此页面介绍了 Kotlin 的代码生成测试,这是编译器测试基础设施的关键部分。代码生成测试会验证 Kotlin 源代码是否已正确编译为目标平台(JVM、JS、Native、WebAssembly),以及生成的代码在运行时是否按预期运行。

有关验证编译器错误和警告的诊断测试信息,请参阅诊断测试

概述

Kotlin 中的代码生成测试采用“黑盒”方法,侧重于验证已编译代码的行为,而不是检查其内部结构。这些测试会编译 Kotlin 代码,在目标平台上执行,并验证结果是否符合预期。

黑盒方法有几个优点:

  • 即使底层代码生成策略发生变化,测试仍然有效
  • 测试可跨多种编译器后端(JVM、JS、Native、WebAssembly)工作
  • 测试侧重于用户关心的语言行为

架构

代码生成测试框架围绕几个关键组件构建:

来源:compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestGenerated.java wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/FirWasmJsCodegenBoxTestGenerated.java

测试结构

Box Function Convention

测试代码遵循一个约定:每个测试文件必须包含一个作为入口点的 box() 函数。如果 box() 函数返回字符串 "OK",则认为测试成功。

测试组织

测试按以下方式分层组织:

  1. 目标平台:JVM、JS、Native、WebAssembly
  2. 功能区域:Annotations、argument order、arithmetic 等
  3. 特定测试用例:Individual test files

来源:compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java29-985 compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenBoxTestGenerated.java wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/FirWasmJsCodegenBoxTestGenerated.java

测试执行流程

测试执行过程遵循以下步骤:

来源:compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java20-26 compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/inlineScopes/FirBlackBoxCodegenTestWithInlineScopesGenerated.java26-27

Test Variants

黑盒测试在以下不同组合下运行:

Frontends

  • FIR (Frontend IR):新的 Kotlin 编译器前端
  • K1:旧版 Kotlin 编译器前端

Source Representations

  • PSI (Program Structure Interface):IntelliJ 的代码表示
  • LightTree:PSI 的轻量级替代方案

后端

  • JVM:生成 JVM 字节码
  • JS:生成 JavaScript(CommonJS 和 ES6 模块)
  • Native:生成原生可执行文件(带或不带部分链接)
  • WebAssembly:生成 WebAssembly 模块

特殊配置

  • Inline scopes:具有增强的内联函数处理的测试
  • IR inliner:专门侧重于基于 IR 的内联的测试
  • ABI consistency:验证二进制兼容性的测试

来源:compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/inlineScopes/FirBlackBoxCodegenTestWithInlineScopesGenerated.java compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/JvmAbiConsistencyTestBoxGenerated.java

Test Generation

测试类是通过测试数据目录使用测试生成器自动生成的。每个测试类对应一个特定的前端/后端组合,嵌套类代表功能区域,测试方法代表各个测试用例。

例如,使用 FIR 和 PSI 的 JVM 平台上的注解测试生成为:

来源:compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java19-20 compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java29-45

Test Categories and Coverage

测试套件涵盖了全面的语言功能和边缘情况,包括:

类别描述示例测试文件
Annotations注解处理测试annotationsOnTypeAliases.kt, annotationProperty.kt
Argument Order函数参数求值顺序测试argumentOrderInSuperCall.kt, capturedInExtension.kt
算术数值运算测试basic_charConversions.kt, divisionByZero.kt
数组数组处理测试arrayConstructor.kt, arrayLiterals.kt
Casting类型转换操作测试implicitCastToUnit.kt, safeCastSureToBe.kt
类声明和使用测试abstractMethodInFakeOverride.kt, compactConstructor.kt
合集集合操作测试forInArrayWithIndex.kt, mapGetWithDefaultWithNullableValues.kt
控制流分支和循环测试breakContinueInLoopWithLabel.kt, whenByDelegated.kt
Delegated Properties属性委托测试delegateToNestedInlineFunction.kt, delegationsByMap.kt
泛型泛型测试boundedTypeParameterUpperChecker.kt, invariantArraysOfGenericCompare.kt
内联内联函数测试constructorInlineCallInitOrder.kt, lambdaAddingThis.kt
Coroutines挂起函数测试suspendFunctionAsBooleanCallable.kt, suspendFunctionWithJvmStaticSupertype.kt

来源:compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java28-984

Writing Black Box Tests

编写新的黑盒测试时:

  1. compiler/testData/codegen/box/ 下的相应功能目录下创建 Kotlin 文件。
  2. 实现一个返回 "OK" 的 box() 函数,表示测试通过。
  3. 使用描述性的测试名称,表明正在测试的方面。

注解保留的测试示例

来源:compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java398-402

Multi-module Tests

某些测试涉及多个模块,用于验证增量编译、跨模块内联或二进制兼容性等功能。这些测试通常使用特殊的命名或目录结构来指示模块边界。

来自注解测试的示例

来源:compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java86-90

结论

代码生成测试提供了一个关键的验证层,确保 Kotlin 代码在所有目标平台上都能正确编译并按预期运行。黑盒方法侧重于行为而非实现细节,允许编译器内部进行演进,同时保持与现有代码的兼容性。

这些测试是 Kotlin 编译器质量保证流程的重要组成部分,确保了语言功能在所有目标平台上的持续一致性。