Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bidi][java] Add high-level logging APIs #14225

Merged
merged 3 commits into from
Jul 18, 2024

Conversation

pujagani
Copy link
Contributor

@pujagani pujagani commented Jul 3, 2024

User description

Thanks for contributing to Selenium!
A PR well described will help maintainers to quickly review and merge it

Before submitting your PR, please check our contributing guidelines.
Avoid large PRs, help reviewers by making them as simple and short as possible.

Description

Related to #14135.

Motivation and Context

Implement high-level BiDi logging API.

The core logic did not take time, but trying to avoid the RemoteWebDriver casting took a lot of time to figure out but after spending sufficient time could not find a way to avoid circular dependency issues. Hence this PR took time. We could restructure it in a later release like Selenium 6, when everything uses BiDi. The current goal is to focus on getting the high-level APIs implemented.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the contributing document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

PR Type

Enhancement, Tests


Description

  • Added RemoteScript class to implement high-level BiDi logging API.
  • Integrated RemoteScript with RemoteWebDriver to handle console messages and JavaScript errors.
  • Created Script interface defining methods for logging handlers.
  • Added comprehensive tests for RemoteScript functionality, including handler addition, removal, and multiple handler scenarios.
  • Updated Bazel build file to include necessary BiDi logging dependencies.

Changes walkthrough 📝

Relevant files
Enhancement
RemoteScript.java
Add `RemoteScript` class for BiDi logging API integration

java/src/org/openqa/selenium/remote/RemoteScript.java

  • Added new RemoteScript class implementing Script interface.
  • Integrated BiDi logging API for console messages and JavaScript
    errors.
  • Added methods to add and remove console message and JavaScript error
    handlers.
  • +58/-0   
    RemoteWebDriver.java
    Integrate `RemoteScript` with `RemoteWebDriver`                   

    java/src/org/openqa/selenium/remote/RemoteWebDriver.java

  • Added remoteScript field to RemoteWebDriver.
  • Implemented script() method to initialize and return RemoteScript.
  • +9/-0     
    Script.java
    Define `Script` interface for logging handlers                     

    java/src/org/openqa/selenium/remote/Script.java

  • Created Script interface with methods for handling console messages
    and JavaScript errors.
  • +35/-0   
    Tests
    WebScriptTest.java
    Add tests for `RemoteScript` logging functionality             

    java/test/org/openqa/selenium/WebScriptTest.java

  • Added tests for RemoteScript functionality.
  • Verified adding and removing console message and JavaScript error
    handlers.
  • Tested multiple handlers and their interactions.
  • +190/-0 
    Configuration changes
    BUILD.bazel
    Update Bazel build file for BiDi logging dependencies       

    java/src/org/openqa/selenium/remote/BUILD.bazel

    • Updated dependencies to include BiDi logging and module packages.
    +2/-0     

    💡 PR-Agent usage:
    Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    Copy link
    Contributor

    PR Reviewer Guide 🔍

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Key issues to review

    Possible Bug:
    The implementation of RemoteScript assumes that the WebDriver instance passed to it will always implement HasBiDi. This might not always be the case, which could lead to a ClassCastException. Consider adding a check to ensure that the driver actually implements this interface before casting.

    Design Concern:
    The RemoteScript class is tightly coupled with the LogInspector and BiDi implementations. This could make unit testing difficult and the code less modular. Consider abstracting these dependencies or using dependency injection for better testability and modularity.

    Copy link
    Contributor

    PR Code Suggestions ✨

    CategorySuggestion                                                                                                                                    Score
    Possible bug
    Add type checking before casting to avoid ClassCastException

    Consider checking if the driver instance is of type HasBiDi before casting it. This will
    prevent a potential ClassCastException if the driver does not implement the HasBiDi
    interface.

    java/src/org/openqa/selenium/remote/RemoteScript.java [35]

    -this.biDi = ((HasBiDi) driver).getBiDi();
    +if (driver instanceof HasBiDi) {
    +    this.biDi = ((HasBiDi) driver).getBiDi();
    +} else {
    +    throw new IllegalArgumentException("Driver must implement HasBiDi");
    +}
     
    • Apply this suggestion
    Suggestion importance[1-10]: 10

    Why: This suggestion addresses a potential ClassCastException by adding a type check before casting, which is crucial for preventing runtime errors and ensuring the code's robustness.

    10
    Add null checks for driver to prevent NullPointerException

    Consider adding null checks for driver in the constructor to prevent NullPointerException
    in subsequent method calls if driver is null.

    java/src/org/openqa/selenium/remote/RemoteScript.java [34-37]

     public RemoteScript(WebDriver driver) {
    +    if (driver == null) {
    +        throw new IllegalArgumentException("Driver cannot be null");
    +    }
         this.biDi = ((HasBiDi) driver).getBiDi();
         this.logInspector = new LogInspector(driver);
     }
     
    • Apply this suggestion
    Suggestion importance[1-10]: 10

    Why: This suggestion prevents a potential NullPointerException by adding null checks for the driver parameter, which is essential for ensuring the stability and reliability of the code.

    10
    Thread safety
    Add synchronization to ensure thread-safe lazy initialization of remoteScript

    To ensure thread safety when accessing remoteScript, consider synchronizing the block of
    code where remoteScript is checked and instantiated. This prevents potential issues in a
    multi-threaded environment where remoteScript could be instantiated multiple times.

    java/src/org/openqa/selenium/remote/RemoteWebDriver.java [492-495]

    -if (this.remoteScript == null) {
    -    this.remoteScript = new RemoteScript(this);
    +synchronized (this) {
    +    if (this.remoteScript == null) {
    +        this.remoteScript = new RemoteScript(this);
    +    }
     }
     return this.remoteScript;
     
    • Apply this suggestion
    Suggestion importance[1-10]: 9

    Why: This suggestion improves thread safety by synchronizing the block of code where remoteScript is checked and instantiated, preventing potential issues in a multi-threaded environment.

    9
    Possible issue
    Ensure unique IDs for handlers to prevent incorrect listener removal

    It is recommended to handle the scenario where logInspector.onConsoleEntry(consumer) and
    logInspector.onJavaScriptException(consumer) might return the same id for different
    handlers, potentially leading to incorrect removal of listeners.

    java/src/org/openqa/selenium/remote/RemoteScript.java [41-51]

    -return this.logInspector.onConsoleEntry(consumer);
    -return this.logInspector.onJavaScriptException(consumer);
    +long consoleId = this.logInspector.onConsoleEntry(consumer);
    +long jsErrorId = this.logInspector.onJavaScriptException(consumer);
    +if (consoleId == jsErrorId) {
    +    throw new IllegalStateException("Duplicate handler ID generated");
    +}
    +return consoleId;
    +return jsErrorId;
     
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: This suggestion addresses a potential issue where duplicate IDs could lead to incorrect listener removal. Ensuring unique IDs is important for the correct functioning of the handlers.

    8

    @pujagani
    Copy link
    Contributor Author

    @diemol Does this look alright?

    Copy link
    Member

    @diemol diemol left a comment

    Choose a reason for hiding this comment

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

    Thank you, @pujagani!

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    2 participants