11import typing
22import inspect
3+ import asyncio
4+ from unittest import mock
5+
6+ import mitmproxy .types
37from mitmproxy import command
48from mitmproxy import flow
59from mitmproxy import exceptions
610from mitmproxy .test import tflow
711from mitmproxy .test import taddons
8- import mitmproxy . types
12+
913import io
1014import pytest
1115
@@ -36,6 +40,15 @@ def cmd5(self, choices: typing.Sequence[str]) -> typing.Sequence[str]:
3640 def cmd6 (self , pipe_value : str ) -> str :
3741 return pipe_value
3842
43+ @command .command ("cmd7" )
44+ async def cmd7 (self , foo : str ) -> str :
45+ await asyncio .sleep (0.01 )
46+ return foo
47+
48+ @command .command ("cmd8" )
49+ async def cmd8 (self , foo : str ) -> str :
50+ return 99
51+
3952 @command .command ("subcommand" )
4053 def subcommand (self , cmd : mitmproxy .types .Cmd , * args : mitmproxy .types .Arg ) -> str :
4154 return "ok"
@@ -44,6 +57,10 @@ def subcommand(self, cmd: mitmproxy.types.Cmd, *args: mitmproxy.types.Arg) -> st
4457 def empty (self ) -> None :
4558 pass
4659
60+ @command .command ("empty" )
61+ async def asyncempty (self ) -> None :
62+ pass
63+
4764 @command .command ("varargs" )
4865 def varargs (self , one : str , * var : str ) -> typing .Sequence [str ]:
4966 return list (var )
@@ -82,6 +99,35 @@ def invalidarg(self, u: Unsupported):
8299 pass
83100
84101
102+ class TestAsyncExecutionManager :
103+ def test_add_command (self ):
104+ aem = command .AsyncExecutionManager ()
105+ dummy_command = command .RunningCommand ("addon.command" , mock .Mock ())
106+ aem .add_command (dummy_command )
107+ assert aem .running_cmds == {1 : dummy_command }
108+
109+ def test_stop_command (self ):
110+ aem = command .AsyncExecutionManager ()
111+ dummy_command = command .RunningCommand ("addon.command" , mock .Mock ())
112+ aem .add_command (dummy_command )
113+ with pytest .raises (ValueError , match = "There is not the command" ):
114+ aem .stop_command (100 )
115+
116+ aem .stop_command (1 )
117+ assert aem .running_cmds == {}
118+
119+ def test_get_runnings (self ):
120+ aem = command .AsyncExecutionManager ()
121+ expected_res = []
122+ for i in range (3 ):
123+ cmd = f"addon.command{ i } "
124+ dummy = command .RunningCommand (cmd , mock .Mock ())
125+ aem .add_command (dummy )
126+ expected_res .append ((i + 1 , cmd ))
127+
128+ assert aem .get_running () == expected_res
129+
130+
85131class TestCommand :
86132 def test_typecheck (self ):
87133 with taddons .context (loadcore = False ) as tctx :
@@ -115,9 +161,25 @@ def test_call(self):
115161 with pytest .raises (exceptions .CommandError ):
116162 c .call (["foo" ])
117163
164+ with pytest .raises (exceptions .CommandError , match = "unexpected data" ):
165+ c .call ([123 ])
166+
118167 c = command .Command (cm , "cmd.three" , a .cmd3 )
119168 assert c .call (["1" ]) == 1
120169
170+ @pytest .mark .asyncio
171+ async def test_async_call (self ):
172+ with taddons .context () as tctx :
173+ cm = command .CommandManager (tctx .master )
174+ a = TAddon ()
175+
176+ c = command .Command (cm , "async.empty" , a .asyncempty )
177+ await c .async_call ([])
178+
179+ c = command .Command (cm , "asynccmd.two" , a .cmd8 )
180+ with pytest .raises (exceptions .CommandError , match = "unexpected data" ):
181+ await c .async_call (["foo" ])
182+
121183 def test_parse_partial (self ):
122184 tests = [
123185 [
@@ -301,6 +363,7 @@ def test_simple():
301363 c .add ("one.two" , a .cmd1 )
302364 c .add ("array.command" , a .cmd5 )
303365 c .add ("pipe.command" , a .cmd6 )
366+ c .add ("strasync.command" , a .cmd7 )
304367
305368 assert c .commands ["one.two" ].help == "cmd1 help"
306369 assert (c .execute ("one.two foo" ) == "ret foo" )
@@ -320,6 +383,8 @@ def test_simple():
320383 c .execute ("" )
321384 with pytest .raises (exceptions .CommandError , match = "argument mismatch" ):
322385 c .execute ("one.two too many args" )
386+ with pytest .raises (exceptions .ExecutionError , match = "sync executor" ):
387+ c .execute ("strasync.command abc" )
323388 with pytest .raises (exceptions .CommandError , match = "Unknown" ):
324389 c .call ("nonexistent" )
325390
@@ -331,6 +396,19 @@ def test_simple():
331396 assert fp .getvalue ()
332397
333398
399+ @pytest .mark .asyncio
400+ async def test_async_execute ():
401+ with taddons .context () as tctx :
402+ c = command .CommandManager (tctx .master )
403+ a = TAddon ()
404+ c .add ("strasync.command" , a .cmd7 )
405+
406+ c .async_execute ("strasync.command abc" )
407+ assert c .async_manager .get_running () == [(1 , "strasync.command abc" )]
408+ assert "abc" == await c .async_manager .running_cmds [1 ].task
409+ assert c .async_manager .get_running () == []
410+
411+
334412def test_typename ():
335413 assert command .typename (str ) == "str"
336414 assert command .typename (typing .Sequence [flow .Flow ]) == "[flow]"
0 commit comments