Why is RandomizedRunner required to use ES test framework?

I'm upgrading a legacy app that uses both Elasticsearch test framework (MockNode and cluster from the org.elasticsearch.test:framework:6.5.3) and EmbeddedKafka/Zookeeper frameworks. I'm facing an issue with upgrading from zoookeeper version 3.4 to version 3.5, because in v3.5 Zookeeper added the following static code to do more logging in it's NIOServerCnxnFactory:

static {
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                public void uncaughtException(Thread t, Throwable e) {
                    LOG.error("Thread " + t + " died", e);
                }
            });

At the same time it looks like Elasticsearch requires the use of the RandomizedRunner in order to use it in Unit tests. So, I have to run all unit tests as following:

@RunWith(RandomizedRunner.class)
@ThreadLeakScope(ThreadLeakScope.Scope.NONE)
class ElasticsearchClusterSelectorServiceSpec { ... }

Also, the RandomizedRunner does not like when a default UnhandledExceptionHandler is changed! So, when I run the unit tests that run both ES and ZK now I get the following exception:

java.lang.RuntimeException: Suite replaced Thread.defaultUncaughtExceptionHandler. It's better not to touch it. Or at least revert it to what it was before. Current: class org.apache.zookeeper.server.NIOServerCnxnFactory$1

I'm assuming it is due to this code in the RandomizedRunner:

UncaughtExceptionHandler current = Thread.getDefaultUncaughtExceptionHandler();
    if (current != handler) {
      notifier.fireTestFailure(new Failure(suiteDescription, 
          new RuntimeException("Suite replaced Thread.defaultUncaughtExceptionHandler. " +
          		"It's better not to touch it. Or at least revert it to what it was before. Current: " + 
              (current == null ? "(null)" : current.getClass()))));
    }

If I try to remove the RandomizedRunner as the unit test runner, I get the following errors:

java.lang.IllegalStateException: running tests but failed to invoke RandomizedContext#getRandom

	at org.elasticsearch.common.Randomness.get(Randomness.java:106)
	at org.elasticsearch.common.Randomness.get(Randomness.java:80)
	at org.elasticsearch.env.NodeEnvironment.generateNodeId(NodeEnvironment.java:404)
	at org.elasticsearch.env.NodeEnvironment.loadOrCreateNodeMetaData(NodeEnvironment.java:396)
	at org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:302)
	at org.elasticsearch.node.Node.<init>(Node.java:296)
	at org.elasticsearch.node.MockNode.<init>(MockNode.java:105)
	at org.elasticsearch.node.MockNode.<init>(MockNode.java:91)
	at org.elasticsearch.node.MockNode.<init>(MockNode.java:76)
	at org.elasticsearch.node.MockNode.<init>(MockNode.java:69)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:255)
	at com.netapp.oci.rest.es.ElasticsearchClusterTestUtils.createTestCluster(ElasticsearchClusterTestUtils.groovy:59)
	at com.netapp.oci.rest.es.ElasticsearchClusterTestUtils$createTestCluster.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at com.netapp.oci.rest.es.ElasticsearchClusterSelectorServiceSpec.createTestClusters(ElasticsearchClusterSelectorServiceSpec.groovy:82)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.elasticsearch.common.Randomness.get(Randomness.java:102)
	... 39 more
Caused by: java.lang.IllegalStateException: No context information for thread: Thread[id=1, name=main, state=RUNNABLE, group=main]. Is this thread running under a class com.carrotsearch.randomizedtesting.RandomizedRunner runner context? Add @RunWith(class com.carrotsearch.randomizedtesting.RandomizedRunner.class) to your test class. Make sure your code accesses random contexts within @BeforeClass and @AfterClass boundary (for example, static test class initializers are not permitted to access random contexts).
	at com.carrotsearch.randomizedtesting.RandomizedContext.context(RandomizedContext.java:249)
	at com.carrotsearch.randomizedtesting.RandomizedContext.current(RandomizedContext.java:134)
	... 44 more



So, my questions:

  1. why is RandomizedRunner required in order to create a mock ES node?
  2. I see it might be due to the need to generate random node ID.... if that's the case - is there a way I could provide this as part of the MockNode creation and avoid using the RandomizedRunner?
  3. is there any other option to work around this issue? (I tried starting ZK in a separate thread but that does not help as the default handler is set for ALL threads ....)

Thank you!
Marina

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.