j2cl_test breaks when classpath contains package named "java"
- Dominant language
- Java
- Stars
- 1.4k
- Forks
- 161
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
The `j2cl_test` rule has logic to automatically find the java package name for use in the generated files. The package name is found by finding the closest parent folder who's name equals "java" (See the function here [get_java_package in j2cl_util](https://github.com/google/j2cl/blob/1fed2607c9beb4759991eb0fbedc22f3373a5614/build_defs/internal_do_not_use/j2cl_util.bzl#L3). The logic works fine for most cases, but not when the classpath contains a java package named "java".
For example, a test class path of `com.acme.java.extensions` (path `src/test/java/com/acme/java/extensions`) will not compile because `j2cl_test` stops too soon at the first "java" resulting in the generated files starting at `src/test/java/com/acme/java` instead of `src/test/java` like I would expect.
I can set `j2cl_test`'s `test_class` parameter which fixes the class name used in the `@J2clTestInput` annotation (without `test_class` parameter: `@J2clTestInput(.HelloWorldTest.class)`), but then I run into the error shown in the output below.
**To Reproduce**
- Start with the `examples/helloworld` project.
- Rename the folder `helloworldlib` to `java`:
`samples/helloworld/src/test/java/com/google/j2cl/samples/helloworldlib`
to
`samples/helloworld/src/test/java/com/google/j2cl/samples/java`
- Edit `samples/helloworld/src/test/java/com/google/j2cl/samples/java/BUILD` to set the `test_class` parameter manually:
```
load("@j2cl//build_defs:rules.bzl", "j2cl_test")
package(
default_applicable_licenses = ["@j2cl//:j2cl_license"],
licenses = ["notice"],
)
j2cl_test(
name = "HelloWorldTest",
srcs = glob(["*.java"]),
test_class = "com.google.j2cl.samples.java.HelloWorldTest", # Add this line to force correct class name used in the generated suite file.
deps = [
"//src/main/java/com/google/j2cl/samples/helloworldlib",
"@j2cl//:junit",
],
)
```
- Run `bazel build //src/test/java/com/google/j2cl/samples/java:HelloWorldTest`
```
❯ bazel build //src/test/java/com/google/j2cl/samples/java:HelloWorldTest --verbose_failures
DEBUG: Rule 'j2cl+' indicated that a canonical reproducible form can be obtained by modifying arguments commit = "b22267f8fc5e73f0d4cac5994f11077a2120da58" and dropping ["tag"]
DEBUG: Repository j2cl+ instantiated at:
: in
Repository rule git_repository defined at:
/home/user/.cache/bazel/_bazel_user/41a9ab5b7375ca59d673203c7a70444b/external/bazel_tools/tools/build_defs/repo/git.bzl:208:33: in
WARNING: /home/user/.cache/bazel/_bazel_user/41a9ab5b7375ca59d673203c7a70444b/external/rules_closure+/java/com/google/javascript/jscomp/BUILD:19:13: in java_library rule @@rules_closure+//java/com/google/javascript/jscomp:jscomp: target '@@rules_closure+//java/com/google/javascript/jscomp:jscomp' depends on deprecated target '@@rules_closure+//java/io/bazel/rules/closure:build_info_java_proto': Use java_proto_library from @com_google_protobuf//bazel:java_proto_library.bzl
INFO: Analyzed target //src/test/java/com/google/j2cl/samples/java:HelloWorldTest (270 packages loaded, 8155 targets configured).
INFO: Multiplexer process for Javac has closed its output stream
ERROR: /home/user/a/prog/2026-j2cl/j2cl/samples/helloworld/src/test/java/com/google/j2cl/samples/java/BUILD:8:10: Building src/test/java/com/google/j2cl/samples/java/libHelloWorldTest_generated_suite_lib.jar (1 source jar) and running annotation processors (J2clTestingProcessor) failed: (Exit 1): java failed: error executing Javac command (from target //src/test/java/com/google/j2cl/samples/java:HelloWorldTest_generated_suite_lib)
(cd /home/user/.cache/bazel/_bazel_user/41a9ab5b7375ca59d673203c7a70444b/execroot/_main && \
exec env - \
LC_CTYPE=C.UTF-8 \
PATH=/home/user/.cache/bazelisk/downloads/sha256/17247e8a84245f59d3bc633d0cfe0a840992a7760a11af1a30012d03da31604c/bin:/home/user/.pyenv/shims:/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/snapd/snap/bin:/home/user/.local/share/JetBrains/Toolbox/scripts \
external/rules_java++toolchains+remotejdk21_linux/bin/java '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.resources=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED' '--add-opens=java.base/java.nio=ALL-UNNAMED' '--add-opens=java.base/java.lang=ALL-UNNAMED' '-Dsun.io.useCanonCaches=false' -XX:-CompactStrings -Xlog:disable '-Xlog:all=warning:stderr:uptime,level,tags' -jar external/rules_java++toolchains+remote_java_tools/java_tools/JavaBuilder_deploy.jar @bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/libHelloWorldTest_generated_suite_lib.jar-0.params @bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/libHelloWorldTest_generated_suite_lib.jar-1.params)
# Configuration: d4c5211d3491ee25bd7b54263a1e1a8b876173641d0da1bff9b2c3ffd34d12a4
# Execution platform: @@platforms//host:host
bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/_javac/HelloWorldTest_generated_suite_lib/libHelloWorldTest_generated_suite_lib_tmp/bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/Helloworldtest_Generated_SuiteJ2clTestInput.java:14: error: cannot find symbol
@J2clTestInput(com.google.j2cl.samples.java.HelloWorldTest.class)
^
symbol: class HelloWorldTest
location: package com.google.j2cl.samples.java
error: Test class is not found. Ensure that test_class is a fully qualified class name and exists in the classpath.
bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/_javac/HelloWorldTest_generated_suite_lib/libHelloWorldTest_generated_suite_lib_tmp/bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/Helloworldtest_Generated_SuiteJ2clTestInput.java:15: error: [J2clTestingProcessor:MiscError] com.google.j2cl.junit.apt.J2clTestingProcessor was unable to process this class because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.
public class Helloworldtest_Generated_SuiteJ2clTestInput {}
^
Target //src/test/java/com/google/j2cl/samples/java:HelloWorldTest failed to build
ERROR: /home/user/a/prog/2026-j2cl/j2cl/samples/helloworld/src/test/java/com/google/j2cl/samples/java/BUILD:8:10 Middleman _middlemen/src_Stest_Sjava_Scom_Sgoogle_Sj2cl_Ssamples_Sjava_SHelloWorldTest-runfiles failed: (Exit 1): java failed: error executing Javac command (from target //src/test/java/com/google/j2cl/samples/java:HelloWorldTest_generated_suite_lib)
(cd /home/user/.cache/bazel/_bazel_user/41a9ab5b7375ca59d673203c7a70444b/execroot/_main && \
exec env - \
LC_CTYPE=C.UTF-8 \
PATH=/home/user/.cache/bazelisk/downloads/sha256/17247e8a84245f59d3bc633d0cfe0a840992a7760a11af1a30012d03da31604c/bin:/home/user/.pyenv/shims:/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/snapd/snap/bin:/home/user/.local/share/JetBrains/Toolbox/scripts \
external/rules_java++toolchains+remotejdk21_linux/bin/java '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.resources=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED' '--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED' '--add-opens=java.base/java.nio=ALL-UNNAMED' '--add-opens=java.base/java.lang=ALL-UNNAMED' '-Dsun.io.useCanonCaches=false' -XX:-CompactStrings -Xlog:disable '-Xlog:all=warning:stderr:uptime,level,tags' -jar external/rules_java++toolchains+remote_java_tools/java_tools/JavaBuilder_deploy.jar @bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/libHelloWorldTest_generated_suite_lib.jar-0.params @bazel-out/k8-fastbuild/bin/src/test/java/com/google/j2cl/samples/java/libHelloWorldTest_generated_suite_lib.jar-1.params)
# Configuration: d4c5211d3491ee25bd7b54263a1e1a8b876173641d0da1bff9b2c3ffd34d12a4
# Execution platform: @@platforms//host:host
INFO: Elapsed time: 5.224s, Critical Path: 0.67s
INFO: 3 processes: 1139 action cache hit, 3 internal.
ERROR: Build did NOT complete successfully
```
**Bazel version**
8.3.1
**Expected behavior**
I would expect to be able to write unit tests for classes who's classpath contains a package named "java", e.g. `com.acme.java.extensions`.
**Solution?**
`BUILD.bazel` files can be placed anywhere relative to test source files without any expectation of folder structure (unlike other build systems such as Gradle that usually expect test sources to exist within a `src/test/java` directory relative to the `build.gradle` file).
I think the easiest solution might be to add an optional parameter to the `j2cl_test` rule to override the test sources root.
Alternatively, the test sources root could be derived from the `test_class` parameter.
Contributor guide
Assessment
This issue has not been assessed yet.