Skip to content

keep JSyntaxTextArea text value for use in headless mode#696

Closed
stokpop wants to merge 9 commits intoapache:masterfrom
stokpop:minor-fixes
Closed

keep JSyntaxTextArea text value for use in headless mode#696
stokpop wants to merge 9 commits intoapache:masterfrom
stokpop:minor-fixes

Conversation

@stokpop
Copy link
Contributor

@stokpop stokpop commented Jan 25, 2022

Description

Keep the text that is set on overridden JSyntaxTextArea anonymous class in headless mode.

Motivation and Context

Working on a project that uses jMeter components in a headless way (java.awt.headless=true), we found that the setText(...) is not kept on the JSyntaxTextArea from getInstance(...). Following getText() call returns null. With java.awt.headless=false, to try and run with the original JSyntaxTextArea on headless linux it fails as there is no X11 display.

This might benefit headless unit test as well.

How Has This Been Tested?

Unit tests added. Snapshot build works in project.

Types of changes

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

Checklist:

  • My code follows the [code style][style-guide] of this project.
  • I have updated the documentation accordingly (javadocs and code comments)

public void discardAllEdits() { }
@Override
public void setText(String t) { }
public void setText(String t) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just wondering, does the removal of setText override solves the issue?

Copy link
Contributor

Choose a reason for hiding this comment

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

If I add a super.setText(t) here, I get the following stacktrace:

java.lang.NullPointerException
        at org.fife.ui.rsyntaxtextarea.RSyntaxTextArea.getFontMetricsForTokenType(RSyntaxTextArea.java:1204)
        at org.fife.ui.rsyntaxtextarea.TokenImpl.getWidthUpTo(TokenImpl.java:578)
        at org.fife.ui.rsyntaxtextarea.TokenImpl.getWidth(TokenImpl.java:570)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.calculateBreakPosition(WrappedSyntaxView.java:127)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.calculateLineCount(WrappedSyntaxView.java:1191)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.handleDocumentEvent(WrappedSyntaxView.java:1440)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.insertUpdate(WrappedSyntaxView.java:1464)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.insertUpdate(WrappedSyntaxView.java:705)
        at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1610)
        at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1869)
        at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:201)
        at org.fife.ui.rsyntaxtextarea.RSyntaxDocument.fireInsertUpdate(RSyntaxDocument.java:187)
        at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:748)
        at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:707)
        at javax.swing.text.PlainDocument.insertString(PlainDocument.java:130)
        at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:669)
        at javax.swing.text.JTextComponent.setText(JTextComponent.java:1669)
        at org.apache.jmeter.gui.util.JSyntaxTextArea$1.setText(JSyntaxTextArea.java:122)

So, I would say, no, it does not resolve the issue :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, I saw same NPE.

public void discardAllEdits() { }
@Override
public void setText(String t) { }
public void setText(String t) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If I add a super.setText(t) here, I get the following stacktrace:

java.lang.NullPointerException
        at org.fife.ui.rsyntaxtextarea.RSyntaxTextArea.getFontMetricsForTokenType(RSyntaxTextArea.java:1204)
        at org.fife.ui.rsyntaxtextarea.TokenImpl.getWidthUpTo(TokenImpl.java:578)
        at org.fife.ui.rsyntaxtextarea.TokenImpl.getWidth(TokenImpl.java:570)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.calculateBreakPosition(WrappedSyntaxView.java:127)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.calculateLineCount(WrappedSyntaxView.java:1191)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.handleDocumentEvent(WrappedSyntaxView.java:1440)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.insertUpdate(WrappedSyntaxView.java:1464)
        at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.insertUpdate(WrappedSyntaxView.java:705)
        at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1610)
        at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1869)
        at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:201)
        at org.fife.ui.rsyntaxtextarea.RSyntaxDocument.fireInsertUpdate(RSyntaxDocument.java:187)
        at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:748)
        at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:707)
        at javax.swing.text.PlainDocument.insertString(PlainDocument.java:130)
        at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:669)
        at javax.swing.text.JTextComponent.setText(JTextComponent.java:1669)
        at org.apache.jmeter.gui.util.JSyntaxTextArea$1.setText(JSyntaxTextArea.java:122)

So, I would say, no, it does not resolve the issue :)

Copy link
Contributor

Choose a reason for hiding this comment

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

This has nothing to do with the description of the issue. I don't think it is needed here and should be done in it's own PR (if at all).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true, typo unrelated to PR, removed it

} catch (HeadlessException he) {
// Does not work in headless mode
// Does not work in headless mode, which depends on value of java.awt.headless property
// and the OS (e.g. might work on MacOS and not on Linux due to missing X11).
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand this new comment. Can you explain it to me?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How I got here: I have Kotlin code (to generate a jmx file based on open-api spec) that calls setText() and getText() for the json payload. When running from Kotlin code on MacOS laptop, the code runs fine in Intellij: getText() returns a value. When running it from Kotlin script, the getText() returns null after setText(). Why? Debugging shows that java.awt.headless=true when running Kotlin script. When running Kotlin code the java.awt.headless property is not present, so does not run headless. (In that case it I guess it might work because awt.toolkit=sun.lwawt.macosx.LWCToolkit is present). Then on linux docker (target system) running non-headless does not work because it says no DISPLAY is set (awt.toolkit is missing?). And running headless (with java.awt.headless=true), the getText() returns null.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've filed bobbylight/RSyntaxTextArea#424 to RSyntaxTextArea. I hope we can remove headless workaround then.

String key = "java.awt.headless";
String initialValue = System.getProperty(key);
try {
System.setProperty(key, "true");
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this really a sane way to test headless mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe there is a better way? It is indeed tricky as it might impact other tests, that's why the @Isolated is added. The code directly depends on the property value in its behaviour. I've seen some mock framework code that overrides the System.getProperty() to return a certain value, but there might be classloading issues.

Copy link
Contributor

Choose a reason for hiding this comment

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

For the other tests, we are expecting the test suite to be set up in the correct way (for example most of our CI stuff is done in a headless setup). But if this works, we can use it.

JSyntaxTextArea textArea = JSyntaxTextArea.getInstance(10,20);

String myText = "my text";
textArea.setText(myText);
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you testing set/getText here, or the creation of a specialised subclass?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Test if the textArea returned by getInstance() in headless mode is retaining the text. Without the fix of the specialised subclass this will fail, because getText() returns null.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, but why the call textArea.setCodeFoldingEnabled(true);? It seems that you want to test, that we get a special variant, that works in headless mode. But in my eyes, you know, that it works in headless mode (or could not check it anyway) and this test is about saving the text. One test should assert one thing (at least new ones should :))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agree, I removed the NPE implicit check

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this expected? I would expect, that this fail should never be reached and should point this out a bit more clearly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The exception is not expected here, because the explicit java.awt.headless=true, so the fail. This is indeed different from the other test, that seems to allow the HeadlessException by ignoring it. I can change fail text.

@codecov-commenter
Copy link

codecov-commenter commented Jan 26, 2022

Codecov Report

Attention: Patch coverage is 0% with 4 lines in your changes missing coverage. Please review.

Project coverage is 55.58%. Comparing base (85580b4) to head (6ea80ac).
Report is 701 commits behind head on master.

Files Patch % Lines
...va/org/apache/jmeter/gui/util/JSyntaxTextArea.java 0.00% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #696      +/-   ##
============================================
- Coverage     55.59%   55.58%   -0.01%     
  Complexity    10336    10336              
============================================
  Files          1059     1059              
  Lines         65050    65056       +6     
  Branches       7401     7401              
============================================
  Hits          36163    36163              
- Misses        26337    26343       +6     
  Partials       2550     2550              
Files Coverage Δ
...va/org/apache/jmeter/gui/util/JSyntaxTextArea.java 59.57% <0.00%> (-1.97%) ⬇️

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 85580b4...6ea80ac. Read the comment docs.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we could drop this catch, as every exception here is unexpected and should be seen after.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree, I dropped the catch.

@asfgit asfgit closed this in 2ca7cf9 Mar 9, 2022
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.

4 participants

Comments