1"""Test rules for `current_*_files` targets"""
2
3def _current_toolchain_files_test_impl(ctx):
4    runfiles_files = []
5    if ctx.attr.kind == "files":
6        manifest = ctx.actions.declare_file("{}.files.manifest".format(
7            ctx.label.name,
8        ))
9        ctx.actions.write(
10            output = manifest,
11            content = "\n".join([file.short_path for file in ctx.files.tool]),
12        )
13        runfiles_files.append(manifest)
14        runfiles_files.extend(ctx.files.tool)
15        input = manifest
16    elif ctx.attr.kind == "executable":
17        tool_files = ctx.files.tool
18        if len(tool_files) != 1:
19            fail("Unexpected number of files provided by tool for {}: {}".format(
20                ctx.label,
21                tool_files,
22            ))
23        input = tool_files[0]
24        runfiles_files.append(input)
25    else:
26        fail("Unexpected kind: {}".format(ctx.attr.kind))
27
28    extension = ".{}".format(ctx.executable._test_runner.extension) if ctx.executable._test_runner.extension else ""
29    test_runner = ctx.actions.declare_file("{}{}".format(ctx.label.name, extension))
30    ctx.actions.symlink(
31        output = test_runner,
32        target_file = ctx.executable._test_runner,
33    )
34
35    runfiles = ctx.runfiles(files = runfiles_files)
36    runfiles = runfiles.merge(ctx.attr._test_runner[DefaultInfo].default_runfiles)
37    runfiles = runfiles.merge(ctx.attr.tool[DefaultInfo].default_runfiles)
38
39    return [
40        DefaultInfo(
41            runfiles = runfiles,
42            executable = test_runner,
43        ),
44        testing.TestEnvironment({
45            "CURRENT_TOOLCHAIN_FILES_TEST_INPUT": input.short_path,
46            "CURRENT_TOOLCHAIN_FILES_TEST_KIND": ctx.attr.kind,
47            "CURRENT_TOOLCHAIN_FILES_TEST_PATTERN": ctx.attr.pattern,
48        }),
49    ]
50
51current_toolchain_files_test = rule(
52    doc = "Test that `current_*_toolchain` tools consumable (executables are executable and filegroups contain expected sources)",
53    implementation = _current_toolchain_files_test_impl,
54    attrs = {
55        "kind": attr.string(
56            doc = "The kind of the component.",
57            values = ["executable", "files"],
58            mandatory = True,
59        ),
60        "pattern": attr.string(
61            doc = (
62                "A pattern used to confirm either executables produce an expected " +
63                "value or lists of files contain expected contents."
64            ),
65            mandatory = True,
66        ),
67        "tool": attr.label(
68            doc = "The current toolchain component.",
69            allow_files = True,
70            mandatory = True,
71        ),
72        "_test_runner": attr.label(
73            doc = "A shared test runner for validating targets.",
74            cfg = "exec",
75            allow_files = True,
76            executable = True,
77            default = Label("//test/current_toolchain_files:current_toolchain_files_test_runner.sh"),
78        ),
79    },
80    test = True,
81)
82