Closed stephan-herrmann closed 3 months ago
See also recent activity in #42 and history in https://bugs.eclipse.org/302850 and https://bugs.eclipse.org/482991
I have another reproducer and know why that happens.
The reason is that we have tests, that import/copy/create projects and if the projects contain .settings
directory, code goes to org.eclipse.jdt.launching.JavaRuntime.updateCompliance(IVMInstall)
that will set compliance settings to these from the currently used JVM via JavaCore.setOptions()
.
Stack:
at org.eclipse.jdt.launching.JavaRuntime.updateCompliance(JavaRuntime.java:3382)
at org.eclipse.jdt.launching.JavaRuntime.initializeVMs(JavaRuntime.java:3316)
at org.eclipse.jdt.launching.JavaRuntime.getVMInstallTypes(JavaRuntime.java:581)
at org.eclipse.jdt.internal.launching.JREPreferenceModifyListener.preApply(JREPreferenceModifyListener.java:133)
at org.eclipse.core.internal.preferences.PreferencesService.lambda$6(PreferencesService.java:411)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:75)
at org.eclipse.core.internal.preferences.PreferencesService.firePreApplyEvent(PreferencesService.java:411)
at org.eclipse.core.internal.preferences.PreferencesService.applyPreferences(PreferencesService.java:105)
at org.eclipse.core.internal.resources.ProjectPreferences.read(ProjectPreferences.java:240)
at org.eclipse.core.internal.resources.ProjectPreferences.updatePreferences(ProjectPreferences.java:361)
at org.eclipse.core.internal.resources.File.updateMetadataFiles(File.java:508)
at org.eclipse.core.internal.localstore.CopyVisitor.copyContents(CopyVisitor.java:109)
at org.eclipse.core.internal.localstore.CopyVisitor.copy(CopyVisitor.java:73)
at org.eclipse.core.internal.localstore.CopyVisitor.visit(CopyVisitor.java:207)
at org.eclipse.core.internal.localstore.UnifiedTree.accept(UnifiedTree.java:119)
at org.eclipse.core.internal.localstore.FileSystemResourceManager.copy(FileSystemResourceManager.java:383)
at org.eclipse.core.internal.resources.Resource.copy(Resource.java:572)
at org.eclipse.core.internal.resources.Project.internalCopy(Project.java:721)
at org.eclipse.core.internal.resources.Project.copy(Project.java:262)
at org.eclipse.core.internal.resources.Resource.copy(Resource.java:554)
at org.eclipse.jdt.core.tests.model.JavaSearchMultipleProjectsTests.testMethodOccurences(JavaSearchMultipleProjectsTests.java:388)
To fix that, we should make sure that JavaRuntime.updateCompliance()
never changes JavaCore options if not asked :-)
Options were: 1) set/check JVM properties indicating we are in the JDT tests. => will not work for manual test execution, as every launch config will need extra option. 2) set/check a preference in the JavaOptions itself, indicating we are in the JDT tests. => would also work for manual test execution if set in the base test class / common infra code. 3) dynamically find out that we are testing. => no idea what to look for.
I have a patch that works for 2) but I would like to hear opinions how to fix that, if there are other options possible I didn't listed above.
@stephan-herrmann, @jarthana, @SarikaSinha - WDYT?
I vaguely remember we have something that will tell us that we are running tests. Perhaps in the area of module resolution. Quick search didn't bring up anything. I have a feeling that @stephan-herrmann remembers this.
Worst case, I am sure we have some vm attributes that we are setting only in case of tests, for e.g -Dcomplinace
which we can use for options 1/3
If 3) can be done, it will be the preferred way. Where are we planning to add this check? In Preference Modify Listener?
If 3) can be done, it will be the preferred way.
Sure. I'm currently thinking about check for the TEST_LIB
classpath variable, that is defined in org.eclipse.jdt.core.tests.model
plugin and so shouldn't exist in "usual" SDK.
The check in org.eclipse.jdt.launching.JavaRuntime.updateCompliance(IVMInstall)
would be trivial like:
boolean testsRunning = List.of(JavaCore.getClasspathVariableNames()).contains("TEST_LIB"); //$NON-NLS-1$
if (testsRunning) {
return;
}
Where are we planning to add this check? In Preference Modify Listener?
In org.eclipse.jdt.launching.JavaRuntime.updateCompliance(IVMInstall)
I will prefer it handled in initializeVMs where we should set updateCompliance as false for testing condition.
Before reading through all your great findings: I seem to recall that in previous editions of this problem we tried to avoid touching any plugins from JDT/Debug during these tests. There might even be tests checking which plugins where started during tests. Anyone seen this recently?
No, and that's not what the reason here. Here the discovery of project settings by launcher code triggered JVM update / JavaCore options change. The stack is self explaining.
No, and that's not what the reason here. Here the discovery of project settings by launcher code triggered JVM update / JavaCore options change. The stack is self explaining.
My reasoning was and is: if plugin jdt.launching is not active, then nothing gets triggered.
I have another reproducer and know why that happens. The reason is that we have tests, that import/copy/create projects and if the projects contain
.settings
directory, code goes toorg.eclipse.jdt.launching.JavaRuntime.updateCompliance(IVMInstall)
that will set compliance settings to these from the currently used JVM viaJavaCore.setOptions()
. Stack:at org.eclipse.jdt.launching.JavaRuntime.updateCompliance(JavaRuntime.java:3382) at org.eclipse.jdt.launching.JavaRuntime.initializeVMs(JavaRuntime.java:3316)
See
Eventually I dropped the idea to control the set of running plugins: https://bugs.eclipse.org/bugs/show_bug.cgi?id=482991#c14
after all the hassle we had in this area, let me naively ask if everybody is sure that updating JDT/Core default options like this is a good idea? Which problem does it solve?
My reasoning was and is: if plugin jdt.launching is not active, then nothing gets triggered.
I haven't checked it now, but from previous discussions I believe to remember it wasn't easy/possible to not activete it.
after all the hassle we had in this area, let me naively ask if everybody is sure that updating JDT/Core default options like this is a good idea? Which problem does it solve?
I believe the intent is to provide "reasonable" defaults for the user. We usually ship "default" compliance to be lowest possible (1.8 would be now after https://github.com/eclipse-jdt/eclipse.jdt.core/pull/2551) but of course most users would prefer "current" (or better) JVM version to be default target, so the code does exactly that and sets default compliance to "better" JLS.
after all the hassle we had in this area, let me naively ask if everybody is sure that updating JDT/Core default options like this is a good idea? Which problem does it solve?
I believe the intent is to provide "reasonable" defaults for the user. We usually ship "default" compliance to be lowest possible (1.8 would be now after #2551) but of course most users would prefer "current" (or better) JVM version to be default target, so the code does exactly that and sets default compliance to "better" JLS.
Thanks, sounds fair. I guess I'm just not the audience wanting to create tons of projects without explicitly setting compliance settings :)
The infamous test failure "Workspace options should be back to their default" can be reproduced by running
AllJavaModelTests
with everything prior toJavaCorePreferenceModifyListenerTest
disabled / commented. The sequence ofJavaCorePreferenceModifyListenerTest
+NullAnnotationModelTests
creates the following failure (interestingly only once):