How does JUnit find the eclipse plug-in being tested?
Asked Answered
G

2

2

I am writing a plug-in (ClassRefactoringPlugin) that examines source code in Eclipse 3.6.1. The plug-in contains a CallData class that examines a Java source file and figures out which Java elements are called from a method using JDT operations. I wrote a JUnit 4 test for this class that also resides in the ClassRefactoringPlugin project. When I ran it as a JUnit plug-in test, I got:

Java Model Exception: Java Model Status [ClassRefactoringPlugin does not exist]

What have I done wrong? The configuration specifies to launch with all workspace and enabled target plug-ins, and ClassRefactoringPlugin is in my dropins directory. (Although shouldn't the project's version of the plug-in be recognized by the spawned workspace?)

Here's the stack trace:

!MESSAGE CallData.calculateCalledMethods: Java Model Exception: Java Model Status [ClassRefactoringPlugin does not exist]
Java Model Exception: Java Model Status [ClassRefactoringPlugin does not exist]
        at org.eclipse.jdt.internal.core.JavaElement.newJavaModelException(JavaElement.java:502)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:246)
        at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
        at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
        at org.eclipse.jdt.internal.core.Openable.openAncestors(Openable.java:504)
        at org.eclipse.jdt.internal.core.CompilationUnit.openAncestors(CompilationUnit.java:1170)
        at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:240)
        at org.eclipse.jdt.internal.core.SourceRefElement.generateInfos(SourceRefElement.java:107)
        at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:515)
        at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:252)
        at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:238)
        at org.eclipse.jdt.internal.core.JavaElement.getChildren(JavaElement.java:193)
        at org.eclipse.jdt.internal.core.JavaElement.getChildrenOfType(JavaElement.java:207)
        at org.eclipse.jdt.internal.core.SourceType.getMethods(SourceType.java:403)
        at nz.ac.vuw.ecs.kcassell.utils.EclipseSearchUtils.addDesiredMethods(EclipseSearchUtils.java:333)
        at nz.ac.vuw.ecs.kcassell.utils.EclipseSearchUtils.getMethods(EclipseSearchUtils.java:210)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallData.collectMethodCallData(CallData.java:203)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallData.calculateCalledMethods(CallData.java:176)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallData.collectCallData(CallData.java:151)
        at nz.ac.vuw.ecs.kcassell.callgraph.CallDataTest.testCollectCallData(CallDataTest.java:67)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at junit.framework.TestCase.runTest(TestCase.java:168)
        at junit.framework.TestCase.runBare(TestCase.java:134)
        at junit.framework.TestResult$1.protect(TestResult.java:110)
        at junit.framework.TestResult.runProtected(TestResult.java:128)
        at junit.framework.TestResult.run(TestResult.java:113)
        at junit.framework.TestCase.run(TestCase.java:124)
        at junit.framework.TestSuite.runTest(TestSuite.java:232)
        at junit.framework.TestSuite.run(TestSuite.java:227)
        at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
        at org.eclipse.pde.internal.junit.runtime.RemotePluginTestRunner.main(RemotePluginTestRunner.java:62)
        at org.eclipse.pde.internal.junit.runtime.UITestApplication$1.run(UITestApplication.java:116)
        at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
        at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
        at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3515)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3164)
        at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
        at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
        at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
        at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
        at org.eclipse.pde.internal.junit.runtime.UITestApplication.start(UITestApplication.java:47)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1383)

I am wondering if the error message might be a red herring. The error occurs when making a call to IMethod[] methods = type.getMethods();

If I set a breakpoint there and look at type in the Variables view of the debugger, I see:

CallDataTest (not open) [in CallDataTest.java [in nz.ac.vuw.ecs.kcassell.callgraph [in test [in ClassRefactoringPlugin]]]]

I wonder if I am omitting some important preliminary step to make the project available for examination. First, I attempt to activate the workbench, like so:

public static void activateWorkbench() {
    // possible for PlatformUI.getWorkbench to throw an IllegalStateException
    // if the workbench is not yet started e.g createAndRunWorkbench() has not yet been called
    IWorkbench workbench = PlatformUI.getWorkbench();
    IWorkbenchWindow workbenchWindow =
        workbench.getActiveWorkbenchWindow();
    workbenchWindow.getActivePage();
}

Then I try to get type using its handle:

protected IType iType = EclipseUtils.getTypeFromHandle(
        "=ClassRefactoringPlugin/test<nz.ac.vuw.ecs.kcassell.callgraph{CallDataTest.java[CallDataTest");

public static IType getTypeFromHandle(String handle) {
IType type = null;
IJavaElement element = JavaCore.create(handle);
if (element == null) {
    System.err.println("  No element created from " + handle);
} else if (element instanceof IType) {
    type = (IType) element;
}
    return type;
}

I am new to plug-in development, so any help would be much appreciated.

Cheers, Keith

Gosplan answered 29/7, 2010 at 2:53 Comment(4)
I confirm that you don't need to put your exported plugin in the dropins folder because Eclipse is using the project's version of the plugin you are writing when running the JUnit Launch configuration. Can you paste the full stack trace because I don't think the issue is about the Junit run config. If you are able to lauch it, I guess the test class is available in the main Junit Run configuration tab ?Valvate
I'm not entirely sure what you mean by the "main Junit Run configuration tab"? From Eclipse, if I do Run->Run Configurations, I get a "Run Configurations" window that lists CallDataTest as a "JUnit Plug-in Test". Is this what you wanted to know? I'm editing the original post to include the stack trace.Gosplan
I've updated the information in the main post to reflect a move to a newer Eclipse version.Gosplan
Hello kc2001. You've offered a bounty and up-voted my answer for a similar question as the solution to yours. Please mark my question as the accepted answer. It'd be a shame to throw those points to waste. Thank you.Gath
J
1

I am a little unsure exactly what you are trying to do here, but it looks like you are trying to write a JUnit test for your plugin. Is this right?

According to the java element handle identifier that you are creating, there should be a project called ClassRefactoringPlugin in your workspace and in there, is a source folder called test, and a java class called CallDataTest in a package called nz.ac.vuw.ecs.kcassell.callgraph.

I'm guessing that this is not the case and that you want to reference a class file in the plugin that you just created.

Before you can do any of that, you need to import a project into your test workspace, set its classpath, and then you can access its contents using handle identifiers.

I may be misunderstanding what you are trying to do, but it does seem like you are trying to access a java file that doesn't exist in your workspace. If you can confirm that this is what you want to do, I can point you to some test code that does exactly what you want.


There are some open source projects that do exactly this and you can borrow some of their source code for your purpose. A project that I am familiar with is Groovy-Eclipse http://groovy.codehaus.org/Eclipse+Plugin (since I am the lead on that project).

Here is a link to the class that we use to create and manage test projects:

https://svn.codehaus.org/groovy/eclipse/trunk/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/TestProject.java

You can use some or all of this code for your own tests. Just remember to delete all projects at the end of each test.

Jojo answered 19/4, 2011 at 3:56 Comment(5)
I believe that all of the preconditions you mentioned are set correctly. I don't understand is your reference to a "test workspace". I have a workspace containing my ClassRefactoringPlugin that has both src and test folders. When I right click on CallDataTest and "Run as JUnit plugin test", a new workbench is spawned. If I do that in debug mode, I can actually step through the code in the test using the debugger. That's why I'm wondering if the error message may be misleading. BTW, I plugin code runs fine in a spawned workspace when I debug it, just not when I try to run JUnit tests.Gosplan
Right. JUnit plugin tests spawn a new workspace, but this workspace is initially empty. You are trying to access a project (and its source code) that exists in the regular workspace, but not your runtime JUnit workspace. I am presuming that when you launch a runtime (not a JUnit runtime) workspace, then you have a project in that workspace called CallDataTest. You need to import CallDataTest into your JUnit workspace if you want to create an IJavaElements based on it. There is no simple API to do this, but there many open source projects that need to do a similar thing.Jojo
Updated my answer to include a link to some sample source code.Jojo
I think that my major problem was the failure to set up the project in the junit-workspace. While I don't have it working just yet, I feel like your help should be enough for me to get it. Unless a super answer arrives soon, you'll get the bounty. Cheers!Gosplan
This is not easy stuff. :) And it took us a long time to get it right. So, feel free to come back if you have more questions.Jojo
G
0

Had a similar error for different reasons. My error started after renaming the target package in the project. After I tried the solution from paskster without success, I started diggin'.

The actual problem was that renaming the package name from the manifest file didn't work as expected. I thought it would change everything everywhere. However, the old package name was still in the manifest file in the test directory, and in some views in the resources. After renaming those manually and rebuilding the project, the error was gone.

This is the accepted answer for another question: Java Model Exception: Java Model Status [gen [in MyApp] does not exist] after Eclipse Android project Clean

Since the owner of this question up-voted this answer as a solution with a link to this question, I thought I'd post it here as well.

Gath answered 17/4, 2011 at 11:14 Comment(1)
Unfortunately, my initial joy on reading your post was premature. I made every name consistent that I could think of and still had the problem. However, I did not notice any specific "test" information in the MANIFEST.Gosplan

© 2022 - 2024 — McMap. All rights reserved.