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

[macOS] NPE in Menu.setVisible(boolean) despite the menu showing up #1178

Open
thahnen opened this issue Apr 16, 2024 · 1 comment
Open

[macOS] NPE in Menu.setVisible(boolean) despite the menu showing up #1178

thahnen opened this issue Apr 16, 2024 · 1 comment

Comments

@thahnen
Copy link

thahnen commented Apr 16, 2024

Describe the bug

I think this is closely related to #922 and #923.

We are running our integration tests with the latest RedDeer against the latest Eclipse release. At first, I thought it might be an issue with RedDeer itself, but a closer look reveals it seems to be the underlying SWT that is used, and that is the core of the issue here.
When running tests from the IDE that invoke the UI for some context menu options (more I couldn't test yet) the test will fail with a stack trace similar to this one:

org.eclipse.reddeer.common.exception.RedDeerException: Exception during sync execution in UI thread
	at org.eclipse.reddeer.common.util.Display.handleErrorOccured(Display.java:112)
	at org.eclipse.reddeer.common.util.Display.syncExec(Display.java:84)
	at org.eclipse.reddeer.core.lookup.MenuLookup.getToolItemMenu(MenuLookup.java:98)
	at org.eclipse.reddeer.swt.impl.menu.ToolItemMenuItem.<init>(ToolItemMenuItem.java:50)
	at org.eclipse.reddeer.swt.impl.menu.ToolItemMenuItem.<init>(ToolItemMenuItem.java:38)
	at org.sonarlint.eclipse.its.reddeer.views.SonarLintConsole.enableVerboseOutput(SonarLintConsole.java:59)
	at org.sonarlint.eclipse.its.AbstractSonarLintTest.beforeClass(AbstractSonarLintTest.java:241)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.eclipse.reddeer.junit.internal.runner.statement.RunBeforeClasses.evaluate(RunBeforeClasses.java:68)
	at org.eclipse.reddeer.junit.internal.runner.statement.FulfillRequirementsStatement.evaluate(FulfillRequirementsStatement.java:46)
	at org.eclipse.reddeer.junit.internal.runner.statement.RunIBeforeClassExtensions.evaluate(RunIBeforeClassExtensions.java:72)
	at org.eclipse.reddeer.junit.internal.runner.statement.RunAfterClasses.evaluate(RunAfterClasses.java:68)
	at org.eclipse.reddeer.junit.internal.runner.statement.CleanUpRequirementStatement.evaluate(CleanUpRequirementStatement.java:45)
	at org.eclipse.reddeer.junit.internal.runner.statement.RunIAfterClassExtensions.evaluate(RunIAfterClassExtensions.java:57)
	at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
	at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.eclipse.reddeer.junit.internal.runner.RequirementsRunner.run(RequirementsRunner.java:153)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:757)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
	at org.eclipse.reddeer.jdt.junit.RemotePluginTestRunner.main(RemotePluginTestRunner.java:71)
	at org.eclipse.reddeer.jdt.junit.UITestApplication.runTests(UITestApplication.java:133)
	at org.eclipse.e4.ui.internal.workbench.swt.E4Testable.lambda$0(E4Testable.java:79)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "org.eclipse.swt.widgets.Menu.setVisible(boolean)" because the return value of "org.eclipse.reddeer.core.lookup.MenuLookup$ShowMenuListener.getMenu()" is null
	at org.eclipse.reddeer.core.lookup.MenuLookup$1.run(MenuLookup.java:101)
	at org.eclipse.reddeer.core.lookup.MenuLookup$1.run(MenuLookup.java:1)
	at org.eclipse.reddeer.common.util.Display$ErrorHandlingRunnable.run(Display.java:162)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4365)
	at org.eclipse.swt.widgets.Display.observerProc(Display.java:3901)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
	at org.eclipse.swt.widgets.Display.applicationNextEventMatchingMask(Display.java:5561)
	at org.eclipse.swt.widgets.Display.applicationProc(Display.java:5962)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
	at org.eclipse.swt.internal.cocoa.NSMenu.popUpContextMenu(NSMenu.java:80)
	at org.eclipse.swt.widgets.Menu._setVisible(Menu.java:273)
	at org.eclipse.swt.widgets.Display.runPopups(Display.java:4487)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3979)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:152)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:639)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:546)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
	at org.eclipse.reddeer.jdt.junit.UITestApplication.start(UITestApplication.java:69)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:208)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:143)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:109)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:439)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:271)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:651)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:588)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1459)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1432)
java.lang.NullPointerException: Cannot invoke "org.eclipse.swt.widgets.Menu.setVisible(boolean)" because the return value of "org.eclipse.reddeer.core.lookup.MenuLookup$ShowMenuListener.getMenu()" is null
	at org.eclipse.reddeer.core.lookup.MenuLookup$1.run(MenuLookup.java:101)
	at org.eclipse.reddeer.core.lookup.MenuLookup$1.run(MenuLookup.java:1)
	at org.eclipse.reddeer.common.util.Display$ErrorHandlingRunnable.run(Display.java:162)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:132)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4365)
	at org.eclipse.swt.widgets.Display.observerProc(Display.java:3901)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
	at org.eclipse.swt.widgets.Display.applicationNextEventMatchingMask(Display.java:5561)
	at org.eclipse.swt.widgets.Display.applicationProc(Display.java:5962)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
	at org.eclipse.swt.internal.cocoa.NSMenu.popUpContextMenu(NSMenu.java:80)
	at org.eclipse.swt.widgets.Menu._setVisible(Menu.java:273)
	at org.eclipse.swt.widgets.Display.runPopups(Display.java:4487)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3979)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:152)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:639)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:546)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
	at org.eclipse.reddeer.jdt.junit.UITestApplication.start(UITestApplication.java:69)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:208)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:143)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:109)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:439)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:271)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:651)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:588)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1459)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1432)

HERE is the class with the method that is failing.

The error message indicates that there is an NPE and that the menu couldn't be found. While watching the test run I see that the menu is there and stays there even after the test instance of Eclipse is killed and until I manually click somewhere else. My guess is that the OS is not fast enough to "open" the context menu and the SWT code in question is already trying to access it without even waiting if it is slow starting up.

To Reproduce

In order to reproduce it, the user must have macOS Sonoma installed:

  • clone the repository at tag 10.0.1.81733
  • once cloned, run mvn clean verify -DskipTests in the repository main directory
  • importing the Maven projects into Eclipse RCP (with all sub-modules, including the one in the its sub-folder) with RedDeer installed
  • set the target-platforms/dev.target as an active target platform
  • inside SonarQubeConnectedModeTest replace the following lines (sorry, a bit tedious)
@ClassRule
  public static final OrchestratorRule orchestrator = OrchestratorRule.builderEnv()
    .defaultForceAuthentication()
    .useDefaultAdminCredentialsForBuilds(true)
    .keepBundledPlugins()
    .setEdition(Edition.DEVELOPER)
    .activateLicense()
    .setSonarVersion(System.getProperty("sonar.runtimeVersion", "LATEST_RELEASE"))
    // Ensure SSE are processed correctly just after SQ startup
    .setServerProperty("sonar.pushevents.polling.initial.delay", "2")
    .setServerProperty("sonar.pushevents.polling.period", "1")
    .setServerProperty("sonar.pushevents.polling.last.timestamp", "1")
    .build();

with

@ClassRule
  public static final OrchestratorRule orchestrator = OrchestratorRule.builderEnv()
    .defaultForceAuthentication()
    .useDefaultAdminCredentialsForBuilds(true)
    .keepBundledPlugins()
    .setEdition(Edition.COMMUNITY)
    .setOrchestratorProperty("orchestrator.artifactory.url", "https://repo1.maven.org/maven2/")
    .setSonarVersion(System.getProperty("sonar.runtimeVersion", "LATEST_RELEASE"))
    // Ensure SSE are processed correctly just after SQ startup
    .setServerProperty("sonar.pushevents.polling.initial.delay", "2")
    .setServerProperty("sonar.pushevents.polling.period", "1")
    .setServerProperty("sonar.pushevents.polling.last.timestamp", "1")
    .build();
  • Right-click on the check_grouping test and Run As -> RedDeer Test
  • The test should start up, taking some time for SQ to initialize, and then the test should fail, Eclipse test instance will be killed and the menu will still be visible (see the screenshot below for reference) and the stack trace should appear

If I have some time and you require it for testing on your side, I try to create a simple reproducer project, I just haven't done that yet.

Expected behavior

The same behavior as for macOS Ventura, with no errors when running the test. Strictly speaking, SWT should take into account if the context menu is a bit slower starting up (what I guess is happening here).

Screenshots

This is the context menu, that is (despite what the error message says) shown but with a small delay and should, therefore, be found by SWT. It stays open after the Eclipse test instance is killed:

Verwaistes-Kontext-Menu

Environment:

  1. Select the platform(s) on which the behavior is seen:
    • All OS
    • Windows
    • Linux
    • macOS
  1. Additional OS info (e.g. OS version, Linux Desktop, etc)

The issue started after updating to the newest macOS Sonoma (specifically 14.4.1) from macOS Ventura 13.6.6 this Monday.

  1. JRE/JDK version

Eclipse RCP 2024-03 is fully updated, running on the current JustJ plug-in bundled with the installation:

  • JustJ JRE for IDE Packages
  • 17.0.0.v20240120-1430
  • org.eclipse.justj.epp.feature.group

Workaround (or) Additional context

EDIT: Tried to workaround this by using RedDeer, but it didn't work out.

Maybe by using RedDeer *WaitConditions, I could work around this. But we have a lot of different UI interactions, and it is just not feasible to implement it for every UI interaction, not only because it is an overhead to implement but because it will slow down everything eventually.

I would only do so in order to check if it only related to the context menu options or other UI interactions as well.

@thahnen
Copy link
Author

thahnen commented Apr 18, 2024

The issue is independent of RedDeer / SWTBot; I've created a reproducer project that shows it failing on macOS Sonoma.

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

No branches or pull requests

1 participant