Skip to content

Conversation

@sigmaaa
Copy link
Collaborator

@sigmaaa sigmaaa commented Jun 11, 2025

Description

This PR introduces a comprehensive set of unit tests for the IDFUtil class. With the addition of these tests, the overall test coverage for this class (including UI-level tests) exceeds 80%.

Most of the added tests rely heavily on mocking to avoid significant refactoring at this stage. While mocking is not ideal for all scenarios, this approach provides a useful foundation. These tests can serve as a base for extending coverage or reproducing edge cases and bugs in the future.

Note: A few remaining methods are better suited for integration testing due to their system-level dependencies and side effects.

Fixes # (IEP-1553)

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

How has this been tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Test A
  • Test B

Test Configuration:

  • ESP-IDF Version:
  • OS (Windows,Linux and macOS):

Dependent components impacted by this PR:

  • Component 1
  • Component 2

Checklist

  • PR Self Reviewed
  • Applied Code formatting
  • Added Documentation
  • Added Unit Test
  • Verified on all platforms - Windows,Linux and macOS

Summary by CodeRabbit

  • Tests
    • Added comprehensive unit tests for utility methods related to ESP-IDF tool scripts, environment variables, and toolchain paths, ensuring correct behavior under various scenarios.
  • Style
    • Improved code readability by adjusting blank line placement after specific environment variable calls.

@coderabbitai
Copy link

coderabbitai bot commented Jun 11, 2025

Walkthrough

A blank line was added after specific environment variable retrieval calls in the IDFUtil class. Additionally, a comprehensive new test class, IDFUtilTest, was introduced to rigorously test various static methods in IDFUtil, including environment variable handling, file path construction, toolchain lookups, and version-dependent logic. The test bundle manifest was updated to import an additional package required for environment variable handling.

Changes

File(s) Change Summary
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java Added blank lines after environment variable retrievals in three methods.
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java Added a new test class with extensive unit tests for IDFUtil covering environment, file paths, and toolchains.
tests/com.espressif.idf.core.test/META-INF/MANIFEST.MF Added org.eclipse.cdt.core.envvar package to Import-Package section.

Sequence Diagram(s)

sequenceDiagram
    participant Test as IDFUtilTest
    participant Util as IDFUtil
    participant Env as IDFEnvironmentVariables
    participant ToolChain as ESPToolChainManager

    Test->>Util: getIDFPath()
    Util->>Env: getEnvValue("IDF_PATH")
    Env-->>Util: Return path
    Util-->>Test: Return File

    Test->>Util: getXtensaToolchainExecutablePathByTarget(target)
    Util->>ToolChain: getToolchainExecutablePath(target)
    ToolChain-->>Util: Return path or null
    Util-->>Test: Return path or null

    Test->>Util: checkIfIdfSupportsSpaces()
    Util->>Util: getIdfVersion()
    Util-->>Test: Return boolean

    Test->>Util: getIDFExtraPaths()
    Util->>Env: getEnvValue("IDF_PATH")
    Env-->>Util: Return path
    Util-->>Test: Return String
Loading

Possibly related PRs

Suggested reviewers

  • alirana01
  • kolipakakondal

Poem

In the warren, code is neat,
Blank lines hop in, tidy and fleet.
Tests now bloom, robust and bright,
Each path and toolchain checked just right.
With every method put to trial,
This bunny hops another mile! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)

69-71: systemEnvPathProvider is defined but never used

Dead code increases maintenance cost and annotation imports.
If future usage isn’t planned, remove it.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d94c4b and 7f62a2f.

📒 Files selected for processing (3)
  • bundles/com.espressif.idf.core/META-INF/MANIFEST.MF (1 hunks)
  • bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (7 hunks)
  • tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1)
bundles/com.espressif.idf.core/src/com/espressif/idf/core/util/IDFUtil.java (1)
  • IDFUtil (62-894)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos
🔇 Additional comments (1)
bundles/com.espressif.idf.core/META-INF/MANIFEST.MF (1)

66-70: Version-range may not match the Guava bundle actually shipped in the IDE

com.google.common.annotations is exported by the Guava bundle, not by a standalone package.
Declaring [33.4.0,34.0.0) forces the resolver to pick a very recent Guava (33.4+), while most Eclipse distributions still ship 32.x. Unless the target platform has already been upgraded, this import will make the bundle unresolved at run time.

Either:

-Import-Package: com.google.common.annotations;version="[33.4.0,34.0.0)",
+Import-Package: com.google.common.annotations;version="32.0.0"

or declare an explicit dependency on the matching com.google.guava bundle with a looser range (e.g. "[30.0.0,35.0.0)").
Please verify the platform BOM before merging.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (4)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (4)

41-44: Static provider mutation is never rolled-back – tests are order-dependent

IDFUtil.idfEnvVarPathProvider is overwritten here but never restored, so any later test that depends on the default provider will silently inherit "esp_idf_path". This violates test isolation and was already raised in a previous review.
Persist with the earlier advice: capture the original provider in @BeforeEach and restore it in @AfterEach, or introduce a helper such as IDFUtil.swapIdfEnvVarPathProvider(...).


45-60: Path comparison remains platform-fragile

assertEquals(expectedPath, result.getPath()) will fail on Windows because result.getPath() always contains forward slashes (generated by IDFUtil) while Paths.get(...).toString() uses the platform separator. Normalise both sides or compare Path objects. This issue has been pointed out before.

Also applies to: 68-73, 80-85, 92-97


109-115: @AfterEach still resets only the cache flag

The teardown clears idfSupportsSpaces but leaves the mutated idfEnvVarPathProvider (and any other injected providers) intact, so leakage between tests is still possible. Please extend the teardown (or use the suggested swap helper) to restore all mutated static fields.


151-156: Replace Java assert with JUnit assertions for reliability

assert (firstCall); is skipped unless the JVM is started with -ea. Use assertTrue(firstCall) instead (same for secondCall). This has been flagged previously.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f62a2f and 5c4bd02.

📒 Files selected for processing (1)
  • tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: build_macos

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (3)

45-50: 🛠️ Refactor suggestion

Path comparison brittle on Windows – normalise or compare Path objects

result.getPath() always uses '/', whereas Paths.get(...).toString() yields '\' on Windows.
All such direct-string comparisons will therefore fail on CI jobs that run on Windows.

-assertEquals(expectedPath, result.getPath());
+assertEquals(Paths.get(expectedPath).normalize(),
+             result.toPath().normalize());

Please apply the same normalisation (or switch to Path equality) in every test that asserts on file-system paths.


216-221: ⚠️ Potential issue

Replace plain Java assert with JUnit assertions

assert (firstCall); is ignored unless the JVM is started with -ea, rendering the test ineffective under most runners.

-assert (firstCall);
+assertTrue(firstCall, "First call should evaluate to true");

Search & replace any further occurrences to keep the test suite reliable.


241-245: 🛠️ Refactor suggestion

Incorrect PATH construction – Path.append(":") creates invalid segments

Appending ":" with org.eclipse.core.runtime.Path treats the colon as a path segment, producing /:/, not a path-list separator.
Beside breaking on *nix, it is totally wrong on Windows.

-String expected = new Path("esp_idf_path").append("components/esptool_py/esptool").append(":")
-        .append("esp_idf_path").append("components/espcoredump").append(":").append("esp_idf_path")
-        .append("components/partition_table").append(":").append("esp_idf_path").append("components/app_update")
-        .toString();
+String pathSep = File.pathSeparator;
+String expected = String.join(pathSep,
+        "esp_idf_path/components/esptool_py/esptool",
+        "esp_idf_path/components/espcoredump",
+        "esp_idf_path/components/partition_table",
+        "esp_idf_path/components/app_update");

Apply the same fix where similar construction is used.

🧹 Nitpick comments (1)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1)

175-181: Reflection to reset cache is fragile – expose a test-only reset helper

Using reflection to mutate private static state can break with future JDK
module restrictions and obscures intent.
Consider adding a package-private IDFUtil.resetCachesForTest() and calling that
from @AfterEach instead of reflective field writes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb901d8 and d8e8c87.

📒 Files selected for processing (1)
  • tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: build_macos

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (4)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (4)

52-57: ⚠️ Potential issue

Path comparison still OS-dependent → assertions will break on Windows

All these tests build expectedPath via Paths.get(...).toString() and then compare it with result.getPath().
IDFUtil concatenates segments with the forward-slash '/', so on Windows the RHS will contain '/' while the LHS contains '\\', causing false negatives.

Normalize before comparing, e.g.:

-assertEquals(expectedPath, result.getPath());
+assertEquals(
+        Paths.get(expectedPath).toAbsolutePath().normalize(),
+        Paths.get(result.getPath()).toAbsolutePath().normalize());

or compare Path objects directly.

Also applies to: 67-72, 93-98, 108-113, 135-138, 149-153, 162-166


248-252: ⚠️ Potential issue

Expected PATH string built with Path.append(":") is invalid

Using Eclipse Path.append(":") treats ":" as a path segment, producing output like esp_idf_path/:/….
Build the list with File.pathSeparator or plain ':' (if *nix-only) and ordinary string concatenation instead.

-String expected = new Path("esp_idf_path").append("components/esptool_py/esptool").append(":")
-        .append("esp_idf_path").append("components/espcoredump").append(":").append("esp_idf_path")
-        .append("components/partition_table").append(":").append("esp_idf_path").append("components/app_update")
-        .toString();
+String ps = File.pathSeparator;
+String expected = String.join(ps,
+        "esp_idf_path/components/esptool_py/esptool",
+        "esp_idf_path/components/espcoredump",
+        "esp_idf_path/components/partition_table",
+        "esp_idf_path/components/app_update");

223-229: ⚠️ Potential issue

Use JUnit assertions instead of Java assert

assert (firstCall); becomes a no-op unless the JVM runs with -ea.
Replace with assertTrue(firstCall) (and remove the parenthesis).


182-188: ⚠️ Potential issue

Static lambda override not reset → hidden inter-test coupling

@AfterEach only clears idfSupportsSpaces; the overridden idfEnvVarPathProvider
(assigned inside IDFUtil) persists across tests, so one test can influence another.

Save the original provider in @BeforeEach and restore it here, e.g.:

private UnaryOperator<String> originalProvider;

@BeforeEach
void stash() {
    originalProvider = IDFUtil.swapIdfEnvVarPathProvider(original -> "esp_idf_path");
}

@AfterEach
void restore() throws Exception {
    IDFUtil.swapIdfEnvVarPathProvider(originalProvider);
    Field f = IDFUtil.class.getDeclaredField("idfSupportsSpaces");
    f.setAccessible(true);
    f.set(null, null);
}
🧹 Nitpick comments (1)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1)

45-73: Heavy duplication of IDFEnvironmentVariables mocking

Almost every test repeats the same mockConstruction(IDFEnvironmentVariables…) boilerplate.
Extract a helper (or JUnit extension) to provide the mocked IDF path, reducing noise and maintenance overhead.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8e8c87 and fd55442.

📒 Files selected for processing (2)
  • tests/com.espressif.idf.core.test/META-INF/MANIFEST.MF (1 hunks)
  • tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/com.espressif.idf.core.test/META-INF/MANIFEST.MF
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_macos
  • GitHub Check: build

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (2)

223-228: Replace Java assert with JUnit assertion

assert statements are ignored unless the JVM is started with -ea, so this test can silently succeed even when the logic is broken.

 boolean firstCall = IDFUtil.checkIfIdfSupportsSpaces();
-assert (firstCall);
+assertTrue(firstCall);

248-252: Path.append(":") creates an invalid, OS-specific expectation

Path.append treats every argument as a path segment. Appending ":" therefore yields something like .../:/..., which is never a real path list. Build the expected string with the platform path-separator instead:

-String expected = new Path("esp_idf_path").append("components/esptool_py/esptool").append(":")
-        .append("esp_idf_path").append("components/espcoredump").append(":").append("esp_idf_path")
-        .append("components/partition_table").append(":").append("esp_idf_path").append("components/app_update")
-        .toString();
+String pathSep = File.pathSeparator;
+String expected = String.join(pathSep,
+        "esp_idf_path/components/esptool_py/esptool",
+        "esp_idf_path/components/espcoredump",
+        "esp_idf_path/components/partition_table",
+        "esp_idf_path/components/app_update");
🧹 Nitpick comments (1)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1)

235-238: Nit: use System.lineSeparator()

System.lineSeparator() is the idiomatic way to fetch the platform line separator and is a touch clearer than reading the property explicitly.

-String expected = System.getProperty("line.separator"); //$NON-NLS-1$
+String expected = System.lineSeparator();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd55442 and 04a5ca3.

📒 Files selected for processing (1)
  • tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (2)

226-232: Replace Java assert with JUnit assertions

assert (firstCall); relies on the JVM being started with -ea.
Use assertTrue(firstCall) (and similar) so the test is always executed.

-            boolean firstCall = IDFUtil.checkIfIdfSupportsSpaces();
-            assert (firstCall);
+            boolean firstCall = IDFUtil.checkIfIdfSupportsSpaces();
+            assertTrue(firstCall);

251-256: Expected PATH string is built incorrectly & is OS-specific

Path.append(":") appends ":" as a path segment, producing /:/… on *nix and a back-slash mess on Windows.
Build the list with File.pathSeparator and plain strings instead.

-String expected = new Path("esp_idf_path").append("components/esptool_py/esptool").append(":")
-        .append("esp_idf_path").append("components/espcoredump").append(":").append("esp_idf_path")
-        .append("components/partition_table").append(":").append("esp_idf_path").append("components/app_update")
-        .toString();
+String pathSep = File.pathSeparator;
+String expected = String.join(pathSep,
+        "esp_idf_path/components/esptool_py/esptool",
+        "esp_idf_path/components/espcoredump",
+        "esp_idf_path/components/partition_table",
+        "esp_idf_path/components/app_update");
🧹 Nitpick comments (1)
tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1)

48-76: Heavy repetition of the same IDFEnvironmentVariables mocking

Every test re-creates identical mockConstruction(IDFEnvironmentVariables …) boilerplate.
Consider extracting a small helper (e.g. withIdfPathMock("esp_idf_path", () -> { … })) or a JUnit extension to reduce noise and improve maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04a5ca3 and 38a57a3.

📒 Files selected for processing (1)
  • tests/com.espressif.idf.core.test/src/com/espressif/idf/core/util/test/IDFUtilTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_macos

@sigmaaa sigmaaa changed the title DRAFT: IEP 1553 adding unit tests for IDFUtil IEP 1553 adding unit tests for IDFUtil Jun 17, 2025
Copy link
Collaborator

@kolipakakondal kolipakakondal left a comment

Choose a reason for hiding this comment

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

LGTM

@kolipakakondal kolipakakondal merged commit fe67866 into master Jul 24, 2025
4 of 5 checks passed
@kolipakakondal kolipakakondal deleted the IEP-1553 branch July 24, 2025 12:05
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.

3 participants