diff --git a/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java b/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
index c3c9b52dac..bfc7d7bb1b 100644
--- a/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
+++ b/tajo-cluster-tests/src/test/java/org/apache/tajo/QueryTestCaseBase.java
@@ -18,6 +18,9 @@
package org.apache.tajo;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
import com.google.protobuf.ServiceException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -29,7 +32,7 @@
import org.apache.tajo.catalog.CatalogService;
import org.apache.tajo.catalog.CatalogUtil;
import org.apache.tajo.catalog.TableDesc;
-import org.apache.tajo.exception.UndefinedTableException;
+import org.apache.tajo.cli.tsql.InvalidStatementException;
import org.apache.tajo.cli.tsql.ParsedResult;
import org.apache.tajo.cli.tsql.SimpleParser;
import org.apache.tajo.client.TajoClient;
@@ -37,6 +40,7 @@
import org.apache.tajo.engine.parser.SQLAnalyzer;
import org.apache.tajo.engine.query.QueryContext;
import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.exception.UndefinedTableException;
import org.apache.tajo.master.GlobalEngine;
import org.apache.tajo.plan.LogicalOptimizer;
import org.apache.tajo.plan.LogicalPlan;
@@ -80,7 +84,10 @@
*
*
src/test/resources/queries - This is the query directory. It contains sub directories, each of which
* corresponds each test class. All query files in each sub directory can be used in the corresponding test
- * class.
+ * class. This directory also can include positive and negative directories, each
+ * of which include multiple files containing multiple queries. They are used by runPositiveTests() and
+ * runNegativeTests(), which test just successfully completed and failed respectively
+ * without compararing query results.
*
* src/test/resources/results - This is the result directory. It contains sub directories, each of which
* corresponds each test class. All result files in each sub directory can be used in the corresponding test class.
@@ -100,6 +107,10 @@
* |
* |- queries
* | |- TestJoinQuery
+ * | |- positive
+ * | |- valid_join_conditions.sql
+ * | |- negative
+ * | |- invalid_join_conditions.sql
* | |- TestInnerJoin.sql
* | |- table1_ddl.sql
* | |- table2_ddl.sql
@@ -464,6 +475,62 @@ public DummyOption(boolean explain, boolean withExplainGlobal, boolean parameter
public boolean sort() { return sort;}
}
+ protected Collection getBatchQueries(Collection paths) throws IOException, InvalidStatementException {
+ List queries = Lists.newArrayList();
+
+ for (Path p : paths) {
+ for (ParsedResult statement: SimpleParser.parseScript(FileUtil.readTextFile(new File(p.toUri())))) {
+ queries.add(statement.getStatement());
+ }
+ }
+
+ return queries;
+ }
+
+ /**
+ * Run all positive tests
+ *
+ * @throws Exception
+ */
+ protected void runPositiveTests() throws Exception {
+ Collection queries = getBatchQueries(getPositiveQueryFiles());
+
+ ResultSet result = null;
+ for (String query: queries) {
+ try {
+ result = client.executeQueryAndGetResult(query);
+ } catch (TajoException e) {
+ fail("Positive Test Failed: " + e.getMessage());
+ } finally {
+ if (result != null) {
+ result.close();
+ }
+ }
+ }
+ }
+
+ /**
+ * Run all negative tests
+ *
+ * @throws Exception
+ */
+ protected void runNegativeTests() throws Exception {
+ Collection queries = getBatchQueries(getNegativeQueryFiles());
+
+ ResultSet result = null;
+ for (String query: queries) {
+ try {
+ result = client.executeQueryAndGetResult(query);
+ fail("Negative Test Failed: " + query);
+ } catch (TajoException e) {
+ } finally {
+ if (result != null) {
+ result.close();
+ }
+ }
+ }
+ }
+
protected void runSimpleTests() throws Exception {
String methodName = getMethodName();
Method method = current.getTestClass().getMethod(methodName);
@@ -771,6 +838,38 @@ private void verifyResultText(String message, ResultSet res, Path resultFile) th
assertEquals(message, expectedResult.trim(), actualResult.trim());
}
+ private Collection getPositiveQueryFiles() throws IOException {
+ Path positiveQueryDir = StorageUtil.concatPath(currentQueryPath, "positive");
+ FileSystem fs = currentQueryPath.getFileSystem(testBase.getTestingCluster().getConfiguration());
+
+ if (!fs.exists(positiveQueryDir)) {
+ throw new IOException("Cannot find " + positiveQueryDir);
+ }
+
+ return Collections2.transform(Lists.newArrayList(fs.listStatus(positiveQueryDir)), new Function(){
+ @Override
+ public Path apply(@Nullable FileStatus fileStatus) {
+ return fileStatus.getPath();
+ }
+ });
+ }
+
+ private Collection getNegativeQueryFiles() throws IOException {
+ Path positiveQueryDir = StorageUtil.concatPath(currentQueryPath, "nagative");
+ FileSystem fs = currentQueryPath.getFileSystem(testBase.getTestingCluster().getConfiguration());
+
+ if (!fs.exists(positiveQueryDir)) {
+ throw new IOException("Cannot find " + positiveQueryDir);
+ }
+
+ return Collections2.transform(Lists.newArrayList(fs.listStatus(positiveQueryDir)),new Function(){
+ @Override
+ public Path apply(@Nullable FileStatus fileStatus) {
+ return fileStatus.getPath();
+ }
+ });
+ }
+
private Path getQueryFilePath(String fileName) throws IOException {
Path queryFilePath = StorageUtil.concatPath(currentQueryPath, fileName);
FileSystem fs = currentQueryPath.getFileSystem(testBase.getTestingCluster().getConfiguration());
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
index 27c2fcd25f..0fd6fcf2dc 100644
--- a/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
@@ -54,6 +54,16 @@ public TestSelectQuery() {
super(TajoConstants.DEFAULT_DATABASE_NAME);
}
+ @Test
+ public final void testPositives() throws Exception {
+ runPositiveTests();
+ }
+
+ @Test
+ public final void testNegatives() throws Exception {
+ runNegativeTests();
+ }
+
@Test
public final void testNonQualifiedNames() throws Exception {
// select l_orderkey, l_partkey from lineitem;
diff --git a/tajo-core-tests/src/test/resources/queries/TestSelectQuery/nagative/operations.sql b/tajo-core-tests/src/test/resources/queries/TestSelectQuery/nagative/operations.sql
new file mode 100644
index 0000000000..0a0ed7554f
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSelectQuery/nagative/operations.sql
@@ -0,0 +1 @@
+select 1 + col1;
\ No newline at end of file
diff --git a/tajo-core-tests/src/test/resources/queries/TestSelectQuery/nagative/tables.sql b/tajo-core-tests/src/test/resources/queries/TestSelectQuery/nagative/tables.sql
new file mode 100644
index 0000000000..17d040370e
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSelectQuery/nagative/tables.sql
@@ -0,0 +1 @@
+select * from lineite;
\ No newline at end of file
diff --git a/tajo-core-tests/src/test/resources/queries/TestSelectQuery/positive/operations.sql b/tajo-core-tests/src/test/resources/queries/TestSelectQuery/positive/operations.sql
new file mode 100644
index 0000000000..5c00f4e48a
--- /dev/null
+++ b/tajo-core-tests/src/test/resources/queries/TestSelectQuery/positive/operations.sql
@@ -0,0 +1 @@
+select 1 + 2;
\ No newline at end of file