You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2015/08/14 16:30:27 UTC

[48/51] [partial] tajo git commit: TAJO-1761: Separate an integration unit test kit into an independent module.

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestSimpleParser.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestSimpleParser.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestSimpleParser.java
new file mode 100644
index 0000000..69bf30a
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestSimpleParser.java
@@ -0,0 +1,286 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli.tsql;
+
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestSimpleParser {
+
+  @Test
+  public final void testSpecialCases() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("");
+    assertEquals(0, res1.size());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("a");
+    assertEquals(1, res2.size());
+
+    List<ParsedResult> res3 = SimpleParser.parseScript("?");
+    assertEquals(0, res3.size());
+
+    List<ParsedResult> res4 = SimpleParser.parseScript("\\");
+    assertEquals(1, res4.size());
+  }
+
+  @Test
+  public final void testMetaCommands() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("\\d");
+    assertEquals(1, res1.size());
+    assertEquals(ParsedResult.StatementType.META, res1.get(0).getType());
+    assertEquals("\\d", res1.get(0).getHistoryStatement());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("\\d;\\c;\\f;");
+    assertEquals(3, res2.size());
+    assertEquals(ParsedResult.StatementType.META, res2.get(0).getType());
+    assertEquals("\\d", res2.get(0).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.META, res2.get(1).getType());
+    assertEquals("\\c", res2.get(1).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.META, res2.get(2).getType());
+    assertEquals("\\f", res2.get(2).getHistoryStatement());
+
+    List<ParsedResult> res3 = SimpleParser.parseScript("\n\t\t  \\d;\n\\c;\t\t\\f  ;");
+    assertEquals(3, res3.size());
+    assertEquals(ParsedResult.StatementType.META, res3.get(0).getType());
+    assertEquals("\\d", res3.get(0).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.META, res3.get(1).getType());
+    assertEquals("\\c", res3.get(1).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.META, res3.get(2).getType());
+    assertEquals("\\f", res3.get(2).getHistoryStatement());
+
+    List<ParsedResult> res4 = SimpleParser.parseScript("\\\td;");
+    assertEquals(1, res4.size());
+    assertEquals("\\\td", res4.get(0).getHistoryStatement());
+  }
+
+  @Test
+  public final void testParseScript() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("select * from test;");
+    assertEquals(1, res1.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res1.get(0).getType());
+    assertEquals("select * from test", res1.get(0).getStatement());
+    assertEquals("select * from test", res1.get(0).getHistoryStatement());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("select * from test;");
+    assertEquals(1, res2.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res2.get(0).getType());
+    assertEquals("select * from test", res2.get(0).getStatement());
+    assertEquals("select * from test", res2.get(0).getHistoryStatement());
+
+    List<ParsedResult> res3 = SimpleParser.parseScript("select * from test1;select * from test2;");
+    assertEquals(2, res3.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res3.get(0).getType());
+    assertEquals("select * from test1", res3.get(0).getStatement());
+    assertEquals("select * from test1", res3.get(0).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res3.get(1).getType());
+    assertEquals("select * from test2", res3.get(1).getStatement());
+    assertEquals("select * from test2", res3.get(1).getHistoryStatement());
+
+    List<ParsedResult> res4 = SimpleParser.parseScript("\t\t\n\rselect * from \ntest1;select * from test2\n;");
+    assertEquals(2, res4.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res4.get(0).getType());
+    assertEquals("select * from \ntest1", res4.get(0).getStatement());
+    assertEquals("select * from test1", res4.get(0).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res4.get(1).getType());
+    assertEquals("select * from test2", res4.get(1).getStatement());
+    assertEquals("select * from test2", res4.get(1).getHistoryStatement());
+
+    List<ParsedResult> res5 =
+        SimpleParser.parseScript("\t\t\n\rselect * from \ntest1;\\d test;select * from test2;\n\nselect 1;");
+    assertEquals(4, res5.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res5.get(0).getType());
+    assertEquals("select * from \ntest1", res5.get(0).getStatement());
+    assertEquals("select * from test1", res5.get(0).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.META, res5.get(1).getType());
+    assertEquals("\\d test", res5.get(1).getStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res5.get(2).getType());
+    assertEquals("select * from test2", res5.get(2).getStatement());
+    assertEquals("select * from test2", res5.get(2).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res5.get(3).getType());
+    assertEquals("select 1", res5.get(3).getStatement());
+    assertEquals("select 1", res5.get(3).getHistoryStatement());
+
+    List<ParsedResult> res6 =
+        SimpleParser.parseScript("select * from \n--test1; select * from test2;\ntest3;");
+    assertEquals(1, res6.size());
+    assertEquals("select * from test3", res6.get(0).getHistoryStatement());
+    assertEquals("select * from \n--test1; select * from test2;\ntest3", res6.get(0).getStatement());
+
+    List<ParsedResult> res7 =
+        SimpleParser.parseScript("select * from --test1; select * from test2;\ntest3;");
+    assertEquals(1, res7.size());
+    assertEquals("select * from test3", res7.get(0).getHistoryStatement());
+    assertEquals("select * from --test1; select * from test2;\ntest3", res7.get(0).getStatement());
+
+    List<ParsedResult> res8 = SimpleParser.parseScript("\\d test\nselect * \n--from test1;\nfrom test2;\\d test2;");
+    assertEquals(3, res8.size());
+    assertEquals(ParsedResult.StatementType.META, res8.get(0).getType());
+    assertEquals("\\d test", res8.get(0).getStatement());
+    assertEquals("\\d test", res8.get(0).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res8.get(1).getType());
+    assertEquals("select * \n--from test1;\nfrom test2", res8.get(1).getStatement());
+    assertEquals("select * from test2", res8.get(1).getHistoryStatement());
+    assertEquals(ParsedResult.StatementType.META, res8.get(2).getType());
+    assertEquals("\\d test2", res8.get(2).getStatement());
+    assertEquals("\\d test2", res8.get(2).getHistoryStatement());
+  }
+
+  @Test
+  public final void testParseLines() throws InvalidStatementException {
+    SimpleParser simpleParser = new SimpleParser();
+    List<ParsedResult> res1 = null;
+
+    res1 = simpleParser.parseLines("select * from test1; select * from test2;");
+    assertEquals(2, res1.size());
+    assertEquals("select * from test1", res1.get(0).getStatement());
+    assertEquals("select * from test2", res1.get(1).getStatement());
+    assertEquals("select * from test1", res1.get(0).getHistoryStatement());
+    assertEquals("select * from test2", res1.get(1).getHistoryStatement());
+
+    // select * from
+    // test1; select * from test2;
+    simpleParser = new SimpleParser();
+    res1 = simpleParser.parseLines("select * from ");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("test1; select * from test2;");
+    assertEquals(2, res1.size());
+    assertEquals("select * from \ntest1", res1.get(0).getStatement());
+    assertEquals("select * from test2", res1.get(1).getStatement());
+    assertEquals("select * from test1", res1.get(0).getHistoryStatement());
+    assertEquals("select * from test2", res1.get(1).getHistoryStatement());
+
+    // select * from
+    // --test1; select * from test2;
+    // test3;
+    simpleParser = new SimpleParser();
+    res1 = simpleParser.parseLines("select * from ");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("--test1; select * from test2;");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("test3;");
+    assertEquals(1, res1.size());
+    assertEquals("select * from test3", res1.get(0).getHistoryStatement());
+    assertEquals("select * from \n--test1; select * from test2;\ntest3", res1.get(0).getStatement());
+
+    // select * from
+    // test1 --select * from test2;
+    // where col1 = '123';
+    simpleParser = new SimpleParser();
+    res1 = simpleParser.parseLines("select * from ");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("test1 --select * from test2;");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("where col1 = '123';");
+    assertEquals(1, res1.size());
+    assertEquals("select * from test1 where col1 = '123'", res1.get(0).getHistoryStatement());
+    assertEquals("select * from \ntest1 --select * from test2;\nwhere col1 = '123'", res1.get(0).getStatement());
+
+    // Case for sql statement already including '\n'
+    // This test is important for tsql because CLI input always has '\n'.
+    simpleParser = new SimpleParser();
+    res1 = simpleParser.parseLines("select\n");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("*\n");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("from\n");
+    assertEquals(0, res1.size());
+    res1 = simpleParser.parseLines("test1;\n");
+    assertEquals(1, res1.size());
+    assertEquals("select\n*\nfrom\ntest1", res1.get(0).getStatement());
+    assertEquals("select * from test1", res1.get(0).getHistoryStatement());
+  }
+
+  @Test
+  public final void testQuoted() throws InvalidStatementException {
+    List<ParsedResult> res1 = SimpleParser.parseScript("select '\n;' from test;");
+    assertEquals(1, res1.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res1.get(0).getType());
+    assertEquals("select '\n;' from test", res1.get(0).getHistoryStatement());
+    assertEquals("select '\n;' from test", res1.get(0).getStatement());
+
+    List<ParsedResult> res2 = SimpleParser.parseScript("select 'abc\nbbc\nddf' from test;");
+    assertEquals(1, res2.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res2.get(0).getType());
+    assertEquals("select 'abc\nbbc\nddf' from test", res2.get(0).getHistoryStatement());
+    assertEquals("select 'abc\nbbc\nddf' from test", res2.get(0).getStatement());
+
+    List<ParsedResult> res3 = SimpleParser.parseScript("select '--test', \n'--test2' from test");
+    assertEquals(1, res3.size());
+    assertEquals(ParsedResult.StatementType.STATEMENT, res3.get(0).getType());
+    assertEquals("select '--test', '--test2' from test", res3.get(0).getHistoryStatement());
+    assertEquals("select '--test', \n'--test2' from test", res3.get(0).getStatement());
+
+    try {
+      SimpleParser.parseScript("select 'abc");
+      assertTrue(false);
+    } catch (InvalidStatementException is) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public final void testParseLines1() throws InvalidStatementException {
+    String [] lines = {
+      "select abc, ",
+      "bbc from test"
+    };
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> result1 = parser.parseLines(lines[0]);
+    assertEquals(0, result1.size());
+    List<ParsedResult> result2 = parser.parseLines(lines[1]);
+    assertEquals(0, result2.size());
+    List<ParsedResult> result3 = parser.EOF();
+    assertEquals(1, result3.size());
+    assertEquals(lines[0] + lines[1], result3.get(0).getHistoryStatement());
+    assertEquals(lines[0] + "\n" + lines[1], result3.get(0).getStatement());
+  }
+
+  @Test
+  public final void testParseLines2() throws InvalidStatementException {
+    String [] lines = {
+        "select abc, '",
+        "bbc' from test; select * from test3;"
+    };
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> result1 = parser.parseLines(lines[0]);
+    assertEquals(0, result1.size());
+    List<ParsedResult> result2 = parser.parseLines(lines[1]);
+    assertEquals(2, result2.size());
+    assertEquals("select abc, 'bbc' from test", result2.get(0).getHistoryStatement());
+    assertEquals("select * from test3", result2.get(1).getHistoryStatement());
+  }
+
+  @Test
+  public final void testParseLines3() throws InvalidStatementException {
+    String [] lines = {
+        "select abc, 'bbc",
+        "' from test; select * from test3;"
+    };
+    SimpleParser parser = new SimpleParser();
+    List<ParsedResult> result1 = parser.parseLines(lines[0]);
+    assertEquals(0, result1.size());
+    List<ParsedResult> result2 = parser.parseLines(lines[1]);
+    assertEquals(2, result2.size());
+    assertEquals("select abc, 'bbc' from test", result2.get(0).getHistoryStatement());
+    assertEquals("select * from test3", result2.get(1).getHistoryStatement());
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
new file mode 100644
index 0000000..e744631
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCli.java
@@ -0,0 +1,472 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli.tsql;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.PosixParser;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.ConfigKey;
+import org.apache.tajo.SessionVars;
+import org.apache.tajo.TajoTestingCluster;
+import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.client.QueryStatus;
+import org.apache.tajo.client.TajoClient;
+import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.storage.StorageUtil;
+import org.apache.tajo.storage.TablespaceManager;
+import org.apache.tajo.util.FileUtil;
+import org.junit.*;
+import org.junit.rules.TestName;
+
+import java.io.*;
+import java.net.URL;
+
+import static org.junit.Assert.*;
+
+public class TestTajoCli {
+  protected static final TpchTestBase testBase;
+  protected static final TajoTestingCluster cluster;
+
+  /** the base path of result directories */
+  protected static final Path resultBasePath;
+  static {
+    testBase = TpchTestBase.getInstance();
+    cluster = testBase.getTestingCluster();
+    URL resultBaseURL = ClassLoader.getSystemResource("results");
+    resultBasePath = new Path(resultBaseURL.toString());
+  }
+
+  private TajoCli tajoCli;
+  private Path currentResultPath;
+  private ByteArrayOutputStream out;
+
+  @Rule
+  public TestName name = new TestName();
+
+  public TestTajoCli() {
+    String className = getClass().getSimpleName();
+    currentResultPath = new Path(resultBasePath, className);
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    out = new ByteArrayOutputStream();
+    tajoCli = new TajoCli(cluster.getConfiguration(), new String[]{}, System.in, out);
+  }
+
+  @After
+  public void tearDown() throws IOException {
+    out.close();
+    if (tajoCli != null) {
+      tajoCli.close();
+    }
+  }
+
+  private static void setVar(TajoCli cli, ConfigKey key, String val) throws Exception {
+    cli.executeMetaCommand("\\set " + key.keyname() + " " + val);
+  }
+
+  private static void assertSessionVar(TajoCli cli, String key, String expectedVal) {
+    assertEquals(cli.getContext().getCliSideVar(key), expectedVal);
+  }
+
+  private void assertOutputResult(String actual) throws Exception {
+    assertOutputResult(name.getMethodName() + ".result", actual);
+  }
+
+  private void assertOutputResult(String expectedResultFile, String actual) throws Exception {
+    assertOutputResult(expectedResultFile, actual, null, null);
+  }
+
+  private void assertOutputResult(String expectedResultFile, String actual, String[] paramKeys, String[] paramValues)
+    throws Exception {
+    FileSystem fs = currentResultPath.getFileSystem(testBase.getTestingCluster().getConfiguration());
+    Path resultFile = StorageUtil.concatPath(currentResultPath, expectedResultFile);
+    assertTrue(resultFile.toString() + " existence check", fs.exists(resultFile));
+
+    String expectedResult = FileUtil.readTextFile(new File(resultFile.toUri()));
+
+    if (paramKeys != null) {
+      for (int i = 0; i < paramKeys.length; i++) {
+        if (i < paramValues.length) {
+          expectedResult = expectedResult.replace(paramKeys[i], paramValues[i]);
+        }
+      }
+    }
+    assertEquals(expectedResult.trim(), actual.trim());
+  }
+
+  @Test
+  public void testParseParam() throws Exception {
+    String[] args = new String[]{"-f", "test.sql", "--param", "test1=10", "--param", "test2=20"};
+
+    CommandLineParser parser = new PosixParser();
+    CommandLine cmd = parser.parse(TajoCli.options, args);
+
+    String fileName = cmd.getOptionValue("f");
+    assertNotNull(fileName);
+    assertEquals(args[1], fileName);
+
+    String[] paramValues = cmd.getOptionValues("param");
+
+    assertNotNull(paramValues);
+    assertEquals(2, paramValues.length);
+
+    assertEquals("test1=10", paramValues[0]);
+    assertEquals("test2=20", paramValues[1]);
+  }
+
+  @Test
+  public void testParseConf() throws Exception {
+    String[] args = new String[]{"--conf", "tajo.cli.print.pause=false",
+      "--conf", "tajo.executor.join.inner.in-memory-table-num=256"};
+
+    CommandLineParser parser = new PosixParser();
+    CommandLine cmd = parser.parse(TajoCli.options, args);
+    String[] confValues = cmd.getOptionValues("conf");
+
+    assertNotNull(confValues);
+    assertEquals(2, confValues.length);
+
+    assertEquals("tajo.cli.print.pause=false", confValues[0]);
+    assertEquals("tajo.executor.join.inner.in-memory-table-num=256", confValues[1]);
+
+    TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration();
+    TajoCli testCli = new TajoCli(tajoConf, args, System.in, System.out);
+    try {
+      assertEquals("false", testCli.getContext().get(SessionVars.CLI_PAGING_ENABLED));
+      assertEquals("256", testCli.getContext().getConf().get("tajo.executor.join.inner.in-memory-table-num"));
+    } finally {
+      testCli.close();
+    }
+  }
+
+  @Test
+  public void testReplaceParam() throws Exception {
+    String sql = "select * from lineitem where l_tax > ${tax} and l_returnflag > '${returnflag}'";
+    String[] params = new String[]{"tax=10", "returnflag=A"};
+
+
+    String expected = "select * from lineitem where l_tax > 10 and l_returnflag > 'A'";
+    assertEquals(expected, TajoCli.replaceParam(sql, params));
+  }
+
+  @Test
+  public void testLocalQueryWithoutFrom() throws Exception {
+    String sql = "select 'abc', '123'; select substr('123456', 1,3);";
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+    tajoCli.executeScript(sql);
+    String consoleResult = new String(out.toByteArray());
+
+    assertOutputResult(consoleResult);
+  }
+
+  @Test
+  public void testConnectDatabase() throws Exception {
+    String databaseName;
+
+    if (cluster.isHiveCatalogStoreRunning()) {
+      databaseName = "TEST_CONNECTION_DATABASE".toLowerCase();
+    } else {
+      databaseName = "TEST_CONNECTION_DATABASE";
+    }
+    String sql = "create database \"" + databaseName + "\";";
+
+    tajoCli.executeScript(sql);
+
+    tajoCli.executeMetaCommand("\\c " + databaseName);
+    assertEquals(databaseName, tajoCli.getContext().getCurrentDatabase());
+
+    tajoCli.executeMetaCommand("\\c default");
+    assertEquals("default", tajoCli.getContext().getCurrentDatabase());
+
+    tajoCli.executeMetaCommand("\\c \"" + databaseName + "\"");
+    assertEquals(databaseName, tajoCli.getContext().getCurrentDatabase());
+  }
+
+  private void verifyDescTable(String sql, String tableName, String resultFileName) throws Exception {
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+    tajoCli.executeScript(sql);
+
+    tajoCli.executeMetaCommand("\\d " + tableName);
+    tajoCli.executeMetaCommand("\\d \"" + tableName + "\"");
+
+    String consoleResult = new String(out.toByteArray());
+
+    if (!cluster.isHiveCatalogStoreRunning()) {
+      assertOutputResult(resultFileName, consoleResult, new String[]{"${table.path}"},
+        new String[]{TablespaceManager.getDefault().getTableUri("default", tableName).toString()});
+    }
+  }
+
+  @Test
+  public void testDescTable() throws Exception {
+    String tableName;
+    if (cluster.isHiveCatalogStoreRunning()) {
+      tableName = "TEST_DESC_TABLE".toLowerCase();
+    } else {
+      tableName = "TEST_DESC_TABLE";
+    }
+
+    String sql = "create table \"" + tableName + "\" (col1 int4, col2 int4);";
+    verifyDescTable(sql, tableName, "testDescTable.result");
+  }
+
+  @Test
+  public void testDescTableForNestedSchema() throws Exception {
+    String tableName;
+    if (cluster.isHiveCatalogStoreRunning()) {
+      tableName = "TEST_DESC_TABLE_NESTED".toLowerCase();
+    } else {
+      tableName = "TEST_DESC_TABLE_NESTED";
+    }
+
+    String sql = "create table \"" + tableName + "\" (col1 int4, col2 int4, col3 record (col4 record (col5 text)));";
+    verifyDescTable(sql, tableName, "testDescTableForNestedSchema.result");
+  }
+
+  @Test
+  public void testSelectResultWithNullFalse() throws Exception {
+    String sql =
+      "select\n" +
+        "  c_custkey,\n" +
+        "  orders.o_orderkey,\n" +
+        "  orders.o_orderstatus \n" +
+        "from\n" +
+        "  orders full outer join customer on c_custkey = o_orderkey\n" +
+        "order by\n" +
+        "  c_custkey,\n" +
+        "  orders.o_orderkey;\n";
+
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+    tajoCli.executeScript(sql);
+
+    String consoleResult = new String(out.toByteArray());
+    assertOutputResult(consoleResult);
+  }
+
+  private void verifySelectResultWithNullTrue() throws Exception {
+    String sql =
+      "select\n" +
+        "  c_custkey,\n" +
+        "  orders.o_orderkey,\n" +
+        "  orders.o_orderstatus \n" +
+        "from\n" +
+        "  orders full outer join customer on c_custkey = o_orderkey\n" +
+        "order by\n" +
+        "  c_custkey,\n" +
+        "  orders.o_orderkey;\n";
+
+
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+    assertSessionVar(tajoCli, SessionVars.CLI_NULL_CHAR.keyname(), "testnull");
+
+    tajoCli.executeScript(sql);
+
+    String consoleResult = new String(out.toByteArray());
+    assertOutputResult(consoleResult);
+  }
+
+  @Test
+  public void testSelectResultWithNullTrueDeprecated() throws Exception {
+    setVar(tajoCli, TajoConf.ConfVars.$CLI_NULL_CHAR, "testnull");
+    verifySelectResultWithNullTrue();
+  }
+
+  @Test
+  public void testSelectResultWithNullTrue() throws Exception {
+    setVar(tajoCli, SessionVars.CLI_NULL_CHAR, "testnull");
+    verifySelectResultWithNullTrue();
+  }
+
+  private void verifyStopWhenError() throws Exception {
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+
+    assertSessionVar(tajoCli, SessionVars.ON_ERROR_STOP.keyname(), "true");
+
+    tajoCli.executeScript("select count(*) from lineitem; " +
+      "select count(*) from lineitem2; " +
+      "select count(*) from orders");
+
+    String consoleResult = new String(out.toByteArray());
+    assertOutputResult(consoleResult);
+  }
+
+  @Test
+  public void testGetConf() throws Exception {
+    TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration();
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    TajoCli tajoCli = new TajoCli(tajoConf, new String[]{}, System.in, out);
+    try {
+      tajoCli.executeMetaCommand("\\getconf tajo.rootdir");
+
+      String consoleResult = new String(out.toByteArray());
+      assertEquals(consoleResult, tajoCli.getContext().getConf().getVar(TajoConf.ConfVars.ROOT_DIR) + "\n");
+    } finally {
+      tajoCli.close();
+    }
+  }
+
+  @Test
+  public void testShowMasters() throws Exception {
+    TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration();
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    TajoCli tajoCli = new TajoCli(tajoConf, new String[]{}, System.in, out);
+    tajoCli.executeMetaCommand("\\admin -showmasters");
+
+    String consoleResult = new String(out.toByteArray());
+
+    String masterAddress = tajoCli.getContext().getConf().getVar(TajoConf.ConfVars.TAJO_MASTER_UMBILICAL_RPC_ADDRESS);
+    String host = masterAddress.split(":")[0];
+    tajoCli.close();
+    assertEquals(consoleResult, host + "\n");
+  }
+
+  @Test
+  public void testStopWhenErrorDeprecated() throws Exception {
+    tajoCli.executeMetaCommand("\\set tajo.cli.error.stop true");
+    verifyStopWhenError();
+  }
+
+  @Test
+  public void testStopWhenError() throws Exception {
+    tajoCli.executeMetaCommand("\\set ON_ERROR_STOP true");
+    verifyStopWhenError();
+  }
+
+  @Test
+  public void testHelpSessionVars() throws Exception {
+    tajoCli.executeMetaCommand("\\help set");
+    assertOutputResult(new String(out.toByteArray()));
+  }
+
+  @Test
+  public void testTimeZoneSessionVars1() throws Exception {
+    tajoCli.executeMetaCommand("\\set TIMEZONE GMT+1");
+    tajoCli.executeMetaCommand("\\set");
+    String output = new String(out.toByteArray());
+    assertTrue(output.contains("'TIMEZONE'='GMT+1'"));
+  }
+
+  @Test
+  public void testTimeZoneSessionVars2() throws Exception {
+    tajoCli.executeScript("SET TIME ZONE 'GMT+2'");
+    tajoCli.executeMetaCommand("\\set");
+    String output = new String(out.toByteArray());
+    assertTrue(output.contains("'TIMEZONE'='GMT+2'"));
+  }
+
+  @Test
+  public void testTimeZoneTest1() throws Exception {
+    String tableName = "test1";
+    tajoCli.executeMetaCommand("\\set TIMEZONE GMT+0");
+    tajoCli.executeScript("create table " + tableName + " (col1 TIMESTAMP)");
+    tajoCli.executeScript("insert into " + tableName + " select to_timestamp(0)");
+    tajoCli.executeScript("select * from " + tableName);
+    String consoleResult = new String(out.toByteArray());
+    tajoCli.executeScript("DROP TABLE " + tableName + " PURGE");
+    assertTrue(consoleResult.contains("1970-01-01 00:00:00"));
+  }
+
+  @Test
+  public void testTimeZoneTest2() throws Exception {
+    String tableName = "test1";
+    tajoCli.executeMetaCommand("\\set TIMEZONE GMT+1");
+    tajoCli.executeScript("create table " + tableName + " (col1 TIMESTAMP)");
+    tajoCli.executeScript("insert into " + tableName + " select to_timestamp(0)");
+    tajoCli.executeScript("select * from " + tableName);
+    String consoleResult = new String(out.toByteArray());
+    tajoCli.executeScript("DROP TABLE " + tableName + " PURGE");
+    assertTrue(consoleResult.contains("1970-01-01 01:00:00"));
+  }
+
+  @Test(timeout = 3000)
+  public void testNonForwardQueryPause() throws Exception {
+    final String sql = "select * from default.lineitem";
+    TajoCli cli = null;
+    try {
+      TableDesc tableDesc = cluster.getMaster().getCatalog().getTableDesc("default", "lineitem");
+      assertNotNull(tableDesc);
+      assertEquals(0L, tableDesc.getStats().getNumRows().longValue());
+
+      InputStream testInput = new ByteArrayInputStream(new byte[]{(byte) DefaultTajoCliOutputFormatter.QUIT_COMMAND});
+      cli = new TajoCli(cluster.getConfiguration(), new String[]{}, testInput, out);
+      setVar(cli, SessionVars.CLI_PAGE_ROWS, "2");
+      setVar(cli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+
+      cli.executeScript(sql);
+
+      String consoleResult;
+      consoleResult = new String(out.toByteArray());
+      assertOutputResult(consoleResult);
+    } finally {
+      cli.close();
+    }
+  }
+
+  @Test
+  public void testAlterTableAddDropPartition() throws Exception {
+    String tableName = CatalogUtil.normalizeIdentifier("testAlterTableAddPartition");
+
+    tajoCli.executeScript("create table " + tableName + " (col1 int4, col2 int4) partition by column(key float8)");
+    tajoCli.executeScript("alter table " + tableName + " add partition (key2 = 0.1)");
+    tajoCli.executeScript("alter table " + tableName + " add partition (key = 0.1)");
+    tajoCli.executeScript("alter table " + tableName + " drop partition (key = 0.1)");
+    tajoCli.executeScript("alter table " + tableName + " drop partition (key = 0.1)");
+
+    tajoCli.executeScript("drop table " + tableName);
+    tajoCli.executeScript("create table " + tableName
+      + " (col1 int4, col2 int4) partition by column(col3 float8, col4 int4)");
+
+    TajoClient client = testBase.getTestingCluster().newTajoClient();
+    TableDesc tableDesc = client.getTableDesc(tableName);
+
+    String partitionLocation = tableDesc.getUri().toString() + "/col5=0.1/col6=10";
+    tajoCli.executeScript("alter table " + tableName + " add partition (col3 = 0.1, col4 = 10)"
+      + " location '" + partitionLocation + "'");
+
+    Path partitionPath = new Path(partitionLocation);
+    FileSystem fs = testBase.getTestingCluster().getDefaultFileSystem();
+    assertTrue(fs.exists(partitionPath));
+
+    tajoCli.executeScript("alter table " + tableName + " drop partition (col3 = 0.1, col4 = 10)");
+
+    String consoleResult = new String(out.toByteArray());
+    assertOutputResult(consoleResult);
+  }
+
+  public static class TajoCliOutputTestFormatter extends DefaultTajoCliOutputFormatter {
+    @Override
+    protected String getResponseTimeReadable(float responseTime) {
+      return "";
+    }
+    @Override
+    public void printProgress(PrintWriter sout, QueryStatus status) {
+      //nothing to do
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
new file mode 100644
index 0000000..edbeff6
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/TestTajoCliNegatives.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli.tsql;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.ConfigKey;
+import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.SessionVars;
+import org.apache.tajo.client.QueryStatus;
+import org.apache.tajo.util.FileUtil;
+import org.junit.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestTajoCliNegatives extends QueryTestCaseBase {
+  private static TajoCli tajoCli;
+  private static ByteArrayOutputStream out;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    out = new ByteArrayOutputStream();
+    tajoCli = new TajoCli(testingCluster.getConfiguration(), new String[]{}, System.in, out);
+  }
+
+  @AfterClass
+  public static void tearDown() throws IOException {
+    out.close();
+    if (tajoCli != null) {
+      tajoCli.close();
+    }
+  }
+
+  @Before
+  public void resetConsole() throws IOException {
+    out.reset();
+  }
+
+  public void assertMetaCommandFailures(String cmd) throws Exception {
+    Path resultFile = getResultFile(getMethodName() + ".result");
+    String expected = FileUtil.readTextFile(new File(resultFile.toUri()));
+
+    tajoCli.executeMetaCommand(cmd);
+    String consoleResult = new String(out.toByteArray());
+    assertEquals(expected, consoleResult);
+  }
+
+  public void assertMetaCommandFailure(String cmd, String expectedMsg) throws Exception {
+    tajoCli.executeMetaCommand(cmd);
+    String consoleResult = new String(out.toByteArray());
+    assertEquals(expectedMsg, consoleResult);
+  }
+
+  public void assertScriptFailure(String cmd) throws Exception {
+    Path resultFile = getResultFile(getMethodName() + ".result");
+    String expected = FileUtil.readTextFile(new File(resultFile.toUri()));
+
+    tajoCli.executeScript(cmd);
+    String consoleResult = new String(out.toByteArray());
+    assertEquals(expected, consoleResult);
+  }
+
+  public void assertScriptFailure(String cmd, String expectedMsg) throws Exception {
+    tajoCli.executeScript(cmd);
+    String consoleResult = new String(out.toByteArray());
+    assertEquals(expectedMsg, consoleResult);
+  }
+
+  @Test
+  public void testConnectDatabase() throws Exception {
+    assertMetaCommandFailure("\\c unknown_db", "ERROR: database 'unknown_db' does not exist");
+  }
+
+  @Test
+  public void testDescTable() throws Exception {
+    assertMetaCommandFailure("\\d unknown_table", "ERROR: relation 'unknown_table' does not exist\n");
+  }
+
+  @Test
+  public void testQueryVerification() throws Exception {
+    assertScriptFailure("select * from unknown_table", "ERROR: relation 'default.unknown_table' does not exist\n");
+  }
+
+  @Test
+  public void testQuerySyntax() throws Exception {
+    assertScriptFailure("select * from unknown-table");
+  }
+
+  private static void setVar(TajoCli cli, ConfigKey key, String val) throws Exception {
+    cli.executeMetaCommand("\\set " + key.keyname() + " " + val);
+  }
+
+  public static class TajoCliOutputTestFormatter extends DefaultTajoCliOutputFormatter {
+    @Override
+    protected String getResponseTimeReadable(float responseTime) {
+      return "";
+    }
+    @Override
+    public void printProgress(PrintWriter sout, QueryStatus status) {
+      //nothing to do
+    }
+  }
+
+  @Test
+  public void testQueryNotImplementedFeature() throws Exception {
+
+    try {
+      client.updateQuery("CREATE DATABASE TestTajoCliNegatives");
+      client.updateQuery("CREATE TABLE TestTajoCliNegatives.table12u79 ( name RECORD(last TEXT, first TEXT) )");
+
+      assertScriptFailure("select name FROM TestTajoCliNegatives.table12u79",
+          "ERROR: not implemented feature: record field projection\n");
+
+    } finally {
+      client.updateQuery("DROP TABLE IF EXISTS TestTajoCliNegatives.table12u79");
+      client.updateQuery("DROP DATABASE IF EXISTS TestTajoCliNegatives");
+    }
+  }
+
+  @Test
+  public void testQueryFailure() throws Exception {
+    setVar(tajoCli, SessionVars.CLI_FORMATTER_CLASS, TajoCliOutputTestFormatter.class.getName());
+    assertScriptFailure("select fail(3, l_orderkey, 'testQueryFailure') from default.lineitem" ,
+        "ERROR: No error message\n");
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestExecExternalShellCommand.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestExecExternalShellCommand.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestExecExternalShellCommand.java
new file mode 100644
index 0000000..ed7ee4a
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestExecExternalShellCommand.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli.tsql.commands;
+
+import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.cli.tsql.TajoCli;
+import org.apache.tajo.conf.TajoConf;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestExecExternalShellCommand {
+  @Test
+  public void testCommand() throws Exception {
+    TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration();
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+    TajoCli cli = new TajoCli(tajoConf, new String[]{}, null, out);
+
+    cli.executeMetaCommand("\\! echo \"this is test\"");
+    String consoleResult = new String(out.toByteArray());
+    assertEquals("this is test\n", consoleResult);
+
+    assertEquals(-1, cli.executeMetaCommand("\\! error_command"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestHdfsCommand.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestHdfsCommand.java b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestHdfsCommand.java
new file mode 100644
index 0000000..496c7e3
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/cli/tsql/commands/TestHdfsCommand.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.cli.tsql.commands;
+
+import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.cli.tsql.TajoCli;
+import org.apache.tajo.conf.TajoConf;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestHdfsCommand {
+  @Test
+  public void testHdfCommand() throws Exception {
+    TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration();
+
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+    System.setOut(new PrintStream(out));
+    System.setErr(new PrintStream(out));
+    TajoCli cli = new TajoCli(tajoConf, new String[]{}, null, out);
+
+    cli.executeMetaCommand("\\dfs -test");
+    String consoleResult = new String(out.toByteArray());
+    assertEquals("-test: Not enough arguments: expected 1 but got 0\n" +
+        "Usage: hadoop fs [generic options] -test -[defsz] <path>\n", consoleResult);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/client/TestCatalogAdminClientExceptions.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/client/TestCatalogAdminClientExceptions.java b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestCatalogAdminClientExceptions.java
new file mode 100644
index 0000000..4b8000d
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestCatalogAdminClientExceptions.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.client;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.QueryTestCaseBase;
+import org.apache.tajo.TajoTestingCluster;
+import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.catalog.TableMeta;
+import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.exception.*;
+import org.apache.tajo.util.KeyValueSet;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.net.URI;
+
+import static org.junit.Assert.assertFalse;
+
+public class TestCatalogAdminClientExceptions extends QueryTestCaseBase {
+  private static TajoTestingCluster cluster;
+  private static TajoClient client;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    cluster = TpchTestBase.getInstance().getTestingCluster();
+    client = cluster.newTajoClient();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    client.close();
+  }
+
+  @Test(expected = DuplicateDatabaseException.class)
+  public final void testCreateDatabase() throws TajoException {
+    client.createDatabase("default"); // duplicate database
+  }
+
+  @Test
+  public final void testExistDatabase() {
+    assertFalse(client.existDatabase("unknown-database")); // unknown database
+  }
+
+  @Test(expected = UndefinedDatabaseException.class)
+  public final void testDropDatabase() throws TajoException {
+    client.dropDatabase("unknown-database"); // unknown database
+  }
+
+  @Test(expected = UnavailableTableLocationException.class)
+  public final void testCreateExternalTableUnavailableLocation() throws TajoException {
+    client.createExternalTable("table128237", new Schema(), URI.create("/tajo/test1bcd"),
+        new TableMeta("TEXT", new KeyValueSet()));
+  }
+
+  @Test(expected = DuplicateTableException.class)
+  public final void testCreateExternalTableDuplicated() throws TajoException {
+    client.createExternalTable("default.lineitem", new Schema(), URI.create("/"),
+        new TableMeta("TEXT", new KeyValueSet()));
+  }
+
+  @Test(expected = InsufficientPrivilegeException.class)
+  public final void testCreateExternalTableInsufficientPrivilege() throws TajoException {
+    Path p = TajoConf.getWarehouseDir(conf);
+    client.createExternalTable("information_schema.table1237891", new Schema(), p.toUri(),
+        new TableMeta("TEXT", new KeyValueSet()));
+  }
+
+  @Test(expected = UndefinedTableException.class)
+  public final void testDropTableAbsent() throws UndefinedTableException, InsufficientPrivilegeException {
+    client.dropTable("unknown-table"); // unknown table
+  }
+
+  @Test(expected = InsufficientPrivilegeException.class)
+  public final void testDropTableInsufficient() throws UndefinedTableException, InsufficientPrivilegeException {
+    client.dropTable("information_schema.tables"); // cannot be dropped
+  }
+
+  @Test(expected = UndefinedTableException.class)
+  public final void testGetTableDesc() throws UndefinedTableException {
+    client.getTableDesc("unknown-table");
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/client/TestQueryClientExceptions.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/client/TestQueryClientExceptions.java b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestQueryClientExceptions.java
new file mode 100644
index 0000000..0457e23
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestQueryClientExceptions.java
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.client;
+
+import org.apache.tajo.LocalTajoTestingUtility;
+import org.apache.tajo.TajoTestingCluster;
+import org.apache.tajo.TpchTestBase;
+import org.apache.tajo.annotation.NotThreadSafe;
+import org.apache.tajo.error.Errors;
+import org.apache.tajo.exception.*;
+import org.apache.tajo.rpc.protocolrecords.PrimitiveProtos.ReturnState;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+@NotThreadSafe
+public class TestQueryClientExceptions {
+  private static TajoTestingCluster cluster;
+  private static TajoClient client;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    cluster = TpchTestBase.getInstance().getTestingCluster();
+    client = cluster.newTajoClient();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    client.close();
+  }
+
+  @Test
+  public void testExecuteQuery() {
+    // This is just an error propagation unit test. Specified SQL errors will be addressed in other unit tests.
+    ReturnState state = client.executeQuery("select * from unknown_table").getState();
+    assertEquals(Errors.ResultCode.UNDEFINED_TABLE, state.getReturnCode());
+
+    state = client.executeQuery("create table default.lineitem (name int);").getState();
+    assertEquals(Errors.ResultCode.DUPLICATE_TABLE, state.getReturnCode());
+  }
+
+  @Test(expected = DuplicateTableException.class)
+  public void testUpdateQuery() throws TajoException {
+    client.updateQuery("create table default.lineitem (name int);");
+  }
+
+  @Test(expected = UndefinedTableException.class)
+  public void testExecuteQueryAndGetResult() throws TajoException {
+    // This is just an error propagation unit test. Specified SQL errors will be addressed in other unit tests.
+    client.executeQueryAndGetResult("select * from unknown_table");
+  }
+
+  @Test
+  public void testCloseQuery() {
+    // absent query id
+    client.closeQuery(LocalTajoTestingUtility.newQueryId());
+    client.closeNonForwardQuery(LocalTajoTestingUtility.newQueryId());
+  }
+
+  @Test(expected = UndefinedDatabaseException .class)
+  public void testSelectDatabase() throws UndefinedDatabaseException {
+    // absent database name
+    client.selectDatabase("unknown_db");
+  }
+
+  @Test(expected = NoSuchSessionVariableException.class)
+  public void testGetSessionVar() throws NoSuchSessionVariableException {
+    // absent session variable
+    client.getSessionVariable("unknown-var");
+  }
+
+  @Test(expected = QueryNotFoundException.class)
+  public void testGetQueryResult() throws TajoException {
+    // absent query id
+    client.getQueryResult(LocalTajoTestingUtility.newQueryId());
+  }
+
+  @Test(expected = QueryNotFoundException.class)
+  public void testGetResultResponse() throws TajoException {
+    // absent query id
+    client.getResultResponse(LocalTajoTestingUtility.newQueryId());
+  }
+
+  @Test(expected = QueryNotFoundException.class)
+  public void testFetchNextQueryResult() throws TajoException {
+    client.fetchNextQueryResult(LocalTajoTestingUtility.newQueryId(), 100);
+  }
+
+  @Test(expected = QueryNotFoundException.class)
+  public void testKillQuery() throws QueryNotFoundException {
+    client.killQuery(LocalTajoTestingUtility.newQueryId());
+  }
+
+  @Test(expected = QueryNotFoundException.class)
+  public void testGetQueryInfo() throws QueryNotFoundException {
+    client.getQueryInfo(LocalTajoTestingUtility.newQueryId());
+  }
+
+  @Test(expected = QueryNotFoundException.class)
+  public void testGetQueryHistory() throws QueryNotFoundException {
+    client.getQueryHistory(LocalTajoTestingUtility.newQueryId());
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/a4106883/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
----------------------------------------------------------------------
diff --git a/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
new file mode 100644
index 0000000..93a48f0
--- /dev/null
+++ b/tajo-core-tests/src/test/java/org/apache/tajo/client/TestTajoClient.java
@@ -0,0 +1,775 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.client;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.tajo.*;
+import org.apache.tajo.TajoProtos.QueryState;
+import org.apache.tajo.annotation.NotThreadSafe;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.FunctionDesc;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.catalog.proto.CatalogProtos;
+import org.apache.tajo.conf.TajoConf;
+import org.apache.tajo.exception.TajoException;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.ipc.ClientProtos;
+import org.apache.tajo.ipc.ClientProtos.QueryHistoryProto;
+import org.apache.tajo.ipc.ClientProtos.QueryInfoProto;
+import org.apache.tajo.ipc.ClientProtos.StageHistoryProto;
+import org.apache.tajo.storage.StorageConstants;
+import org.apache.tajo.storage.StorageUtil;
+import org.apache.tajo.util.CommonTestingUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+@Category(IntegrationTest.class)
+@NotThreadSafe
+public class TestTajoClient {
+  private static TajoTestingCluster cluster;
+  private static TajoConf conf;
+  private static TajoClient client;
+  private static Path testDir;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    cluster = TpchTestBase.getInstance().getTestingCluster();
+    conf = cluster.getConfiguration();
+    client = cluster.newTajoClient();
+    testDir = CommonTestingUtil.getTestDir();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    client.close();
+  }
+
+  private static Path writeTmpTable(String tableName) throws IOException {
+    Path tablePath = StorageUtil.concatPath(testDir, tableName);
+    BackendTestingUtil.writeTmpTable(conf, tablePath);
+    return tablePath;
+  }
+
+  @Test
+  public final void testCreateAndDropDatabases() throws TajoException {
+    int currentNum = client.getAllDatabaseNames().size();
+
+    String prefix = CatalogUtil.normalizeIdentifier("testCreateDatabase_");
+    for (int i = 0; i < 10; i++) {
+      // test allDatabaseNames
+      assertEquals(currentNum + i, client.getAllDatabaseNames().size());
+
+      // test existence
+      assertFalse(client.existDatabase(prefix + i));
+      client.createDatabase(prefix + i);
+      assertTrue(client.existDatabase(prefix + i));
+
+      // test allDatabaseNames
+      assertEquals(currentNum + i + 1, client.getAllDatabaseNames().size());
+      assertTrue(client.getAllDatabaseNames().contains(prefix + i));
+    }
+
+    // test dropDatabase, existDatabase and getAllDatabaseNames()
+    for (int i = 0; i < 10; i++) {
+      assertTrue(client.existDatabase(prefix + i));
+      assertTrue(client.getAllDatabaseNames().contains(prefix + i));
+      client.dropDatabase(prefix + i);
+      assertFalse(client.existDatabase(prefix + i));
+      assertFalse(client.getAllDatabaseNames().contains(prefix + i));
+    }
+
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testCurrentDatabase() throws IOException, TajoException, InterruptedException {
+    int currentNum = client.getAllDatabaseNames().size();
+    assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase());
+
+    String databaseName = CatalogUtil.normalizeIdentifier("testcurrentdatabase");
+    client.createDatabase(databaseName);
+    assertEquals(currentNum + 1, client.getAllDatabaseNames().size());
+    assertEquals(TajoConstants.DEFAULT_DATABASE_NAME, client.getCurrentDatabase());
+    client.selectDatabase(databaseName);
+    assertEquals(databaseName, client.getCurrentDatabase());
+    client.selectDatabase(TajoConstants.DEFAULT_DATABASE_NAME);
+    client.dropDatabase(databaseName);
+
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testSelectDatabaseToInvalidOne() throws IOException, TajoException, InterruptedException {
+    int currentNum = client.getAllDatabaseNames().size();
+    assertFalse(client.existDatabase("invaliddatabase"));
+
+    try {
+      client.selectDatabase("invaliddatabase");
+      assertFalse(true);
+    } catch (Throwable t) {
+      assertFalse(false);
+    }
+
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testDropCurrentDatabase() throws IOException, TajoException, InterruptedException {
+    int currentNum = client.getAllDatabaseNames().size();
+    String databaseName = CatalogUtil.normalizeIdentifier("testdropcurrentdatabase");
+    client.createDatabase(databaseName);
+    client.selectDatabase(databaseName);
+    assertEquals(databaseName, client.getCurrentDatabase());
+
+    try {
+      client.dropDatabase(databaseName);
+      assertFalse(true);
+    } catch (Throwable t) {
+      assertFalse(false);
+    }
+
+    client.selectDatabase(TajoConstants.DEFAULT_DATABASE_NAME);
+    client.dropDatabase(databaseName);
+    assertEquals(currentNum, client.getAllDatabaseNames().size());
+  }
+
+  @Test
+  public final void testSessionVariables() throws IOException, TajoException, InterruptedException {
+    String prefixName = "key_";
+    String prefixValue = "val_";
+
+    List<String> unsetList = new ArrayList<>();
+    for(Map.Entry<String, String> entry: client.getAllSessionVariables().entrySet()) {
+      unsetList.add(entry.getKey());
+    }
+    client.unsetSessionVariables(unsetList);
+
+    for (int i = 0; i < 10; i++) {
+      String key = prefixName + i;
+      String val = prefixValue + i;
+
+      // Basically,
+      assertEquals(i + 4, client.getAllSessionVariables().size());
+      assertFalse(client.getAllSessionVariables().containsKey(key));
+      assertFalse(client.existSessionVariable(key));
+
+      Map<String, String> map = Maps.newHashMap();
+      map.put(key, val);
+      client.updateSessionVariables(map);
+
+      assertEquals(i + 5, client.getAllSessionVariables().size());
+      assertTrue(client.getAllSessionVariables().containsKey(key));
+      assertTrue(client.existSessionVariable(key));
+    }
+
+    int totalSessionVarNum = client.getAllSessionVariables().size();
+
+    for (int i = 0; i < 10; i++) {
+      String key = prefixName + i;
+
+      assertTrue(client.getAllSessionVariables().containsKey(key));
+      assertTrue(client.existSessionVariable(key));
+
+      client.unsetSessionVariables(Lists.newArrayList(key));
+
+      assertFalse(client.getAllSessionVariables().containsKey(key));
+      assertFalse(client.existSessionVariable(key));
+    }
+
+    assertEquals(totalSessionVarNum - 10, client.getAllSessionVariables().size());
+  }
+
+  @Test
+  public final void testKillQuery() throws IOException, TajoException, InterruptedException {
+    ClientProtos.SubmitQueryResponse res = client.executeQuery("select sleep(1) from lineitem");
+    Thread.sleep(1000);
+    QueryId queryId = new QueryId(res.getQueryId());
+    client.killQuery(queryId);
+    assertEquals(TajoProtos.QueryState.QUERY_KILLED, client.getQueryStatus(queryId).getState());
+  }
+
+  @Test
+  public final void testUpdateQuery() throws IOException, TajoException {
+    final String tableName = CatalogUtil.normalizeIdentifier("testUpdateQuery");
+    Path tablePath = writeTmpTable(tableName);
+
+    assertFalse(client.existTable(tableName));
+    String sql =
+      "create external table " + tableName + " (deptname text, score integer) "
+        + "using csv location '" + tablePath + "'";
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+    client.dropTable(tableName);
+    assertFalse(client.existTable(tableName));
+  }
+
+  @Test
+  public final void testCreateAndDropExternalTable() throws IOException, TajoException {
+    final String tableName = "testCreateAndDropExternalTable";
+    Path tablePath = writeTmpTable(tableName);
+    LOG.error("Full path:" + tablePath.toUri().getRawPath());
+    FileSystem fs = tablePath.getFileSystem(conf);
+    assertTrue(fs.exists(tablePath));
+
+    assertFalse(client.existTable(tableName));
+
+    client.createExternalTable(tableName, BackendTestingUtil.mockupSchema, tablePath.toUri(), BackendTestingUtil.mockupMeta);
+    assertTrue(client.existTable(tableName));
+    client.dropTable(tableName);
+    assertFalse(client.existTable(tableName));
+    fs = tablePath.getFileSystem(conf);
+    assertTrue(fs.exists(tablePath));
+  }
+
+  @Test
+  public final void testCreateAndPurgeExternalTable() throws IOException, TajoException {
+    final String tableName = "testCreateAndPurgeExternalTable";
+    Path tablePath = writeTmpTable(tableName);
+    LOG.error("Full path:" + tablePath.toUri().getRawPath());
+    FileSystem fs = tablePath.getFileSystem(conf);
+    assertTrue(fs.exists(tablePath));
+
+    assertFalse(client.existTable(tableName));
+
+    client.createExternalTable(tableName, BackendTestingUtil.mockupSchema, tablePath.toUri(), BackendTestingUtil.mockupMeta);
+    assertTrue(client.existTable(tableName));
+    client.dropTable(tableName, true);
+    assertFalse(client.existTable(tableName));
+    fs = tablePath.getFileSystem(conf);
+    assertFalse("Checking if table data exists", fs.exists(tablePath));
+  }
+
+  @Test
+  public final void testCreateAndDropExternalTableByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropExternalTableByExecuteQuery");
+
+    Path tablePath = writeTmpTable(tableName);
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create external table " + tableName + " (deptname text, score int4) " + "using csv location '"
+        + tablePath + "'";
+
+    client.executeQueryAndGetResult(sql);
+    assertTrue(client.existTable(tableName));
+
+    client.updateQuery("drop table " + tableName);
+    assertFalse(client.existTable("tableName"));
+    FileSystem localFS = FileSystem.getLocal(conf);
+    assertTrue(localFS.exists(tablePath));
+  }
+
+  @Test
+  public final void testCreateAndPurgeExternalTableByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndPurgeExternalTableByExecuteQuery");
+
+    Path tablePath = writeTmpTable(tableName);
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create external table " + tableName + " (deptname text, score int4) " + "using csv location '"
+      + tablePath + "'";
+
+    client.executeQueryAndGetResult(sql);
+    assertTrue(client.existTable(tableName));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    FileSystem localFS = FileSystem.getLocal(conf);
+    assertFalse(localFS.exists(tablePath));
+  }
+
+  @Test
+  public final void testCreateAndDropTableByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropTableByExecuteQuery");
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName);
+    assertFalse(client.existTable(tableName));
+    assertTrue(hdfs.exists(tablePath));
+  }
+
+  @Test
+  public final void testCreateAndPurgeTableByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndPurgeTableByExecuteQuery");
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    assertFalse(hdfs.exists(tablePath));
+  }
+
+  @Test
+  public final void testDDLByExecuteQuery() throws IOException, TajoException {
+    final String tableName = CatalogUtil.normalizeIdentifier("testDDLByExecuteQuery");
+    Path tablePath = writeTmpTable(tableName);
+
+    assertFalse(client.existTable(tableName));
+    String sql =
+        "create external table " + tableName + " (deptname text, score int4) "
+            + "using csv location '" + tablePath + "'";
+    client.executeQueryAndGetResult(sql);
+    assertTrue(client.existTable(tableName));
+  }
+
+  @Test
+  public final void testGetTableList() throws IOException, TajoException {
+    String tableName1 = "GetTableList1".toLowerCase();
+    String tableName2 = "GetTableList2".toLowerCase();
+
+    assertFalse(client.existTable(tableName1));
+    assertFalse(client.existTable(tableName2));
+    client.updateQuery("create table GetTableList1 (age int, name text);");
+    client.updateQuery("create table GetTableList2 (age int, name text);");
+
+    assertTrue(client.existTable(tableName1));
+    assertTrue(client.existTable(tableName2));
+
+    Set<String> tables = Sets.newHashSet(client.getTableList(null));
+    assertTrue(tables.contains(tableName1));
+    assertTrue(tables.contains(tableName2));
+  }
+
+  Log LOG = LogFactory.getLog(TestTajoClient.class);
+
+  @Test
+  public final void testGetTableDesc() throws IOException, TajoException {
+    final String tableName1 = CatalogUtil.normalizeIdentifier("table3");
+    Path tablePath = writeTmpTable(tableName1);
+    LOG.error("Full path:" + tablePath.toUri().getRawPath());
+    FileSystem fs = tablePath.getFileSystem(conf);
+    assertTrue(fs.exists(tablePath));
+
+    assertNotNull(tablePath);
+    assertFalse(client.existTable(tableName1));
+
+    client.createExternalTable("table3", BackendTestingUtil.mockupSchema, tablePath.toUri(), BackendTestingUtil.mockupMeta);
+    assertTrue(client.existTable(tableName1));
+
+    TableDesc desc = client.getTableDesc(tableName1);
+    assertNotNull(desc);
+    assertEquals(CatalogUtil.buildFQName(TajoConstants.DEFAULT_DATABASE_NAME, tableName1), desc.getName());
+    assertTrue(desc.getStats().getNumBytes() > 0);
+  }
+
+  //@Test
+  public final void testCreateAndDropTablePartitionedHash1ByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = "testCreateAndDropTablePartitionedHash1ByExecuteQuery";
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+    sql += " PARTITION BY HASH (deptname)";
+    sql += " (PARTITION sub_part1, PARTITION sub_part2, PARTITION sub_part3)";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName);
+    assertFalse(client.existTable(tableName));
+    assertTrue(hdfs.exists(tablePath));
+  }
+
+  //@Test
+  public final void testCreateAndPurgeTablePartitionedHash1ByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = "testCreateAndPurgeTablePartitionedHash1ByExecuteQuery";
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+    sql += " PARTITION BY HASH (deptname)";
+    sql += " (PARTITION sub_part1, PARTITION sub_part2, PARTITION sub_part3)";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    assertFalse(hdfs.exists(tablePath));
+  }
+
+  //@Test
+  public final void testCreateAndDropTablePartitionedHash2ByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = "testCreateAndDropTablePartitionedHash2ByExecuteQuery";
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+    sql += "PARTITION BY HASH (deptname)";
+    sql += "PARTITIONS 2";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    assertFalse(hdfs.exists(tablePath));
+  }
+
+  //@Test
+  public final void testCreateAndDropTablePartitionedListByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = "testCreateAndDropTablePartitionedListByExecuteQuery";
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+    sql += "PARTITION BY LIST (deptname)";
+    sql += "( PARTITION sub_part1 VALUES('r&d', 'design'),";
+    sql += "PARTITION sub_part2 VALUES('sales', 'hr') )";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    assertFalse(hdfs.exists(tablePath));
+  }
+
+  //@Test
+  public final void testCreateAndDropTablePartitionedRangeByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = "testCreateAndDropTablePartitionedRangeByExecuteQuery";
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+    sql += "PARTITION BY RANGE (score)";
+    sql += "( PARTITION sub_part1 VALUES LESS THAN (2),";
+    sql += "PARTITION sub_part2 VALUES LESS THAN (5),";
+    sql += "PARTITION sub_part2 VALUES LESS THAN (MAXVALUE) )";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    assertFalse(hdfs.exists(tablePath));
+  }
+
+  @Test
+  public final void testFailCreateTablePartitionedOtherExceptColumn() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = "testFailCreateTablePartitionedOtherExceptColumn";
+
+    assertFalse(client.existTable(tableName));
+
+    String rangeSql = "create table " + tableName + " (deptname text, score int4)";
+    rangeSql += "PARTITION BY RANGE (score)";
+    rangeSql += "( PARTITION sub_part1 VALUES LESS THAN (2),";
+    rangeSql += "PARTITION sub_part2 VALUES LESS THAN (5),";
+    rangeSql += "PARTITION sub_part2 VALUES LESS THAN (MAXVALUE) )";
+
+    try {
+      client.updateQuery(rangeSql);
+      fail();
+    } catch (UnsupportedException se) {
+    }
+ 
+    String listSql = "create table " + tableName + " (deptname text, score int4)";
+    listSql += "PARTITION BY LIST (deptname)";
+    listSql += "( PARTITION sub_part1 VALUES('r&d', 'design'),";
+    listSql += "PARTITION sub_part2 VALUES('sales', 'hr') )";
+
+    try {
+      assertFalse(client.updateQuery(listSql));
+      fail();
+    } catch (UnsupportedException se) {
+    }
+
+    String hashSql = "create table " + tableName + " (deptname text, score int4)";
+    hashSql += "PARTITION BY HASH (deptname)";
+    hashSql += "PARTITIONS 2";
+
+    try {
+      assertFalse(client.updateQuery(hashSql));
+      fail();
+    } catch (UnsupportedException se) {
+    }
+  }
+
+  @Test
+  public final void testCreateAndDropTablePartitionedColumnByExecuteQuery() throws IOException, TajoException {
+    TajoConf conf = cluster.getConfiguration();
+    final String tableName = CatalogUtil.normalizeIdentifier("testCreateAndDropTablePartitionedColumnByExecuteQuery");
+
+    assertFalse(client.existTable(tableName));
+
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+    sql += "PARTITION BY COLUMN (key1 text)";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    Path tablePath = new Path(client.getTableDesc(tableName).getUri());
+    FileSystem hdfs = tablePath.getFileSystem(conf);
+    assertTrue(hdfs.exists(tablePath));
+
+    client.updateQuery("drop table " + tableName + " purge");
+    assertFalse(client.existTable(tableName));
+    assertFalse(hdfs.exists(tablePath));
+  }
+
+  @Test
+  public final void testGetFunctions() throws IOException, TajoException {
+    Collection<FunctionDesc> catalogFunctions = cluster.getMaster().getCatalog().getFunctions();
+    String functionName = "sum";
+    int numFunctions = 0;
+    for(FunctionDesc eachFunction: catalogFunctions) {
+      if(functionName.equals(eachFunction.getFunctionName())) {
+        numFunctions++;
+      }
+    }
+
+    List<CatalogProtos.FunctionDescProto> functions = client.getFunctions(functionName);
+    assertEquals(numFunctions, functions.size());
+
+    functions = client.getFunctions("notmatched");
+    assertEquals(0, functions.size());
+
+    functions = client.getFunctions(null);
+    assertEquals(catalogFunctions.size(), functions.size());
+  }
+
+  @Test
+  public final void testGetFinishedQueryList() throws SQLException, TajoException {
+    final String tableName = CatalogUtil.normalizeIdentifier("testGetFinishedQueryList");
+    String sql = "create table " + tableName + " (deptname text, score int4)";
+
+    client.updateQuery(sql);
+    assertTrue(client.existTable(tableName));
+
+    int numFinishedQueries = client.getFinishedQueryList().size();
+    ResultSet resultSet = client.executeQueryAndGetResult("select * from " + tableName + " order by deptname");
+    assertNotNull(resultSet);
+
+    resultSet = client.executeQueryAndGetResult("select * from " + tableName + " order by deptname");
+    assertNotNull(resultSet);
+    assertEquals(numFinishedQueries + 2, client.getFinishedQueryList().size());
+
+    resultSet.close();
+  }
+
+  /**
+   * The main objective of this test is to get the status of a query which is actually finished.
+   * Statuses of queries regardless of its status should be available for a specified time duration.
+   */
+  @Test(timeout = 20 * 1000)
+  public final void testGetQueryStatusAndResultAfterFinish() throws Exception {
+    String sql = "select * from lineitem order by l_orderkey";
+    ClientProtos.SubmitQueryResponse response = client.executeQuery(sql);
+
+    assertNotNull(response);
+    QueryId queryId = new QueryId(response.getQueryId());
+
+    try {
+      while (true) {
+        Thread.sleep(100);
+
+        List<ClientProtos.BriefQueryInfo> finishedQueries = client.getFinishedQueryList();
+        boolean finished = false;
+        if (finishedQueries != null) {
+          for (ClientProtos.BriefQueryInfo eachQuery: finishedQueries) {
+            if (eachQuery.getQueryId().equals(queryId.getProto())) {
+              finished = true;
+              break;
+            }
+          }
+        }
+
+        if (finished) {
+          break;
+        }
+      }
+
+      QueryStatus queryStatus = client.getQueryStatus(queryId);
+      assertNotNull(queryStatus);
+      assertTrue(TajoClientUtil.isQueryComplete(queryStatus.getState()));
+
+      ResultSet resultSet = client.getQueryResult(queryId);
+      assertNotNull(resultSet);
+
+      int count = 0;
+      while(resultSet.next()) {
+        count++;
+      }
+
+      assertEquals(5, count);
+    } finally {
+      client.closeQuery(queryId);
+    }
+  }
+
+  @Test
+  public void testNullCharSessionInCTAS() throws Exception {
+    String sql =
+        "create table nullcharsession as select\n" +
+          "  c_custkey,\n" +
+          "  orders.o_orderkey,\n" +
+          "  orders.o_orderstatus \n" +
+          "from\n" +
+          "  orders full outer join customer on c_custkey = o_orderkey\n" +
+          "order by\n" +
+          "  c_custkey,\n" +
+          "  orders.o_orderkey;\n";
+
+    Map<String, String> variables = new HashMap<String, String>();
+    variables.put(SessionVars.NULL_CHAR.keyname(), "\\\\T");
+    client.updateSessionVariables(variables);
+    ResultSet res = client.executeQueryAndGetResult(sql);
+    res.close();
+
+    TableDesc resultDesc = client.getTableDesc("nullcharsession");
+    assertNullCharSessionVar(resultDesc);
+  }
+
+
+  public void assertNullCharSessionVar(TableDesc resultDesc) throws Exception {
+    TajoConf tajoConf = TpchTestBase.getInstance().getTestingCluster().getConfiguration();
+
+    assertEquals(resultDesc.getMeta().getOption(StorageConstants.TEXT_NULL), "\\\\T");
+
+    Path path = new Path(resultDesc.getUri());
+    FileSystem fs = path.getFileSystem(tajoConf);
+
+    FileStatus[] files = fs.listStatus(path);
+    assertNotNull(files);
+    assertEquals(1, files.length);
+
+    InputStream in = fs.open(files[0].getPath());
+    byte[] buf = new byte[1024];
+
+
+    int readBytes = in.read(buf);
+    assertTrue(readBytes > 0);
+
+    // text type field's value is replaced with \T
+    String expected = "1|1|O\n" +
+        "2|2|O\n" +
+        "3|3|F\n" +
+        "4||\\T\n" +
+        "5||\\T\n";
+
+    String resultDatas = new String(buf, 0, readBytes);
+
+    assertEquals(expected, resultDatas);
+  }
+
+  @Test(timeout = 30000)
+  public void testGetQueryInfoAndHistory() throws Exception {
+    String sql = "select count(*) from lineitem";
+    ClientProtos.SubmitQueryResponse response = client.executeQuery(sql);
+
+    assertNotNull(response);
+    QueryId queryId = new QueryId(response.getQueryId());
+
+    QueryInfoProto queryInfo;
+    while (true) {
+      queryInfo = client.getQueryInfo(queryId);
+
+      if (queryInfo != null && queryInfo.getQueryState() == QueryState.QUERY_SUCCEEDED) {
+        break;
+      }
+      Thread.sleep(100);
+    }
+
+    assertNotNull(queryInfo);
+    assertEquals(queryId.toString(), queryInfo.getQueryId());
+
+    QueryHistoryProto queryHistory = client.getQueryHistory(queryId);
+    assertNotNull(queryHistory);
+    assertEquals(queryId.toString(), queryHistory.getQueryId());
+    assertEquals(2, queryHistory.getStageHistoriesCount());
+
+    List<ClientProtos.StageHistoryProto> taskHistories =
+        new ArrayList<StageHistoryProto>(queryHistory.getStageHistoriesList());
+    Collections.sort(taskHistories, new Comparator<StageHistoryProto>() {
+      @Override
+      public int compare(ClientProtos.StageHistoryProto o1, StageHistoryProto o2) {
+        return o1.getExecutionBlockId().compareTo(o2.getExecutionBlockId());
+      }
+    });
+    assertEquals(5, taskHistories.get(0).getTotalReadRows());
+    assertEquals(1, taskHistories.get(0).getTotalWriteRows());
+    assertEquals(1, taskHistories.get(1).getTotalReadRows());
+    assertEquals(1, taskHistories.get(1).getTotalWriteRows());
+  }
+}