Forum: Building VoltDB Applications

Post: Automatic JUnit tests

Automatic JUnit tests
tnn
Dec 17, 2011
Hi all.

I'm trying to integrate VoltDB into our existing maven/GWT/JDBC-WAR project and I would like to launch our JUnit integration/system tests from the maven goal, without the need for a ant build.xml file.

For inspiration, I've used jhosync setup's JUnit setup, but the interfaces have changed since, and the sources for the lib is not included in the jar.

Is it possible one (Hint: Hey Tim! :-) ) could make a example for how to launch directly from JUnit?

I'm planning to use a VoltDBTestServer as a singleton pattern, with Client getInstance(), that gets called from all tests, so we are starting the server once and all clients use the same Client instance. The catalog.jar will already have been compiled to 'target/ProjectName-1.0-SNAPSHOT-catalog.jar', deployment.xml should be read from 'voltdb/junit-deployment.xml', as with 'voltdb/project.xml'.
Does the server cleanly shutdown when JVM/JUnit exits, or should I worry about calling client.close(); and server.shutDown();?

Is it really true, that one can not place multiple schema DDL files in a sub directory? (E.g. voltdb/misc-ddl.sql; voltdb/rbac-ddl.sql)

Thanks for a great product. Async procedures are fantastic, among other things! :-)
TestVoltDBServer.java: packag
tnn
Dec 17, 2011
TestVoltDBServer.java:
package com.project.voltdb.procedures;

import java.io.IOException;
import java.net.UnknownHostException;

import org.voltdb.BackendTarget;
import org.voltdb.client.Client;
import org.voltdb.client.ClientConfig;
import org.voltdb.client.ClientFactory;
import org.voltdb.compiler.VoltProjectBuilder;
import org.voltdb.regressionsuites.LocalSingleProcessServer;

public class VoltDBTestServer {

private static String user = "junit-test-user";
private static String pass = "VerySecretPassword";
private static Client client = null;
private volatile static Object mutex = new Object();
private static LocalSingleProcessServer server = null;

/**
* Singleton getInstance().
* Parse on exceptions, so JUnit can handle them.
*
* @return
* @throws UnknownHostException
* @throws IOException
*/
public static Client getInstance() throws UnknownHostException, IOException {
synchronized(mutex) {
if(client == null) {
String serverHost = launchServer();
ClientConfig config = null;
config = new ClientConfig(user, pass);
client = ClientFactory.createClient(config);
client.createConnection(serverHost);
}
}
return client;
}

/**
* Launch a VoltDB Server instance.
*
* @return String Listener host
*/
private static String launchServer() {
server = new LocalSingleProcessServer("target/project-0.1-SNAPSHOT-catalog.jar", 1, BackendTarget.NATIVE_EE_JNI);
VoltProjectBuilder project = new DummyVoltProjectBuilder();
server.compile(project);
server.startUp();
return server.getListenerAddresses().get(0);
}
}

But I'm missing the class org.voltdb.regressionsuites.EEProcess:

java.lang.NoClassDefFoundError: org/voltdb/regressionsuites/EEProcess
at org.voltdb.regressionsuites.LocalSingleProcessServer.startUp(LocalSingleProcessServer.java:198)
at org.voltdb.regressionsuites.LocalSingleProcessServer.startUp(LocalSingleProcessServer.java:220)
at com.project.voltdb.procedures.VoltDBTestServer.launchServer(VoltDBTestServer.java:53)
at com.project.voltdb.procedures.VoltDBTestServer.getInstance(VoltDBTestServer.java:32)
at com.project.voltdb.procedures.AbstractVoltDBTest.getClientInstance(AbstractVoltDBTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassNotFoundException: org.voltdb.regressionsuites.EEProcess
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 28 more
Is it possible one (Hint: Hey
rbetts
Dec 17, 2011
Is it possible one (Hint: Hey Tim! :-) ) could make a example for how to launch directly from JUnit?

If you want to start a server as as separate process, you can start voltdb using the bin/voltdb scripts.

There are black box regressionsuite tests that start VoltDB from within a JUnit suite - all of these tests are in the regressionsuites directory of the voltdb source tree. They tend to have names that end in "Suite" - like "voltdb/tests/frontend/org/voltdb/regressionsuites/TestSqlAggregatesSuite.java." That Junit interface isn't a stable API, we muck with it on a regular basis as we add features or otherwise adjust testcases. The magic for these is found in the junit.framework.Test suite() method.

Is it really true, that one can not place multiple schema DDL files in a sub directory?

You can list an arbitrary number of ddl files in your project file with separate DDL elements. Or, if you are using the regession suites code, you can call VoltProjectBuilder.addSchema multiple times (I think).

Shutdown...

Calling shutdown can't hurt?

We're always open to ideas around writing tests for Volt - let us know where you end up with this?

Ryan.