xonsh/tests/test_history.py

204 lines
6.3 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2015-08-11 20:16:02 -04:00
"""Tests the xonsh history."""
# pylint: disable=protected-access
import io
2015-08-11 20:16:02 -04:00
import os
import sys
import shlex
2015-08-11 20:16:02 -04:00
from xonsh.lazyjson import LazyJSON
2016-07-20 15:16:46 +03:00
from xonsh.history import History, _hist_create_parser, _hist_parse_args
from xonsh import history
2015-08-11 20:16:02 -04:00
2016-07-16 21:39:32 +03:00
import pytest
2015-11-27 13:17:57 -07:00
2016-07-16 21:39:32 +03:00
@pytest.yield_fixture
def hist():
h = History(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:
2015-08-11 20:16:02 -04:00
obs = lj['here']
2016-06-22 17:41:13 -04:00
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."""
2016-06-28 13:47:35 +03:00
xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set()
hf = hist.append({'joco': 'still alive'})
2016-06-22 17:41:13 -04:00
assert hf is None
assert 'still alive' == hist.buffer[0]['joco']
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
2016-06-28 13:47:35 +03:00
xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set()
hist.append({'joco': 'still alive'})
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:
2015-08-11 20:16:02 -04:00
obs = lj['cmds'][0]['joco']
2016-06-22 18:23:36 -04:00
assert 'still alive' == obs
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
2016-06-28 13:47:35 +03:00
xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set()
hf = hist.append({'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
2016-08-27 17:30:53 +03:00
CMDS = ['ls', 'cat hello kitty', 'abc', 'def', 'touch me', 'grep from me']
2016-07-23 11:38:20 +03:00
@pytest.mark.parametrize('inp, commands, offset', [
2016-08-27 17:30:53 +03:00
('', 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-23 11:38:20 +03:00
])
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
2016-06-28 13:47:35 +03:00
xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set()
2016-08-27 17:30:53 +03:00
for ts,cmd in enumerate(CMDS): # populate the shell history
2016-06-28 13:47:35 +03:00
hist.append({'inp': cmd, 'rtn': 0, 'ts':(ts+1, ts+1.5)})
2015-11-27 13:17:57 -07:00
2016-07-31 02:22:26 +03: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
2016-07-31 02:22:26 +03:00
history.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"""
2016-06-28 13:47:35 +03:00
xonsh_builtins.__xonsh_env__['HISTCONTROL'] = 'ignoredups,ignoreerr'
assert len(hist.buffer) == 0
# An error, buffer remains empty
hist.append({'inp': 'ls foo', 'rtn': 2})
assert len(hist.buffer) == 0
# Success
hist.append({'inp': 'ls foobazz', 'rtn': 0})
assert len(hist.buffer) == 1
assert 'ls foobazz' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
# Error
hist.append({'inp': 'ls foo', 'rtn': 2})
assert len(hist.buffer) == 1
assert 'ls foobazz' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
# File now exists, success
hist.append({'inp': 'ls foo', 'rtn': 0})
assert len(hist.buffer) == 2
assert 'ls foo' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
# Success
hist.append({'inp': 'ls', 'rtn': 0})
assert len(hist.buffer) == 3
assert 'ls' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
# Dup
hist.append({'inp': 'ls', 'rtn': 0})
assert len(hist.buffer) == 3
# Success
hist.append({'inp': '/bin/ls', 'rtn': 0})
assert len(hist.buffer) == 4
assert '/bin/ls' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
# Error
hist.append({'inp': 'ls bazz', 'rtn': 1})
assert len(hist.buffer) == 4
assert '/bin/ls' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
# Error
hist.append({'inp': 'ls bazz', 'rtn': -1})
assert len(hist.buffer) == 4
assert '/bin/ls' == hist.buffer[-1]['inp']
assert 0 == hist.buffer[-1]['rtn']
@pytest.mark.parametrize('args', [ '-h', '--help', 'show -h', 'show --help'])
def test_parse_args_help(args, capsys):
with pytest.raises(SystemExit):
2016-07-20 15:16:46 +03:00
args = _hist_parse_args(shlex.split(args))
assert 'show this help message and exit' in capsys.readouterr()[0]
@pytest.mark.parametrize('args, exp', [
2016-07-29 19:24:08 +03:00
('', ('show', 'session', [], False, False)),
2016-07-30 23:29:53 +03:00
('1:5', ('show', 'session', ['1:5'], False, False)),
2016-07-29 19:24:08 +03:00
('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
exp_ns = {'action': exp[0],
'session': exp[1],
'slices': exp[2],
'numerate': exp[3],
2016-08-01 12:09:48 +03:00
'reverse': exp[4],
'start_time': None,
2016-08-09 21:26:08 +03:00
'end_time': None,
2016-08-10 17:20:33 +03:00
'datetime_format': None,
'timestamp': False}
2016-07-29 19:24:08 +03:00
ns = _hist_parse_args(shlex.split(args))
assert ns.__dict__ == exp_ns
2016-08-27 17:30:53 +03:00
# CMDS = ['ls', 'cat hello kitty', 'abc', 'def', 'touch me', 'grep from me']
def test_history_getitem(hist, xonsh_builtins):
xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set()
for ts,cmd in enumerate(CMDS): # populate the shell history
hist.append({'inp': cmd, 'rtn': 0, 'ts':(ts+1, ts+1.5)})
# indexing
assert hist[-1] == 'grep from me'
assert hist['hello'] == 'cat hello kitty'
# word parts
assert hist[-1, -1] == 'me'
assert hist['hello', 1] == 'hello'