Package org.voltdb.regressionsuites

Source Code of org.voltdb.regressionsuites.TestCatalogUpdateSuite

/* This file is part of VoltDB.
* Copyright (C) 2008-2014 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

package org.voltdb.regressionsuites;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import junit.framework.Test;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.zookeeper_voltpatches.CreateMode;
import org.apache.zookeeper_voltpatches.ZooDefs;
import org.apache.zookeeper_voltpatches.ZooKeeper;
import org.voltcore.zk.ZKUtil;
import org.voltdb.BackendTarget;
import org.voltdb.TheHashinator;
import org.voltdb.VoltDB.Configuration;
import org.voltdb.VoltTable;
import org.voltdb.VoltType;
import org.voltdb.VoltZK;
import org.voltdb.benchmark.tpcc.TPCCProjectBuilder;
import org.voltdb.benchmark.tpcc.procedures.InsertNewOrder;
import org.voltdb.client.Client;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.ProcCallException;
import org.voltdb.client.ProcedureCallback;
import org.voltdb.client.SyncCallback;
import org.voltdb.compiler.VoltProjectBuilder.GroupInfo;
import org.voltdb.compiler.VoltProjectBuilder.ProcedureInfo;
import org.voltdb.compiler.VoltProjectBuilder.UserInfo;
import org.voltdb.types.TimestampType;
import org.voltdb.utils.MiscUtils;

/**
* Tests a mix of multi-partition and single partition procedures on a
* mix of replicated and partititioned tables on a mix of single-site and
* multi-site VoltDB instances.
*
*/
public class TestCatalogUpdateSuite extends RegressionSuite {

    static final int SITES_PER_HOST = 2;
    static final int HOSTS = 2;
    static final int K = MiscUtils.isPro() ? 1 : 0;

    // procedures used by these tests
    static Class<?>[] BASEPROCS = { org.voltdb.benchmark.tpcc.procedures.InsertNewOrder.class,
                                    org.voltdb.benchmark.tpcc.procedures.SelectAll.class,
                                    org.voltdb.benchmark.tpcc.procedures.delivery.class };

    static Class<?>[] BASEPROCS_OPROCS =  { org.voltdb.benchmark.tpcc.procedures.InsertNewOrder.class,
                                            org.voltdb.benchmark.tpcc.procedures.SelectAll.class,
                                            org.voltdb.benchmark.tpcc.procedures.delivery.class,
                                            org.voltdb_testprocs.regressionsuites.orderbyprocs.InsertO1.class};


    static Class<?>[] EXPANDEDPROCS = { org.voltdb.benchmark.tpcc.procedures.InsertNewOrder.class,
                                        org.voltdb.benchmark.tpcc.procedures.SelectAll.class,
                                        org.voltdb.benchmark.tpcc.procedures.delivery.class,
                                        org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class };

    static Class<?>[] CONFLICTPROCS = { org.voltdb.catalog.InsertNewOrder.class,
                                        org.voltdb.benchmark.tpcc.procedures.SelectAll.class,
                                        org.voltdb.benchmark.tpcc.procedures.delivery.class };

    static Class<?>[] SOMANYPROCS =   { org.voltdb.benchmark.tpcc.procedures.InsertNewOrder.class,
                                        org.voltdb.benchmark.tpcc.procedures.SelectAll.class,
                                        org.voltdb.benchmark.tpcc.procedures.neworder.class,
                                        org.voltdb.benchmark.tpcc.procedures.ostatByCustomerId.class,
                                        org.voltdb.benchmark.tpcc.procedures.ostatByCustomerName.class,
                                        org.voltdb.benchmark.tpcc.procedures.paymentByCustomerId.class,
                                        org.voltdb.benchmark.tpcc.procedures.paymentByCustomerName.class,
                                        org.voltdb.benchmark.tpcc.procedures.slev.class,
                                        org.voltdb.benchmark.tpcc.procedures.delivery.class };

    // testUpdateHonkingBigCatalog constants and statistics. 100/100/40 makes a ~2MB jar.
    private static final int HUGE_TABLES = 100;
    private static final int HUGE_COLUMNS = 100;
    private static final int HUGE_NAME_SIZE = 40;
    private static double hugeCompileElapsed = 0.0;
    private static double hugeTestElapsed = 0.0;
    private static String hugeCatalogXMLPath;
    private static String hugeCatalogJarPath;

    /**
     * Constructor needed for JUnit. Should just pass on parameters to superclass.
     * @param name The name of the method to test. This is just passed to the superclass.
     */
    public TestCatalogUpdateSuite(String name) {
        super(name);
    }

    AtomicInteger m_outstandingCalls = new AtomicInteger(0);

    boolean callbackSuccess;

    class CatTestCallback implements ProcedureCallback {

        final byte m_expectedStatus;

        CatTestCallback(byte expectedStatus) {
            m_expectedStatus = expectedStatus;
            m_outstandingCalls.incrementAndGet();
        }

        @Override
        public void clientCallback(ClientResponse clientResponse) {
            m_outstandingCalls.decrementAndGet();
            if (m_expectedStatus != clientResponse.getStatus()) {
                if (clientResponse.getStatusString() != null)
                    System.err.println(clientResponse.getStatusString());
                callbackSuccess = false;
            }
        }
    }

    public void testUpdateWithNoDeploymentFile() throws Exception {
        System.out.println("\n\n-----\n testUpdateWithNoDeploymentFile \n-----\n\n");
        Client client = getClient();
        String newCatalogURL;
        CatTestCallback callback;

        loadSomeData(client, 0, 25);
        client.drain();
        assertTrue(callbackSuccess);

        negativeTests(client);
        assertTrue(callbackSuccess);

        // asynchronously call some random inserts
        loadSomeData(client, 25, 25);
        assertTrue(callbackSuccess);

        // add a procedure "InsertOrderLineBatched"
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-expanded.jar");
        callback = new CatTestCallback(ClientResponse.SUCCESS);
        client.updateApplicationCatalog(callback, new File(newCatalogURL), null);

        // don't care if this succeeds or fails.
        // calling the new proc before the cat change returns is not guaranteed to work
        // we just hope it doesn't crash anything
        int x = 3;
        SyncCallback cb = new SyncCallback();
        client.callProcedure(cb,
                org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});
        cb.waitForResponse();

        // make sure the previous catalog change has completed
        client.drain();
        assertTrue(callbackSuccess);

        // now calling the new proc better work
        x = 2;
        client.callProcedure(org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, (short)x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});

        loadSomeData(client, 50, 5);
        assertTrue(callbackSuccess);
    }

    /**
     * Start with snapshots disabled. Enable them to one directory, check that the snapshot files are created
     * with the correct prefix. Update the catalog to do the snapshots in a different directory with a
     * different prefix and check to make sure they start going to the right place. Update the catalog
     * to disable them and then make sure no snapshots appear.
     * @throws Exception
     */
    public void testEnableModifyDisableSnapshot() throws Exception {
        m_config.deleteDirectory(new File("/tmp/snapshotdir1"));
        m_config.deleteDirectory(new File("/tmp/snapshotdir2"));
        try {
            m_config.createDirectory(new File("/tmp/snapshotdir1"));
            m_config.createDirectory(new File("/tmp/snapshotdir2"));
            Client client = getClient();

            //
            // Test that we can enable snapshots
            //
            String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-enable_snapshot.jar");
            String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-enable_snapshot.xml");
            VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
            Thread.sleep(5000);

            //
            // Make sure snapshot files are generated
            //
            for (File f : m_config.listFiles(new File("/tmp/snapshotdir1"))) {
                assertTrue(f.getName().startsWith("foo1"));
            }

            //
            // Test that we can change settings like the path
            //
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
            Thread.sleep(5000);

            //
            // Check that files are made in the new path
            //
            for (File f : m_config.listFiles(new File("/tmp/snapshotdir2"))) {
                assertTrue(f.getName().startsWith("foo2"));
            }

            //
            // Change the snapshot path to something that doesn't exist, no crashes
            //
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot_dir_not_exist.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot_dir_not_exist.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);

            System.out.println("Waiting for failed snapshots");
            Thread.sleep(5000);

            //
            // Change it back
            //
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
            Thread.sleep(5000);

            //
            // Make sure snapshots resume
            //
            for (File f : m_config.listFiles(new File("/tmp/snapshotdir2"))) {
                assertTrue(f.getName().startsWith("foo2"));
            }

            //
            // Make sure you can disable snapshots
            //
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
            for (File f : m_config.listFiles(new File("/tmp/snapshotdir2"))) {
                f.delete();
            }

            Thread.sleep(5000);

            //
            // Make sure you can reenable snapshot files
            //
            assertEquals( 0, m_config.listFiles(new File("/tmp/snapshotdir2")).size());

            //
            // Test that we can enable snapshots
            //
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-enable_snapshot.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-enable_snapshot.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
            Thread.sleep(5000);

            //
            // Make sure snapshot files are generated
            //
            for (File f : m_config.listFiles(new File("/tmp/snapshotdir1"))) {
                assertTrue(f.getName().startsWith("foo1"));
            }

            //
            // Turn snapshots off so that we can clean up
            //
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
            Thread.sleep(1000);

            m_config.deleteDirectory(new File("/tmp/snapshotdir1"));
            m_config.deleteDirectory(new File("/tmp/snapshotdir2"));
            m_config.createDirectory(new File("/tmp/snapshotdir1"));
            m_config.createDirectory(new File("/tmp/snapshotdir2"));
            Thread.sleep(5000);
            assertTrue(m_config.listFiles(new File("/tmp/snapshotdir1")).isEmpty());
            assertTrue(m_config.listFiles(new File("/tmp/snapshotdir2")).isEmpty());
        } finally {
            deleteDirectory(new File("/tmp/snapshotdir1"));
            deleteDirectory(new File("/tmp/snapshotdir2"));
        }
    }

    public void testUpdate() throws Exception {
        Client client = getClient();
        String newCatalogURL;
        String deploymentURL;
        VoltTable[] results;
        CatTestCallback callback;

        loadSomeData(client, 0, 25);
        client.drain();
        assertTrue(callbackSuccess);

        negativeTests(client);
        assertTrue(callbackSuccess);

        // asynchronously call some random inserts
        loadSomeData(client, 25, 25);
        assertTrue(callbackSuccess);

        // add a procedure "InsertOrderLineBatched"
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-expanded.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-expanded.xml");
        callback = new CatTestCallback(ClientResponse.SUCCESS);
        client.updateApplicationCatalog(callback, new File(newCatalogURL), new File(deploymentURL));

        // don't care if this succeeds or fails.
        // calling the new proc before the cat change returns is not guaranteed to work
        // we just hope it doesn't crash anything
        int x = 3;
        SyncCallback cb = new SyncCallback();
        client.callProcedure(cb,
                org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});
        cb.waitForResponse();

        // make sure the previous catalog change has completed
        client.drain();
        assertTrue(callbackSuccess);

        // now calling the new proc better work
        x = 2;
        client.callProcedure(org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, (short)x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});

        loadSomeData(client, 50, 5);
        assertTrue(callbackSuccess);

        // this is a do nothing change... shouldn't affect anything
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-expanded.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-expanded.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);
        client.drain();
        assertTrue(callbackSuccess);

        // now calling the new proc better work
        x = 4;
        client.callProcedure(org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, (short)x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});

        loadSomeData(client, 55, 5);

        // remove the procedure we just added async
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
        callback = new CatTestCallback(ClientResponse.SUCCESS);
        client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL));

        // don't care if this works now
        x = 4;
        cb = new SyncCallback();
        client.callProcedure(cb,
                org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, (short)x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});
        cb.waitForResponse();

        // make sure the previous catalog change has completed
        client.drain();
        assertTrue(callbackSuccess);

        // now calling the new proc better fail
        x = 5;
        cb = new SyncCallback();
        client.callProcedure(cb,
                org.voltdb.benchmark.tpcc.procedures.InsertOrderLineBatched.class.getSimpleName(),
                new long[] {x}, new long[] {x}, (short)x, new long[] {x},
                new long[] {x}, new long[] {x}, new TimestampType[] { new TimestampType() }, new long[] {x},
                new double[] {x}, new String[] {"a"});
        cb.waitForResponse();
        assertNotSame(cb.getResponse().getStatus(), ClientResponse.SUCCESS);

        loadSomeData(client, 60, 5);

        // change the insert new order procedure
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-conflict.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-conflict.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // call the new proc and make sure the one we want gets run
        results = client.callProcedure(InsertNewOrder.class.getSimpleName(), 100, 100, 100, 100, (short)100, 100, 1.0, "a").getResults();
        assertEquals(1, results.length);
        assertEquals(1776, results[0].asScalarLong());

        // load a big catalog change just to make sure nothing fails horribly
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-many.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-many.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        loadSomeData(client, 65, 5);

        //Check that if a catalog update blocker exists the catalog update fails
        ZooKeeper zk = ZKUtil.getClient(((LocalCluster) m_config).zkinterface(0), 10000, new HashSet<Long>());
        final String catalogUpdateBlockerPath = zk.create(
                VoltZK.elasticJoinActiveBlocker,
                null,
                ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL_SEQUENTIAL );
        try {
            /*
             * Update the catalog and expect failure
             */
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
            boolean threw = false;
            try {
                client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL));
            } catch (ProcCallException e) {
                e.printStackTrace();
                threw = true;
            }
            assertTrue(threw);
        }
        finally {
            zk.delete(catalogUpdateBlockerPath, -1);
        }

        //Expect success
        client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL));

        client.drain();
        assertTrue(callbackSuccess);
        assertTrue(true);
    }

    public void testEnableSecurityAndHeartbeatTimeoutChange()
    throws IOException, ProcCallException, InterruptedException
    {
        System.out.println("\n\n-----\n testEnabledSecurity \n-----\n\n");
        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base-secure.jar");
        String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base-secure.xml");
        VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // a new client should need a username/password other than the regression suite default.
        boolean caught = false;
        try {
            getClient();
        } catch (IOException e) {
            caught = true;
        }
        assertTrue(caught);

        // create a valid client and call some procedures
        this.m_username = "user1";
        this.m_password = "userpass1";
        Client client3 = getClient();
        loadSomeData(client3, 50, 10);
        client3.drain();
        assertTrue(callbackSuccess);

        // the old client should not work because the user has been removed.
        loadSomeData(client, 100, 10);
        client.drain();
        assertFalse(callbackSuccess);
        callbackSuccess = true;

        checkDeploymentPropertyValue(client3, "heartbeattimeout", "6000");
    }

    private void loadSomeData(Client client, int start, int count) throws IOException, ProcCallException {
        for (int i = start; i < (start + count); i++) {
            CatTestCallback callback = new CatTestCallback(ClientResponse.SUCCESS);
            client.callProcedure(callback, InsertNewOrder.class.getSimpleName(), i, i, (short)i);
        }
    }

    public void negativeTests(Client client) throws UnsupportedEncodingException {
        // this fails because the catalog URL isn't a real thing but needs to point at
        // a file that actually exists.  Point to the compiled java class for this suite
        URL url = TestCatalogUpdateSuite.class.getResource("TestCatalogUpdateSuite.class");
        String newCatalogURL = URLDecoder.decode(url.getPath(), "UTF-8");
        String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtables.xml");
        try {
            client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL));
            fail();
        }
        catch (Exception e) {
            assertTrue(e.getMessage().startsWith("Database catalog not found"));
        }
    }

    public static long indexEntryCountFromStats(Client client, String tableName, String indexName) throws Exception {
        ClientResponse callProcedure = client.callProcedure("@Statistics", "INDEX", 0);
        assertTrue(callProcedure.getResults().length == 1);
        assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);
        VoltTable result = callProcedure.getResults()[0];
        long tupleCount = 0;
        while (result.advanceRow()) {
            if (result.getString("TABLE_NAME").equals(tableName) && result.getString("INDEX_NAME").equals(indexName)) {
                tupleCount += result.getLong("ENTRY_COUNT");
            }
        }
        return tupleCount;
    }

    public void testAddDropIndex() throws Exception
    {
        ClientResponse callProcedure;
        String explanation;
        VoltTable result;

        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        // check that no index was used by checking the plan itself
        callProcedure = client.callProcedure("@Explain", "select * from NEW_ORDER where NO_O_ID = 5;");
        explanation = callProcedure.getResults()[0].fetchRow(0).getString(0);
        assertFalse(explanation.contains("INDEX SCAN"));

        // add index to NEW_ORDER
        String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addindex.jar");
        String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addindex.xml");
        VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // check the index for non-zero size

        long tupleCount = -1;
        while (tupleCount <= 0) {
            tupleCount = indexEntryCountFromStats(client, "NEW_ORDER", "NEWINDEX");
        }
        assertTrue(tupleCount > 0);

        // verify that the new table(s) support an insert
        callProcedure = client.callProcedure("@AdHoc", "insert into NEW_ORDER values (-1, -1, -1);");
        assertTrue(callProcedure.getResults().length == 1);
        assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);

        // do a call that uses the index
        callProcedure = client.callProcedure("@AdHoc", "select * from NEW_ORDER where NO_O_ID = 5;");
        result = callProcedure.getResults()[0];
        result.advanceRow();
        assertEquals(5, result.getLong("NO_O_ID"));

        // check that an index was used by checking the plan itself
        callProcedure = client.callProcedure("@Explain", "select * from NEW_ORDER where NO_O_ID = 5;");
        explanation = callProcedure.getResults()[0].fetchRow(0).getString(0);
        assertTrue(explanation.contains("INDEX SCAN"));

        // tables can still be accessed
        loadSomeData(client, 20, 10);
        client.drain();
        assertTrue(callbackSuccess);

        // check table for the right number of tuples
        callProcedure = client.callProcedure("@AdHoc", "select count(*) from NEW_ORDER;");
        long rowCount = callProcedure.getResults()[0].asScalarLong();
        // check the index for even biggerer size from stats
        long newTupleCount = indexEntryCountFromStats(client, "NEW_ORDER", "NEWINDEX");
        while (newTupleCount != (rowCount * (K + 1))) {
            newTupleCount = indexEntryCountFromStats(client, "NEW_ORDER", "NEWINDEX");
        }
        assertTrue(newTupleCount > tupleCount);
        assertEquals(newTupleCount, rowCount * (K + 1)); // index count is double for k=1

        // revert to the original schema
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // do a call that uses the index
        callProcedure = client.callProcedure("@AdHoc", "select * from NEW_ORDER where NO_O_ID = 5;");
        result = callProcedure.getResults()[0];
        result.advanceRow();
        assertEquals(5, result.getLong("NO_O_ID"));

        // check that no index was used by checking the plan itself
        callProcedure = client.callProcedure("@Explain", "select * from NEW_ORDER where NO_O_ID = 5;");
        explanation = callProcedure.getResults()[0].fetchRow(0).getString(0);
        assertFalse(explanation.contains("INDEX SCAN"));

        // and loading still succeeds
        loadSomeData(client, 30, 10);
        client.drain();
        assertTrue(callbackSuccess);
    }

    public void testAddDropExpressionIndex() throws Exception
    {
        ClientResponse callProcedure;
        String explanation;
        VoltTable result;

        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        // check that no index was used by checking the plan itself
        callProcedure = client.callProcedure("@Explain", "select * from NEW_ORDER where (NO_O_ID+NO_O_ID)-NO_O_ID = 5;");
        explanation = callProcedure.getResults()[0].fetchRow(0).getString(0);
        assertFalse(explanation.contains("INDEX SCAN"));

        // add index to NEW_ORDER
        String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addexpressindex.jar");
        String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addexpressindex.xml");
        VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // check the index for non-zero size

        long tupleCount = -1;
        while (tupleCount <= 0) {
            tupleCount = indexEntryCountFromStats(client, "NEW_ORDER", "NEWEXPRESSINDEX");
        }
        assertTrue(tupleCount > 0);

        // verify that the new table(s) support an insert
        callProcedure = client.callProcedure("@AdHoc", "insert into NEW_ORDER values (-1, -1, -1);");
        assertTrue(callProcedure.getResults().length == 1);
        assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);

        // do a call that uses the index
        callProcedure = client.callProcedure("@AdHoc", "select * from NEW_ORDER where (NO_O_ID+NO_O_ID)-NO_O_ID = 5;");
        result = callProcedure.getResults()[0];
        result.advanceRow();
        assertEquals(5, result.getLong("NO_O_ID"));

        // check that an index was used by checking the plan itself
        callProcedure = client.callProcedure("@Explain", "select * from NEW_ORDER where (NO_O_ID+NO_O_ID)-NO_O_ID = 5;");
        explanation = callProcedure.getResults()[0].fetchRow(0).getString(0);
        assertTrue(explanation.contains("INDEX SCAN"));

        // tables can still be accessed
        loadSomeData(client, 20, 10);
        client.drain();
        assertTrue(callbackSuccess);


        // check table for the right number of tuples
        callProcedure = client.callProcedure("@AdHoc", "select count(*) from NEW_ORDER;");
        long rowCount = callProcedure.getResults()[0].asScalarLong();
        // check the index for even biggerer size from stats
        long newTupleCount = -1;
        while (newTupleCount != (rowCount * (K + 1))) {
            newTupleCount = indexEntryCountFromStats(client, "NEW_ORDER", "NEWEXPRESSINDEX");
        }
        assertTrue(newTupleCount > tupleCount);
        assertEquals(newTupleCount, rowCount * (K + 1)); // index count is double for k=1

        // revert to the original schema
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // do a call that uses the index
        callProcedure = client.callProcedure("@AdHoc", "select * from NEW_ORDER where (NO_O_ID+NO_O_ID)-NO_O_ID = 5;");
        result = callProcedure.getResults()[0];
        result.advanceRow();
        assertEquals(5, result.getLong("NO_O_ID"));

        // check that no index was used by checking the plan itself
        callProcedure = client.callProcedure("@Explain", "select * from NEW_ORDER where (NO_O_ID+NO_O_ID)-NO_O_ID = 5;");
        explanation = callProcedure.getResults()[0].fetchRow(0).getString(0);
        assertFalse(explanation.contains("INDEX SCAN"));

        // and loading still succeeds
        loadSomeData(client, 30, 10);
        client.drain();
        assertTrue(callbackSuccess);
    }

    public void testAddDropTable() throws IOException, ProcCallException, InterruptedException
    {
        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        // verify that an insert w/o a table fails.
        try {
            client.callProcedure("@AdHoc", "insert into O1 values (1, 1, 'foo', 'foobar');");
            fail();
        }
        catch (ProcCallException e) {
        }

        // Also can't call this not-yet-existing stored procedure
        try {
            client.callProcedure("InsertO1", new Integer(100), new Integer(200), "foo", "bar");
            fail();
        }
        catch (ProcCallException e) {
        }

        // add tables O1, O2, O3
        String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtables.jar");
        String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtables.xml");
        VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // verify that the new table(s) support an insert
        ClientResponse callProcedure = client.callProcedure("@AdHoc", "insert into O1 values (1, 1, 'foo', 'foobar');");
        assertTrue(callProcedure.getResults().length == 1);
        assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);

        callProcedure = client.callProcedure("@AdHoc", "insert into O2 values (1, 1, 'foo', 'foobar');");
        assertTrue(callProcedure.getResults().length == 1);
        assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);

        callProcedure = client.callProcedure("@AdHoc", "select * from O1");
        VoltTable result = callProcedure.getResults()[0];
        result.advanceRow();
        assertTrue(result.get(2, VoltType.STRING).equals("foo"));

        // old tables can still be accessed
        loadSomeData(client, 20, 10);
        client.drain();
        assertTrue(callbackSuccess);

        // and this new procedure is happy like clams
        callProcedure = client.callProcedure("InsertO1", new Integer(100), new Integer(200), "foo", "bar");
        assertTrue(callProcedure.getResults().length == 1);
        assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);

        // revert to the original schema
        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // requests to the dropped table should fail
        try {
            client.callProcedure("@AdHoc", "insert into O1 values (1, 1, 'foo', 'foobar');");
            fail();
        }
        catch (ProcCallException e) {
        }

        try {
            client.callProcedure("InsertO1", new Integer(100), new Integer(200), "foo", "bar");
            fail();
        }
        catch (ProcCallException e) {
        }

        // and other requests still succeed
        loadSomeData(client, 30, 10);
        client.drain();
        assertTrue(callbackSuccess);
    }

    public void testAddTableWithMatView() throws IOException, ProcCallException, InterruptedException {
        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        // add new tables and materialized view
        String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtableswithmatview.jar");
        String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtableswithmatview.xml");
        VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);

        // verify that the new table(s) support an insert
        for (int i=0; i < 10; ++i) {
            ClientResponse callProcedure = client.callProcedure("@AdHoc", "insert into O1 values (" + i + ", " + i % 2 + ", 'foo', 'foobar');");
            assertTrue(callProcedure.getResults().length == 1);
            assertTrue(callProcedure.getStatus() == ClientResponse.SUCCESS);
        }

        // read it - expect 10 rows
        ClientResponse callProcedure = client.callProcedure("@AdHoc", "select * from O1");
        VoltTable result = callProcedure.getResults()[0];
        assertTrue(result.getRowCount() == 10);

        // read the mat view. expect two rows (grouped on x % 2)
        callProcedure = client.callProcedure("@AdHoc", "select C1,NUM from MATVIEW_O1 order by C1");
        result = callProcedure.getResults()[0];

        System.out.println("MATVIEW:"); System.out.println(result);
        assertEquals(10, result.getRowCount());
    }

    private void loadSomeDataForNewTable(Client client, int start, int count) throws IOException, ProcCallException {
        for (int i = start; i < (start + count); i++) {
            CatTestCallback callback = new CatTestCallback(ClientResponse.SUCCESS);
            client.callProcedure(callback, "O1.insert", i, i, "abcdefg", "voltdb is a great startup with potential success in future");
        }
    }

    public void testAddDropTableRepeat() throws Exception {
        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        /*
         * Reduced from 100 to 30 so that it doesn't take quite as long
         * We run tests often enough that this will get plenty of fuzzing.
         */
        for (int i=0; i < 30; i++)
        {
            // add tables O1, O2, O3
            String newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtables.jar");
            String deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtables.xml");
            VoltTable[] results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);

            // Thread.sleep(2000);
            // Load table into the new added tables
            loadSomeDataForNewTable(client, 0, 1000 *10);
            client.drain();

            // revert to the original schema
            newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
            deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
            results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
            assertTrue(results.length == 1);
        }
    }

    public void testUpdateHonkingBigCatalog() throws IOException, ProcCallException, InterruptedException {
        System.out.println("\n\n-----\n testUpdateHonkingBigCatalog\n");
        System.out.printf("jar: %s (%.2f MB)\n", hugeCatalogJarPath, new File(hugeCatalogJarPath).length() / 1048576.0);
        System.out.printf("compile: %.2f seconds (%.2f/second)\n", hugeCompileElapsed, HUGE_TABLES / hugeCompileElapsed);
        long t = System.currentTimeMillis();
        Client client = getClient();
        loadSomeData(client, 0, 10);
        client.drain();
        assertTrue(callbackSuccess);

        try {
            VoltTable[] results = client.updateApplicationCatalog(new File(hugeCatalogJarPath), new File(hugeCatalogXMLPath)).getResults();
            assertTrue(results.length == 1);
        }
        catch (ProcCallException e) {
            fail(String.format("@UpdateApplicationCatalog: ProcCallException: %s", e.getLocalizedMessage()));
        }
        hugeTestElapsed = (System.currentTimeMillis() - t) / 1000.0;
        System.out.printf("test: %.2f seconds (%.2f/second)\n", hugeTestElapsed, HUGE_TABLES / hugeTestElapsed);
        System.out.println("-----\n\n");
    }

    public void testSystemSettingsUpdateTimeout() throws IOException, ProcCallException, InterruptedException  {
        Client client = getClient();
        String newCatalogURL, deploymentURL;
        VoltTable[] results;

        // check the catalog update with query timeout
        String key = "querytimeout";
        checkDeploymentPropertyValue(client, key, "0"); // check default value

        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-1000.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-1000.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);
        checkDeploymentPropertyValue(client, key, "1000");

        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-5000.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-5000.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);
        checkDeploymentPropertyValue(client, key, "5000");

        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-600.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-600.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);
        checkDeploymentPropertyValue(client, key, "600");

        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);
        checkDeploymentPropertyValue(client, key, "0"); // check default value

        // check the catalog update with elastic duration and throughput
        String duration = "elasticduration", throughput = "elasticthroughput";
        checkDeploymentPropertyValue(client, duration, "50"); // check default value
        checkDeploymentPropertyValue(client, throughput, "2"); // check default value

        newCatalogURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-elastic-100-5.jar");
        deploymentURL = Configuration.getPathToCatalogForTest("catalogupdate-cluster-elastic-100-5.xml");
        results = client.updateApplicationCatalog(new File(newCatalogURL), new File(deploymentURL)).getResults();
        assertTrue(results.length == 1);
        checkDeploymentPropertyValue(client, duration, "100");
        checkDeploymentPropertyValue(client, throughput, "5");
    }

    private void deleteDirectory(File dir) {
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }

        for (File f : dir.listFiles()) {
            assertTrue(f.delete());
        }
        assertTrue(dir.delete());
    }

    private static String generateRandomDDL(String name, int ntables, int ncols, int width)
            throws IOException {
        // Generate huge DDL file. Make it relatively uncompressible with randomness.
        File temp = File.createTempFile(name, ".sql");
        temp.deleteOnExit();
        FileWriter out = new FileWriter(temp);
        char[] charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".toCharArray();
        Random random = new Random(99);
        for (int itable = 0; itable < ntables; itable++) {
            out.write(String.format("\nCREATE TABLE HUGE_TABLE_%d (\n", itable));
            out.write("C_FIRST INTEGER,\n");
            for (int icolumn = 0; icolumn < ncols; icolumn++) {
                String columnID = RandomStringUtils.random(width,
                                                           0,
                                                           charset.length,
                                                           false,
                                                           false,
                                                           charset,
                                                           random);
                out.write(String.format("C_%s INTEGER,\n", columnID));
            }
            out.write("PRIMARY KEY (C_FIRST));\n");
        }
        out.close();
        return URLEncoder.encode(temp.getAbsolutePath(), "UTF-8");
    }

    /**
     * Build a list of the tests that will be run when TestTPCCSuite gets run by JUnit.
     * Use helper classes that are part of the RegressionSuite framework.
     * This particular class runs all tests on the the local JNI backend with both
     * one and two partition configurations, as well as on the hsql backend.
     *
     * @return The TestSuite containing all the tests to be run.
     * @throws Exception
     */
    static public Test suite() throws Exception {
        TheHashinator.initialize(TheHashinator.getConfiguredHashinatorClass(), TheHashinator.getConfigureBytes(2));

        // the suite made here will all be using the tests from this class
        MultiConfigSuiteBuilder builder = new MultiConfigSuiteBuilder(TestCatalogUpdateSuite.class);

        /////////////////////////////////////////////////////////////
        // CONFIG #1: 1 Local Site/Partitions running on JNI backend
        /////////////////////////////////////////////////////////////

        // get a server config for the native backend with one sites/partitions
        VoltServerConfig config = new LocalCluster("catalogupdate-cluster-base.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);

        // Catalog upgrade test(s) sporadically fail if there's a local server because
        // a file pipe isn't available for grepping local server output.
        ((LocalCluster) config).setHasLocalServer(true);

        // build up a project builder for the workload
        TPCCProjectBuilder project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        // build the jarfile
        boolean basecompile = config.compile(project);
        assertTrue(basecompile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-base.xml"));

        // add this config to the set of tests to run
        builder.addServerConfig(config);

        /////////////////////////////////////////////////////////////
        // DELTA CATALOGS FOR TESTING
        /////////////////////////////////////////////////////////////

        // As catalogupdate-cluster-base but with security enabled. This requires users and groups..
        // We piggy-back the heartbeat change here.
        GroupInfo groups[] = new GroupInfo[] {new GroupInfo("group1", false, false, true, false, false, false)};
        UserInfo users[] = new UserInfo[] {new UserInfo("user1", "userpass1", new String[] {"group1"})};
        ProcedureInfo procInfo = new ProcedureInfo(new String[] {"group1"}, InsertNewOrder.class);

        config = new LocalCluster("catalogupdate-cluster-base-secure.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addUsers(users);
        project.addGroups(groups);
        project.addProcedures(procInfo);
        project.setSecurityEnabled(true);
        project.setDeadHostTimeout(6000);
        boolean compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-base-secure.xml"));

        //config = new LocalSingleProcessServer("catalogupdate-local-addtables.jar", 2, BackendTarget.NATIVE_EE_JNI);
        config = new LocalCluster("catalogupdate-cluster-addtables.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addSchema(TestCatalogUpdateSuite.class.getResource("testorderby-ddl.sql").getPath());
        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS_OPROCS);
        project.setElasticDuration(100);
        project.setElasticThroughput(50);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtables.xml"));

        // as above but also with a materialized view added to O1
        try {
            config = new LocalCluster("catalogupdate-cluster-addtableswithmatview.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
            project = new TPCCProjectBuilder();
            project.addDefaultSchema();
            project.addSchema(TestCatalogUpdateSuite.class.getResource("testorderby-ddl.sql").getPath());
            project.addLiteralSchema("CREATE VIEW MATVIEW_O1(C1, C2, NUM) AS SELECT A_INT, PKEY, COUNT(*) FROM O1 GROUP BY A_INT, PKEY;");
            project.addDefaultPartitioning();
            project.addProcedures(BASEPROCS_OPROCS);
            compile = config.compile(project);
            assertTrue(compile);
            MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-addtableswithmatview.xml"));
        } catch (IOException e) {
            fail();
        }

        config = new LocalCluster("catalogupdate-cluster-addindex.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addLiteralSchema("CREATE INDEX NEWINDEX ON NEW_ORDER (NO_O_ID);");
        // history is good because this new index is the only one (no pkey)
        project.addLiteralSchema("CREATE INDEX NEWINDEX2 ON HISTORY (H_C_ID);");
        // unique index
        project.addLiteralSchema("CREATE UNIQUE INDEX NEWINDEX3 ON STOCK (S_I_ID, S_W_ID, S_QUANTITY);");

        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-addindex.xml"));

        config = new LocalCluster("catalogupdate-cluster-addexpressindex.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addLiteralSchema("CREATE INDEX NEWEXPRESSINDEX ON NEW_ORDER ((NO_O_ID+NO_O_ID)-NO_O_ID);");
        // history is good because this new index is the only one (no pkey)
        project.addLiteralSchema("CREATE INDEX NEWEXPRESSINDEX2 ON HISTORY ((H_C_ID+H_C_ID)-H_C_ID);");
        // unique index
        // This needs to wait until the test for unique index coverage for indexed expressions can parse out any simple column expressions
        // and discover a unique index on some subset.
        //TODO: project.addLiteralSchema("CREATE UNIQUE INDEX NEWEXPRESSINDEX3 ON STOCK (S_I_ID, S_W_ID, S_QUANTITY+S_QUANTITY-S_QUANTITY);");

        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-addexpressindex.xml"));

        //config = new LocalSingleProcessServer("catalogupdate-local-expanded.jar", 2, BackendTarget.NATIVE_EE_JNI);
        config = new LocalCluster("catalogupdate-cluster-expanded.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(EXPANDEDPROCS);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-expanded.xml"));

        //config = new LocalSingleProcessServer("catalogupdate-local-conflict.jar", 2, BackendTarget.NATIVE_EE_JNI);
        config = new LocalCluster("catalogupdate-cluster-conflict.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(CONFLICTPROCS);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-conflict.xml"));

        //config = new LocalSingleProcessServer("catalogupdate-local-many.jar", 2, BackendTarget.NATIVE_EE_JNI);
        config = new LocalCluster("catalogupdate-cluster-many.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(SOMANYPROCS);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-many.xml"));


        // A catalog change that enables snapshots
        config = new LocalCluster("catalogupdate-cluster-enable_snapshot.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        project.setSnapshotSettings( "1s", 3, "/tmp/snapshotdir1", "foo1");
        // build the jarfile
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-enable_snapshot.xml"));

        //Another catalog change to modify the schedule
        config = new LocalCluster("catalogupdate-cluster-change_snapshot.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        project.setSnapshotSettings( "1s", 3, "/tmp/snapshotdir2", "foo2");
        // build the jarfile
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot.xml"));

        //Another catalog change to modify the schedule
        config = new LocalCluster("catalogupdate-cluster-change_snapshot_dir_not_exist.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        project.setSnapshotSettings( "1s", 3, "/tmp/snapshotdirasda2", "foo2");
        // build the jarfile
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot_dir_not_exist.xml"));

        //A huge catalog update to test size limits
        config = new LocalCluster("catalogupdate-cluster-huge.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        long t = System.currentTimeMillis();
        String hugeSchemaURL = generateRandomDDL("catalogupdate-cluster-huge",
                                                  HUGE_TABLES, HUGE_COLUMNS, HUGE_NAME_SIZE);
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addSchema(hugeSchemaURL);
        project.addProcedures(BASEPROCS);
        compile = config.compile(project);
        assertTrue(compile);
        hugeCompileElapsed = (System.currentTimeMillis() - t) / 1000.0;
        hugeCatalogXMLPath = Configuration.getPathToCatalogForTest("catalogupdate-cluster-huge.xml");
        hugeCatalogJarPath = Configuration.getPathToCatalogForTest("catalogupdate-cluster-huge.jar");
        MiscUtils.copyFile(project.getPathToDeployment(), hugeCatalogXMLPath);

        config = new LocalCluster("catalogupdate-cluster-change_snapshot_dir_not_exist.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.addDefaultPartitioning();
        project.addProcedures(BASEPROCS);
        project.setSnapshotSettings( "1s", 3, "/tmp/snapshotdirasda2", "foo2");
        // build the jarfile
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-change_snapshot_dir_not_exist.xml"));

        // Catalogs with different system settings on query time out
        config = new LocalCluster("catalogupdate-cluster-timeout-1000.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.setQueryTimeout(1000);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-1000.xml"));

        config = new LocalCluster("catalogupdate-cluster-timeout-5000.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.setQueryTimeout(5000);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-5000.xml"));

        config = new LocalCluster("catalogupdate-cluster-timeout-600.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        project.setQueryTimeout(600);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-timeout-600.xml"));

        // elastic duration and throughput catalog update tests
        config = new LocalCluster("catalogupdate-cluster-elastic-100-5.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI);
        project = new TPCCProjectBuilder();
        project.addDefaultSchema();
        // build the jarfile
        project.setElasticDuration(100);
        project.setElasticThroughput(5);
        compile = config.compile(project);
        assertTrue(compile);
        MiscUtils.copyFile(project.getPathToDeployment(), Configuration.getPathToCatalogForTest("catalogupdate-cluster-elastic-100-5.xml"));


        return builder;
    }

    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        assertTrue(callbackSuccess);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
        callbackSuccess = true;
    }
}
TOP

Related Classes of org.voltdb.regressionsuites.TestCatalogUpdateSuite

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.