'Write access is allowed from event dispatch thread only' error while running IdeaTestCase

Here is snip of testcase:
public class RefreshCommandTest extends IdeaTestCase {
   ...
  @Override
  protected void setUp() throws Exception {
    super.setUp();
    ...
  }
}

Here is stacktrace:

ERROR: Write access is allowed from event dispatch thread only
java.lang.Throwable
    at com.intellij.openapi.diagnostic.Logger.error(Logger.java:55)
    at com.intellij.openapi.application.impl.ApplicationImpl.assertIsDispatchThread(ApplicationImpl.java:952)
    at com.intellij.openapi.application.impl.ApplicationImpl.assertCanRunWriteAction(ApplicationImpl.java:932)
    at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:805)
    at com.intellij.testFramework.PlatformTestCase.setUpJdk(PlatformTestCase.java:458)
    at com.intellij.testFramework.PlatformTestCase.setUpProject(PlatformTestCase.java:197)
    at com.intellij.testFramework.PlatformTestCase.setUp(PlatformTestCase.java:162)
    at com...RefreshCommandTest.setUp(RefreshCommandTest.java:43)
    at com.intellij.testFramework.PlatformTestCase$5.run(PlatformTestCase.java:503)
    at com...RefreshCommandTest.runBareRunnable(RefreshCommandTest.java:64)
    at com.intellij.testFramework.PlatformTestCase.runBareImpl(PlatformTestCase.java:532)
    at com.intellij.testFramework.PlatformTestCase.runBare(PlatformTestCase.java:476)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:118)
    at junit.textui.TestRunner.doRun(TestRunner.java:116)
    at com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.java:108)
    at junit.textui.TestRunner.doRun(TestRunner.java:109)
    at com.intellij.junit3.JUnit3IdeaTestRunner.startRunnerWithArgs(JUnit3IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:192)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
details:
Current thread: Thread[main,5,main] 24130647
Our dispatch thread:Thread[AWT-EventQueue-0,6,main] 17390721
SystemEventQueueThread: Thread[AWT-EventQueue-0,6,main] 17390721
- Access is allowed from event dispatch thread only.


Any idea on how to fix this?

9 comments
Comment actions Permalink

Hello chandra,

This should be fixed by running the initialization code in the event dispatch
thread. The test framework does this by default, but it looks like you've
overridden some parts of it and thus disabled this behavior.

Here is snip of testcase:
public class RefreshCommandTest extends IdeaTestCase {
...
@Override
protected void setUp() throws Exception {
super.setUp();
...
}
}
Here is stacktrace:

ERROR: Write access is allowed from event dispatch thread only
java.lang.Throwable
at com.intellij.openapi.diagnostic.Logger.error(Logger.java:55)
at
com.intellij.openapi.application.impl.ApplicationImpl.assertIsDispatch
Thread(ApplicationImpl.java:952)
at
com.intellij.openapi.application.impl.ApplicationImpl.assertCanRunWrit
eAction(ApplicationImpl.java:932)
at
com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(A
pplicationImpl.java:805)
at
com.intellij.testFramework.PlatformTestCase.setUpJdk(PlatformTestCase.
java:458)
at
com.intellij.testFramework.PlatformTestCase.setUpProject(PlatformTestC
ase.java:197)
at
com.intellij.testFramework.PlatformTestCase.setUp(PlatformTestCase.jav
a:162)
at com...RefreshCommandTest.setUp(RefreshCommandTest.java:43)
at
com.intellij.testFramework.PlatformTestCase$5.run(PlatformTestCase.jav
a:503)
at
com...RefreshCommandTest.runBareRunnable(RefreshCommandTest.java:64)
at
com.intellij.testFramework.PlatformTestCase.runBareImpl(PlatformTestCa
se.java:532)
at
com.intellij.testFramework.PlatformTestCase.runBare(PlatformTestCase.j
ava:476)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.textui.TestRunner.doRun(TestRunner.java:116)
at
com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.ja
va:108)
at junit.textui.TestRunner.doRun(TestRunner.java:109)
at
com.intellij.junit3.JUnit3IdeaTestRunner.startRunnerWithArgs(JUnit3Ide
aTestRunner.java:42)
at
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JU
nitStarter.java:192)
at
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:64
)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.j
ava:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccess
orImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at
com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
details:
Current thread: Thread[main,5,main] 24130647
Our dispatch thread:Thread[AWT-EventQueue-0,6,main] 17390721
SystemEventQueueThread: Thread[AWT-EventQueue-0,6,main] 17390721
- Access is allowed from event dispatch thread only.
Any idea on how to fix this?

---
Original message URL:
http://devnet.jetbrains.net/message/5301936#5301936


--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Comment actions Permalink

Dmitry,

thanks for the hint.

I am debugging a test which runs outside AWT event thread [here is related post on how to do this: http://devnet.jetbrains.net/message/5176841]
This test sets jdk which seems to work fine in Intellij-9, where as this is failing when run against Intellij-10.

This test has overriden the following methods:
protected void runBareRunnable(Runnable runnable) throws Throwable {
    runnable.run();
  }

  protected void invokeTestRunnable(Runnable runnable) throws Exception {
    runnable.run();
  }

here is the test method causing the problem:

private static Sdk createJdk(final String jdkName, final String javaHome) {
    return UiUtil.runWriteAction(ApplicationManager.getApplication(),
      new Computable<Sdk>() {
        public Sdk compute() {
          ProjectJdkTable jdkTable = ProjectJdkTable.getInstance();
          JavaSdk sdkFactory = JavaSdk.getInstance();
          Sdk myJdk = sdkFactory.createJdk(jdkName, javaHome);
          jdkTable.addJdk(myJdk);
          return myJdk;
        }
      });
  }

where UiUtil.runWriteAction() returns Computable.compute(); [when run in unit test mode]

Any idea on how to add JDK to projects from non-AWT threads?

Thanks,
Chandra

0
Comment actions Permalink

Hello chandra,

There is no way to perform a write action from outside the AWT event thread.

Dmitry,

thanks for the hint.

I am debugging a test which runs outside AWT event thread [here is
related post on how to do this:
http://devnet.jetbrains.net/message/5176841]

This test sets jdk which seems to work fine in Intellij-9, where as
this is failing when run against Intellij-10.

This test has overriden the following methods:
protected void runBareRunnable(Runnable runnable) throws Throwable {
runnable.run();
}
protected void invokeTestRunnable(Runnable runnable) throws
Exception {
runnable.run();
}
here is the test method causing the problem:

private static Sdk createJdk(final String jdkName, final String
javaHome) {
return UiUtil.runWriteAction(ApplicationManager.getApplication(),
new Computable<Sdk>() {
public Sdk compute() {
ProjectJdkTable jdkTable = ProjectJdkTable.getInstance();
JavaSdk sdkFactory = JavaSdk.getInstance();
Sdk myJdk = sdkFactory.createJdk(jdkName, javaHome);
jdkTable.addJdk(myJdk);
return myJdk;
}
});
}
where UiUtil.runWriteAction() returns Computable.compute(); [when run
in unit test mode]

Any idea on how to add JDK to projects from non-AWT threads?

Thanks,
Chandra
---
Original message URL:
http://devnet.jetbrains.net/message/5301950#5301950


--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Comment actions Permalink

Hi Dmitry,

"This should be fixed by running the initialization code in the event dispatch thread. The test framework does this by default..."

Could you give me a pointer to where this is done? I'd like to replicate this in JUnit 4 tests and I couldn't see how to do it.

0
Comment actions Permalink

Hello Colin,

"This should be fixed by running the initialization code in the event
dispatch thread. The test framework does this by default..."

Could you give me a pointer to where this is done? I'd like to
replicate this in JUnit 4 tests and I couldn't see how to do it.


UsefulTestCase.runBare()

--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Comment actions Permalink

Great, thanks Dmitry.

0
Comment actions Permalink

ApplicationImpl.assertIsDispatchThread() has been changed between 9.0.4 and 10.0.3.
In 9.0.4 assertIsDispatchThread() is as follows:

private void assertIsDispatchThread(String message) {
    if (myTestModeFlag || myHeadlessMode || ShutDownTracker.isShutdownHookRunning()) return;
    final Thread currentThread = Thread.currentThread();
    if (ourDispatchThread == currentThread) return;

    if (EventQueue.isDispatchThread()) {
      ourDispatchThread = currentThread;
    }
    if (ourDispatchThread == currentThread) return;

    Integer safeCounter = ourEdtSafe.get();
    if (safeCounter != null && safeCounter > 0) return;

    LOG.error(message,
              "Current thread: " + describe(Thread.currentThread()),
              "Our dispatch thread:" + describe(ourDispatchThread),
              "SystemEventQueueThread: " + describe(getEventQueueThread()));
  }

It returns when application is in test mode.

Where as in 10.0.3 assertIsDispatchThread() is as follows:

  private static void assertIsDispatchThread(String message) {
    if (ShutDownTracker.isShutdownHookRunning()) return;
    final Thread currentThread = Thread.currentThread();
    if (ourDispatchThread == currentThread) return;

    if (EventQueue.isDispatchThread()) {
      ourDispatchThread = currentThread;
    }
    if (ourDispatchThread == currentThread) return;

    Integer safeCounter = ourEdtSafe.get();
    if (safeCounter != null && safeCounter > 0) return;

    LOG.error(message,
              "Current thread: " + describe(Thread.currentThread()),
              "Our dispatch thread:" + describe(ourDispatchThread),
              "SystemEventQueueThread: " + describe(getEventQueueThread()));
  }
test mode related code is removed and this method is now made static.

Is there any reason for not allowing write action from outside of AWT event thread (even for tests)?

Thx,
Chandra

0
Comment actions Permalink

Hello chandra,

The reason for the change was to make the tests closer to real life. We want
our tests to test the actual behavior of IntelliJ IDEA, not of some artificial
construct that does not exist on our users' PCs.

I think ApplicationImpl has been changed between 9.0.4 and 10.0.3.
In 9.0.4 assertIsDispatchThread() is as follows:
private void assertIsDispatchThread(String message) {
*if (myTestModeFlag || myHeadlessMode ||
ShutDownTracker.isShutdownHookRunning()) return;*
final Thread currentThread = Thread.currentThread();
if (ourDispatchThread == currentThread) return;
if (EventQueue.isDispatchThread()) {
ourDispatchThread = currentThread;
}
if (ourDispatchThread == currentThread) return;
Integer safeCounter = ourEdtSafe.get();
if (safeCounter != null && safeCounter > 0) return;
LOG.error(message,
"Current thread: " + describe(Thread.currentThread()),
"Our dispatch thread:" + describe(ourDispatchThread),
"SystemEventQueueThread: " +
describe(getEventQueueThread()));
}
It returns when application is in test mode.

Where as in 10.0.3 assertIsDispatchThread() is as follows:
private static void assertIsDispatchThread(String message) {
if (ShutDownTracker.isShutdownHookRunning()) return;
final Thread currentThread = Thread.currentThread();
if (ourDispatchThread == currentThread) return;
if (EventQueue.isDispatchThread()) {
ourDispatchThread = currentThread;
}
if (ourDispatchThread == currentThread) return;
Integer safeCounter = ourEdtSafe.get();
if (safeCounter != null && safeCounter > 0) return;
LOG.error(message,
"Current thread: " + describe(Thread.currentThread()),
"Our dispatch thread:" + describe(ourDispatchThread),
"SystemEventQueueThread: " +
describe(getEventQueueThread()));
}
test mode related code is removed and this method is now made static.
Is there any reason for not allowing write action from outside of AWT
event thread (even for tests)?

Thx,
Chandra
---
Original message URL:
http://devnet.jetbrains.net/message/5303500#5303500


--
Dmitry Jemerov
Development Lead
JetBrains, Inc.
http://www.jetbrains.com/
"Develop with Pleasure!"


0
Comment actions Permalink

Hi Dimitry,

Bringing the discussion back to our original problem.

We want to test certain actions on the event Queue by waiting for those actions as described in http://devnet.jetbrains.net/message/5176841

The default model of IdeaTestCase does not allow that since tests run in the AWT event thread.

Please advise on how we can write tests that wait for events on the queue in Intellij 10.x since without that we cannot port our plugin tests to Intellij 10.

thanks
Siddharth

0

Please sign in to leave a comment.