Skip to content

ci(common): code coverage - #4

Merged
bladehan1 merged 13 commits into
release_1.0from
feat/code_coverage
Apr 1, 2026
Merged

bladehan1 merged 13 commits into
release_1.0from
feat/code_coverage

Conversation

@bladehan1

@bladehan1 bladehan1 commented Apr 1, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Why are these changes required?

This PR has been tested by:

  • Unit Tests
  • Manual Testing

Follow up

Extra details


Summary by cubic

Adds PR code coverage with a multi-OS/JDK matrix and aggregates JaCoCo across modules to show coverage on pull requests. Also tightens CI with refined path filters, newer actions, per-PR concurrency, cancellation on PR close, and separates builds from checks; improves test reliability and config safety.

  • New Features

    • Added pr-build workflow (macOS/Linux matrix, JDK 8/11/17) to build, test, and upload aggregated JaCoCo XML; root aggregation and codecov.yml added (comments disabled); supports workflow_dispatch to run a single target.
    • Updated pr-check, codeql, math-check, and system-test with refined paths-ignore, per-PR concurrency, latest actions (checkout@v5, setup-java@v5, upload-artifact@v6, github-script@v8), and manual CodeQL build on JDK 8; moved build duties from pr-check to pr-build.
    • Added pr-cancel to stop in-progress pr-build, system-test, and codeql runs when a PR closes.
  • Refactors

    • Tests: introduced BaseMethodTest for per-method Spring isolation; unified DB tests into DbDataSourceImplTest; added dual LevelDB/RocksDB coverage; tuned Gradle test tasks (retries, heap/fork/jvmArgs, Windows excludes); fixed flaky cases (port checks via ServerSocket, documented Trie flakiness).
    • Config/CLI: deprecated flags (e.g., --es, --fast-forward, seed-node flags) in favor of config keys; added event.subscribe.enable with defaults in config; expanded Args mappings and guardrails; safer NeedBeanCondition null checks.
    • Stability: removed arch-based DB engine auto-switch; NativeMessageQueue.stop() now nulls state and resets the singleton; minor template tweaks to mark fields as “Optional”; fixed typos in api.proto comments.

Written for commit da57158. Summary will update on new commits.

@coderabbitai

coderabbitai Bot commented Apr 1, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71336bef-bcc8-49a9-815f-853cb1ec0625

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/code_coverage

Comment @coderabbitai help to get the list of available commands and usage tips.

@bladehan1 bladehan1 changed the title Feat/code coverage feat(ci):code coverage Apr 1, 2026
@bladehan1 bladehan1 changed the title feat(ci):code coverage ci:code coverage Apr 1, 2026
@bladehan1 bladehan1 changed the title ci:code coverage ci(framework):code coverage Apr 1, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 issues found across 50 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="framework/src/test/java/org/tron/common/BaseMethodTest.java">

<violation number="1" location="framework/src/test/java/org/tron/common/BaseMethodTest.java:80">
P2: `beforeDestroy()` is called even when initialization failed, so subclass overrides that access `dbManager`, `context`, etc. will NPE and mask the real test failure. Move the call inside the `context != null` guard.</violation>
</file>

<file name=".github/workflows/pr-cancel.yml">

<violation number="1" location=".github/workflows/pr-cancel.yml:42">
P2: Wrap `cancelWorkflowRun` in a try/catch. If a run finishes between the list and cancel calls, the API returns 409, which throws and aborts the rest of the loop—leaving other in-progress runs uncancelled.</violation>
</file>

<file name="framework/src/test/java/org/tron/core/db2/ChainbaseTest.java">

<violation number="1" location="framework/src/test/java/org/tron/core/db2/ChainbaseTest.java:23">
P2: `ChainbaseTest` doesn't use any Spring beans (`context`, `appT`, `dbManager`, `chainBaseManager`) from `BaseMethodTest`, yet extending it spins up and tears down a full `TronApplicationContext` per test method. This contradicts the base class's own guideline: *"Tests that don't need Spring should NOT extend either base class."* Consider a lighter-weight base that only provides `TemporaryFolder` + `Args.setParam`/`clearParam` lifecycle, or inline the setup.</violation>
</file>

<file name="framework/src/test/java/org/tron/core/config/args/ArgsTest.java">

<violation number="1" location="framework/src/test/java/org/tron/core/config/args/ArgsTest.java:357">
P2: Tautological assertion: the expected value mirrors the production code's logic. If the code reads `System.getProperty("storage.db.engine")` to pick the engine, this test will always pass regardless of correctness. Consider controlling the environment instead — e.g., save and clear the system property before the test, assert `"LEVELDB"`, then restore it — so the test validates a concrete behavior rather than echoing the code path.</violation>
</file>

<file name="framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java">

<violation number="1" location="framework/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java:62">
P1: Setting `instance = null` in `stop()` introduces a concurrency bug because `instance` is not `volatile`. After `stop()` runs, other threads calling `getInstance()` can still see the stale (stopped) instance at the first unsynchronized null-check, skipping the synchronized block entirely and returning a dead singleton.

The field must be declared `volatile` for the double-checked locking + reset pattern to work correctly under the Java Memory Model.</violation>
</file>

<file name="framework/src/test/java/org/tron/common/utils/PublicMethod.java">

<violation number="1" location="framework/src/test/java/org/tron/common/utils/PublicMethod.java:347">
P2: `setReuseAddress(true)` is called after the `ServerSocket(port)` constructor already bound the socket, so it has no effect. Use the no-arg constructor and bind after setting the option, otherwise the port may not be immediately reusable after this check closes the socket.</violation>
</file>

<file name="framework/src/test/java/org/tron/common/storage/DbDataSourceImplTest.java">

<violation number="1" location="framework/src/test/java/org/tron/common/storage/DbDataSourceImplTest.java:157">
P2: `dataSource.closeDB()` is unreachable because the preceding `dataSource.updateByBatch(rows)` is expected to throw a `RuntimeException` (via `exception.expect()`). The database resource will never be closed. Consider moving `closeDB()` before the `exception.expect()` call or using a try-finally / `@After` to ensure cleanup.</violation>
</file>

<file name="framework/build.gradle">

<violation number="1" location="framework/build.gradle:109">
P3: Closure parameter is typed as `Task` but uses `Test`-specific APIs (`retry`, `exclude`, `maxHeapSize`, `forkEvery`, `jvmArgs`). This works only because Gradle uses dynamic Groovy dispatch. Type it as `Test` for correctness and better IDE support.</violation>
</file>

<file name=".github/workflows/pr-build.yml">

<violation number="1" location=".github/workflows/pr-build.yml:214">
P1: Version mismatch: artifacts are uploaded with `upload-artifact@v6` but downloaded with `download-artifact@v4`. These actions must use compatible major versions to share the same artifact backend. This will likely cause the `coverage` job to fail at the download step.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread .github/workflows/pr-build.yml Outdated
Comment thread framework/src/test/java/org/tron/common/BaseMethodTest.java
Comment thread .github/workflows/pr-cancel.yml
Comment thread framework/src/test/java/org/tron/core/db2/ChainbaseTest.java
} else {
Assert.assertEquals("LEVELDB", parameter.getStorage().getDbEngine());
}
String expectedEngine = System.getProperty("storage.db.engine") != null

@cubic-dev-ai cubic-dev-ai Bot Apr 1, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Tautological assertion: the expected value mirrors the production code's logic. If the code reads System.getProperty("storage.db.engine") to pick the engine, this test will always pass regardless of correctness. Consider controlling the environment instead — e.g., save and clear the system property before the test, assert "LEVELDB", then restore it — so the test validates a concrete behavior rather than echoing the code path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At framework/src/test/java/org/tron/core/config/args/ArgsTest.java, line 357:

<comment>Tautological assertion: the expected value mirrors the production code's logic. If the code reads `System.getProperty("storage.db.engine")` to pick the engine, this test will always pass regardless of correctness. Consider controlling the environment instead — e.g., save and clear the system property before the test, assert `"LEVELDB"`, then restore it — so the test validates a concrete behavior rather than echoing the code path.</comment>

<file context>
@@ -333,11 +354,9 @@ public void testConfigStorageDefaults() {
-    } else {
-      Assert.assertEquals("LEVELDB", parameter.getStorage().getDbEngine());
-    }
+    String expectedEngine = System.getProperty("storage.db.engine") != null
+        ? System.getProperty("storage.db.engine") : "LEVELDB";
+    Assert.assertEquals(expectedEngine, parameter.getStorage().getDbEngine());
</file context>
Fix with Cubic

socket.getPort();
} catch (IOException e) {
try (java.net.ServerSocket ss = new java.net.ServerSocket(port)) {
ss.setReuseAddress(true);

@cubic-dev-ai cubic-dev-ai Bot Apr 1, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: setReuseAddress(true) is called after the ServerSocket(port) constructor already bound the socket, so it has no effect. Use the no-arg constructor and bind after setting the option, otherwise the port may not be immediately reusable after this check closes the socket.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At framework/src/test/java/org/tron/common/utils/PublicMethod.java, line 347:

<comment>`setReuseAddress(true)` is called after the `ServerSocket(port)` constructor already bound the socket, so it has no effect. Use the no-arg constructor and bind after setting the option, otherwise the port may not be immediately reusable after this check closes the socket.</comment>

<file context>
@@ -343,13 +343,11 @@ public static int chooseRandomPort(int min, int max) {
-      socket.getPort();
-    } catch (IOException e) {
+    try (java.net.ServerSocket ss = new java.net.ServerSocket(port)) {
+      ss.setReuseAddress(true);
       return true;
+    } catch (IOException e) {
</file context>
Fix with Cubic

assertEquals(new ArrayList<>(), doGetKeysNext(dataSource, key1, 0));
assertEquals(Sets.newHashSet(), doGetValuesNext(dataSource, key1, 0));
assertEquals(Sets.newHashSet(), getlatestValues(dataSource, 0));
dataSource.closeDB();

@cubic-dev-ai cubic-dev-ai Bot Apr 1, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: dataSource.closeDB() is unreachable because the preceding dataSource.updateByBatch(rows) is expected to throw a RuntimeException (via exception.expect()). The database resource will never be closed. Consider moving closeDB() before the exception.expect() call or using a try-finally / @After to ensure cleanup.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At framework/src/test/java/org/tron/common/storage/DbDataSourceImplTest.java, line 157:

<comment>`dataSource.closeDB()` is unreachable because the preceding `dataSource.updateByBatch(rows)` is expected to throw a `RuntimeException` (via `exception.expect()`). The database resource will never be closed. Consider moving `closeDB()` before the `exception.expect()` call or using a try-finally / `@After` to ensure cleanup.</comment>

<file context>
@@ -0,0 +1,454 @@
+    assertEquals(new ArrayList<>(), doGetKeysNext(dataSource, key1, 0));
+    assertEquals(Sets.newHashSet(), doGetValuesNext(dataSource, key1, 0));
+    assertEquals(Sets.newHashSet(), getlatestValues(dataSource, 0));
+    dataSource.closeDB();
+  }
+
</file context>
Fix with Cubic

Comment thread framework/build.gradle

test {
retry {
def configureTestTask = { Task t ->

@cubic-dev-ai cubic-dev-ai Bot Apr 1, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Closure parameter is typed as Task but uses Test-specific APIs (retry, exclude, maxHeapSize, forkEvery, jvmArgs). This works only because Gradle uses dynamic Groovy dispatch. Type it as Test for correctness and better IDE support.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At framework/build.gradle, line 109:

<comment>Closure parameter is typed as `Task` but uses `Test`-specific APIs (`retry`, `exclude`, `maxHeapSize`, `forkEvery`, `jvmArgs`). This works only because Gradle uses dynamic Groovy dispatch. Type it as `Test` for correctness and better IDE support.</comment>

<file context>
@@ -106,19 +106,38 @@ run {
 
-test {
-    retry {
+def configureTestTask = { Task t ->
+    t.retry {
         maxRetries = 5
</file context>
Suggested change
def configureTestTask = { Task t ->
def configureTestTask = { Test t ->
Fix with Cubic

@bladehan1 bladehan1 changed the title ci(framework):code coverage ci:code coverage Apr 1, 2026
@bladehan1 bladehan1 changed the title ci:code coverage ci(workflow):code coverage Apr 1, 2026
@github-actions

github-actions Bot commented Apr 1, 2026 •

Copy link
Copy Markdown

Code Coverage Report

Overall Project 76.55% -0.03% 🍏
Files changed 77.39% 🍏

Module Coverage
common 88.25% 🍏
framework 67.7% -0.07% 🍏
Files
Module File Coverage
common Storage.java 80.13% 🍏
framework NeedBeanCondition.java 94.12% -5.88% 🍏
NativeMessageQueue.java 86.79% 🍏
Args.java 77.3% -1.24% 🍏

@bladehan1 bladehan1 changed the title ci(workflow):code coverage ci(common):code coverage Apr 1, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/pr-build.yml">

<violation number="1" location=".github/workflows/pr-build.yml:7">
P2: The new `paths` allowlist is too narrow: workflow/config-only PRs won’t trigger this pipeline, so broken CI coverage changes can land unvalidated.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread .github/workflows/pr-build.yml Outdated
@bladehan1 bladehan1 changed the title ci(common):code coverage ci(common): code coverage Apr 1, 2026
@bladehan1
bladehan1 merged commit 7e32a2d into release_1.0 Apr 1, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants