Documentation > Development > Writing New Tests

There are two types of test cases in H-Store. The first is a simple unit test that checks a small feature of the system’s internals without needing to deploy the entire database. The other type is referred to as a regression test which is designed to execute the end-to-end functionality of the entire system. We now describe how to write each of these types of tests.

Writing a Unit Test Case

The testing source code files for the main part of the H-Store system are located in tests/frontend. This directory mirrors the heirachy of src/frontend. For a given class file in src, there will be a corresponding class file in the same directory in tests, except that the class name will have the Test prefix. That is, if the source class file that you want to write a test case for is called MyClass, then the test class file will be called TestMyClass.

There is a special abstract class called BaseTestCase that extends the default JUnit TestCase class. BaseTestCase provides various helper methods for working with built-in benchmarks and their catalogs.

For example, the following test case will automatically create the TPC-C project catalog for each test case. After the setUp() method is complete, the test cases can retrieve various objects from compiled Catalog using the
BaseTestCase API:

public class TestExample extends BaseTestCase {
    @Override
    protected void setUp() throws Exception {
        super.setUp(ProjectType.TPCC);
    }
 
    public void testExample() {
        Catalog catalog = getCatalog();
        Database catalog_db = getDatabase();
        // Additional testing code...
    }
}

Writing a Regression Test

A regression test case is more involved. The test case will need to extend the RegressionSuite base class. The implementing class will need to include a suite() method that returns a MultiConfigSuiteBuilder. It is here that one must declare what cluster configurations to execute for each of the test cases. Each test case will be executed
once for each of these configurations.

  • LocalSingleProcessServer: Execute a single-site H-Store instance with one or more partitions within the same JVM that is running the JUnit testing harness.
  • LocalCluster: Execute a local cluster of multiple H-Store instances on the same host. The first site will execute within the same JVM that is running the JUnit testing harness. All other sites will be invoked using the ant hstore-site. command. The output log files for these additional sites can be found in obj/release/testoutput. Note that if changes are made to the H-Store frontend in Eclipse, you must compile the system from the commandline before running a multi-site test using the LocalCluster configuration.

In the example below, the suite() method first creates a project builder for the target application to be used in the tests. This project builder is then provided to the two different cluster configuration objects.

package edu.brown.hstore;
 
import java.io.IOException;
 
import org.junit.Test;
import org.voltdb.BackendTarget;
import org.voltdb.VoltTable;
import org.voltdb.client.*;
import org.voltdb.compiler.VoltProjectBuilder;
import org.voltdb.regressionsuites.*;
 
import edu.brown.hstore.Hstoreservice.Status;
 
public class TestSampleSuite extends RegressionSuite {
 
    /**
     * JUnit / RegressionSuite Boilerplate Constructor
     * @param name The name of this test suite
     */
    public TestLoggerSuite(String name) {
        super(name);
    }
 
    public static junit.framework.Test suite() {
        MultiConfigSuiteBuilder builder = 
                new MultiConfigSuiteBuilder(TestLoggerSuite.class);
        VoltProjectBuilder project = new VoltProjectBuilder("logger");
        VoltServerConfig config = null;
 
        // Schema + Table Partitions
        project.addSchema(TestLoggerSuite.class.getResource("logger-ddl.sql"));
        project.addTablePartitionInfo("P1", "ID");
 
        // Single Statement Procedures
        project.addStmtProcedure("TestInsert", "INSERT INTO P1 VALUES (?, ?)");
        project.addStmtProcedure("TestSelect", "SELECT * FROM P1 WHERE ID = ?");
 
        // CLUSTER CONFIG #1
        // One site with two partitions running in this JVM
        config = new LocalSingleProcessServer("logger-twoPart.jar", 2,
                                              BackendTarget.NATIVE_EE_JNI);
        config.compile(project);
        builder.addServerConfig(config);
 
        // CLUSTER CONFIG #2
        // Two sites, each with two partitions running in separate JVMs
        config = new LocalCluster("logger-twoSiteTwoPart.jar", 2, 2, 1,
                                  BackendTarget.NATIVE_EE_JNI);
        config.compile(project);
        builder.addServerConfig(config);
 
        return builder;
    }
 
    @Test
    public void testInsert() throws IOException, ProcCallException {
        int id = 1234;
        String val = "ABCD";
 
        Client client = getClient();
        ClientResponse cr = client.callProcedure("TestInsert", id, val);
        assertEquals(Status.OK, cr.getStatus());
 
        cr = client.callProcedure("TestSelect", id);
        assertEquals(Status.OK, cr.getStatus());
        VoltTable result = cr.getResults()[0];
        assertTrue(result.advanceRow());
        assertEquals(id, (int)result.getLong(0));
        assertEquals(val, result.getString(1));
    }
}

Important: In order to run this test case in Eclipse, you must add following the java.library.path option to the VM Arguments options to the run configuration of target test case under Run Configurations -> JUnit -> Arguments:

-Djava.library.path=obj/release/nativelibs