14
14
import os
15
15
import re
16
16
import queue
17
+ import shutil
17
18
import tempfile
19
+ import time
18
20
19
21
from core import cmd
20
22
from core import log_open_sec , log_end_sec , log_init
23
25
from core import Tree
24
26
from core import Tester
25
27
28
+ CONSOLE_WIDTH = None
29
+ BOLD = '\033 [1m'
30
+ RED = '\033 [31m'
31
+ GREEN = '\033 [32m'
32
+ YELLOW = '\033 [33m'
33
+ RESET = '\033 [0m'
34
+
26
35
config = configparser .ConfigParser ()
27
36
28
37
config .add_section ('dirs' )
40
49
help = 'the directory where results will be generated' )
41
50
42
51
52
+ def get_console_width ():
53
+ """ Get console width to avoid line wraps where we can. """
54
+
55
+ global CONSOLE_WIDTH
56
+
57
+ if CONSOLE_WIDTH is None :
58
+ try :
59
+ terminal_size = shutil .get_terminal_size ()
60
+ CONSOLE_WIDTH = terminal_size .columns
61
+ except OSError :
62
+ CONSOLE_WIDTH = 80
63
+ return CONSOLE_WIDTH
64
+
65
+
43
66
def get_series_id (result_dir ):
44
67
""" Find an unused series ID. """
45
68
@@ -49,9 +72,134 @@ def get_series_id(result_dir):
49
72
return i
50
73
51
74
75
+ def print_summary_singleton (print_state , files , full_path , patch_id ):
76
+ """
77
+ Print summaries, single patch mode.
78
+ Output differs if we have one patch vs many because tester will
79
+ run the same test on all the patches in sequence.
80
+ """
81
+
82
+ if len (print_state ['seen' ]) == 1 :
83
+ print ()
84
+ print (BOLD + "Series level tests:" )
85
+
86
+ if patch_id != print_state ['last_patch' ]:
87
+ print_state ['last_patch' ] = patch_id
88
+ print (BOLD + "Patch level tests:" )
89
+
90
+ test_name = os .path .basename (full_path )
91
+ with open (os .path .join (full_path , "retcode" ), "r" , encoding = "utf-8" ) as fp :
92
+ retcode = int (fp .read ())
93
+ desc = None
94
+ if "desc" in files :
95
+ with open (os .path .join (full_path , "desc" ), "r" , encoding = "utf-8" ) as fp :
96
+ desc = fp .read ().strip ().replace ('\n ' , ' ' )
97
+
98
+ print (BOLD + f" { test_name :32} " , end = '' )
99
+ if retcode == 0 :
100
+ print (GREEN + "OKAY " + RESET , end = '' )
101
+ elif retcode == 250 :
102
+ print (YELLOW + "WARNING" + RESET , end = '' )
103
+ else :
104
+ print (RED + "FAIL " + RESET + f"({ retcode } )" , end = '' )
105
+
106
+ if desc :
107
+ if len (desc ) > get_console_width () - 41 :
108
+ print ()
109
+ print ("" , desc , end = '' )
110
+ print ('' , flush = True )
111
+
112
+
113
+ def print_summary_series (print_state , files , full_path , patch_id ):
114
+ """ Print summaries, series mode (more than one patch). """
115
+
116
+ test_name = os .path .basename (full_path )
117
+ if test_name != print_state .get ('last_test' ):
118
+ print_state ['last_test' ] = test_name
119
+ print ()
120
+ print (BOLD + test_name )
121
+
122
+ with open (os .path .join (full_path , "retcode" ), "r" , encoding = "utf-8" ) as fp :
123
+ retcode = int (fp .read ())
124
+ desc = None
125
+ if "desc" in files :
126
+ with open (os .path .join (full_path , "desc" ), "r" , encoding = "utf-8" ) as fp :
127
+ desc = fp .read ().strip ().replace ('\n ' , ' ' )
128
+
129
+ if patch_id >= 0 :
130
+ patch_str = f"Patch { patch_id + 1 :<6} "
131
+ else :
132
+ patch_str = "Full series "
133
+
134
+ failed = False
135
+ print (BOLD + " " + patch_str , end = '' )
136
+ if retcode == 0 :
137
+ print (GREEN + "OKAY " + RESET , end = '' )
138
+ elif retcode == 250 :
139
+ print (YELLOW + "WARNING" + RESET , end = '' )
140
+ else :
141
+ print (RED + "FAIL " + RESET + f"({ retcode } )" , end = '' )
142
+ failed = True
143
+
144
+ if failed or (desc and len (desc ) > get_console_width () - 21 ):
145
+ print ("\n " , end = " " )
146
+ if desc :
147
+ print ("" , desc , end = '' )
148
+ if failed :
149
+ print ("\n " , end = " " )
150
+ if failed :
151
+ print (" Outputs:" , full_path , end = '' )
152
+ print ('' , flush = True )
153
+
154
+
155
+ def print_test_summary (args , series , print_state ):
156
+ """
157
+ Report results based on files created by the tester in the filesystem.
158
+ Track which files we have already as this function should be called
159
+ periodically to check for new results, as the tester runs.
160
+ """
161
+
162
+ seen = print_state .get ('seen' , set ())
163
+ print_state ['seen' ] = seen
164
+ print_state ['last_patch' ] = print_state .get ('last_patch' , - 1 )
165
+
166
+ for full_path , _ , files in os .walk (os .path .join (args .result_dir ,
167
+ str (series .id ))):
168
+ if full_path in seen :
169
+ continue
170
+ if "summary" not in files :
171
+ continue
172
+ seen .add (full_path )
173
+
174
+ rel_path = full_path [len (args .result_dir ) + 1 :].split ('/' )
175
+
176
+ patch_id = - 1
177
+ if len (rel_path ) == 3 :
178
+ patch_id = int (rel_path [- 2 ]) - 1
179
+
180
+ if len (series .patches ) == 1 :
181
+ print_summary_singleton (print_state , files , full_path , patch_id )
182
+ else :
183
+ print_summary_series (print_state , files , full_path , patch_id )
184
+
185
+
186
+ def print_series_info (series ):
187
+ """ Print list of patches """
188
+
189
+ if len (series .patches ) > 2 and series .cover_letter is None :
190
+ print (BOLD + "No cover letter" + RESET )
191
+ elif series .cover_letter :
192
+ print (BOLD + series .title + RESET )
193
+
194
+ for p in series .patches :
195
+ print (" " + f"[{ p .id } ] " + p .title )
196
+
197
+
52
198
def run_tester (args , tree , series ):
53
199
""" Run the tester, report results as they appear """
54
200
201
+ summary_seen = {}
202
+
55
203
try :
56
204
done = queue .Queue ()
57
205
pending = queue .Queue ()
@@ -61,8 +209,15 @@ def run_tester(args, tree, series):
61
209
62
210
pending .put (series )
63
211
pending .put (None )
212
+
213
+ while done .empty ():
214
+ print_test_summary (args , series , summary_seen )
215
+ time .sleep (0.2 )
64
216
except :
217
+ print ("Error / Interrupt detected, asking runner to stop" )
65
218
tester .should_die = True
219
+ tester .join ()
220
+ raise
66
221
finally :
67
222
tester .join ()
68
223
@@ -134,6 +289,8 @@ def main():
134
289
tree_name = "unknown"
135
290
print ("Tree name unknown" )
136
291
292
+ print_series_info (series )
293
+
137
294
try :
138
295
tree = Tree (tree_name , tree_name , args .tree , current_branch = True )
139
296
except cmd .CmdError :
@@ -152,13 +309,6 @@ def main():
152
309
tree .git_checkout (tree .branch )
153
310
tree .git_reset (head , hard = True )
154
311
155
- # Summary hack
156
- os .system (f'for i in $(find { args .result_dir } /{ series .id } -type f -name summary); do ' +
157
- 'dir=$(dirname "$i"); ' +
158
- 'head -n2 "$dir"/summary; ' +
159
- 'cat "$dir"/desc 2>/dev/null; done'
160
- )
161
-
162
312
163
313
if __name__ == "__main__" :
164
314
main ()
0 commit comments