Skip to content

Commit d19674f

Browse files
acozzetteclaude
andcommitted
test: add tests for js_run_binary exec and target cfg behavior
Add a test package at js/private/test/js_run_binary with tests that verify: - When hoist_runfiles_to_exec_cfg = True, the tool's data dependencies are built in the exec configuration (path matches a genrule tools dependency). - When hoist_runfiles_to_exec_cfg = False, the tool's data dependencies are built in the target configuration (path matches a genrule srcs dependency). - Dependencies passed via the srcs parameter are always built for the target platform, verified by transitioning to linux, macos, and windows platforms. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
1 parent 82a7e1d commit d19674f

3 files changed

Lines changed: 180 additions & 0 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
load("@bazel_lib//lib:diff_test.bzl", "diff_test")
2+
load("@bazel_lib//lib:testing.bzl", "assert_contains")
3+
load("@bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")
4+
load("@bazel_skylib//rules:write_file.bzl", "write_file")
5+
load("//js:defs.bzl", "js_binary", "js_run_binary")
6+
7+
# Verify that the js_binary tool's data dependencies are built in the exec configuration
8+
# when hoist_runfiles_to_exec_cfg is True.
9+
# To do this we check that js_run_binary agrees with genrule on the location of a
10+
# tool dependency.
11+
write_file(
12+
name = "gen_cfg_probe",
13+
out = "cfg_probe.txt",
14+
content = ["probe"],
15+
)
16+
17+
js_binary(
18+
name = "find_cfg_probe",
19+
data = [":cfg_probe.txt"],
20+
entry_point = "find_cfg_probe.mjs",
21+
)
22+
23+
js_run_binary(
24+
name = "tools_cfg_location",
25+
hoist_runfiles_to_exec_cfg = True,
26+
stdout = "tools_cfg_location.txt",
27+
tool = ":find_cfg_probe",
28+
)
29+
30+
genrule(
31+
name = "expected_tools_cfg_location",
32+
outs = ["expected_tools_cfg_location.txt"],
33+
cmd = "echo $(execpath :cfg_probe.txt) > $@",
34+
tools = [":cfg_probe.txt"],
35+
)
36+
37+
diff_test(
38+
name = "tools_exec_cfg_test",
39+
file1 = ":tools_cfg_location.txt",
40+
file2 = ":expected_tools_cfg_location.txt",
41+
)
42+
43+
# Verify the opposite: with hoist_runfiles_to_exec_cfg = False, the tool's data
44+
# dependencies are built in the target configuration, matching a genrule srcs path.
45+
js_run_binary(
46+
name = "target_cfg_location",
47+
hoist_runfiles_to_exec_cfg = False,
48+
stdout = "target_cfg_location.txt",
49+
tool = ":find_cfg_probe",
50+
)
51+
52+
genrule(
53+
name = "expected_target_cfg_location",
54+
srcs = [":cfg_probe.txt"],
55+
outs = ["expected_target_cfg_location.txt"],
56+
cmd = "echo $(execpath :cfg_probe.txt) > $@",
57+
)
58+
59+
diff_test(
60+
name = "target_cfg_test",
61+
file1 = ":target_cfg_location.txt",
62+
file2 = ":expected_target_cfg_location.txt",
63+
)
64+
65+
# Verify that dependencies passed via the srcs parameter are always built for
66+
# the target platform, unlike the tool parameter and its dependencies.
67+
# We use a select() on the OS to produce a platform-specific file, then
68+
# transition to three different target platforms and assert the contents match.
69+
write_file(
70+
name = "gen_os_name",
71+
out = "os_name.txt",
72+
content = select({
73+
"@platforms//os:linux": ["linux"],
74+
"@platforms//os:macos": ["macos"],
75+
"@platforms//os:windows": ["windows"],
76+
"//conditions:default": ["other"],
77+
}),
78+
tags = ["manual"],
79+
)
80+
81+
platform(
82+
name = "linux",
83+
constraint_values = ["@platforms//os:linux"],
84+
)
85+
86+
platform(
87+
name = "macos",
88+
constraint_values = ["@platforms//os:macos"],
89+
)
90+
91+
platform(
92+
name = "windows",
93+
constraint_values = ["@platforms//os:windows"],
94+
)
95+
96+
js_binary(
97+
name = "read_file",
98+
entry_point = "read_file.mjs",
99+
)
100+
101+
js_run_binary(
102+
name = "gen_target_os",
103+
srcs = [":os_name.txt"],
104+
args = ["$(rootpath :os_name.txt)"],
105+
stdout = "target_os.txt",
106+
tags = ["manual"],
107+
tool = ":read_file",
108+
)
109+
110+
platform_transition_filegroup(
111+
name = "target_os_linux",
112+
srcs = [":gen_target_os"],
113+
target_platform = ":linux",
114+
)
115+
116+
platform_transition_filegroup(
117+
name = "target_os_macos",
118+
srcs = [":gen_target_os"],
119+
target_platform = ":macos",
120+
)
121+
122+
platform_transition_filegroup(
123+
name = "target_os_windows",
124+
srcs = [":gen_target_os"],
125+
target_platform = ":windows",
126+
)
127+
128+
assert_contains(
129+
name = "linux_target_platform_test",
130+
actual = ":target_os_linux",
131+
expected = "linux",
132+
)
133+
134+
assert_contains(
135+
name = "macos_target_platform_test",
136+
actual = ":target_os_macos",
137+
expected = "macos",
138+
)
139+
140+
assert_contains(
141+
name = "windows_target_platform_test",
142+
actual = ":target_os_windows",
143+
expected = "windows",
144+
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// The purpose of this binary is to determine where the generated file
2+
// cfg_probe.txt ended up. We look for it in both the exec and target bin
3+
// directories and output the path where it appears.
4+
import fs from 'fs'
5+
import path from 'path'
6+
7+
const suffix = 'js/private/test/js_run_binary/cfg_probe.txt'
8+
const execCfgRelPath = path.join(process.env.JS_BINARY__BINDIR, suffix)
9+
const targetCfgRelPath = path.join(process.env.BAZEL_BINDIR, suffix)
10+
11+
function fileExists(absPath) {
12+
try {
13+
fs.lstatSync(absPath)
14+
return true
15+
} catch (_) {
16+
return false
17+
}
18+
}
19+
20+
const foundInExecCfg = fileExists(path.join(process.env.JS_BINARY__EXECROOT, execCfgRelPath))
21+
const foundInTargetCfg = fileExists(path.join(process.env.JS_BINARY__EXECROOT, targetCfgRelPath))
22+
23+
if (foundInExecCfg && foundInTargetCfg) {
24+
process.stderr.write('cfg_probe.txt unexpectedly found in both exec cfg and target cfg paths\n')
25+
process.exit(1)
26+
}
27+
if (!foundInExecCfg && !foundInTargetCfg) {
28+
process.stderr.write('cfg_probe.txt not found in either exec cfg or target cfg path\n')
29+
process.exit(1)
30+
}
31+
32+
process.stdout.write((foundInExecCfg ? execCfgRelPath : targetCfgRelPath) + '\n')
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import fs from 'fs'
2+
3+
const content = fs.readFileSync(process.argv[2], 'utf8').trim()
4+
process.stdout.write(content + '\n')

0 commit comments

Comments
 (0)