/* 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.voltdb.benchmark.tpcc.TPCCProjectBuilder;
import org.voltdb.catalog.Catalog;
import org.voltdb.compiler.VoltProjectBuilder.RoleInfo;
import org.voltdb.compiler.VoltProjectBuilder.UserInfo;
import org.voltdb.utils.BuildDirectoryUtils;
import org.voltdb.utils.CatalogUtil;
import org.voltdb.utils.MiscUtils;
final public class TestVoltDB {
@BeforeClass
public static void setupClass() throws Exception {
System.setProperty("VOLT_JUSTATEST", "YESYESYES");
}
@Before
public void setup() {
VoltDB.ignoreCrash = true;
}
@Rule
public final TemporaryFolder tmp = new TemporaryFolder();
@Test
public void testConfigurationConstructor() {
VoltDB.Configuration blankConfig = new VoltDB.Configuration();
assertFalse(blankConfig.m_noLoadLibVOLTDB);
assertEquals(BackendTarget.NATIVE_EE_JNI, blankConfig.m_backend);
assertEquals(null, blankConfig.m_pathToCatalog);
assertEquals(null, blankConfig.m_pathToDeployment);
assertEquals(VoltDB.DEFAULT_PORT, blankConfig.m_port);
String args1[] = { "create", "noloadlib" };
assertTrue(new VoltDB.Configuration(args1).m_noLoadLibVOLTDB);
String args2[] = { "create", "hsqldb" };
VoltDB.Configuration cfg2 = new VoltDB.Configuration(args2);
assertEquals(BackendTarget.HSQLDB_BACKEND, cfg2.m_backend);
String args3[] = { "create", "jni" };
VoltDB.Configuration cfg3 = new VoltDB.Configuration(args3);
assertEquals(BackendTarget.NATIVE_EE_JNI, cfg3.m_backend);
String args4[] = { "create", "ipc" };
VoltDB.Configuration cfg4 = new VoltDB.Configuration(args4);
assertEquals(BackendTarget.NATIVE_EE_IPC, cfg4.m_backend);
// what happens if arguments conflict?
String args5[] = { "create", "ipc", "hsqldb" };
VoltDB.Configuration cfg5 = new VoltDB.Configuration(args5);
assertEquals(BackendTarget.HSQLDB_BACKEND, cfg5.m_backend);
String args9[] = { "create", "catalog xtestxstringx" };
VoltDB.Configuration cfg9 = new VoltDB.Configuration(args9);
assertEquals("xtestxstringx", cfg9.m_pathToCatalog);
String args10[] = { "create", "catalog", "ytestystringy" };
VoltDB.Configuration cfg10 = new VoltDB.Configuration(args10);
assertEquals("ytestystringy", cfg10.m_pathToCatalog);
String args12[] = { "create", "port", "1234" };
VoltDB.Configuration cfg12 = new VoltDB.Configuration(args12);
assertEquals(1234, cfg12.m_port);
String args13[] = { "create", "port", "5678" };
VoltDB.Configuration cfg13 = new VoltDB.Configuration(args13);
assertEquals(5678, cfg13.m_port);
String args14[] = { "create" };
VoltDB.Configuration cfg14 = new VoltDB.Configuration(args14);
assertEquals(StartAction.CREATE, cfg14.m_startAction);
String args15[] = { "recover" };
VoltDB.Configuration cfg15 = new VoltDB.Configuration(args15);
assertEquals(StartAction.RECOVER, cfg15.m_startAction);
String args16[] = { "recover", "safemode" };
VoltDB.Configuration cfg16 = new VoltDB.Configuration(args16);
assertEquals(StartAction.SAFE_RECOVER, cfg16.m_startAction);
// test host:port formats
String args18[] = {"create", "port", "localhost:5678"};
VoltDB.Configuration cfg18 = new VoltDB.Configuration(args18);
assertEquals(5678, cfg18.m_port);
assertEquals("localhost", cfg18.m_clientInterface);
String args19[] = {"create", "adminport", "localhost:5678"};
VoltDB.Configuration cfg19 = new VoltDB.Configuration(args19);
assertEquals(5678, cfg19.m_adminPort);
assertEquals("localhost", cfg19.m_adminInterface);
String args20[] = {"create", "httpport", "localhost:7777"};
VoltDB.Configuration cfg20 = new VoltDB.Configuration(args20);
assertEquals(7777, cfg20.m_httpPort);
assertEquals("localhost", cfg20.m_httpPortInterface);
String args21[] = {"create", "internalport", "localhost:7777"};
VoltDB.Configuration cfg21 = new VoltDB.Configuration(args21);
assertEquals(7777, cfg21.m_internalPort);
assertEquals("localhost", cfg21.m_internalInterface);
//with override
String args22[] = {"create", "internalinterface", "xxxxxx", "internalport", "localhost:7777"};
VoltDB.Configuration cfg22 = new VoltDB.Configuration(args22);
assertEquals(7777, cfg22.m_internalPort);
assertEquals("localhost", cfg22.m_internalInterface);
// XXX don't test what happens if port is invalid, because the code
// doesn't handle that
}
@Test
public void testConfigurationValidate() throws Exception {
VoltDB.Configuration config;
// missing leader provided deployment - not okay.
String[] argsya = {"create", "catalog", "qwerty", "deployment", "qwerty"};
config = new VoltDB.Configuration(argsya);
assertFalse(config.validate());
// missing deployment (it's okay now that a default deployment is supported)
String[] args3 = {"create", "host", "hola", "catalog", "teststring2"};
config = new VoltDB.Configuration(args3);
assertTrue(config.validate());
// default deployment with default leader -- okay.
config = new VoltDB.Configuration(new String[]{"create", "catalog", "catalog.jar"});
assertTrue(config.validate());
// empty leader -- tests could pass in empty leader to indicate bind to all interfaces on mac
String[] argsyo = {"create", "host", "", "catalog", "sdfs", "deployment", "sdfsd"};
config = new VoltDB.Configuration(argsyo);
assertTrue(config.validate());
// empty deployment
String[] args6 = {"create", "host", "hola", "catalog", "teststring6", "deployment", ""};
config = new VoltDB.Configuration(args6);
assertFalse(config.validate());
// replica with explicit create
String[] args8 = {"host", "hola", "deployment", "teststring4", "catalog", "catalog.jar", "create"};
config = new VoltDB.Configuration(args8);
assertTrue(config.validate());
// valid config
String[] args10 = {"create", "leader", "localhost", "deployment", "te", "catalog", "catalog.jar"};
config = new VoltDB.Configuration(args10);
assertTrue(config.validate());
// valid config
String[] args100 = {"create", "host", "hola", "deployment", "teststring4", "catalog", "catalog.jar"};
config = new VoltDB.Configuration(args100);
assertTrue(config.validate());
// valid rejoin config
String[] args200 = {"rejoin", "host", "localhost"};
config = new VoltDB.Configuration(args200);
assertEquals(config.validate(), MiscUtils.isPro());
// invalid rejoin config, missing rejoin host
String[] args250 = {"rejoin"};
config = new VoltDB.Configuration(args250);
assertFalse(config.validate()); // false in both pro and community
// rejoinhost should still work
String[] args201 = {"rejoinhost", "localhost"};
config = new VoltDB.Configuration(args201);
assertEquals(config.validate(), MiscUtils.isPro());
// valid rejoin config
String[] args300 = {"live", "rejoin", "host", "localhost"};
config = new VoltDB.Configuration(args300);
assertEquals(MiscUtils.isPro(), config.validate());
assertEquals(StartAction.LIVE_REJOIN, config.m_startAction);
}
AtomicReference<Throwable> serverException = new AtomicReference<>(null);
final Thread.UncaughtExceptionHandler handleUncaught = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
serverException.compareAndSet(null, e);
}
};
@Test
public void testHostCountValidations() throws Exception {
final File path = tmp.newFolder();
String [] init = {"initialize", "voltdbroot", path.getPath()};
VoltDB.Configuration config = new VoltDB.Configuration(init);
assertTrue(config.validate()); // false in both pro and community]
ServerThread server = new ServerThread(config);
server.setUncaughtExceptionHandler(handleUncaught);
server.start();
server.join();
// invalid host count
String [] args400 = {"probe", "voltdbroot", path.getPath(), "hostcount", "2", "mesh", "uno,", "due", ",","tre", ",quattro" };
config = new VoltDB.Configuration(args400);
assertFalse(config.validate()); // false in both pro and community
String [] args401 = {"probe", "voltdbroot", path.getPath(), "hostcount", "-3" , "mesh", "uno,", "due", ",","tre", ",quattro"};
config = new VoltDB.Configuration(args401);
assertFalse(config.validate()); // false in both pro and community
String [] args402 = {"probe", "voltdbroot", path.getPath(), "hostcount", "4" , "mesh", "uno,", "due", ",","tre", ",quattro"};
config = new VoltDB.Configuration(args402);
assertTrue(config.validate()); // false in both pro and community
String [] args403 = {"probe", "voltdbroot", path.getPath(), "hostcount", "6" , "mesh", "uno,", "due", ",","tre", ",quattro"};
config = new VoltDB.Configuration(args403);
assertTrue(config.validate()); // false in both pro and community
String [] args404 = {"probe", "voltdbroot", path.getPath(), "mesh", "uno,", "due", ",","tre", ",quattro"};
config = new VoltDB.Configuration(args404);
assertTrue(config.validate()); // false in both pro and community
assertEquals(4, config.m_hostCount);
}
/**
* ENG-7088: Validate that deployment file users that want to belong to roles which
* don't yet exist don't render the deployment file invalid.
*/
@Test
public void testCompileDeploymentAddUserToNonExistentGroup() throws IOException {
TPCCProjectBuilder project = new TPCCProjectBuilder();
project.addDefaultSchema();
project.addDefaultPartitioning();
project.addDefaultProcedures();
project.setSecurityEnabled(true, true);
RoleInfo groups[] = new RoleInfo[] {
new RoleInfo("foo", false, false, false, false, false, false),
new RoleInfo("blah", false, false, false, false, false, false)
};
project.addRoles(groups);
UserInfo users[] = new UserInfo[] {
new UserInfo("john", "hugg", new String[] {"foo"}),
new UserInfo("ryan", "betts", new String[] {"foo", "bar"}),
new UserInfo("ariel", "weisberg", new String[] {"bar"})
};
project.addUsers(users);
String testDir = BuildDirectoryUtils.getBuildDirectoryPath();
String jarName = "compile-deployment.jar";
String catalogJar = testDir + File.separator + jarName;
assertTrue("Project failed to compile", project.compile(catalogJar));
byte[] bytes = MiscUtils.fileToBytes(new File(catalogJar));
String serializedCatalog = CatalogUtil.getSerializedCatalogStringFromJar(CatalogUtil.loadAndUpgradeCatalogFromJar(bytes, false).getFirst());
assertNotNull("Error loading catalog from jar", serializedCatalog);
Catalog catalog = new Catalog();
catalog.execute(serializedCatalog);
// this should succeed even though group "bar" does not exist
assertTrue("Deployment file should have been able to validate",
CatalogUtil.compileDeployment(catalog, project.getPathToDeployment(), true) == null);
}
}