org.apache.hadoop.hive.cli.TestCliDriverMethods.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.hive.cli.TestCliDriverMethods.java

Source

/**
 * 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.hadoop.hive.cli;

import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import jline.console.ConsoleReader;
import jline.console.completer.ArgumentCompleter;
import jline.console.completer.Completer;
import junit.framework.TestCase;

import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.hadoop.hive.metastore.api.Schema;
import org.apache.hadoop.hive.ql.CommandNeedRetryException;
import org.apache.hadoop.hive.ql.Driver;
import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse;
import org.apache.hadoop.util.Shell;

// Cannot call class TestCliDriver since that's the name of the generated
// code for the script-based testing
public class TestCliDriverMethods extends TestCase {

    SecurityManager securityManager;

    // Some of these tests require intercepting System.exit() using the SecurityManager.
    // It is safer to  register/unregister our SecurityManager during setup/teardown instead
    // of doing it within the individual test cases.
    @Override
    public void setUp() {
        securityManager = System.getSecurityManager();
        System.setSecurityManager(new NoExitSecurityManager(securityManager));
    }

    @Override
    public void tearDown() {
        System.setSecurityManager(securityManager);
    }

    // If the command has an associated schema, make sure it gets printed to use
    public void testThatCliDriverPrintsHeaderForCommandsWithSchema() throws CommandNeedRetryException {
        Schema mockSchema = mock(Schema.class);
        List<FieldSchema> fieldSchemas = new ArrayList<FieldSchema>();
        String fieldName = "FlightOfTheConchords";
        fieldSchemas.add(new FieldSchema(fieldName, "type", "comment"));

        when(mockSchema.getFieldSchemas()).thenReturn(fieldSchemas);

        PrintStream mockOut = headerPrintingTestDriver(mockSchema);
        // Should have printed out the header for the field schema
        verify(mockOut, times(1)).print(fieldName);
    }

    // If the command has no schema, make sure nothing is printed
    public void testThatCliDriverPrintsNoHeaderForCommandsWithNoSchema() throws CommandNeedRetryException {
        Schema mockSchema = mock(Schema.class);
        when(mockSchema.getFieldSchemas()).thenReturn(null);

        PrintStream mockOut = headerPrintingTestDriver(mockSchema);
        // Should not have tried to print any thing.
        verify(mockOut, never()).print(anyString());
    }

    /**
     * Do the actual testing against a mocked CliDriver based on what type of schema
     *
     * @param mockSchema
     *          Schema to throw against test
     * @return Output that would have been sent to the user
     * @throws CommandNeedRetryException
     *           won't actually be thrown
     */
    private PrintStream headerPrintingTestDriver(Schema mockSchema) throws CommandNeedRetryException {
        CliDriver cliDriver = new CliDriver();

        // We want the driver to try to print the header...

        Configuration conf = mock(Configuration.class);
        when(conf.getBoolean(eq(ConfVars.HIVE_CLI_PRINT_HEADER.varname), anyBoolean())).thenReturn(true);
        cliDriver.setConf(conf);

        Driver proc = mock(Driver.class);

        CommandProcessorResponse cpr = mock(CommandProcessorResponse.class);
        when(cpr.getResponseCode()).thenReturn(0);
        when(proc.run(anyString())).thenReturn(cpr);

        // and then see what happens based on the provided schema
        when(proc.getSchema()).thenReturn(mockSchema);

        CliSessionState mockSS = mock(CliSessionState.class);
        PrintStream mockOut = mock(PrintStream.class);

        mockSS.out = mockOut;

        cliDriver.processLocalCmd("use default;", proc, mockSS);
        return mockOut;
    }

    public void testGetCommandCompletor() {
        Completer[] completors = CliDriver.getCommandCompleter();
        assertEquals(2, completors.length);
        assertTrue(completors[0] instanceof ArgumentCompleter);
        assertTrue(completors[1] instanceof Completer);

        //comletor add space after last delimeter
        List<CharSequence> testList = new ArrayList<CharSequence>(Arrays.asList(new String[] { ")" }));
        completors[1].complete("fdsdfsdf", 0, testList);
        assertEquals(") ", testList.get(0));
        testList = new ArrayList<CharSequence>();
        completors[1].complete("len", 0, testList);
        assertTrue(testList.get(0).toString().endsWith("length("));

        testList = new ArrayList<CharSequence>();
        completors[0].complete("set f", 0, testList);
        assertEquals("set", testList.get(0));

    }

    public void testRun() throws Exception {
        // clean history
        String historyDirectory = System.getProperty("user.home");
        if ((new File(historyDirectory)).exists()) {
            File historyFile = new File(historyDirectory + File.separator + ".hivehistory");
            historyFile.delete();
        }
        HiveConf configuration = new HiveConf();
        configuration.setBoolVar(ConfVars.HIVE_SESSION_HISTORY_ENABLED, true);
        PrintStream oldOut = System.out;
        ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(dataOut));
        PrintStream oldErr = System.err;
        ByteArrayOutputStream dataErr = new ByteArrayOutputStream();
        System.setErr(new PrintStream(dataErr));
        CliSessionState ss = new CliSessionState(configuration);
        CliSessionState.start(ss);
        String[] args = {};

        try {
            new FakeCliDriver().run(args);
            assertTrue(dataOut.toString(), dataOut.toString().contains("test message"));
            assertTrue(dataErr.toString(), dataErr.toString().contains("Hive history file="));
            assertTrue(dataErr.toString(), dataErr.toString().contains("File: fakeFile is not a file."));
            dataOut.reset();
            dataErr.reset();

        } finally {
            System.setOut(oldOut);
            System.setErr(oldErr);

        }

    }

    /**
     * Test commands exit and quit
     */
    public void testQuit() throws Exception {

        CliSessionState ss = new CliSessionState(new HiveConf());
        ss.err = System.err;
        ss.out = System.out;

        try {
            CliSessionState.start(ss);
            CliDriver cliDriver = new CliDriver();
            cliDriver.processCmd("quit");
            fail("should be exit");
        } catch (ExitException e) {
            assertEquals(0, e.getStatus());

        } catch (Exception e) {
            throw e;
        }

        try {
            CliSessionState.start(ss);
            CliDriver cliDriver = new CliDriver();
            cliDriver.processCmd("exit");
            fail("should be exit");
        } catch (ExitException e) {
            assertEquals(0, e.getStatus());

        }

    }

    public void testProcessSelectDatabase() throws Exception {
        CliSessionState sessinState = new CliSessionState(new HiveConf());
        CliSessionState.start(sessinState);
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        sessinState.err = new PrintStream(data);
        sessinState.database = "database";
        CliDriver driver = new CliDriver();

        try {
            driver.processSelectDatabase(sessinState);
            fail("shuld be exit");
        } catch (ExitException e) {
            e.printStackTrace();
            assertEquals(40000, e.getStatus());
        }

        assertTrue(
                data.toString().contains("FAILED: ParseException line 1:4 cannot recognize input near 'database'"));
    }

    public void testprocessInitFiles() throws Exception {
        String oldHiveHome = System.getenv("HIVE_HOME");
        String oldHiveConfDir = System.getenv("HIVE_CONF_DIR");

        File homeFile = File.createTempFile("test", "hive");
        String tmpDir = homeFile.getParentFile().getAbsoluteFile() + File.separator + "TestCliDriverMethods";
        homeFile.delete();
        FileUtils.deleteDirectory(new File(tmpDir));
        homeFile = new File(tmpDir + File.separator + "bin" + File.separator + CliDriver.HIVERCFILE);
        homeFile.getParentFile().mkdirs();
        homeFile.createNewFile();
        FileUtils.write(homeFile, "-- init hive file for test ");
        setEnv("HIVE_HOME", homeFile.getParentFile().getParentFile().getAbsolutePath());
        setEnv("HIVE_CONF_DIR", homeFile.getParentFile().getAbsolutePath());
        CliSessionState sessionState = new CliSessionState(new HiveConf());

        ByteArrayOutputStream data = new ByteArrayOutputStream();

        sessionState.err = new PrintStream(data);
        sessionState.out = System.out;
        try {
            CliSessionState.start(sessionState);
            CliDriver cliDriver = new CliDriver();
            cliDriver.processInitFiles(sessionState);
            assertTrue(
                    data.toString().contains("Putting the global hiverc in $HIVE_HOME/bin/.hiverc is deprecated. "
                            + "Please use $HIVE_CONF_DIR/.hiverc instead."));
            FileUtils.write(homeFile, "bla bla bla");
            // if init file contains incorrect row
            try {
                cliDriver.processInitFiles(sessionState);
                fail("should be exit");
            } catch (ExitException e) {
                assertEquals(40000, e.getStatus());
            }
            setEnv("HIVE_HOME", null);
            try {
                cliDriver.processInitFiles(sessionState);
                fail("should be exit");
            } catch (ExitException e) {
                assertEquals(40000, e.getStatus());
            }

        } finally {
            // restore data
            setEnv("HIVE_HOME", oldHiveHome);
            setEnv("HIVE_CONF_DIR", oldHiveConfDir);
            FileUtils.deleteDirectory(new File(tmpDir));
        }

        File f = File.createTempFile("hive", "test");
        FileUtils.write(f, "bla bla bla");
        try {
            sessionState.initFiles = Arrays.asList(new String[] { f.getAbsolutePath() });
            CliDriver cliDriver = new CliDriver();
            cliDriver.processInitFiles(sessionState);
            fail("should be exit");
        } catch (ExitException e) {
            assertEquals(40000, e.getStatus());
            assertTrue(data.toString().contains("cannot recognize input near 'bla' 'bla' 'bla'"));

        }
    }

    private static void setEnv(String key, String value) throws Exception {
        Class[] classes = Collections.class.getDeclaredClasses();
        Map<String, String> env = System.getenv();
        for (Class cl : classes) {
            if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
                Field field = cl.getDeclaredField("m");
                field.setAccessible(true);
                Object obj = field.get(env);
                Map<String, String> map = (Map<String, String>) obj;
                if (value == null) {
                    map.remove(key);
                } else {
                    map.put(key, value);
                }
            }
        }
    }

    private static class FakeCliDriver extends CliDriver {

        @Override
        protected void setupConsoleReader() throws IOException {
            reader = new FakeConsoleReader();
        }

    }

    private static class FakeConsoleReader extends ConsoleReader {
        private int counter = 0;
        File temp = null;

        public FakeConsoleReader() throws IOException {
            super();

        }

        @Override
        public String readLine(String prompt) throws IOException {
            FileWriter writer;
            switch (counter++) {
            case 0:
                return "!echo test message;";
            case 1:
                temp = File.createTempFile("hive", "test");
                temp.deleteOnExit();
                return "source  " + temp.getAbsolutePath() + ";";
            case 2:
                temp = File.createTempFile("hive", "test");
                temp.deleteOnExit();
                writer = new FileWriter(temp);
                writer.write("bla bla bla");
                writer.close();
                return "list file file://" + temp.getAbsolutePath() + ";";
            case 3:
                return "!echo ";
            case 4:
                return "test message;";
            case 5:
                return "source  fakeFile;";
            case 6:
                temp = File.createTempFile("hive", "test");
                temp.deleteOnExit();
                writer = new FileWriter(temp);
                writer.write("source  fakeFile;");
                writer.close();
                return "list file file://" + temp.getAbsolutePath() + ";";

            // drop table over10k;
            default:
                return null;
            }
        }
    }

    private static class NoExitSecurityManager extends SecurityManager {

        public SecurityManager parentSecurityManager;

        public NoExitSecurityManager(SecurityManager parent) {
            super();
            parentSecurityManager = parent;
            System.setSecurityManager(this);
        }

        @Override
        public void checkPermission(Permission perm, Object context) {
            if (parentSecurityManager != null) {
                parentSecurityManager.checkPermission(perm, context);
            }
        }

        @Override
        public void checkPermission(Permission perm) {
            if (parentSecurityManager != null) {
                parentSecurityManager.checkPermission(perm);
            }
        }

        @Override
        public void checkExit(int status) {
            throw new ExitException(status);
        }
    }

    private static class ExitException extends RuntimeException {
        int status;

        public ExitException(int status) {
            this.status = status;
        }

        public int getStatus() {
            return status;
        }
    }
}