22import os
33import subprocess
44from rich .console import Console
5+ import platform
56
67
78def get_cli_args ():
@@ -60,25 +61,59 @@ def get_cli_args():
6061 required = False ,
6162 help = "Protocols to test" ,
6263 )
63-
64+ parser .add_argument (
65+ "--line-nums" ,
66+ nargs = "+" ,
67+ type = parse_line_nums ,
68+ required = False ,
69+ help = "Specify line numbers or ranges to run commands from" ,
70+ )
71+ parser .add_argument (
72+ "--print-failures" ,
73+ action = "store_true" ,
74+ required = False ,
75+ help = "Prints all the commands of failed tests at the end"
76+ )
6477 return parser .parse_args ()
6578
79+ def parse_line_nums (value ):
80+ line_nums = []
81+ for item in value .split ():
82+ if "-" in item :
83+ start , end = item .split ("-" )
84+ line_nums .extend (range (int (start ), int (end ) + 1 ))
85+ else :
86+ line_nums .append (int (item ))
87+ return line_nums
6688
6789def generate_commands (args ):
6890 lines = []
6991 file_loc = os .path .realpath (os .path .join (os .getcwd (), os .path .dirname (__file__ )))
7092 commands_file = os .path .join (file_loc , "e2e_commands.txt" )
7193
7294 with open (commands_file ) as file :
73- for line in file :
74- if line .startswith ("#" ):
75- continue
76- line = line .strip ()
77- if args .protocols :
78- if line .split ()[1 ] in args .protocols :
95+ if args .line_nums :
96+ flattened_list = list ({num for sublist in args .line_nums for num in sublist })
97+ for i , line in enumerate (file ):
98+ if i + 1 in flattened_list :
99+ if line .startswith ("#" ):
100+ continue
101+ line = line .strip ()
102+ if args .protocols :
103+ if line .split ()[1 ] in args .protocols :
104+ lines .append (replace_command (args , line ))
105+ else :
106+ lines .append (replace_command (args , line ))
107+ else :
108+ for line in file :
109+ if line .startswith ("#" ):
110+ continue
111+ line = line .strip ()
112+ if args .protocols :
113+ if line .split ()[1 ] in args .protocols :
114+ lines .append (replace_command (args , line ))
115+ else :
79116 lines .append (replace_command (args , line ))
80- else :
81- lines .append (replace_command (args , line ))
82117 return lines
83118
84119def replace_command (args , line ):
@@ -93,6 +128,7 @@ def replace_command(args, line):
93128def run_e2e_tests (args ):
94129 console = Console ()
95130 tasks = generate_commands (args )
131+ failures = []
96132
97133 result = subprocess .Popen (
98134 "netexec --version" ,
@@ -107,10 +143,13 @@ def run_e2e_tests(args):
107143 failed = 0
108144
109145 while tasks :
110- task = tasks .pop (0 )
111- console .log (f"Running command: { task !s} " )
146+ task = str (tasks .pop (0 ))
147+ # replace double quotes with single quotes for Linux due to special chars/escaping
148+ if platform .system () == "Linux" :
149+ task = task .replace ('"' , "'" )
150+ console .log (f"Running command: { task } " )
112151 result = subprocess .Popen (
113- str ( task ) ,
152+ task ,
114153 shell = True ,
115154 stdin = subprocess .PIPE ,
116155 stdout = subprocess .PIPE ,
@@ -125,6 +164,7 @@ def run_e2e_tests(args):
125164 passed += 1
126165 else :
127166 console .log (f"[bold red]{ task .strip ()} :cross_mark:[/]" )
167+ failures .append (task .strip ())
128168 failed += 1
129169
130170 if args .errors :
@@ -136,6 +176,11 @@ def run_e2e_tests(args):
136176 if args .verbose :
137177 # this prints sorta janky, but it does its job
138178 console .log (f"[*] Results:\n { text .decode ('utf-8' )} " )
179+
180+ if args .print_failures and failures :
181+ console .log ("[bold red]Failed Commands:" )
182+ for failure in failures :
183+ console .log (f"[bold red]{ failure } " )
139184 console .log (f"Tests [bold green] Passed: { passed } [bold red] Failed: { failed } " )
140185
141186
0 commit comments