/* This file is part of VoltDB. * Copyright (C) 2008-2017 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.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Set; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertTrue; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.voltdb.BackendTarget; import org.voltdb.SQLStmt; import org.voltdb.VoltTable; import org.voltdb.client.Client; import org.voltdb.utils.MiscUtils; import org.voltdb.ServerThread; import org.voltdb.VoltDB; import org.voltdb.VoltDB.Configuration; import org.voltdb.VoltProcedure; import org.voltdb.client.ClientFactory; import org.voltdb.client.ClientResponse; import org.voltdb.client.NoConnectionsException; import org.voltdb.client.ProcCallException; import org.voltdb.compiler.VoltCompiler; import org.voltdb.compiler.VoltProjectBuilder; import org.voltdb.compiler.deploymentfile.DeploymentType; import org.voltdb.utils.CatalogUtil; import org.voltdb.utils.InMemoryJarfile; /** * Test LocalCluster startup with one in process and other out of process. * */ public class TestInitStartLocalClusterInProcess extends JUnit4LocalClusterTest { static final int SITES_PER_HOST = 8; static final int HOSTS = 3; static final int K = MiscUtils.isPro() ? 1 : 0; VoltProjectBuilder builder; LocalCluster cluster; String listener; Client client; String voltDbRootPath; String voltDBRootParentPath; @Before public void setUp() throws Exception { String simpleSchema = "create table blah (" + "ival bigint default 0 not null, " + "PRIMARY KEY(ival));"; builder = new VoltProjectBuilder(); builder.setUseDDLSchema(true); builder.addLiteralSchema(simpleSchema); cluster = new LocalCluster("collect.jar", SITES_PER_HOST, HOSTS, K, BackendTarget.NATIVE_EE_JNI); boolean success = cluster.compile(builder); assert (success); File voltDbRoot; cluster.startUp(true); //Get server specific root after startup. if (cluster.isNewCli()) { voltDbRoot = new File(cluster.getServerSpecificRoot("1")); } else { String voltDbFilePrefix = cluster.getSubRoots().get(0).getPath(); voltDbRoot = new File(voltDbFilePrefix, builder.getPathToVoltRoot().getPath()); } voltDbRootPath = voltDbRoot.getCanonicalPath(); voltDBRootParentPath = voltDbRoot.getParentFile().getCanonicalPath(); listener = cluster.getListenerAddresses().get(0); client = ClientFactory.createClient(); client.createConnection(listener); } @After public void tearDown() throws Exception { client.close(); cluster.shutDown(); } @Test public void testClusterUp() throws Exception { boolean found = false; int timeout = -1; VoltTable result = client.callProcedure("@SystemInformation", "DEPLOYMENT").getResults()[0]; while (result.advanceRow()) { if (result.getString("PROPERTY").equalsIgnoreCase("heartbeattimeout")) { found = true; timeout = Integer.valueOf(result.getString("VALUE")); } } assertTrue(found); assertEquals(org.voltcore.common.Constants.DEFAULT_HEARTBEAT_TIMEOUT_SECONDS, timeout); if (!cluster.isNewCli()) { // get command is not supported in legacy cli as voltdbroot // under the parent can't be determined deterministically // using voltdbroot as the root of database directory return; } testGetDeployment(); testGetSchema(); testGetClasses(); } // Test get deployment public void testGetDeployment() throws Exception { File deployment = File.createTempFile("get_deployment", ".xm"); Configuration config = new VoltDB.Configuration(new String[]{"get", "deployment", "getvoltdbroot", voltDBRootParentPath, "file", deployment.getAbsolutePath() + "l", "forceget"}); ServerThread server = new ServerThread(config); try { server.cli(); } catch (Throwable ex) { //Good } DeploymentType dt = CatalogUtil.parseDeployment(deployment.getAbsolutePath() + "l"); assertNotNull(dt); assertEquals(dt.getPaths().getVoltdbroot().getPath(), voltDbRootPath); } // Test get schema public void testGetSchema() throws Exception { File schema = File.createTempFile("schema", ".sql"); Configuration config = new VoltDB.Configuration(new String[]{"get", "schema", "getvoltdbroot", voltDBRootParentPath, "file", schema.getAbsolutePath(), "forceget"}); ServerThread server = new ServerThread(config); try { server.cli(); } catch (Throwable ex) { //Good } byte[] encoded = Files.readAllBytes(Paths.get(schema.getAbsolutePath())); assertNotNull(encoded); assertTrue(encoded.length > 0); String ddl = new String(encoded, StandardCharsets.UTF_8); assertTrue(ddl.toLowerCase().contains("create table blah (")); assertTrue(ddl.toLowerCase().contains("ival bigint default '0' not null")); assertTrue(ddl.toLowerCase().contains("primary key (ival)")); } class RangeCount extends VoltProcedure { SQLStmt sql = new SQLStmt("select count(*) from blah where ival > ? and ival < ?;"); public VoltTable[] run(long value1, long value2) { voltQueueSQL(sql, value1, value2); return voltExecuteSQL(true); } } void loadAndAddProcs() throws IOException, NoConnectionsException { ClientResponse resp = null; long numberOfClasses = 0; try { resp = client.callProcedure("@SystemCatalog", "CLASSES"); } catch (ProcCallException excp) { assert false : "@SystemCatalogClasses failed"; } numberOfClasses = resp.getResults()[0].getRowCount(); InMemoryJarfile jarfile = new InMemoryJarfile(); VoltCompiler comp = new VoltCompiler(false); try { comp.addClassToJar(jarfile, org.voltdb_testprocs.updateclasses.testImportProc.class); comp.addClassToJar(jarfile, org.voltdb_testprocs.updateclasses.testCreateProcFromClassProc.class); comp.addClassToJar(jarfile, org.voltdb_testprocs.updateclasses.InnerClassesTestProc.class); comp.addClassToJar(jarfile, RangeCount.class); } catch (Exception e) { assert false : "Failed add class to jar: " + e.getMessage(); } try { client.callProcedure("@UpdateClasses", jarfile.getFullJarBytes(), null); } catch (ProcCallException excp) { assert false : "Failed updating the class"; } try { resp = client.callProcedure("@SystemCatalog", "CLASSES"); } catch (ProcCallException excp) { assert false : "@SystemCatalogClasses failed"; } assertTrue( (numberOfClasses + jarfile.getLoader().getClassNames().size()) == resp.getResults()[0].getRowCount()); } InMemoryJarfile getProcJarFromCatalog() throws IOException { File jar = File.createTempFile("procedure", ".jar"); Configuration config = new VoltDB.Configuration(new String[]{"get", "classes", "getvoltdbroot", voltDBRootParentPath, "file", jar.getAbsolutePath(), "forceget"}); ServerThread server = new ServerThread(config); try { server.cli(); } catch (Throwable ex) { //Good } byte[] bytesRead = Files.readAllBytes(Paths.get(jar.getAbsolutePath())); assertNotNull(bytesRead); assertTrue(bytesRead.length > 0); return new InMemoryJarfile(bytesRead); } static boolean anyCatalogDefaultArtifactsExists(InMemoryJarfile jarFile) { Set<String> files = jarFile.keySet(); // if empty, none if (files.size() == 0) return false; for (String artifacts : CatalogUtil.CATALOG_DEFAULT_ARTIFACTS) { if (files.contains(artifacts)) return true; } return false; } public void testGetClasses() throws IOException { InMemoryJarfile jarFile = getProcJarFromCatalog(); assertTrue(!anyCatalogDefaultArtifactsExists(jarFile)); org.voltdb.client.ClientResponse resp = null; // No java stored proc at this time, will give jar with no classes try { resp = client.callProcedure("@SystemCatalog", "CLASSES"); } catch (ProcCallException excp) { assert false : "@SystemCatalogClasses failed"; } assertTrue(jarFile.getLoader().getClassNames().size() == resp.getResults()[0].getRowCount()); // load java stored proc classes and verify the retrieved classes count loadAndAddProcs(); jarFile = getProcJarFromCatalog(); assertTrue(!anyCatalogDefaultArtifactsExists(jarFile)); try { resp = client.callProcedure("@SystemCatalog", "CLASSES"); } catch (ProcCallException excp) { assert false : "@SystemCatalogClasses failed"; } assertTrue(jarFile.getLoader().getClassNames().size() == resp.getResults()[0].getRowCount()); } }