def test_history_does_not_duplicate_on_interrupt(self, vector, tmp_history_file): """This test verifies that once the cmdloop is broken the history file will not be re-read. The cmdloop can be broken when the user sends a SIGINT or exceptions occur.""" # readline gets its input from tty, so using stdin does not work. shell_cmd = get_shell_cmd(vector) child_proc = spawn_shell(shell_cmd) # set up history child_proc.expect(PROMPT_REGEX) child_proc.sendline("select 1;") child_proc.expect("Fetched 1 row\(s\) in [0-9]+\.?[0-9]*s") child_proc.expect(PROMPT_REGEX) child_proc.sendline("quit;") child_proc.wait() child_proc = spawn_shell(shell_cmd) child_proc.expect(PROMPT_REGEX) # send SIGINT then quit to save history child_proc.sendintr() child_proc.sendline("select 2;") child_proc.expect("Fetched 1 row\(s\) in [0-9]+\.?[0-9]*s") child_proc.sendline("quit;") child_proc.wait() # check history in a new instance p = ImpalaShell(vector) p.send_cmd('history') result = p.get_result().stderr.splitlines() assert "[1]: select 1;" == result[1] assert "[2]: quit;" == result[2] assert "[3]: select 2;" == result[3] assert "[4]: quit;" == result[4]
def test_shell_prompt(self, vector): shell_cmd = get_shell_cmd(vector) proc = spawn_shell(shell_cmd) proc.expect(":{0}] default>".format(get_impalad_port(vector))) self._expect_with_cmd(proc, "use foo", vector, (), 'default') self._expect_with_cmd(proc, "use functional", vector, (), 'functional') self._expect_with_cmd(proc, "use foo", vector, (), 'functional') self._expect_with_cmd(proc, 'use `tpch`', vector, (), 'tpch') self._expect_with_cmd(proc, 'use ` tpch `', vector, (), 'tpch') proc = spawn_shell(shell_cmd + ['-d', 'functional']) proc.expect(":{0}] functional>".format(get_impalad_port(vector))) self._expect_with_cmd(proc, "use foo", vector, (), 'functional') self._expect_with_cmd(proc, "use tpch", vector, (), 'tpch') self._expect_with_cmd(proc, "use foo", vector, (), 'tpch') proc = spawn_shell(shell_cmd + ['-d', ' functional ']) proc.expect(":{0}] functional>".format(get_impalad_port(vector))) proc = spawn_shell(shell_cmd + ['-d', '` functional `']) proc.expect(":{0}] functional>".format(get_impalad_port(vector))) # Start an Impala shell with an invalid DB. proc = spawn_shell(shell_cmd + ['-d', 'foo']) proc.expect(":{0}] default>".format(get_impalad_port(vector))) self._expect_with_cmd(proc, "use foo", vector, (), 'default') self._expect_with_cmd(proc, "use functional", vector, (), 'functional') self._expect_with_cmd(proc, "use foo", vector, (), 'functional') proc.sendeof() proc.wait()
def test_cancellation_mid_command(self, vector): """The test starts with sending in a multi-line input without a command delimiter. When the impala-shell is waiting for more input, the test sends a SIGINT signal (to simulate pressing Ctrl-C) followed by a final query terminated with semicolon. The expected behavior for the impala shell is to discard everything before the SIGINT signal was sent and execute the final query only.""" shell_cmd = get_shell_cmd(vector) queries = [ "line 1\n", "line 2\n", "line 3\n\n", "line 4 and", " 5\n", "line 6\n", "line 7\n", "line 8\n", "line 9\n", "line 10"] # Check when the last line before Ctrl-C doesn't end with newline. child_proc = spawn_shell(shell_cmd) for query in queries: child_proc.send(query) child_proc.sendintr() child_proc.send('select "test without newline";\n') child_proc.expect("test without newline") child_proc.sendline('quit;') child_proc.wait() # Check when the last line before Ctrl-C ends with newline. child_proc = spawn_shell(shell_cmd) for query in queries: child_proc.send(query) # Sending in a newline so it will end with one child_proc.send("\n") # checking if it realy is a new line child_proc.expect(" > ") child_proc.sendintr() child_proc.send('select "test with newline";\n') child_proc.expect("test with newline") child_proc.sendline('quit;') child_proc.wait()
def test_http_codes(self, vector): """Check that the shell prints a good message when using hs2-http protocol and the http server returns a 503 error.""" protocol = vector.get_value("protocol") if protocol != 'hs2-http': pytest.skip() # Start an http server that always returns 503. HOST = "localhost" PORT = get_unused_port() httpd = None http_server_thread = None try: httpd = SocketServer.TCPServer((HOST, PORT), UnavailableRequestHandler) http_server_thread = threading.Thread(target=httpd.serve_forever) http_server_thread.start() # Check that we get a message about the 503 error when we try to connect. shell_args = ["--protocol={0}".format(protocol), "-i{0}:{1}".format(HOST, PORT)] shell_proc = spawn_shell([IMPALA_SHELL_EXECUTABLE] + shell_args) shell_proc.expect("HTTP code 503", timeout=10) finally: # Clean up. if httpd is not None: httpd.shutdown() if http_server_thread is not None: http_server_thread.join()
def test_rerun(self, vector, tmp_history_file): """Smoke test for the 'rerun' command""" child_proc = spawn_shell(get_shell_cmd(vector)) child_proc.expect(":{0}] default>".format(get_impalad_port(vector))) self._expect_with_cmd(child_proc, "@1", vector, ("Command index out of range")) self._expect_with_cmd(child_proc, "rerun -1", vector, ("Command index out of range")) self._expect_with_cmd(child_proc, "select 'first_command'", vector, ("first_command")) self._expect_with_cmd(child_proc, "rerun 1", vector, ("first_command")) self._expect_with_cmd(child_proc, "@ -1", vector, ("first_command")) self._expect_with_cmd(child_proc, "select 'second_command'", vector, ("second_command")) child_proc.sendline('history;') child_proc.expect(":{0}] default>".format(get_impalad_port(vector))) assert '[1]: select \'first_command\';' in child_proc.before assert '[2]: select \'second_command\';' in child_proc.before assert '[3]: history;' in child_proc.before # Rerunning command should not add an entry into history. assert '[4]' not in child_proc.before self._expect_with_cmd(child_proc, "@0", vector, ("Command index out of range")) self._expect_with_cmd(child_proc, "rerun 4", vector, ("Command index out of range")) self._expect_with_cmd(child_proc, "@-4", vector, ("Command index out of range")) self._expect_with_cmd(child_proc, " @ 3 ", vector, ("second_command")) self._expect_with_cmd(child_proc, "@-3", vector, ("first_command")) self._expect_with_cmd(child_proc, "@", vector, ("Command index to be rerun must be an integer.")) self._expect_with_cmd(child_proc, "@1foo", vector, ("Command index to be rerun must be an integer.")) self._expect_with_cmd(child_proc, "@1 2", vector, ("Command index to be rerun must be an integer.")) self._expect_with_cmd(child_proc, "rerun1", vector, ("Syntax error")) child_proc.sendline('quit;') child_proc.wait()
def test_multiline_queries_in_history(self, vector, tmp_history_file): """Test to ensure that multiline queries with comments are preserved in history Ensure that multiline queries are preserved when they're read back from history. Additionally, also test that comments are preserved. """ # readline gets its input from tty, so using stdin does not work. child_proc = spawn_shell(get_shell_cmd(vector)) # List of (input query, expected text in output). # The expected output is usually the same as the input with a number prefix, except # where the shell strips newlines before a semicolon. queries = [ ("select\n1;--comment", "[1]: select\n1;--comment"), ("select 1 --comment\n;", "[2]: select 1 --comment;"), ("select 1 --comment\n\n\n;", "[3]: select 1 --comment;"), ("select /*comment*/\n1;", "[4]: select /*comment*/\n1;"), ("select\n/*comm\nent*/\n1;", "[5]: select\n/*comm\nent*/\n1;")] for query, _ in queries: child_proc.expect(PROMPT_REGEX) child_proc.sendline(query) child_proc.expect("Fetched 1 row\(s\) in [0-9]+\.?[0-9]*s") child_proc.expect(PROMPT_REGEX) child_proc.sendline('quit;') child_proc.wait() p = ImpalaShell(vector) p.send_cmd('history') result = p.get_result() for _, history_entry in queries: assert history_entry in result.stderr, "'%s' not in '%s'" % (history_entry, result.stderr)
def test_local_shell_options(self, vector): """Test that setting the local shell options works""" proc = spawn_shell(get_shell_cmd(vector)) proc.expect(":{0}] default>".format(get_impalad_port(vector))) self._expect_with_cmd(proc, "set", vector, ("LIVE_PROGRESS: True", "LIVE_SUMMARY: False")) self._expect_with_cmd(proc, "set live_progress=true", vector) self._expect_with_cmd(proc, "set", vector, ("LIVE_PROGRESS: True", "LIVE_SUMMARY: False")) self._expect_with_cmd(proc, "set live_summary=1", vector) self._expect_with_cmd(proc, "set", vector, ("LIVE_PROGRESS: True", "LIVE_SUMMARY: True")) self._expect_with_cmd(proc, "set", vector, ("WRITE_DELIMITED: False", "VERBOSE: True")) self._expect_with_cmd(proc, "set", vector, ("DELIMITER: \\t", "OUTPUT_FILE: None")) self._expect_with_cmd(proc, "set write_delimited=true", vector) self._expect_with_cmd(proc, "set", vector, ("WRITE_DELIMITED: True", "VERBOSE: True")) self._expect_with_cmd(proc, "set DELIMITER=,", vector) self._expect_with_cmd(proc, "set", vector, ("DELIMITER: ,", "OUTPUT_FILE: None")) self._expect_with_cmd(proc, "set output_file=/tmp/clmn.txt", vector) self._expect_with_cmd(proc, "set", vector, ("DELIMITER: ,", "OUTPUT_FILE: /tmp/clmn.txt")) proc.sendeof() proc.wait()
def test_history_file_option(self, vector, tmp_history_file): """ Setting the 'tmp_history_file' fixture above means that the IMPALA_HISTFILE environment will be overridden. Here we override that environment by passing the --history_file command line option, ensuring that the history ends up in the appropriate spot. """ with NamedTemporaryFile() as new_hist: shell_cmd = get_shell_cmd(vector) + ["--history_file=%s" % new_hist.name] child_proc = spawn_shell(shell_cmd) child_proc.expect(":{0}] default>".format(get_impalad_port(vector))) self._expect_with_cmd(child_proc, "select 'hi'", vector, ('hi')) child_proc.sendline('exit;') child_proc.expect(pexpect.EOF) history_contents = file(new_hist.name).read() assert "select 'hi'" in history_contents