mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
226 lines
7.5 KiB
Python
226 lines
7.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Tests the xonsh history."""
|
|
# pylint: disable=protected-access
|
|
# TODO: Remove the following pylint directive when it correctly handles calls
|
|
# to nose assert_xxx functions.
|
|
# pylint: disable=no-value-for-parameter
|
|
from __future__ import unicode_literals, print_function
|
|
import io
|
|
import os
|
|
import sys
|
|
|
|
import nose
|
|
from nose.tools import assert_equal, assert_is_none, assert_is_not_none
|
|
|
|
from xonsh.lazyjson import LazyJSON
|
|
from xonsh.history import History
|
|
from xonsh import history
|
|
|
|
from tests.tools import mock_xonsh_env
|
|
|
|
HIST_TEST_KWARGS = dict(sessionid='SESSIONID', gc=False)
|
|
|
|
|
|
def test_hist_init():
|
|
"""Test initialization of the shell history."""
|
|
FNAME = 'xonsh-SESSIONID.json'
|
|
FNAME += '.init'
|
|
History(filename=FNAME, here='yup', **HIST_TEST_KWARGS)
|
|
with LazyJSON(FNAME) as lj:
|
|
obs = lj['here']
|
|
assert_equal('yup', obs)
|
|
os.remove(FNAME)
|
|
|
|
|
|
def test_hist_append():
|
|
"""Verify appending to the history works."""
|
|
FNAME = 'xonsh-SESSIONID.json'
|
|
FNAME += '.append'
|
|
hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS)
|
|
with mock_xonsh_env({'HISTCONTROL': set()}):
|
|
hf = hist.append({'joco': 'still alive'})
|
|
yield assert_is_none, hf
|
|
yield assert_equal, 'still alive', hist.buffer[0]['joco']
|
|
os.remove(FNAME)
|
|
|
|
|
|
def test_hist_flush():
|
|
"""Verify explicit flushing of the history works."""
|
|
FNAME = 'xonsh-SESSIONID.json'
|
|
FNAME += '.flush'
|
|
hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS)
|
|
hf = hist.flush()
|
|
yield assert_is_none, hf
|
|
with mock_xonsh_env({'HISTCONTROL': set()}):
|
|
hist.append({'joco': 'still alive'})
|
|
hf = hist.flush()
|
|
yield assert_is_not_none, hf
|
|
while hf.is_alive():
|
|
pass
|
|
with LazyJSON(FNAME) as lj:
|
|
obs = lj['cmds'][0]['joco']
|
|
yield assert_equal, 'still alive', obs
|
|
os.remove(FNAME)
|
|
|
|
|
|
def test_cmd_field():
|
|
"""Test basic history behavior."""
|
|
FNAME = 'xonsh-SESSIONID.json'
|
|
FNAME += '.cmdfield'
|
|
hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS)
|
|
# in-memory
|
|
with mock_xonsh_env({'HISTCONTROL': set()}):
|
|
hf = hist.append({'rtn': 1})
|
|
yield assert_is_none, hf
|
|
yield assert_equal, 1, hist.rtns[0]
|
|
yield assert_equal, 1, hist.rtns[-1]
|
|
yield assert_equal, None, hist.outs[-1]
|
|
# slice
|
|
yield assert_equal, [1], hist.rtns[:]
|
|
# on disk
|
|
hf = hist.flush()
|
|
yield assert_is_not_none, hf
|
|
yield assert_equal, 1, hist.rtns[0]
|
|
yield assert_equal, 1, hist.rtns[-1]
|
|
yield assert_equal, None, hist.outs[-1]
|
|
os.remove(FNAME)
|
|
|
|
|
|
def test_show_cmd():
|
|
"""Verify that CLI history commands work."""
|
|
FNAME = 'xonsh-SESSIONID.json'
|
|
FNAME += '.show_cmd'
|
|
cmds = ['ls', 'cat hello kitty', 'abc', 'def', 'touch me', 'grep from me']
|
|
|
|
def format_hist_line(idx, cmd):
|
|
"""Construct a history output line."""
|
|
return ' {:d} {:s}\n'.format(idx, cmd)
|
|
|
|
def run_show_cmd(hist_args, commands, base_idx=0, step=1):
|
|
"""Run and evaluate the output of the given show command."""
|
|
stdout.seek(0, io.SEEK_SET)
|
|
stdout.truncate()
|
|
history._main(hist, hist_args)
|
|
stdout.seek(0, io.SEEK_SET)
|
|
hist_lines = stdout.readlines()
|
|
yield assert_equal, len(commands), len(hist_lines)
|
|
for idx, (cmd, actual) in enumerate(zip(commands, hist_lines)):
|
|
expected = format_hist_line(base_idx + idx * step, cmd)
|
|
yield assert_equal, expected, actual
|
|
|
|
hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS)
|
|
stdout = io.StringIO()
|
|
saved_stdout = sys.stdout
|
|
sys.stdout = stdout
|
|
|
|
with mock_xonsh_env({'HISTCONTROL': set()}):
|
|
for cmd in cmds: # populate the shell history
|
|
hist.append({'inp': cmd, 'rtn': 0})
|
|
|
|
# Verify an implicit "show" emits the entire history.
|
|
for x in run_show_cmd([], cmds):
|
|
yield x
|
|
|
|
# Verify an explicit "show" with no qualifiers emits the entire history.
|
|
for x in run_show_cmd(['show'], cmds):
|
|
yield x
|
|
|
|
# Verify an explicit "show" with a reversed qualifier emits the entire
|
|
# history in reverse order.
|
|
for x in run_show_cmd(['show', '-r'], list(reversed(cmds)),
|
|
len(cmds) - 1, -1):
|
|
yield x
|
|
|
|
# Verify that showing a specific history entry relative to the start of the
|
|
# history works.
|
|
for x in run_show_cmd(['show', '0'], [cmds[0]], 0):
|
|
yield x
|
|
for x in run_show_cmd(['show', '1'], [cmds[1]], 1):
|
|
yield x
|
|
|
|
# Verify that showing a specific history entry relative to the end of the
|
|
# history works.
|
|
for x in run_show_cmd(['show', '-2'], [cmds[-2]], len(cmds) - 2):
|
|
yield x
|
|
|
|
# Verify that showing a history range relative to the start of the
|
|
# history works.
|
|
for x in run_show_cmd(['show', '0:2'], cmds[0:2], 0):
|
|
yield x
|
|
for x in run_show_cmd(['show', '1::2'], cmds[1::2], 1, 2):
|
|
yield x
|
|
|
|
# Verify that showing a history range relative to the end of the
|
|
# history works.
|
|
for x in run_show_cmd(['show', '-2:'], cmds[-2:], len(cmds) - 2):
|
|
yield x
|
|
for x in run_show_cmd(['show', '-4:-2'], cmds[-4:-2], len(cmds) - 4):
|
|
yield x
|
|
|
|
sys.stdout = saved_stdout
|
|
os.remove(FNAME)
|
|
|
|
def test_histcontrol():
|
|
"""Test HISTCONTROL=ignoredups,ignoreerr"""
|
|
FNAME = 'xonsh-SESSIONID.json'
|
|
FNAME += '.append'
|
|
hist = History(filename=FNAME, here='yup', **HIST_TEST_KWARGS)
|
|
|
|
with mock_xonsh_env({'HISTCONTROL': 'ignoredups,ignoreerr'}):
|
|
yield assert_equal, len(hist.buffer), 0
|
|
|
|
# An error, buffer remains empty
|
|
hist.append({'inp': 'ls foo', 'rtn': 2})
|
|
yield assert_equal, len(hist.buffer), 0
|
|
|
|
# Success
|
|
hist.append({'inp': 'ls foobazz', 'rtn': 0})
|
|
yield assert_equal, len(hist.buffer), 1
|
|
yield assert_equal, 'ls foobazz', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
# Error
|
|
hist.append({'inp': 'ls foo', 'rtn': 2})
|
|
yield assert_equal, len(hist.buffer), 1
|
|
yield assert_equal, 'ls foobazz', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
# File now exists, success
|
|
hist.append({'inp': 'ls foo', 'rtn': 0})
|
|
yield assert_equal, len(hist.buffer), 2
|
|
yield assert_equal, 'ls foo', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
# Success
|
|
hist.append({'inp': 'ls', 'rtn': 0})
|
|
yield assert_equal, len(hist.buffer), 3
|
|
yield assert_equal, 'ls', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
# Dup
|
|
hist.append({'inp': 'ls', 'rtn': 0})
|
|
yield assert_equal, len(hist.buffer), 3
|
|
|
|
# Success
|
|
hist.append({'inp': '/bin/ls', 'rtn': 0})
|
|
yield assert_equal, len(hist.buffer), 4
|
|
yield assert_equal, '/bin/ls', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
# Error
|
|
hist.append({'inp': 'ls bazz', 'rtn': 1})
|
|
yield assert_equal, len(hist.buffer), 4
|
|
yield assert_equal, '/bin/ls', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
# Error
|
|
hist.append({'inp': 'ls bazz', 'rtn': -1})
|
|
yield assert_equal, len(hist.buffer), 4
|
|
yield assert_equal, '/bin/ls', hist.buffer[-1]['inp']
|
|
yield assert_equal, 0, hist.buffer[-1]['rtn']
|
|
|
|
os.remove(FNAME)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
nose.runmodule()
|