/**
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.hive.beeline.cli;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
public class TestHiveCli {
private static final Logger LOG = LoggerFactory.getLogger(TestHiveCli.class.getName());
private static final int ERRNO_OK = 0;
private static final int ERRNO_ARGS = 1;
private static final int ERRNO_OTHER = 2;
private final static String SOURCE_CONTEXT =
"create table if not exists test.testSrcTbl(sc1 string);";
private final static String SOURCE_CONTEXT2 =
"create table if not exists test.testSrcTbl2(sc2 string);";
private final static String SOURCE_CONTEXT3 =
"create table if not exists test.testSrcTbl3(sc3 string);";
private final static String SOURCE_CONTEXT4 = "show tables;!ls;show tables;\nquit;";
final static String CMD =
"create database if not exists test;\ncreate table if not exists test.testTbl(a string, b "
+ "string);\n";
private HiveCli cli;
private OutputStream os;
private PrintStream ps;
private OutputStream errS;
private PrintStream errPs;
private File tmp = null;
private void executeCMD(String[] args, String input, int retCode) {
InputStream inputStream = null;
int ret = 0;
try {
if (input != null) {
inputStream = IOUtils.toInputStream(input);
}
ret = cli.runWithArgs(args, inputStream);
} catch (Throwable e) {
LOG.error("Failed to execute command due to the error: " + e);
} finally {
if (retCode != ret) {
LOG.error("Failed due to the error:" + errS.toString());
Assert.fail("Supported return code is " + retCode + " while the actual is " + ret);
}
}
}
/**
* This method is used for verifying CMD to see whether the output contains the keywords provided.
*
* @param CMD
* @param keywords
* @param os
* @param options
* @param retCode
* @param contains
*/
private void verifyCMD(String CMD, String keywords, OutputStream os, String[] options, int retCode,
boolean contains) {
executeCMD(options, CMD, retCode);
String output = os.toString();
LOG.debug(output);
if (contains) {
Assert.assertTrue("The expected keyword \"" + keywords + "\" occur in the output: " + output,
output.contains(keywords));
} else {
Assert.assertFalse(
"The expected keyword \"" + keywords + "\" should be excluded occurred in the output: "
+ output, output.contains(keywords));
}
}
@Test
public void testInValidCmd() {
verifyCMD("!lss\n", "Failed to execute lss", errS, null, ERRNO_OTHER, true);
}
@Test
public void testCmd() {
verifyCMD("show tables;!ls;show tables;\n", "src", os, null, ERRNO_OK, true);
}
@Test
public void testSetPromptValue() {
verifyCMD("set hive.cli.prompt=MYCLI;SHOW\nTABLES;", "MYCLI> ", errS, null,
ERRNO_OK, true);
}
@Test
public void testSetHeaderValue() {
verifyCMD(
"create database if not exists test;\ncreate table if not exists test.testTbl(a string, b string);\nset hive.cli.print.header=true;\n select * from test.testTbl;\n",
"testtbl.a testtbl.b", os, null, ERRNO_OK, true);
}
@Test
public void testHelp() {
verifyCMD(null, "usage: hive", os, new String[] { "-H" }, ERRNO_ARGS, true);
}
@Test
public void testInvalidDatabaseOptions() {
verifyCMD("\nshow tables;\nquit;\n", "Database does not exist: invalidDB",
errS, new String[] { "--database", "invalidDB" }, ERRNO_OK, true);
}
@Test
public void testDatabaseOptions() {
verifyCMD("\nshow tables;\nquit;", "testtbl", os,
new String[] { "--database", "test" }, ERRNO_OK, true);
}
@Test
public void testSourceCmd() {
File f = generateTmpFile(SOURCE_CONTEXT);
verifyCMD("source " + f.getPath() + ";" + "desc testSrcTbl;\nquit;\n",
"sc1", os, new String[] { "--database", "test" }, ERRNO_OK, true);
f.delete();
}
@Test
public void testSourceCmd2() {
File f = generateTmpFile(SOURCE_CONTEXT3);
verifyCMD("source " + f.getPath() + ";" + "desc testSrcTbl3;\nquit;\n",
"sc3", os, new String[] { "--database", "test" }, ERRNO_OK, true);
f.delete();
}
@Test
public void testSourceCmd3() {
File f = generateTmpFile(SOURCE_CONTEXT4);
verifyCMD("source " + f.getPath() + ";" + "desc testSrcTbl4;\nquit;\n", "src", os,
new String[] { "--database", "test" }, ERRNO_OTHER, true);
f.delete();
}
@Test
public void testSqlFromCmd() {
verifyCMD(null, "", os, new String[] { "-e", "show databases;" }, ERRNO_OK, true);
}
@Test
public void testSqlFromCmdWithDBName() {
verifyCMD(null, "testtbl", os,
new String[] { "-e", "show tables;", "--database", "test" }, ERRNO_OK, true);
}
@Test
public void testInvalidOptions() {
verifyCMD(null,
"The '-e' and '-f' options cannot be specified simultaneously", errS,
new String[] { "-e", "show tables;", "-f", "path/to/file" }, ERRNO_ARGS, true);
}
@Test
public void testInvalidOptions2() {
verifyCMD(null, "Unrecognized option: -k", errS, new String[] { "-k" },
ERRNO_ARGS, true);
}
@Test
public void testVariables() {
verifyCMD(
"set system:xxx=5;\nset system:yyy=${system:xxx};\nset system:yyy;", "", os, null, ERRNO_OK, true);
}
@Test
public void testVariablesForSource() {
File f = generateTmpFile(SOURCE_CONTEXT2);
verifyCMD(
"set hiveconf:zzz=" + f.getAbsolutePath() + ";\nsource ${hiveconf:zzz};\ndesc testSrcTbl2;",
"sc2", os, new String[] { "--database", "test" }, ERRNO_OK, true);
f.delete();
}
@Test
public void testErrOutput() {
verifyCMD("show tables;set system:xxx=5;set system:yyy=${system:xxx};\nlss;",
"cannot recognize input near 'lss' '<EOF>' '<EOF>'", errS, null, ERRNO_OTHER, true);
}
@Test
public void testUseCurrentDB1() {
verifyCMD(
"create database if not exists testDB; set hive.cli.print.current.db=true;use testDB;\n"
+ "use default;drop if exists testDB;", "hive (testDB)>", errS, null, ERRNO_OTHER, true);
}
@Test
public void testUseCurrentDB2() {
verifyCMD(
"create database if not exists testDB; set hive.cli.print.current.db=true;use\ntestDB;\nuse default;drop if exists testDB;",
"hive (testDB)>", errS, null, ERRNO_OTHER, true);
}
@Test
public void testUseCurrentDB3() {
verifyCMD(
"create database if not exists testDB; set hive.cli.print.current.db=true;use testDB;\n"
+ "use default;drop if exists testDB;", "hive (testDB)>", errS, null, ERRNO_OTHER, true);
}
@Test
public void testUseInvalidDB() {
verifyCMD("set hive.cli.print.current.db=true;use invalidDB;",
"hive (invalidDB)>", os, null, ERRNO_OTHER, false);
}
@Test
public void testNoErrorDB() {
verifyCMD(null, "Error: Method not supported (state=,code=0)", errS, new String[] { "-e", "show tables;" },
ERRNO_OK, false);
}
private void redirectOutputStream() {
// Setup output stream to redirect output to
os = new ByteArrayOutputStream();
ps = new PrintStream(os);
errS = new ByteArrayOutputStream();
errPs = new PrintStream(errS);
System.setOut(ps);
System.setErr(errPs);
}
private void initFromFile() {
tmp = generateTmpFile(CMD);
if (tmp == null) {
Assert.fail("Fail to create the initial file");
}
executeCMD(new String[] { "-f", "\"" + tmp.getAbsolutePath() + "\"" }, null, 0);
}
private File generateTmpFile(String context) {
File file = null;
BufferedWriter bw = null;
try {
file = File.createTempFile("test", ".sql");
bw = new BufferedWriter(new FileWriter(file));
bw.write(context);
} catch (IOException e) {
LOG.error("Failed to write tmp file due to the exception: " + e);
} finally {
IOUtils.closeQuietly(bw);
}
return file;
}
@Before
public void setup() {
System.setProperty("datanucleus.schema.autoCreateAll", "true");
cli = new HiveCli();
redirectOutputStream();
initFromFile();
}
@After
public void tearDown() {
tmp.delete();
}
}