blob: f2df365f70104f5546f0ce39ff5c7d1468c60e9f [file] [log] [blame]
package edu.uci.ics.asterix.test.metadata;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Logger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import edu.uci.ics.asterix.api.common.AsterixHyracksIntegrationUtil;
import edu.uci.ics.asterix.api.java.AsterixJavaClient;
import edu.uci.ics.asterix.common.config.GlobalConfig;
import edu.uci.ics.asterix.test.aql.TestsUtils;
@RunWith(Parameterized.class)
public class MetadataTransactionsTest {
private static final Logger LOGGER = Logger.getLogger(MetadataTransactionsTest.class.getName());
private static final PrintWriter ERR = new PrintWriter(System.err);
private static final String EXTENSION_QUERY = "aql";
private static final String EXTENSION_RESULT = "adm";
private static final String PATH_ACTUAL = "rttest/";
private static final String PATH_BASE = "src/test/resources/metadata-transactions/";
private static final String CHECK_STATE_QUERIES_PATH = PATH_BASE + "check-state-queries/";
private static final String CHECK_STATE_RESULTS_PATH = PATH_BASE + "check-state-results/";
private static final String CHECK_STATE_FILE = PATH_BASE + "check-state-queries.txt";
private static final String INIT_STATE_QUERIES_PATH = PATH_BASE + "init-state-queries/";
private static final String INIT_STATE_FILE = PATH_BASE + "init-state-queries.txt";
private static final String TEST_QUERIES_PATH = PATH_BASE + "queries/";
private static final String QUERIES_FILE = PATH_BASE + "queries.txt";
private static String _oldConfigFileName;
private static final String TEST_CONFIG_FILE_NAME = "asterix-metadata.properties";
private static final String[] ASTERIX_DATA_DIRS = new String[] { "nc1data", "nc2data" };
private static String aqlExtToResExt(String fname) {
int dot = fname.lastIndexOf('.');
return fname.substring(0, dot + 1) + EXTENSION_RESULT;
}
private static void executeQueryTuple(Object[] queryTuple, boolean expectFailure, boolean executeQuery) {
String queryFileName = (String) queryTuple[0];
String expectedFileName = (String) queryTuple[1];
String actualFileName = (String) queryTuple[2];
try {
Reader query = new BufferedReader(new InputStreamReader(new FileInputStream(queryFileName), "UTF-8"));
AsterixJavaClient asterix = new AsterixJavaClient(
AsterixHyracksIntegrationUtil.getHyracksClientConnection(), query, ERR);
LOGGER.info("Query is: " + queryFileName);
try {
asterix.compile(true, false, false, false, false, executeQuery, false);
} finally {
query.close();
}
// We don't want to execute a query if we expect only DDL
// modifications.
if (executeQuery) {
asterix.execute();
}
query.close();
} catch (Exception e) {
if (!expectFailure) {
fail("Unexpected failure of AQL query in file: " + queryFileName + "\n" + e.getMessage());
}
return;
}
// Do we expect failure?
if (expectFailure) {
fail("Unexpected success of AQL query in file: " + queryFileName);
}
// If no expected or actual file names were given, then we don't want to
// compare them.
if (expectedFileName == null || actualFileName == null) {
return;
}
// Compare actual and expected results.
try {
File actualFile = new File(actualFileName);
File expectedFile = new File(expectedFileName);
if (actualFile.exists() && false) {
BufferedReader readerExpected = new BufferedReader(new InputStreamReader(new FileInputStream(
expectedFile), "UTF-8"));
BufferedReader readerActual = new BufferedReader(new InputStreamReader(new FileInputStream(actualFile),
"UTF-8"));
String lineExpected, lineActual;
int num = 1;
try {
while ((lineExpected = readerExpected.readLine()) != null) {
lineActual = readerActual.readLine();
if (lineActual == null) {
fail("Result for " + queryFileName + " changed at line " + num + ":\n< " + lineExpected
+ "\n> ");
}
if (!lineExpected.split("Timestamp")[0].equals(lineActual.split("Timestamp")[0])) {
fail("Result for " + queryFileName + " changed at line " + num + ":\n< " + lineExpected
+ "\n> " + lineActual);
}
++num;
}
lineActual = readerActual.readLine();
if (lineActual != null) {
fail("Result for " + queryFileName + " changed at line " + num + ":\n< \n> " + lineActual);
}
// actualFile.delete();
} finally {
readerExpected.close();
readerActual.close();
}
}
} catch (Exception e) {
fail("Execption occurred while comparing expected and actual results: " + e.getMessage());
}
}
// Collection of object arrays. Each object array contains exactly 3 string
// elements:
// 1. String QueryFile
// 2. String expectedFile
// 3. String actualFile
private static Collection<Object[]> checkQuerySuite = new ArrayList<Object[]>();
private static void checkMetadataState() {
for (Object[] checkTuple : checkQuerySuite) {
executeQueryTuple(checkTuple, false, true);
}
}
@BeforeClass
public static void setUp() throws Exception {
_oldConfigFileName = System.getProperty(GlobalConfig.CONFIG_FILE_PROPERTY);
System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, TEST_CONFIG_FILE_NAME);
File outdir = new File(PATH_ACTUAL);
outdir.mkdirs();
AsterixHyracksIntegrationUtil.init();
// Create initial metadata state by adding the customers and orders
// metadata.
Collection<Object[]> initQuerySuite = new ArrayList<Object[]>();
prepareQuerySuite(INIT_STATE_FILE, INIT_STATE_QUERIES_PATH, null, null, initQuerySuite);
for (Object[] queryTuple : initQuerySuite) {
executeQueryTuple(queryTuple, false, false);
}
// Prepare the query suite for checking the metadata state is still
// correct.
prepareQuerySuite(CHECK_STATE_FILE, CHECK_STATE_QUERIES_PATH, CHECK_STATE_RESULTS_PATH, PATH_ACTUAL,
checkQuerySuite);
// Make sure the initial metadata state is set up correctly.
checkMetadataState();
}
@AfterClass
public static void tearDown() throws Exception {
// _bootstrap.stop();
AsterixHyracksIntegrationUtil.deinit();
File outdir = new File(PATH_ACTUAL);
File[] files = outdir.listFiles();
if (files == null || files.length == 0) {
// outdir.delete();
}
if (_oldConfigFileName != null) {
System.setProperty(GlobalConfig.CONFIG_FILE_PROPERTY, _oldConfigFileName);
}
// clean up the files written by the ASTERIX storage manager
for (String d : ASTERIX_DATA_DIRS) {
TestsUtils.deleteRec(new File(d));
}
}
private static void prepareQuerySuite(String queryListPath, String queryPath, String expectedPath,
String actualPath, Collection<Object[]> output) throws IOException {
BufferedReader br = null;
try {
File queryListFile = new File(queryListPath);
br = new BufferedReader(new InputStreamReader(new FileInputStream(queryListFile), "UTF-8"));
String strLine;
String queryFileName;
File queryFile;
while ((strLine = br.readLine()) != null) {
// Ignore commented test files.
if (strLine.startsWith("//")) {
continue;
}
queryFileName = queryPath + strLine;
queryFile = new File(queryPath + strLine);
// If no expected or actual path was given, just add the
// queryFile.
if (expectedPath == null || actualPath == null) {
output.add(new Object[] { queryFileName, null, null });
continue;
}
// We want to compare expected and actual results. Construct the
// expected and actual files.
if (queryFile.getName().endsWith(EXTENSION_QUERY)) {
String resultFileName = aqlExtToResExt(queryFile.getName());
String expectedFileName = expectedPath + resultFileName;
String actualFileName = actualPath + resultFileName;
output.add(new Object[] { queryFileName, expectedFileName, actualFileName });
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
br.close();
}
}
}
@Parameters
public static Collection<Object[]> tests() throws IOException {
Collection<Object[]> testArgs = new ArrayList<Object[]>();
prepareQuerySuite(QUERIES_FILE, TEST_QUERIES_PATH, null, null, testArgs);
return testArgs;
}
private String actualFileName;
private String expectedFileName;
private String queryFileName;
public MetadataTransactionsTest(String queryFileName, String expectedFileName, String actualFileName) {
this.queryFileName = queryFileName;
this.expectedFileName = expectedFileName;
this.actualFileName = actualFileName;
}
@Test
public void test() throws Exception {
// Re-create query tuple.
Object[] queryTuple = new Object[] { queryFileName, expectedFileName, actualFileName };
// Execute query tuple, expecting failure.
executeQueryTuple(queryTuple, true, false);
// Validate metadata state after failed query above.
checkMetadataState();
}
}