diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/mitmproxy/addons/test_command_history.py | 265 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_dumper.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_script.py | 11 | ||||
-rw-r--r-- | test/mitmproxy/contentviews/test_api.py | 12 | ||||
-rw-r--r-- | test/mitmproxy/data/addonscripts/configure.py | 21 | ||||
-rw-r--r-- | test/mitmproxy/net/http/test_headers.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http2.py | 65 | ||||
-rw-r--r-- | test/mitmproxy/test_command.py | 9 | ||||
-rw-r--r-- | test/mitmproxy/test_version.py | 2 | ||||
-rw-r--r-- | test/mitmproxy/tools/console/test_commander.py | 405 |
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() |