55import os
66import sys
77import urllib .parse
8+ import zipfile
89from xml .etree import ElementTree as ET
910from mute_utils import mute_target , pattern_to_re
1011from junit_utils import add_junit_link_property , is_faulty_testcase
@@ -53,6 +54,10 @@ class YTestReportTrace:
5354 def __init__ (self , out_root ):
5455 self .out_root = out_root
5556 self .traces = {}
57+ self .logs_dir = None
58+
59+ def abs_path (self , path ):
60+ return path .replace ("$(BUILD_ROOT)" , self .out_root )
5661
5762 def load (self , subdir ):
5863 test_results_dir = os .path .join (self .out_root , f"{ subdir } /test-results/" )
@@ -61,6 +66,7 @@ def load(self, subdir):
6166 log_print (f"Directory { test_results_dir } doesn't exist" )
6267 return
6368
69+ # find the test result
6470 for folder in os .listdir (test_results_dir ):
6571 fn = os .path .join (self .out_root , test_results_dir , folder , "ytest.report.trace" )
6672
@@ -76,6 +82,9 @@ def load(self, subdir):
7682 subtest = event ["subtest" ]
7783 cls = cls .replace ("::" , "." )
7884 self .traces [(cls , subtest )] = event
85+ logs_dir = self .abs_path (event ['logs' ]['logsdir' ])
86+ self .logs_dir = logs_dir
87+ break
7988
8089 def has (self , cls , name ):
8190 return (cls , name ) in self .traces
@@ -93,7 +102,7 @@ def get_logs(self, cls, name):
93102 if k == "logsdir" :
94103 continue
95104
96- result [k ] = path . replace ( "$(BUILD_ROOT)" , self .out_root )
105+ result [k ] = self .abs_path ( path )
97106
98107 return result
99108
@@ -135,7 +144,26 @@ def save_log(build_root, fn, out_dir, log_url_prefix, trunc_size):
135144 return f"{ log_url_prefix } { quoted_fpath } "
136145
137146
138- def transform (fp , mute_check : YaMuteCheck , ya_out_dir , save_inplace , log_url_prefix , log_out_dir , log_trunc_size ):
147+ def save_zip (suite_name , out_dir , url_prefix , logs_dir ):
148+ arc_name = f"{ suite_name .replace ('/' , '-' )} .zip"
149+
150+ arc_fn = os .path .join (out_dir , arc_name )
151+
152+ zf = zipfile .ZipFile (arc_fn , mode = "w" , compression = zipfile .ZIP_DEFLATED , compresslevel = 9 )
153+
154+ log_print (f"put { logs_dir } into { arc_name } " )
155+ for root , dirs , files in os .walk (logs_dir ):
156+ for f in files :
157+ filename = os .path .join (root , f )
158+ zf .write (filename , os .path .relpath (filename , logs_dir ))
159+ zf .close ()
160+
161+ quoted_fpath = urllib .parse .quote (arc_name )
162+ return f"{ url_prefix } { quoted_fpath } "
163+
164+
165+ def transform (fp , mute_check : YaMuteCheck , ya_out_dir , save_inplace , log_url_prefix , log_out_dir , log_trunc_size ,
166+ test_stuff_out , test_stuff_prefix ):
139167 tree = ET .parse (fp )
140168 root = tree .getroot ()
141169
@@ -144,11 +172,14 @@ def transform(fp, mute_check: YaMuteCheck, ya_out_dir, save_inplace, log_url_pre
144172 traces = YTestReportTrace (ya_out_dir )
145173 traces .load (suite_name )
146174
175+ has_fail_tests = False
176+
147177 for case in suite .findall ("testcase" ):
148178 test_name = case .get ("name" )
149179 case .set ("classname" , suite_name )
150180
151181 is_fail = is_faulty_testcase (case )
182+ has_fail_tests |= is_fail
152183
153184 if mute_check (suite_name , test_name ):
154185 log_print ("mute" , suite_name , test_name )
@@ -164,6 +195,16 @@ def transform(fp, mute_check: YaMuteCheck, ya_out_dir, save_inplace, log_url_pre
164195 url = save_log (ya_out_dir , fn , log_out_dir , log_url_prefix , log_trunc_size )
165196 add_junit_link_property (case , name , url )
166197
198+ if has_fail_tests :
199+ if not traces .logs_dir :
200+ log_print (f"no logsdir for { suite_name } " )
201+ continue
202+
203+ url = save_zip (suite_name , test_stuff_out , test_stuff_prefix , traces .logs_dir )
204+
205+ for case in suite .findall ("testcase" ):
206+ add_junit_link_property (case , 'logsdir' , url )
207+
167208 if save_inplace :
168209 tree .write (fp .name )
169210 else :
@@ -187,6 +228,8 @@ def main():
187228 help = "truncate log after specific size, 0 disables truncation" ,
188229 )
189230 parser .add_argument ("--ya-out" , help = "ya make output dir (for searching logs and artifacts)" )
231+ parser .add_argument ('--test-stuff-out' , help = 'output folder for archive testing_out_stuff' )
232+ parser .add_argument ('--test-stuff-prefix' , help = 'url prefix for testing_out_stuff' )
190233 parser .add_argument ("in_file" , type = argparse .FileType ("r" ))
191234
192235 args = parser .parse_args ()
@@ -204,6 +247,8 @@ def main():
204247 args .log_url_prefix ,
205248 args .log_out_dir ,
206249 args .log_trunc_size ,
250+ args .test_stuff_out ,
251+ args .test_stuff_prefix ,
207252 )
208253
209254
0 commit comments