xonsh/tests/test_history.py

311 lines
9.7 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2016-12-10 22:45:21 +08:00
"""Tests the json history backend."""
# pylint: disable=protected-access
2015-08-11 20:16:02 -04:00
import os
import shlex
2015-08-11 20:16:02 -04:00
2017-01-26 18:24:33 +02:00
import pytest
2015-08-11 20:16:02 -04:00
from xonsh.lazyjson import LazyJSON
2017-02-05 22:02:27 +08:00
from xonsh.history.dummy import DummyHistory
2016-11-27 16:40:39 +08:00
from xonsh.history.json import JsonHistory
2017-02-05 22:02:27 +08:00
from xonsh.history.main import history_main, _xh_parse_args, construct_history
2015-08-11 20:16:02 -04:00
2016-07-16 21:39:32 +03:00
2018-08-30 09:18:49 -05:00
CMDS = ["ls", "cat hello kitty", "abc", "def", "touch me", "grep from me"]
2015-11-27 13:17:57 -07:00
2016-07-16 21:39:32 +03:00
@pytest.yield_fixture
def hist():
2018-08-30 09:18:49 -05:00
h = JsonHistory(
filename="xonsh-HISTORY-TEST.json", here="yup", sessionid="SESSIONID", gc=False
)
2016-07-16 21:39:32 +03:00
yield h
os.remove(h.filename)
def test_hist_init(hist):
"""Test initialization of the shell history."""
2016-07-16 21:39:32 +03:00
with LazyJSON(hist.filename) as lj:
2018-08-30 09:18:49 -05:00
obs = lj["here"]
assert "yup" == obs
2015-08-11 20:16:02 -04:00
2016-07-16 21:39:32 +03:00
def test_hist_append(hist, xonsh_builtins):
"""Verify appending to the history works."""
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = set()
hf = hist.append({"inp": "still alive", "rtn": 0})
2016-06-22 17:41:13 -04:00
assert hf is None
2018-08-30 09:18:49 -05:00
assert "still alive" == hist.buffer[0]["inp"]
assert 0 == hist.buffer[0]["rtn"]
2016-12-10 22:45:21 +08:00
assert 0 == hist.rtns[-1]
2018-08-30 09:18:49 -05:00
hf = hist.append({"inp": "dead now", "rtn": 1})
assert "dead now" == hist.buffer[1]["inp"]
assert 1 == hist.buffer[1]["rtn"]
2016-12-10 22:45:21 +08:00
assert 1 == hist.rtns[-1]
2018-08-30 09:18:49 -05:00
hf = hist.append({"inp": "reborn", "rtn": 0})
assert "reborn" == hist.buffer[2]["inp"]
assert 0 == hist.buffer[2]["rtn"]
2016-12-10 22:45:21 +08:00
assert 0 == hist.rtns[-1]
2015-08-11 20:16:02 -04:00
2016-07-16 21:39:32 +03:00
def test_hist_flush(hist, xonsh_builtins):
"""Verify explicit flushing of the history works."""
2015-08-11 20:16:02 -04:00
hf = hist.flush()
2016-06-22 17:41:13 -04:00
assert hf is None
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = set()
hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"})
2015-08-11 20:16:02 -04:00
hf = hist.flush()
2016-06-22 17:41:13 -04:00
assert hf is not None
2015-08-11 20:16:02 -04:00
while hf.is_alive():
pass
2016-07-16 21:39:32 +03:00
with LazyJSON(hist.filename) as lj:
2018-08-30 09:18:49 -05:00
assert len(lj["cmds"]) == 1
cmd = lj["cmds"][0]
assert cmd["inp"] == "still alive?"
assert not cmd.get("out", None)
def test_hist_flush_with_store_stdout(hist, xonsh_builtins):
"""Verify explicit flushing of the history works."""
hf = hist.flush()
assert hf is None
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = set()
xonsh_builtins.__xonsh_env__["XONSH_STORE_STDOUT"] = True
hist.append({"inp": "still alive?", "rtn": 0, "out": "yes"})
hf = hist.flush()
assert hf is not None
while hf.is_alive():
pass
with LazyJSON(hist.filename) as lj:
2018-08-30 09:18:49 -05:00
assert len(lj["cmds"]) == 1
assert lj["cmds"][0]["inp"] == "still alive?"
assert lj["cmds"][0]["out"].strip() == "yes"
def test_hist_flush_with_hist_control(hist, xonsh_builtins):
"""Verify explicit flushing of the history works."""
hf = hist.flush()
assert hf is None
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = "ignoredups,ignoreerr"
hist.append({"inp": "ls foo1", "rtn": 0})
hist.append({"inp": "ls foo1", "rtn": 1})
hist.append({"inp": "ls foo1", "rtn": 0})
hist.append({"inp": "ls foo2", "rtn": 2})
hist.append({"inp": "ls foo3", "rtn": 0})
hf = hist.flush()
assert hf is not None
while hf.is_alive():
pass
assert len(hist.buffer) == 0
with LazyJSON(hist.filename) as lj:
2018-08-30 09:18:49 -05:00
cmds = list(lj["cmds"])
assert len(cmds) == 2
2018-08-30 09:18:49 -05:00
assert [x["inp"] for x in cmds] == ["ls foo1", "ls foo3"]
assert [x["rtn"] for x in cmds] == [0, 0]
2015-08-11 20:16:02 -04:00
2016-07-16 21:39:32 +03:00
def test_cmd_field(hist, xonsh_builtins):
2015-08-16 21:41:02 -04:00
# in-memory
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = set()
hf = hist.append({"inp": "ls foo", "rtn": 1})
2016-06-22 17:41:13 -04:00
assert hf is None
assert 1 == hist.rtns[0]
assert 1 == hist.rtns[-1]
assert None == hist.outs[-1]
2015-08-16 21:41:02 -04:00
# slice
2016-06-22 17:41:13 -04:00
assert [1] == hist.rtns[:]
2015-08-16 21:41:02 -04:00
# on disk
hf = hist.flush()
2016-06-22 17:41:13 -04:00
assert hf is not None
assert 1 == hist.rtns[0]
assert 1 == hist.rtns[-1]
assert None == hist.outs[-1]
2015-08-11 20:16:02 -04:00
2016-07-23 11:38:20 +03:00
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize(
"inp, commands, offset",
[
("", CMDS, (0, 1)),
("-r", list(reversed(CMDS)), (len(CMDS) - 1, -1)),
("0", CMDS[0:1], (0, 1)),
("1", CMDS[1:2], (1, 1)),
("-2", CMDS[-2:-1], (len(CMDS) - 2, 1)),
("1:3", CMDS[1:3], (1, 1)),
("1::2", CMDS[1::2], (1, 2)),
("-4:-2", CMDS[-4:-2], (len(CMDS) - 4, 1)),
],
)
2016-07-31 02:22:26 +03:00
def test_show_cmd_numerate(inp, commands, offset, hist, xonsh_builtins, capsys):
"""Verify that CLI history commands work."""
2016-07-23 11:38:20 +03:00
base_idx, step = offset
2016-07-16 21:39:32 +03:00
xonsh_builtins.__xonsh_history__ = hist
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = set()
for ts, cmd in enumerate(CMDS): # populate the shell history
2018-08-30 09:18:49 -05:00
hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
2015-11-27 13:17:57 -07:00
2018-08-30 09:18:49 -05:00
exp = (
"{}: {}".format(base_idx + idx * step, cmd)
for idx, cmd in enumerate(list(commands))
)
exp = "\n".join(exp)
2016-07-23 11:38:20 +03:00
2018-08-30 09:18:49 -05:00
history_main(["show", "-n"] + shlex.split(inp))
2016-07-23 11:38:20 +03:00
out, err = capsys.readouterr()
assert out.rstrip() == exp
2016-07-16 21:39:32 +03:00
def test_histcontrol(hist, xonsh_builtins):
2015-11-27 13:17:57 -07:00
"""Test HISTCONTROL=ignoredups,ignoreerr"""
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = "ignoredups,ignoreerr"
2016-06-28 13:47:35 +03:00
assert len(hist.buffer) == 0
# An error, buffer remains empty
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls foo", "rtn": 2})
assert len(hist.buffer) == 1
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 2
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls foo"
2016-06-28 13:47:35 +03:00
# Success
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls foobazz", "rtn": 0})
assert len(hist.buffer) == 2
2018-08-30 09:18:49 -05:00
assert "ls foobazz" == hist.buffer[-1]["inp"]
assert 0 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 0
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls foobazz"
2016-06-28 13:47:35 +03:00
# Error
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls foo", "rtn": 2})
assert len(hist.buffer) == 3
2018-08-30 09:18:49 -05:00
assert "ls foo" == hist.buffer[-1]["inp"]
assert 2 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 2
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls foo"
2016-06-28 13:47:35 +03:00
# File now exists, success
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls foo", "rtn": 0})
assert len(hist.buffer) == 4
2018-08-30 09:18:49 -05:00
assert "ls foo" == hist.buffer[-1]["inp"]
assert 0 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 0
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls foo"
2016-06-28 13:47:35 +03:00
# Success
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls", "rtn": 0})
assert len(hist.buffer) == 5
2018-08-30 09:18:49 -05:00
assert "ls" == hist.buffer[-1]["inp"]
assert 0 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 0
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls"
2016-06-28 13:47:35 +03:00
# Dup
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls", "rtn": 0})
assert len(hist.buffer) == 6
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 0
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls"
2016-06-28 13:47:35 +03:00
# Success
2018-08-30 09:18:49 -05:00
hist.append({"inp": "/bin/ls", "rtn": 0})
assert len(hist.buffer) == 7
2018-08-30 09:18:49 -05:00
assert "/bin/ls" == hist.buffer[-1]["inp"]
assert 0 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 0
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "/bin/ls"
2016-06-28 13:47:35 +03:00
# Error
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls bazz", "rtn": 1})
assert len(hist.buffer) == 8
2018-08-30 09:18:49 -05:00
assert "ls bazz" == hist.buffer[-1]["inp"]
assert 1 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == 1
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls bazz"
2016-06-28 13:47:35 +03:00
# Error
2018-08-30 09:18:49 -05:00
hist.append({"inp": "ls bazz", "rtn": -1})
assert len(hist.buffer) == 9
2018-08-30 09:18:49 -05:00
assert "ls bazz" == hist.buffer[-1]["inp"]
assert -1 == hist.buffer[-1]["rtn"]
2016-12-10 22:45:21 +08:00
assert hist.rtns[-1] == -1
2018-08-30 09:18:49 -05:00
assert hist.inps[-1] == "ls bazz"
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize("args", ["-h", "--help", "show -h", "show --help"])
def test_parse_args_help(args, capsys):
with pytest.raises(SystemExit):
2016-11-27 16:40:39 +08:00
args = _xh_parse_args(shlex.split(args))
2018-08-30 09:18:49 -05:00
assert "show this help message and exit" in capsys.readouterr()[0]
@pytest.mark.parametrize(
"args, exp",
[
("", ("show", "session", [], False, False)),
("1:5", ("show", "session", ["1:5"], False, False)),
("show", ("show", "session", [], False, False)),
("show 15", ("show", "session", ["15"], False, False)),
("show bash 3:5 15:66", ("show", "bash", ["3:5", "15:66"], False, False)),
("show -r", ("show", "session", [], False, True)),
("show -rn bash", ("show", "bash", [], True, True)),
("show -n -r -30:20", ("show", "session", ["-30:20"], True, True)),
("show -n zsh 1:2:3", ("show", "zsh", ["1:2:3"], True, False)),
],
)
def test_parser_show(args, exp):
2016-07-29 19:24:08 +03:00
# use dict instead of argparse.Namespace for pretty pytest diff
2018-08-30 09:18:49 -05:00
exp_ns = {
"action": exp[0],
"session": exp[1],
"slices": exp[2],
"numerate": exp[3],
"reverse": exp[4],
"start_time": None,
"end_time": None,
"datetime_format": None,
"timestamp": False,
"null_byte": False,
}
2016-11-27 16:40:39 +08:00
ns = _xh_parse_args(shlex.split(args))
2016-07-29 19:24:08 +03:00
assert ns.__dict__ == exp_ns
2016-08-27 17:30:53 +03:00
2018-08-30 09:18:49 -05:00
@pytest.mark.parametrize(
"index, exp",
[
(-1, ("grep from me", "out", 0, (5, 6))),
(1, ("cat hello kitty", "out", 0, (1, 2))),
(
slice(1, 3),
[("cat hello kitty", "out", 0, (1, 2)), ("abc", "out", 0, (2, 3))],
),
],
)
2016-08-28 22:17:26 +03:00
def test_history_getitem(index, exp, hist, xonsh_builtins):
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["HISTCONTROL"] = set()
attrs = ("inp", "out", "rtn", "ts")
2016-08-27 17:30:53 +03:00
2018-08-30 09:18:49 -05:00
for ts, cmd in enumerate(CMDS): # populate the shell history
entry = {k: v for k, v in zip(attrs, [cmd, "out", 0, (ts, ts + 1)])}
hist.append(entry)
entry = hist[index]
if isinstance(entry, list):
assert [(e.cmd, e.out, e.rtn, e.ts) for e in entry] == exp
else:
assert (entry.cmd, entry.out, entry.rtn, entry.ts) == exp
2017-02-05 22:02:27 +08:00
def test_construct_history_str(xonsh_builtins):
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["XONSH_HISTORY_BACKEND"] = "dummy"
2017-02-05 22:02:27 +08:00
assert isinstance(construct_history(), DummyHistory)
def test_construct_history_class(xonsh_builtins):
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["XONSH_HISTORY_BACKEND"] = DummyHistory
2017-02-05 22:02:27 +08:00
assert isinstance(construct_history(), DummyHistory)
def test_construct_history_instance(xonsh_builtins):
2018-08-30 09:18:49 -05:00
xonsh_builtins.__xonsh_env__["XONSH_HISTORY_BACKEND"] = DummyHistory()
2017-02-05 22:02:27 +08:00
assert isinstance(construct_history(), DummyHistory)