bazel-contrib / bazel-contrib/rules_jvm

get_class_name incorrectly matches .net/.org/.io sub-packages inside com.* packages

Open
#437 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
54
Forks
98
Avg merge
6d 2h
Merged PRs (30d)
7

Description

## Description

`get_class_name()` in `java/private/package.bzl` produces an incorrect `test_class` when a `com.*` Java package contains a sub-package named `net`, `org`, `io`, `ai`, `co`, `me`, or `dev`.

This is related to #104 but is a **different failure mode**: #104 is about uncommon TLDs not being recognized at all. This bug is about a known TLD prefix (`.net.`, `.org.`, etc.) being matched **inside** a `com.*` package name instead of at the top level.

## Example

Source path: `com/example/net/NetTest.java`

1. `get_class_name` converts it to `com.example.net.NetTest`
2. Scans `_PREFIXES = (".com.", ".org.", ".net.", ...)`
3. `.com.` is checked first via `name.find(".com.")` — but the string starts with `com.` (no leading dot), so it returns `-1`
4. `.net.` matches at position 12 inside `com.example.net.NetTest`
5. Returns `net.NetTest` instead of `com.example.net.NetTest`

Result: `Class not found: [net.NetTest]`

## Minimal reproduction

Unzip the attached `rules-jvm-bug-poc.zip` and run:

```bash
bazel test //src/test/java/...
```

**Expected:** Both tests pass.
**Actual:** `NetTest` fails with `Class not found: [net.NetTest]`, `UtilsTest` passes.

Reproduction project structure

```
├── .bazelrc # Java 17 toolchain
├── .bazelversion # 9.0.0
├── BUILD.bazel
├── MODULE.bazel # contrib_rules_jvm 0.32.0
└── src/test/java/
├── BUILD.bazel # java_test_suite with two tests
└── com/example/
├── net/NetTest.java # FAILS
└── utils/UtilsTest.java # PASSES
```

`src/test/java/BUILD.bazel`:
```python
load("@contrib_rules_jvm//java:defs.bzl", "java_test_suite")

java_test_suite(
name = "tests",
srcs = [
"com/example/net/NetTest.java",
"com/example/utils/UtilsTest.java",
],
deps = ["@maven//:junit_junit"],
)
```

## Root cause

In [`java/private/package.bzl`](https://github.com/bazel-contrib/rules_jvm/blob/main/java/private/package.bzl#L20-L31):

```python
_PREFIXES = (".com.", ".org.", ".net.", ".io.", ".ai.", ".co.", ".me.", ".dev.")

def get_class_name(package, src, prefixes=[]):
idx = src.rindex(".")
name = src[:idx].replace("/", ".")
# ...
for prefix in prefixes:
idx = name.find(prefix)
if idx != -1:
return name[idx + 1:]
```

`name.find(".com.")` fails when the string **starts** with `com.` because there's no dot at position -1. The scan then falls through to `.net.` which matches inside the string.

## Workaround

Pass `package_prefixes` to anchor the match:

```python
java_test_suite(
...
package_prefixes = [".com.example."],
)
```

## Affected packages

Any `com.*` (or `org.*`, etc.) package that has a sub-package matching one of the entries in `_PREFIXES`: `net`, `org`, `io`, `ai`, `co`, `me`, `dev`.

Contributor guide

Open the contributing guide

Research direction

Start in java/private/package.bzl at get_class_name and review how package prefixes are matched. Unzip the reproduction project and run bazel test //src/test/java/... to confirm the NetTest failure. Done means both NetTest and UtilsTest pass without the incorrect net.NetTest class name.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
build-system
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.