aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/mitmproxy/addons/test_command_history.py265
-rw-r--r--test/mitmproxy/addons/test_dumper.py2
-rw-r--r--test/mitmproxy/addons/test_script.py11
-rw-r--r--test/mitmproxy/contentviews/test_api.py12
-rw-r--r--test/mitmproxy/data/addonscripts/configure.py21
-rw-r--r--test/mitmproxy/net/http/test_headers.py2
-rw-r--r--test/mitmproxy/proxy/protocol/test_http2.py65
-rw-r--r--test/mitmproxy/test_command.py9
-rw-r--r--test/mitmproxy/test_version.py2
-rw-r--r--test/mitmproxy/tools/console/test_commander.py405
10 files changed, 623 insertions, 171 deletions
diff --git a/test/mitmproxy/addons/test_command_history.py b/test/mitmproxy/addons/test_command_history.py
new file mode 100644
index 00000000..df20fba7
--- /dev/null
+++ b/test/mitmproxy/addons/test_command_history.py
@@ -0,0 +1,265 @@
+import os
+
+from mitmproxy.addons import command_history
+from mitmproxy.test import taddons
+
+
+class TestCommandHistory:
+ def test_load_from_file(self, tmpdir):
+ commands = ['cmd1', 'cmd2', 'cmd3']
+ with open(tmpdir.join('command_history'), 'w') as f:
+ f.write("\n".join(commands))
+
+ ch = command_history.CommandHistory()
+ with taddons.context(ch) as tctx:
+ tctx.options.confdir = str(tmpdir)
+ assert ch.history == commands
+
+ def test_add_command(self):
+ history = command_history.CommandHistory()
+
+ history.add_command('cmd1')
+ history.add_command('cmd2')
+
+ assert history.history == ['cmd1', 'cmd2']
+
+ history.add_command('')
+ assert history.history == ['cmd1', 'cmd2']
+
+ def test_get_next_and_prev(self, tmpdir):
+ ch = command_history.CommandHistory()
+
+ with taddons.context(ch) as tctx:
+ tctx.options.confdir = str(tmpdir)
+
+ ch.add_command('cmd1')
+
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+
+ ch.add_command('cmd2')
+
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == 'cmd2'
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+
+ ch.add_command('cmd3')
+
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+ assert ch.get_prev() == 'cmd3'
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == 'cmd2'
+ assert ch.get_next() == 'cmd3'
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+ assert ch.get_prev() == 'cmd3'
+ assert ch.get_prev() == 'cmd2'
+
+ ch.add_command('cmd4')
+
+ assert ch.get_prev() == 'cmd4'
+ assert ch.get_prev() == 'cmd3'
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == 'cmd2'
+ assert ch.get_next() == 'cmd3'
+ assert ch.get_next() == 'cmd4'
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+
+ ch.add_command('cmd5')
+ ch.add_command('cmd6')
+
+ assert ch.get_next() == ''
+ assert ch.get_prev() == 'cmd6'
+ assert ch.get_prev() == 'cmd5'
+ assert ch.get_prev() == 'cmd4'
+ assert ch.get_next() == 'cmd5'
+ assert ch.get_prev() == 'cmd4'
+ assert ch.get_prev() == 'cmd3'
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_next() == 'cmd3'
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == 'cmd2'
+ assert ch.get_next() == 'cmd3'
+ assert ch.get_next() == 'cmd4'
+ assert ch.get_next() == 'cmd5'
+ assert ch.get_next() == 'cmd6'
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+
+ ch.clear_history()
+
+ def test_clear(self, tmpdir):
+ ch = command_history.CommandHistory()
+
+ with taddons.context(ch) as tctx:
+ tctx.options.confdir = str(tmpdir)
+ ch.add_command('cmd1')
+ ch.add_command('cmd2')
+ ch.clear_history()
+
+ saved_commands = ch.get_history()
+ assert saved_commands == []
+
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+ assert ch.get_prev() == ''
+ assert ch.get_prev() == ''
+
+ ch.clear_history()
+
+ def test_filter(self, tmpdir):
+ ch = command_history.CommandHistory()
+
+ with taddons.context(ch) as tctx:
+ tctx.options.confdir = str(tmpdir)
+
+ ch.add_command('cmd1')
+ ch.add_command('cmd2')
+ ch.add_command('abc')
+ ch.set_filter('c')
+
+ assert ch.get_next() == 'c'
+ assert ch.get_next() == 'c'
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == 'cmd2'
+ assert ch.get_next() == 'c'
+ assert ch.get_next() == 'c'
+
+ ch.set_filter('')
+
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+ assert ch.get_prev() == 'abc'
+ assert ch.get_prev() == 'cmd2'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_prev() == 'cmd1'
+ assert ch.get_next() == 'cmd2'
+ assert ch.get_next() == 'abc'
+ assert ch.get_next() == ''
+ assert ch.get_next() == ''
+
+ ch.clear_history()
+
+ def test_multiple_instances(self, tmpdir):
+ ch = command_history.CommandHistory()
+ with taddons.context(ch) as tctx:
+ tctx.options.confdir = str(tmpdir)
+
+ instances = [
+ command_history.CommandHistory(),
+ command_history.CommandHistory(),
+ command_history.CommandHistory()
+ ]
+
+ for i in instances:
+ i.configure('command_history')
+ saved_commands = i.get_history()
+ assert saved_commands == []
+
+ instances[0].add_command('cmd1')
+ saved_commands = instances[0].get_history()
+ assert saved_commands == ['cmd1']
+
+ # These instances haven't yet added a new command, so they haven't
+ # yet reloaded their commands from the command file.
+ # This is expected, because if the user is filtering a command on
+ # another window, we don't want to interfere with that
+ saved_commands = instances[1].get_history()
+ assert saved_commands == []
+ saved_commands = instances[2].get_history()
+ assert saved_commands == []
+
+ # Since the second instanced added a new command, its list of
+ # saved commands has been updated to have the commands from the
+ # first instance + its own commands
+ instances[1].add_command('cmd2')
+ saved_commands = instances[1].get_history()
+ assert saved_commands == ['cmd2']
+
+ saved_commands = instances[0].get_history()
+ assert saved_commands == ['cmd1']
+
+ # Third instance is still empty as it has not yet ran any command
+ saved_commands = instances[2].get_history()
+ assert saved_commands == []
+
+ instances[2].add_command('cmd3')
+ saved_commands = instances[2].get_history()
+ assert saved_commands == ['cmd3']
+
+ instances[0].add_command('cmd4')
+ saved_commands = instances[0].get_history()
+ assert saved_commands == ['cmd1', 'cmd4']
+
+ instances.append(command_history.CommandHistory())
+ instances[3].configure('command_history')
+ saved_commands = instances[3].get_history()
+ assert saved_commands == ['cmd1', 'cmd2', 'cmd3', 'cmd4']
+
+ instances[0].add_command('cmd_before_close')
+ instances.pop(0).done()
+
+ saved_commands = instances[0].get_history()
+ assert saved_commands == ['cmd2']
+
+ instances[0].add_command('new_cmd')
+ saved_commands = instances[0].get_history()
+ assert saved_commands == ['cmd2', 'new_cmd']
+
+ instances.pop(0).done()
+ instances.pop(0).done()
+ instances.pop(0).done()
+
+ _path = os.path.join(tctx.options.confdir, 'command_history')
+ lines = open(_path, 'r').readlines()
+ saved_commands = [cmd.strip() for cmd in lines]
+ assert saved_commands == ['cmd1', 'cmd2', 'cmd3', 'cmd4', 'cmd_before_close', 'new_cmd']
+
+ instances = [
+ command_history.CommandHistory(),
+ command_history.CommandHistory()
+ ]
+
+ for i in instances:
+ i.configure('command_history')
+ i.clear_history()
+ saved_commands = i.get_history()
+ assert saved_commands == []
+
+ instances[0].add_command('cmd1')
+ instances[0].add_command('cmd2')
+ instances[1].add_command('cmd3')
+ instances[1].add_command('cmd4')
+ instances[1].add_command('cmd5')
+
+ saved_commands = instances[1].get_history()
+ assert saved_commands == ['cmd3', 'cmd4', 'cmd5']
+
+ instances.pop().done()
+ instances.pop().done()
+
+ _path = os.path.join(tctx.options.confdir, 'command_history')
+ lines = open(_path, 'r').readlines()
+ saved_commands = [cmd.strip() for cmd in lines]
+ assert saved_commands == ['cmd1', 'cmd2', 'cmd3', 'cmd4', 'cmd5']
diff --git a/test/mitmproxy/addons/test_dumper.py b/test/mitmproxy/addons/test_dumper.py
index 7a41c7b9..841e2a01 100644
--- a/test/mitmproxy/addons/test_dumper.py
+++ b/test/mitmproxy/addons/test_dumper.py
@@ -123,7 +123,7 @@ def test_echo_body():
d = dumper.Dumper(sio, sio_err)
with taddons.context(d) as ctx:
ctx.configure(d, flow_detail=3)
- d._echo_message(f.response)
+ d._echo_message(f.response, f)
t = sio.getvalue()
assert "cut off" in t
diff --git a/test/mitmproxy/addons/test_script.py b/test/mitmproxy/addons/test_script.py
index 05472d9a..61e19174 100644
--- a/test/mitmproxy/addons/test_script.py
+++ b/test/mitmproxy/addons/test_script.py
@@ -137,6 +137,17 @@ class TestScript:
assert await tctx.master.await_log("error.py")
@pytest.mark.asyncio
+ async def test_optionexceptions(self, tdata):
+ with taddons.context() as tctx:
+ sc = script.Script(
+ tdata.path("mitmproxy/data/addonscripts/configure.py"),
+ True,
+ )
+ tctx.master.addons.add(sc)
+ tctx.configure(sc)
+ assert await tctx.master.await_log("Options Error")
+
+ @pytest.mark.asyncio
async def test_addon(self, tdata):
with taddons.context() as tctx:
sc = script.Script(
diff --git a/test/mitmproxy/contentviews/test_api.py b/test/mitmproxy/contentviews/test_api.py
index 3fc06d7c..82fd0672 100644
--- a/test/mitmproxy/contentviews/test_api.py
+++ b/test/mitmproxy/contentviews/test_api.py
@@ -5,6 +5,7 @@ from mitmproxy import contentviews
from mitmproxy.exceptions import ContentViewException
from mitmproxy.net.http import Headers
from mitmproxy.test import tutils
+from mitmproxy.test import tflow
class TestContentView(contentviews.View):
@@ -60,21 +61,22 @@ def test_get_content_view():
def test_get_message_content_view():
+ f = tflow.tflow()
r = tutils.treq()
- desc, lines, err = contentviews.get_message_content_view("raw", r)
+ desc, lines, err = contentviews.get_message_content_view("raw", r, f)
assert desc == "Raw"
- desc, lines, err = contentviews.get_message_content_view("unknown", r)
+ desc, lines, err = contentviews.get_message_content_view("unknown", r, f)
assert desc == "Raw"
r.encode("gzip")
- desc, lines, err = contentviews.get_message_content_view("raw", r)
+ desc, lines, err = contentviews.get_message_content_view("raw", r, f)
assert desc == "[decoded gzip] Raw"
r.headers["content-encoding"] = "deflate"
- desc, lines, err = contentviews.get_message_content_view("raw", r)
+ desc, lines, err = contentviews.get_message_content_view("raw", r, f)
assert desc == "[cannot decode] Raw"
r.content = None
- desc, lines, err = contentviews.get_message_content_view("raw", r)
+ desc, lines, err = contentviews.get_message_content_view("raw", r, f)
assert list(lines) == [[("error", "content missing")]]
diff --git a/test/mitmproxy/data/addonscripts/configure.py b/test/mitmproxy/data/addonscripts/configure.py
new file mode 100644
index 00000000..6f6ac06a
--- /dev/null
+++ b/test/mitmproxy/data/addonscripts/configure.py
@@ -0,0 +1,21 @@
+import typing
+
+from mitmproxy import exceptions
+
+
+class OptionAddon:
+ def load(self, loader):
+ loader.add_option(
+ name = "optionaddon",
+ typespec = typing.Optional[int],
+ default = None,
+ help = "Option Addon",
+ )
+
+ def configure(self, updates):
+ raise exceptions.OptionsError("Options Error")
+
+addons = [
+ OptionAddon()
+]
+
diff --git a/test/mitmproxy/net/http/test_headers.py b/test/mitmproxy/net/http/test_headers.py
index 8fc8b027..5f208dcb 100644
--- a/test/mitmproxy/net/http/test_headers.py
+++ b/test/mitmproxy/net/http/test_headers.py
@@ -88,6 +88,8 @@ class TestHeaders:
headers = Headers(Host="foobarfoo.com", Accept="foo/bar")
replacements = headers.replace("foo", "bar", count=1)
assert replacements == 1
+ assert headers["Host"] == "barbarfoo.com"
+ assert headers["Accept"] == "foo/bar"
def test_parse_content_type():
diff --git a/test/mitmproxy/proxy/protocol/test_http2.py b/test/mitmproxy/proxy/protocol/test_http2.py
index b5f21413..0afa6305 100644
--- a/test/mitmproxy/proxy/protocol/test_http2.py
+++ b/test/mitmproxy/proxy/protocol/test_http2.py
@@ -496,6 +496,71 @@ class TestStreamResetFromServer(_Http2Test):
assert self.master.state.flows[0].response is None
+class TestAllStreamResetsFromServer(_Http2Test):
+
+ current_error_name = None
+ current_error_code = None
+
+ @classmethod
+ def handle_server_event(cls, event, h2_conn, rfile, wfile):
+ if isinstance(event, h2.events.ConnectionTerminated):
+ return False
+ elif isinstance(event, h2.events.RequestReceived):
+ h2_conn.reset_stream(event.stream_id, int(cls.current_error_code))
+ wfile.write(h2_conn.data_to_send())
+ wfile.flush()
+ return True
+
+ def test_all_stream_reset_error_codes(self):
+ for error_name, error_code in h2.errors.ErrorCodes.__members__.items():
+ self.__class__.current_error_name = error_name
+ self.__class__.current_error_code = error_code
+ try:
+ self.run_test_for_stream_reset()
+ except:
+ print('Exception occurred during test for error code {} ({})'.format(
+ error_name, error_code
+ ))
+ raise
+
+ def run_test_for_stream_reset(self):
+ h2_conn = self.setup_connection()
+
+ self._send_request(
+ self.client.wfile,
+ h2_conn,
+ headers=[
+ (':authority', "127.0.0.1:{}".format(self.server.server.address[1])),
+ (':method', 'GET'),
+ (':scheme', 'https'),
+ (':path', '/'),
+ ],
+ )
+
+ self.client.rfile.o.settimeout(1)
+
+ done = False
+ while not done:
+ try:
+ raw = b''.join(http2.read_raw_frame(self.client.rfile))
+ events = h2_conn.receive_data(raw)
+ except exceptions.HttpException:
+ print(traceback.format_exc())
+ assert False
+
+ self.client.wfile.write(h2_conn.data_to_send())
+ self.client.wfile.flush()
+
+ for event in events:
+ if isinstance(event, h2.events.StreamReset):
+ assert event.error_code == int(self.current_error_code)
+ done = True
+
+ h2_conn.close_connection()
+ self.client.wfile.write(h2_conn.data_to_send())
+ self.client.wfile.flush()
+
+
class TestBodySizeLimit(_Http2Test):
@classmethod
diff --git a/test/mitmproxy/test_command.py b/test/mitmproxy/test_command.py
index a432f9e3..7158935a 100644
--- a/test/mitmproxy/test_command.py
+++ b/test/mitmproxy/test_command.py
@@ -512,9 +512,15 @@ class TAttr:
raise IOError
+class TAttr2:
+ def __getattr__(self, item):
+ return TAttr2()
+
+
class TCmds(TAttr):
def __init__(self):
self.TAttr = TAttr()
+ self.TAttr2 = TAttr2()
@command.command("empty")
def empty(self) -> None:
@@ -524,7 +530,8 @@ class TCmds(TAttr):
@pytest.mark.asyncio
async def test_collect_commands():
"""
- This tests for the error thrown by hasattr()
+ This tests for errors thrown by getattr() or __getattr__ implementations
+ that return an object for .command_name.
"""
with taddons.context() as tctx:
c = command.CommandManager(tctx.master)
diff --git a/test/mitmproxy/test_version.py b/test/mitmproxy/test_version.py
index 924f2d96..c0722537 100644
--- a/test/mitmproxy/test_version.py
+++ b/test/mitmproxy/test_version.py
@@ -30,5 +30,5 @@ def test_get_version():
m.return_value = b"tag-2-cafecafe"
assert version.get_dev_version() == "3.0.0rc2 (+2, commit cafecaf)"
- m.side_effect = subprocess.CalledProcessError(-1, 'git describe --long')
+ m.side_effect = subprocess.CalledProcessError(-1, 'git describe --tags --long')
assert version.get_dev_version() == "3.0.0rc2"
diff --git a/test/mitmproxy/tools/console/test_commander.py b/test/mitmproxy/tools/console/test_commander.py
index a77be043..839f81e5 100644
--- a/test/mitmproxy/tools/console/test_commander.py
+++ b/test/mitmproxy/tools/console/test_commander.py
@@ -1,9 +1,30 @@
import pytest
+from mitmproxy import options
+from mitmproxy.addons import command_history
from mitmproxy.test import taddons
from mitmproxy.tools.console.commander import commander
+@pytest.fixture(autouse=True)
+def tctx(tmpdir):
+ # This runs before each test
+ dir_name = tmpdir.mkdir('mitmproxy').dirname
+ confdir = dir_name
+
+ opts = options.Options()
+ opts.set(*[f"confdir={confdir}"])
+ tctx = taddons.context(options=opts)
+ ch = command_history.CommandHistory()
+ tctx.master.addons.add(ch)
+ ch.configure('command_history')
+
+ yield tctx
+
+ # This runs after each test
+ ch.clear_history()
+
+
class TestListCompleter:
def test_cycle(self):
tests = [
@@ -23,178 +44,237 @@ class TestListCompleter:
["b", "ba", "bb", "b"]
],
]
- for start, options, cycle in tests:
- c = commander.ListCompleter(start, options)
+ for start, opts, cycle in tests:
+ c = commander.ListCompleter(start, opts)
for expected in cycle:
assert c.cycle() == expected
class TestCommandEdit:
- def test_open_command_bar(self):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
- try:
- edit.update()
- except IndexError:
- pytest.faied("Unexpected IndexError")
+ def test_open_command_bar(self, tctx):
+ edit = commander.CommandEdit(tctx.master, '')
- def test_insert(self):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
- edit.keypress(1, 'a')
- assert edit.get_edit_text() == 'a'
-
- # Don't let users type a space before starting a command
- # as a usability feature
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
- edit.keypress(1, ' ')
- assert edit.get_edit_text() == ''
+ try:
+ edit.update()
+ except IndexError:
+ pytest.faied("Unexpected IndexError")
- def test_backspace(self):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
- edit.keypress(1, 'a')
- edit.keypress(1, 'b')
- assert edit.get_edit_text() == 'ab'
- edit.keypress(1, 'backspace')
- assert edit.get_edit_text() == 'a'
+ def test_insert(self, tctx):
+ edit = commander.CommandEdit(tctx.master, '')
+ edit.keypress(1, 'a')
+ assert edit.get_edit_text() == 'a'
- def test_left(self):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
- edit.keypress(1, 'a')
- assert edit.cbuf.cursor == 1
- edit.keypress(1, 'left')
- assert edit.cbuf.cursor == 0
+ # Don't let users type a space before starting a command
+ # as a usability feature
+ edit = commander.CommandEdit(tctx.master, '')
+ edit.keypress(1, ' ')
+ assert edit.get_edit_text() == ''
- # Do it again to make sure it won't go negative
- edit.keypress(1, 'left')
- assert edit.cbuf.cursor == 0
+ def test_backspace(self, tctx):
+ edit = commander.CommandEdit(tctx.master, '')
- def test_right(self):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
- edit.keypress(1, 'a')
- assert edit.cbuf.cursor == 1
-
- # Make sure cursor won't go past the text
- edit.keypress(1, 'right')
- assert edit.cbuf.cursor == 1
-
- # Make sure cursor goes left and then back right
- edit.keypress(1, 'left')
- assert edit.cbuf.cursor == 0
- edit.keypress(1, 'right')
- assert edit.cbuf.cursor == 1
-
- def test_up_and_down(self):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- edit = commander.CommandEdit(tctx.master, '', history)
-
- buf = commander.CommandBuffer(tctx.master, 'cmd1')
- history.add_command(buf)
- buf = commander.CommandBuffer(tctx.master, 'cmd2')
- history.add_command(buf)
-
- edit.keypress(1, 'up')
- assert edit.get_edit_text() == 'cmd2'
- edit.keypress(1, 'up')
- assert edit.get_edit_text() == 'cmd1'
- edit.keypress(1, 'up')
- assert edit.get_edit_text() == 'cmd1'
-
- history = commander.CommandHistory(tctx.master, size=5)
- edit = commander.CommandEdit(tctx.master, '', history)
- edit.keypress(1, 'a')
- edit.keypress(1, 'b')
- edit.keypress(1, 'c')
- assert edit.get_edit_text() == 'abc'
- edit.keypress(1, 'up')
- assert edit.get_edit_text() == ''
- edit.keypress(1, 'down')
- assert edit.get_edit_text() == 'abc'
- edit.keypress(1, 'down')
- assert edit.get_edit_text() == 'abc'
-
- history = commander.CommandHistory(tctx.master, size=5)
- edit = commander.CommandEdit(tctx.master, '', history)
- buf = commander.CommandBuffer(tctx.master, 'cmd3')
- history.add_command(buf)
- edit.keypress(1, 'z')
- edit.keypress(1, 'up')
- assert edit.get_edit_text() == 'cmd3'
- edit.keypress(1, 'down')
- assert edit.get_edit_text() == 'z'
-
-
-class TestCommandHistory:
- def fill_history(self, commands):
- with taddons.context() as tctx:
- history = commander.CommandHistory(tctx.master, size=3)
- for c in commands:
- cbuf = commander.CommandBuffer(tctx.master, c)
- history.add_command(cbuf)
- return history, tctx.master
-
- def test_add_command(self):
- commands = ["command1", "command2"]
- history, tctx_master = self.fill_history(commands)
-
- saved_commands = [buf.text for buf in history.saved_commands]
- assert saved_commands == [""] + commands
-
- # The history size is only 3. So, we forget the first
- # one command, when adding fourth command
- cbuf = commander.CommandBuffer(tctx_master, "command3")
- history.add_command(cbuf)
- saved_commands = [buf.text for buf in history.saved_commands]
- assert saved_commands == commands + ["command3"]
-
- # Commands with the same text are not repeated in the history one by one
- history.add_command(cbuf)
- saved_commands = [buf.text for buf in history.saved_commands]
- assert saved_commands == commands + ["command3"]
-
- # adding command in execution mode sets index at the beginning of the history
- # and replace the last command buffer if it is empty or has the same text
- cbuf = commander.CommandBuffer(tctx_master, "")
- history.add_command(cbuf)
- history.index = 0
- cbuf = commander.CommandBuffer(tctx_master, "command4")
- history.add_command(cbuf, True)
- assert history.index == history.last_index
- saved_commands = [buf.text for buf in history.saved_commands]
- assert saved_commands == ["command2", "command3", "command4"]
-
- def test_get_next(self):
- commands = ["command1", "command2"]
- history, tctx_master = self.fill_history(commands)
-
- history.index = -1
- expected_items = ["", "command1", "command2"]
- for i in range(3):
- assert history.get_next().text == expected_items[i]
- # We are at the last item of the history
- assert history.get_next() is None
-
- def test_get_prev(self):
- commands = ["command1", "command2"]
- history, tctx_master = self.fill_history(commands)
-
- expected_items = ["command2", "command1", ""]
- history.index = history.last_index + 1
- for i in range(3):
- assert history.get_prev().text == expected_items[i]
- # We are at the first item of the history
- assert history.get_prev() is None
+ edit.keypress(1, 'a')
+ edit.keypress(1, 'b')
+ assert edit.get_edit_text() == 'ab'
+
+ edit.keypress(1, 'backspace')
+ assert edit.get_edit_text() == 'a'
+
+ def test_left(self, tctx):
+ edit = commander.CommandEdit(tctx.master, '')
+
+ edit.keypress(1, 'a')
+ assert edit.cbuf.cursor == 1
+
+ edit.keypress(1, 'left')
+ assert edit.cbuf.cursor == 0
+
+ # Do it again to make sure it won't go negative
+ edit.keypress(1, 'left')
+ assert edit.cbuf.cursor == 0
+
+ def test_right(self, tctx):
+ edit = commander.CommandEdit(tctx.master, '')
+
+ edit.keypress(1, 'a')
+ assert edit.cbuf.cursor == 1
+
+ # Make sure cursor won't go past the text
+ edit.keypress(1, 'right')
+ assert edit.cbuf.cursor == 1
+
+ # Make sure cursor goes left and then back right
+ edit.keypress(1, 'left')
+ assert edit.cbuf.cursor == 0
+
+ edit.keypress(1, 'right')
+ assert edit.cbuf.cursor == 1
+
+ def test_up_and_down(self, tctx):
+ edit = commander.CommandEdit(tctx.master, '')
+
+ tctx.master.commands.execute('commands.history.clear')
+ tctx.master.commands.execute('commands.history.add "cmd1"')
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit = commander.CommandEdit(tctx.master, '')
+
+ tctx.master.commands.execute('commands.history.clear')
+ tctx.master.commands.execute('commands.history.add "cmd1"')
+ tctx.master.commands.execute('commands.history.add "cmd2"')
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'a')
+ edit.keypress(1, 'b')
+ edit.keypress(1, 'c')
+ assert edit.get_edit_text() == 'abc'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'abc'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'abc'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'abc'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'abc'
+
+ edit = commander.CommandEdit(tctx.master, '')
+ tctx.master.commands.execute('commands.history.add "cmd3"')
+
+ edit.keypress(1, 'z')
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'z'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'z'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'z'
+
+ edit.keypress(1, 'backspace')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'c')
+ assert edit.get_edit_text() == 'c'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'backspace')
+ assert edit.get_edit_text() == ''
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'up')
+ assert edit.get_edit_text() == 'cmd1'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd2'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == 'cmd3'
+
+ edit.keypress(1, 'down')
+ assert edit.get_edit_text() == ''
class TestCommandBuffer:
@@ -255,8 +335,7 @@ class TestCommandBuffer:
cb.cursor = len(cb.text)
cb.cycle_completion()
- ch = commander.CommandHistory(tctx.master, 30)
- ce = commander.CommandEdit(tctx.master, "se", ch)
+ ce = commander.CommandEdit(tctx.master, "se")
ce.keypress(1, 'tab')
ce.update()
ret = ce.cbuf.render()