【问题标题】:How to write a Bazel test rule using a provided tool rather than a rule-built one?如何使用提供的工具而不是规则构建的工具来编写 Bazel 测试规则?
【发布时间】:2019-10-06 01:39:56
【问题描述】:

我有一个测试工具(大致是一个差异工具),它接受两个输入,并返回一个输出(两个输入之间的差异)和一个返回码(如果两个输入匹配,则返回 0,否则返回 1) .它是在 Kotlin 中构建的,可以在我的仓库中的 //java/fr/enoent/phosphorus 获得。

我想编写一个规则来测试由某物生成的文件是否与存储库中已经存在的参考文件相同。我尝试了ctx.actions.run,问题是我的规则设置了test = True,需要返回一个可执行文件由该规则构建(所以不是提供给规则的工具)。然后我尝试将其包装在example 之后的 shell 脚本中,如下所示:

def _phosphorus_test_impl(ctx):
    output = ctx.actions.declare_file("{name}.phs".format(name = ctx.label.name))
    script = phosphorus_compare(
        ctx,
        reference = ctx.file.reference,
        comparison = ctx.file.comparison,
        out = output,
    )

    ctx.actions.write(
        output = ctx.outputs.executable,
        content = script,
    )

    runfiles = ctx.runfiles(files = [ctx.executable._phosphorus_tool, ctx.file.reference, ctx.file.comparison])
    return [DefaultInfo(runfiles = runfiles)]

phosphorus_test = rule(
    _phosphorus_test_impl,
    attrs = {
        "comparison": attr.label(
            allow_single_file = [".phs"],
            doc = "File to compare to the reference",
            mandatory = True,
        ),
        "reference": attr.label(
            allow_single_file = [".phs"],
            doc = "Reference file",
            mandatory = True,
        ),
        "_phosphorus_tool": attr.label(
            default = "//java/fr/enoent/phosphorus",
            executable = True,
            cfg = "host",
        ),
    },
    doc = "Compares two files, and fails if they are different.",
    test = True,
)

phosphorus_compare 只是一个生成实际命令的宏。)

但是,这种方法有两个问题:

  • 不能以这种方式声明输出。它与任何行动都没有关联(Bazel 正在抱怨它)。也许我真的不需要为测试声明输出?测试失败时,Bazel 是否使测试文件夹中的任何内容可用?
  • 运行该工具所需的运行文件似乎在测试运行时不可用: java/fr/enoent/phosphorus/phosphorus: line 359: /home/kernald/.cache/bazel/_bazel_kernald/58c025fbb926eac6827117ef80f7d2fa/sandbox/linux-sandbox/1979/execroot/fr_enoent/bazel-out/k8-fastbuild/bin/tools/phosphorus/tests/should_pass.runfiles/remotejdk11_linux/bin/java: No such file or directory

总的来说,我觉得使用 shell 脚本只是添加了不必要的间接性,并丢失了一些上下文(例如工具的运行文件)。理想情况下,我只会使用ctx.actions.run 并依赖它的返回码,但它似乎不是一个选项,因为测试显然需要生成可执行文件。编写这样一条规则的正确方法是什么?

【问题讨论】:

    标签: bazel starlark


    【解决方案1】:

    事实证明,生成脚本是正确的方法,(据我所知)不可能返回某种指向ctx.actions.run 的指针。测试规则需要有一个可执行的输出。

    关于工具生成的输出文件:根本不需要声明它。我只需要确保它是在$TEST_UNDECLARED_OUTPUTS_DIR 中生成的。此目录中的每个文件都将添加到 Bazel 名为 output.zip 的存档中。这是(部分)记录在here

    关于运行文件,嗯,我有工具的二进制文件,但没有它自己的运行文件。这是固定规则:

    def _phosphorus_test_impl(ctx):
        script = phosphorus_compare(
            ctx,
            reference = ctx.file.reference,
            comparison = ctx.file.comparison,
            out = "%s.phs" % ctx.label.name,
        )
    
        ctx.actions.write(
            output = ctx.outputs.executable,
            content = script,
        )
    
        return [
            DefaultInfo(
                runfiles = ctx.runfiles(
                    files = [
                        ctx.executable._phosphorus_tool,
                        ctx.file.reference,
                        ctx.file.comparison,
                    ],
                ).merge(ctx.attr._phosphorus_tool[DefaultInfo].default_runfiles),
                executable = ctx.outputs.executable,
            ),
        ]
    
    def phosphorus_test(size = "small", **kwargs):
        _phosphorus_test(size = size, **kwargs)
    
    _phosphorus_test = rule(
        _phosphorus_test_impl,
        attrs = {
            "comparison": attr.label(
                allow_single_file = [".phs"],
                doc = "File to compare to the reference",
                mandatory = True,
            ),
            "reference": attr.label(
                allow_single_file = [".phs"],
                doc = "Reference file",
                mandatory = True,
            ),
            "_phosphorus_tool": attr.label(
                default = "//java/fr/enoent/phosphorus",
                executable = True,
                cfg = "target",
            ),
        },
        doc = "Compares two files, and fails if they are different.",
        test = True,
    )
    

    返回的DefaultInfo中的关键部分是.merge(ctx.attr._phosphorus_tool[DefaultInfo].default_runfiles)

    我在配置上也犯了一个小错误,因为此测试旨在在目标配置上运行,而不是在主机上运行,​​因此已相应修复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-23
      • 2021-11-23
      • 2019-07-31
      相关资源
      最近更新 更多