1*33de042dSApple OSS Distributions#!/usr/bin/python3 2*33de042dSApple OSS Distributions 3*33de042dSApple OSS Distributions# format_vm_parameter_validation.py 4*33de042dSApple OSS Distributions# Pretty-print the output of tests/vm/vm_parameter_validation.c 5*33de042dSApple OSS Distributions# 6*33de042dSApple OSS Distributions# usage: 7*33de042dSApple OSS Distributions# vm_parameter_validation | format_vm_parameter_validation.py 8*33de042dSApple OSS Distributions 9*33de042dSApple OSS Distributionsimport re 10*33de042dSApple OSS Distributionsimport sys 11*33de042dSApple OSS Distributionsimport copy 12*33de042dSApple OSS Distributionsimport itertools 13*33de042dSApple OSS Distributions 14*33de042dSApple OSS Distributions# magic return values used for in-band signalling 15*33de042dSApple OSS Distributions# fixme duplicated in vm_parameter_validation.c 16*33de042dSApple OSS Distributions# fixme also duplicated in other_return_values below 17*33de042dSApple OSS DistributionsRESULT_SUCCESS = 0 18*33de042dSApple OSS DistributionsRESULT_BUSTED = -99 19*33de042dSApple OSS DistributionsRESULT_IGNORED = -98 20*33de042dSApple OSS DistributionsRESULT_ZEROSIZE = -97 21*33de042dSApple OSS DistributionsRESULT_PANIC = -96 22*33de042dSApple OSS DistributionsRESULT_GUARD = -95 23*33de042dSApple OSS DistributionsRESULT_MISMATCH = -94 24*33de042dSApple OSS DistributionsRESULT_OUT_PARAM_BAD = -93 25*33de042dSApple OSS DistributionsRESULT_MACH_SEND_INVALID_MEMORY = 0x1000000c 26*33de042dSApple OSS Distributions 27*33de042dSApple OSS Distributions# output formatting 28*33de042dSApple OSS Distributionsformat_result = { 29*33de042dSApple OSS Distributions RESULT_SUCCESS : ' .', 30*33de042dSApple OSS Distributions RESULT_BUSTED : ' **', 31*33de042dSApple OSS Distributions RESULT_MISMATCH : ' ##', 32*33de042dSApple OSS Distributions RESULT_IGNORED : ' ', 33*33de042dSApple OSS Distributions RESULT_ZEROSIZE : ' o', 34*33de042dSApple OSS Distributions RESULT_PANIC : ' pp', 35*33de042dSApple OSS Distributions RESULT_GUARD : ' gg', 36*33de042dSApple OSS Distributions RESULT_OUT_PARAM_BAD: ' ot', 37*33de042dSApple OSS Distributions RESULT_MACH_SEND_INVALID_MEMORY : ' mi', 38*33de042dSApple OSS Distributions} 39*33de042dSApple OSS Distributions 40*33de042dSApple OSS Distributionsformat_default = '%3d' 41*33de042dSApple OSS Distributionsformat_col_width = 3 42*33de042dSApple OSS Distributionsformat_empty_col = format_col_width * ' ' 43*33de042dSApple OSS Distributionsformat_indent_width = 4 44*33de042dSApple OSS Distributionsformat_indent = format_indent_width * ' ' 45*33de042dSApple OSS Distributions 46*33de042dSApple OSS Distributions 47*33de042dSApple OSS Distributions# record the result of one trial: 48*33de042dSApple OSS Distributions# ret: the return value from the tested function 49*33de042dSApple OSS Distributions# parameters: array of the input parameter names for that trial 50*33de042dSApple OSS Distributions# (for example ["start PGSZ-2", "size -1"]) 51*33de042dSApple OSS Distributionsclass Result: 52*33de042dSApple OSS Distributions def __init__(self, new_ret, new_parameters): 53*33de042dSApple OSS Distributions self.ret = new_ret 54*33de042dSApple OSS Distributions self.parameters = new_parameters 55*33de042dSApple OSS Distributions def __repr__(self): 56*33de042dSApple OSS Distributions return str(self.ret) + " = " + str(self.parameters) 57*33de042dSApple OSS Distributions 58*33de042dSApple OSS Distributions# record the results of all trials in one test 59*33de042dSApple OSS Distributions# testname: the name of the test (including the function being tested) 60*33de042dSApple OSS Distributions# config: a string describing OS, CPU, etc 61*33de042dSApple OSS Distributions# compat: code for error compatibility 62*33de042dSApple OSS Distributions# results: an array of Result, one per trial 63*33de042dSApple OSS Distributionsclass Test: 64*33de042dSApple OSS Distributions def __init__(self, new_name, new_config, new_compat, new_results = []): 65*33de042dSApple OSS Distributions self.testname = new_name 66*33de042dSApple OSS Distributions self.config = new_config 67*33de042dSApple OSS Distributions self.compat = new_compat 68*33de042dSApple OSS Distributions self.results = new_results 69*33de042dSApple OSS Distributions 70*33de042dSApple OSS Distributions# print column labels under some output 71*33de042dSApple OSS Distributions# example output given indent=2 col_width=4 labels=[foo,bar,baz,qux]: 72*33de042dSApple OSS Distributions# | | | | 73*33de042dSApple OSS Distributions# | | | qux 74*33de042dSApple OSS Distributions# | | baz 75*33de042dSApple OSS Distributions# | bar 76*33de042dSApple OSS Distributions# foo 77*33de042dSApple OSS Distributionsdef print_column_labels(labels, indent_width, col_width): 78*33de042dSApple OSS Distributions indent = indent_width * ' ' 79*33de042dSApple OSS Distributions empty_column = '|' + (col_width-1) * ' ' 80*33de042dSApple OSS Distributions 81*33de042dSApple OSS Distributions unprinted = len(labels) 82*33de042dSApple OSS Distributions print(indent + unprinted*empty_column) 83*33de042dSApple OSS Distributions 84*33de042dSApple OSS Distributions for label in reversed(labels): 85*33de042dSApple OSS Distributions unprinted -= 1 86*33de042dSApple OSS Distributions print(indent + unprinted*empty_column + label) 87*33de042dSApple OSS Distributions 88*33de042dSApple OSS Distributions# pretty-print one function return code 89*33de042dSApple OSS Distributionsdef print_one_result(ret): 90*33de042dSApple OSS Distributions if ret in format_result: 91*33de042dSApple OSS Distributions print(format_result[ret], end='') 92*33de042dSApple OSS Distributions else: 93*33de042dSApple OSS Distributions print(format_default % (ret), end='') 94*33de042dSApple OSS Distributions 95*33de042dSApple OSS Distributions# choose the appropriate error code table for a test 96*33de042dSApple OSS Distributions# (either errno_return_values or kern_return_values) 97*33de042dSApple OSS Distributionsdef error_code_values_for_test(test): 98*33de042dSApple OSS Distributions errno_fns = ['mprotect', 'msync', 'minherit', 'mincore', 'mlock', 'munlock', 99*33de042dSApple OSS Distributions 'mmap', 'munmap', 'mremap_encrypted', 'vslock', 'vsunlock', 100*33de042dSApple OSS Distributions 'madvise', 'useracc'] 101*33de042dSApple OSS Distributions for fn in errno_fns: 102*33de042dSApple OSS Distributions if test.testname.startswith(fn): 103*33de042dSApple OSS Distributions return errno_return_values 104*33de042dSApple OSS Distributions else: 105*33de042dSApple OSS Distributions return kern_return_values 106*33de042dSApple OSS Distributions 107*33de042dSApple OSS Distributions# print a helpful description of the return values seen in results 108*33de042dSApple OSS Distributions# fixme these won't include RESULT_MISMATCH 109*33de042dSApple OSS Distributionsdef print_legend(test): 110*33de042dSApple OSS Distributions # find all error codes represented in the results 111*33de042dSApple OSS Distributions codes = {} 112*33de042dSApple OSS Distributions for result in test.results: 113*33de042dSApple OSS Distributions codes[result.ret] = True 114*33de042dSApple OSS Distributions 115*33de042dSApple OSS Distributions known_return_values = error_code_values_for_test(test) 116*33de042dSApple OSS Distributions 117*33de042dSApple OSS Distributions # print the names of the detected error codes 118*33de042dSApple OSS Distributions output = [] 119*33de042dSApple OSS Distributions for code in sorted(codes.keys()): 120*33de042dSApple OSS Distributions if code in known_return_values: 121*33de042dSApple OSS Distributions output.append(str(code) + ': ' + known_return_values[code]) 122*33de042dSApple OSS Distributions elif code in other_return_values: 123*33de042dSApple OSS Distributions output.append(other_return_values[code]) 124*33de042dSApple OSS Distributions elif code != 0: 125*33de042dSApple OSS Distributions output.append(str(code) + ': ????') 126*33de042dSApple OSS Distributions 127*33de042dSApple OSS Distributions print(format_indent + '(' + ', '.join(output) + ')') 128*33de042dSApple OSS Distributions 129*33de042dSApple OSS Distributions# display names for error codes returned in errno 130*33de042dSApple OSS Distributionserrno_return_values = { 131*33de042dSApple OSS Distributions 1: 'EPERM', 132*33de042dSApple OSS Distributions 9: 'EBADF', 133*33de042dSApple OSS Distributions 12: 'ENOMEM', 134*33de042dSApple OSS Distributions 13: 'EACCES', 135*33de042dSApple OSS Distributions 14: 'EFAULT', 136*33de042dSApple OSS Distributions 22: 'EINVAL', 137*33de042dSApple OSS Distributions} 138*33de042dSApple OSS Distributions 139*33de042dSApple OSS Distributions# display names for error codes returned in kern_return_t 140*33de042dSApple OSS Distributionskern_return_values = { 141*33de042dSApple OSS Distributions 1: 'KERN_INVALID_ADDRESS', 142*33de042dSApple OSS Distributions 2: 'KERN_PROTECTION_FAILURE', 143*33de042dSApple OSS Distributions 3: 'KERN_NO_SPACE', 144*33de042dSApple OSS Distributions 4: 'KERN_INVALID_ARGUMENT', 145*33de042dSApple OSS Distributions 5: 'KERN_FAILURE', 146*33de042dSApple OSS Distributions 6: 'KERN_RESOURCE_SHORTAGE', 147*33de042dSApple OSS Distributions 7: 'KERN_NOT_RECEIVER', 148*33de042dSApple OSS Distributions 8: 'KERN_NO_ACCESS', 149*33de042dSApple OSS Distributions 9: 'KERN_MEMORY_FAILURE', 150*33de042dSApple OSS Distributions 10: 'KERN_MEMORY_ERROR', 151*33de042dSApple OSS Distributions 11: 'KERN_ALREADY_IN_SET', 152*33de042dSApple OSS Distributions 12: 'KERN_NOT_IN_SET', 153*33de042dSApple OSS Distributions 13: 'KERN_NAME_EXISTS', 154*33de042dSApple OSS Distributions 14: 'KERN_ABORTED', 155*33de042dSApple OSS Distributions 15: 'KERN_INVALID_NAME', 156*33de042dSApple OSS Distributions 16: 'KERN_INVALID_TASK', 157*33de042dSApple OSS Distributions 17: 'KERN_INVALID_RIGHT', 158*33de042dSApple OSS Distributions 18: 'KERN_INVALID_VALUE', 159*33de042dSApple OSS Distributions 19: 'KERN_UREFS_OVERFLOW', 160*33de042dSApple OSS Distributions 20: 'KERN_INVALID_CAPABILITY', 161*33de042dSApple OSS Distributions 21: 'KERN_RIGHT_EXISTS', 162*33de042dSApple OSS Distributions 22: 'KERN_INVALID_HOST', 163*33de042dSApple OSS Distributions 23: 'KERN_MEMORY_PRESENT', 164*33de042dSApple OSS Distributions 24: 'KERN_MEMORY_DATA_MOVED', 165*33de042dSApple OSS Distributions 25: 'KERN_MEMORY_RESTART_COPY', 166*33de042dSApple OSS Distributions 26: 'KERN_INVALID_PROCESSOR_SET', 167*33de042dSApple OSS Distributions 27: 'KERN_POLICY_LIMIT', 168*33de042dSApple OSS Distributions 28: 'KERN_INVALID_POLICY', 169*33de042dSApple OSS Distributions 29: 'KERN_INVALID_OBJECT', 170*33de042dSApple OSS Distributions 30: 'KERN_ALREADY_WAITING', 171*33de042dSApple OSS Distributions 31: 'KERN_DEFAULT_SET', 172*33de042dSApple OSS Distributions 32: 'KERN_EXCEPTION_PROTECTED', 173*33de042dSApple OSS Distributions 33: 'KERN_INVALID_LEDGER', 174*33de042dSApple OSS Distributions 34: 'KERN_INVALID_MEMORY_CONTROL', 175*33de042dSApple OSS Distributions 35: 'KERN_INVALID_SECURITY', 176*33de042dSApple OSS Distributions 36: 'KERN_NOT_DEPRESSED', 177*33de042dSApple OSS Distributions 37: 'KERN_TERMINATED', 178*33de042dSApple OSS Distributions 38: 'KERN_LOCK_SET_DESTROYED', 179*33de042dSApple OSS Distributions 39: 'KERN_LOCK_UNSTABLE', 180*33de042dSApple OSS Distributions 40: 'KERN_LOCK_OWNED', 181*33de042dSApple OSS Distributions 41: 'KERN_LOCK_OWNED_SELF', 182*33de042dSApple OSS Distributions 42: 'KERN_SEMAPHORE_DESTROYED', 183*33de042dSApple OSS Distributions 43: 'KERN_RPC_SERVER_TERMINATED', 184*33de042dSApple OSS Distributions 44: 'KERN_RPC_TERMINATE_ORPHAN', 185*33de042dSApple OSS Distributions 45: 'KERN_RPC_CONTINUE_ORPHAN', 186*33de042dSApple OSS Distributions 46: 'KERN_NOT_SUPPORTED', 187*33de042dSApple OSS Distributions 47: 'KERN_NODE_DOWN', 188*33de042dSApple OSS Distributions 48: 'KERN_NOT_WAITING', 189*33de042dSApple OSS Distributions 49: 'KERN_OPERATION_TIMED_OUT', 190*33de042dSApple OSS Distributions 50: 'KERN_CODESIGN_ERROR', 191*33de042dSApple OSS Distributions 51: 'KERN_POLICY_STATIC', 192*33de042dSApple OSS Distributions 52: 'KERN_INSUFFICIENT_BUFFER_SIZE', 193*33de042dSApple OSS Distributions 53: 'KERN_DENIED', 194*33de042dSApple OSS Distributions 54: 'KERN_MISSING_KC', 195*33de042dSApple OSS Distributions 55: 'KERN_INVALID_KC', 196*33de042dSApple OSS Distributions 56: 'KERN_NOT_FOUND', 197*33de042dSApple OSS Distributions 100: 'KERN_RETURN_MAX', 198*33de042dSApple OSS Distributions -304: 'MIG_BAD_ARGUMENTS (server type check failure)', 199*33de042dSApple OSS Distributions 0x1000000c : 'MACH_SEND_INVALID_MEMORY', 200*33de042dSApple OSS Distributions} 201*33de042dSApple OSS Distributions 202*33de042dSApple OSS Distributions# display names for the special return values used by the test machinery 203*33de042dSApple OSS Distributionsother_return_values = { 204*33de042dSApple OSS Distributions RESULT_BUSTED: format_result[RESULT_BUSTED].lstrip() + ': trial broken, not performed', 205*33de042dSApple OSS Distributions RESULT_IGNORED: '<empty> trial ignored, not performed', 206*33de042dSApple OSS Distributions RESULT_ZEROSIZE: format_result[RESULT_ZEROSIZE].lstrip() + ': size == 0', 207*33de042dSApple OSS Distributions RESULT_PANIC: format_result[RESULT_PANIC].lstrip() + ': trial is believed to panic, not performed', 208*33de042dSApple OSS Distributions RESULT_GUARD: format_result[RESULT_GUARD].lstrip() + ': trial is believed to throw EXC_GUARD, not performed', 209*33de042dSApple OSS Distributions RESULT_OUT_PARAM_BAD: format_result[RESULT_OUT_PARAM_BAD].lstrip() + ': trial set incorrect values to out parameters', 210*33de042dSApple OSS Distributions} 211*33de042dSApple OSS Distributions 212*33de042dSApple OSS Distributions# inside line, replace 'return 123' with 'return ERR_CODE_NAME' 213*33de042dSApple OSS Distributionsdef replace_error_code_return(test, line): 214*33de042dSApple OSS Distributions known_return_values = error_code_values_for_test(test) 215*33de042dSApple OSS Distributions for code, name in known_return_values.items(): 216*33de042dSApple OSS Distributions line = line.replace('return ' + str(code) + ';', 'return ' + name + ';') 217*33de042dSApple OSS Distributions return line 218*33de042dSApple OSS Distributions 219*33de042dSApple OSS Distributionsdef dimensions(results): 220*33de042dSApple OSS Distributions if len(results) == 0: 221*33de042dSApple OSS Distributions return 0 222*33de042dSApple OSS Distributions return len(results[0].parameters) 223*33de042dSApple OSS Distributions 224*33de042dSApple OSS Distributions# given one k-dimensional results 225*33de042dSApple OSS Distributions# return a list of k counts that is the size of each dimension 226*33de042dSApple OSS Distributionsdef count_each_dimension(results): 227*33de042dSApple OSS Distributions if len(results) == 0: 228*33de042dSApple OSS Distributions return [] 229*33de042dSApple OSS Distributions first = results[0].parameters 230*33de042dSApple OSS Distributions k = dimensions(results) 231*33de042dSApple OSS Distributions counts = [] 232*33de042dSApple OSS Distributions step = 1 233*33de042dSApple OSS Distributions for dim in range(k-1, -1, -1): 234*33de042dSApple OSS Distributions count = round(len(results) / step) 235*33de042dSApple OSS Distributions for i in range(0, len(results), step): 236*33de042dSApple OSS Distributions cur = results[i].parameters 237*33de042dSApple OSS Distributions if i != 0 and cur[dim] == first[dim]: 238*33de042dSApple OSS Distributions count = round(i / step) 239*33de042dSApple OSS Distributions break; 240*33de042dSApple OSS Distributions step *= count 241*33de042dSApple OSS Distributions counts.append(count) 242*33de042dSApple OSS Distributions 243*33de042dSApple OSS Distributions counts.reverse() 244*33de042dSApple OSS Distributions return counts; 245*33de042dSApple OSS Distributions 246*33de042dSApple OSS Distributions# Reduce one k-dimensional results to many (k-1) dimensional results 247*33de042dSApple OSS Distributions# Yields a sequence of [results, name] pairs 248*33de042dSApple OSS Distributions# where results has k-1 dimensions 249*33de042dSApple OSS Distributions# and name is the parameter name from the removed dimension 250*33de042dSApple OSS Distributionsdef iterate_dimension(results, dim = 0): 251*33de042dSApple OSS Distributions if len(results) == 0: 252*33de042dSApple OSS Distributions return 253*33de042dSApple OSS Distributions 254*33de042dSApple OSS Distributions k = dimensions(results) 255*33de042dSApple OSS Distributions dim_counts = count_each_dimension(results) 256*33de042dSApple OSS Distributions 257*33de042dSApple OSS Distributions inner_count = 1 258*33de042dSApple OSS Distributions for d in range(dim+1, k): 259*33de042dSApple OSS Distributions inner_count *= dim_counts[d] 260*33de042dSApple OSS Distributions 261*33de042dSApple OSS Distributions outer_step = len(results) 262*33de042dSApple OSS Distributions for d in range(0, dim): 263*33de042dSApple OSS Distributions outer_step = int(outer_step / dim_counts[d]) 264*33de042dSApple OSS Distributions 265*33de042dSApple OSS Distributions for r in range(dim_counts[dim]): 266*33de042dSApple OSS Distributions start = r * inner_count 267*33de042dSApple OSS Distributions name = results[start].parameters[dim] 268*33de042dSApple OSS Distributions new_results = [] 269*33de042dSApple OSS Distributions for i in range(start, len(results), outer_step): 270*33de042dSApple OSS Distributions for j in range(inner_count): 271*33de042dSApple OSS Distributions new_result = copy.deepcopy(results[i+j]) 272*33de042dSApple OSS Distributions del new_result.parameters[dim] 273*33de042dSApple OSS Distributions new_results.append(new_result) 274*33de042dSApple OSS Distributions yield [new_results, name] 275*33de042dSApple OSS Distributions 276*33de042dSApple OSS Distributions# Print the results of a test that has two parameters (for example a test of start/size) 277*33de042dSApple OSS Distributions# If overrides!=None, use any non-SUCCESS return values from override in place of the other results. 278*33de042dSApple OSS Distributionsdef print_results_2D(results, overrides=None): 279*33de042dSApple OSS Distributions # complain if results and override have different dimensions 280*33de042dSApple OSS Distributions if overrides: 281*33de042dSApple OSS Distributions if len(overrides) != len(results): 282*33de042dSApple OSS Distributions print("WARNING: override results have a different height; overrides ignored") 283*33de042dSApple OSS Distributions for i, result in enumerate(results): 284*33de042dSApple OSS Distributions if len(overrides[i].parameters) != len(result.parameters): 285*33de042dSApple OSS Distributions print("WARNING: override results have a different width; overrides ignored") 286*33de042dSApple OSS Distributions 287*33de042dSApple OSS Distributions columns = [] 288*33de042dSApple OSS Distributions prev_row_label = '' 289*33de042dSApple OSS Distributions first_row_label = '' 290*33de042dSApple OSS Distributions for i, result in enumerate(results): 291*33de042dSApple OSS Distributions if overrides: override = overrides[i].ret 292*33de042dSApple OSS Distributions 293*33de042dSApple OSS Distributions if first_row_label == '': 294*33de042dSApple OSS Distributions # record first row's name so we can use it to find columns 295*33de042dSApple OSS Distributions # (assumes every row has the same column labels) 296*33de042dSApple OSS Distributions first_row_label = result.parameters[0] 297*33de042dSApple OSS Distributions 298*33de042dSApple OSS Distributions if result.parameters[0] == first_row_label: 299*33de042dSApple OSS Distributions # record column names in the first row 300*33de042dSApple OSS Distributions columns.append(result.parameters[1]) 301*33de042dSApple OSS Distributions 302*33de042dSApple OSS Distributions if result.parameters[0] != prev_row_label: 303*33de042dSApple OSS Distributions # new row 304*33de042dSApple OSS Distributions if prev_row_label != '': print(format_indent + prev_row_label) 305*33de042dSApple OSS Distributions print(format_indent, end='') 306*33de042dSApple OSS Distributions prev_row_label = result.parameters[0] 307*33de042dSApple OSS Distributions 308*33de042dSApple OSS Distributions if overrides and override != RESULT_SUCCESS: 309*33de042dSApple OSS Distributions print_one_result(override) 310*33de042dSApple OSS Distributions else: 311*33de042dSApple OSS Distributions print_one_result(result.ret) 312*33de042dSApple OSS Distributions 313*33de042dSApple OSS Distributions if prev_row_label: print(format_indent + prev_row_label) 314*33de042dSApple OSS Distributions print_column_labels(columns, format_indent_width + format_col_width - 1, format_col_width) 315*33de042dSApple OSS Distributions 316*33de042dSApple OSS Distributionsdef print_results_2D_try_condensed(results): 317*33de042dSApple OSS Distributions if 0 == len(results): 318*33de042dSApple OSS Distributions return 319*33de042dSApple OSS Distributions singleton = results[0].ret 320*33de042dSApple OSS Distributions if any([result.ret != singleton for result in results]): 321*33de042dSApple OSS Distributions print_results_2D(results) 322*33de042dSApple OSS Distributions return 323*33de042dSApple OSS Distributions # will print as condensed 324*33de042dSApple OSS Distributions rows = set() 325*33de042dSApple OSS Distributions cols = set() 326*33de042dSApple OSS Distributions for result in results: 327*33de042dSApple OSS Distributions rows.add(result.parameters[0].split()[1]) 328*33de042dSApple OSS Distributions cols.add(result.parameters[1].split()[1]) 329*33de042dSApple OSS Distributions print_one_result(result.ret) 330*33de042dSApple OSS Distributions print(" for all pairs") 331*33de042dSApple OSS Distributions 332*33de042dSApple OSS Distributionsdef print_results_3D(results, testname): 333*33de042dSApple OSS Distributions # foreach parameter[1], print 2D table of parameter[0] and parameter[2] 334*33de042dSApple OSS Distributions for results2D, name in iterate_dimension(results, 1): 335*33de042dSApple OSS Distributions print(testname + ': ' + name) 336*33de042dSApple OSS Distributions print_results_2D(results2D) 337*33de042dSApple OSS Distributions 338*33de042dSApple OSS Distributions # foreach parameter[0], print 2D table of parameter[1] and parameter[2] 339*33de042dSApple OSS Distributions # This is redundant but can be useful for human readers. 340*33de042dSApple OSS Distributions for results2D, name in iterate_dimension(results, 0): 341*33de042dSApple OSS Distributions print(testname + ': ' + name) 342*33de042dSApple OSS Distributions print_results_2D(results2D) 343*33de042dSApple OSS Distributions 344*33de042dSApple OSS Distributionsdef print_results_4D(results): 345*33de042dSApple OSS Distributions x, y, z = '', '', '' 346*33de042dSApple OSS Distributions # Make a map[{3rd_param, 4th_param, ...}] = {all options} 347*33de042dSApple OSS Distributions # For now, we print 2d tables of 1st, 2nd param for each possible combination of remaining values 348*33de042dSApple OSS Distributions 349*33de042dSApple OSS Distributions map_of_results = {} 350*33de042dSApple OSS Distributions for _, result in enumerate(results): 351*33de042dSApple OSS Distributions k = tuple(result.parameters[2:]) 352*33de042dSApple OSS Distributions 353*33de042dSApple OSS Distributions if k not in map_of_results: 354*33de042dSApple OSS Distributions map_of_results[k] = [result] 355*33de042dSApple OSS Distributions else: 356*33de042dSApple OSS Distributions map_of_results[k].append(result) 357*33de042dSApple OSS Distributions 358*33de042dSApple OSS Distributions # prepare to iterate 359*33de042dSApple OSS Distributions prev_matrix = [] 360*33de042dSApple OSS Distributions iterable = [] 361*33de042dSApple OSS Distributions for k, result_list in map_of_results.items(): 362*33de042dSApple OSS Distributions one_2d_result = [] 363*33de042dSApple OSS Distributions matrix = [] 364*33de042dSApple OSS Distributions for result in result_list: 365*33de042dSApple OSS Distributions x = result.parameters[0] 366*33de042dSApple OSS Distributions y = result.parameters[1] 367*33de042dSApple OSS Distributions repl_result = Result(result.ret, (x, y)) 368*33de042dSApple OSS Distributions one_2d_result.append(repl_result) 369*33de042dSApple OSS Distributions matrix.append(result.ret) 370*33de042dSApple OSS Distributions if matrix == prev_matrix: 371*33de042dSApple OSS Distributions # if the return codes are the same everywhere, we will print successive tables only once 372*33de042dSApple OSS Distributions # note that this assumes that the sets of 2D labels are the same everywhere, and doesn't check that assumption 373*33de042dSApple OSS Distributions iterable[-1][0].append(k) 374*33de042dSApple OSS Distributions else: 375*33de042dSApple OSS Distributions iterable.append(([k], one_2d_result)) 376*33de042dSApple OSS Distributions prev_matrix = matrix 377*33de042dSApple OSS Distributions 378*33de042dSApple OSS Distributions # print 379*33de042dSApple OSS Distributions for iter in iterable: 380*33de042dSApple OSS Distributions print(iter[0]) 381*33de042dSApple OSS Distributions print_results_2D_try_condensed(iter[1]) 382*33de042dSApple OSS Distributions 383*33de042dSApple OSS Distributions 384*33de042dSApple OSS Distributions# Print the results of a test that has two parameters 385*33de042dSApple OSS Distributions# (for example a test of addr only, or size only) 386*33de042dSApple OSS Distributions# If overrides!=None, use any non-SUCCESS return values from override in place of the other results. 387*33de042dSApple OSS Distributionsdef print_results_1D(results, overrides=None): 388*33de042dSApple OSS Distributions # complain if results and overrides have different dimensions 389*33de042dSApple OSS Distributions if overrides: 390*33de042dSApple OSS Distributions if len(overrides) != len(results): 391*33de042dSApple OSS Distributions print("WARNING: override results have a different height; overrides ignored") 392*33de042dSApple OSS Distributions for i, result in enumerate(results): 393*33de042dSApple OSS Distributions if len(overrides[i].parameters) != len(result.parameters): 394*33de042dSApple OSS Distributions print("WARNING: override results have a different width; overrides ignored") 395*33de042dSApple OSS Distributions 396*33de042dSApple OSS Distributions for i, result in enumerate(results): 397*33de042dSApple OSS Distributions if overrides: override = overrides[i].ret 398*33de042dSApple OSS Distributions 399*33de042dSApple OSS Distributions # indent, value, indent, label 400*33de042dSApple OSS Distributions print(format_indent, end='') 401*33de042dSApple OSS Distributions if overrides and override != RESULT_SUCCESS: 402*33de042dSApple OSS Distributions print_one_result(override) 403*33de042dSApple OSS Distributions else: 404*33de042dSApple OSS Distributions print_one_result(result.ret) 405*33de042dSApple OSS Distributions print(format_indent + result.parameters[0]) 406*33de042dSApple OSS Distributions 407*33de042dSApple OSS Distributionsdef print_results_nD(results, testname, overrides=None): 408*33de042dSApple OSS Distributions if (dimensions(results) == 1): 409*33de042dSApple OSS Distributions print_results_1D(results, overrides) 410*33de042dSApple OSS Distributions elif (dimensions(results) == 2): 411*33de042dSApple OSS Distributions print_results_2D(results, overrides) 412*33de042dSApple OSS Distributions elif dimensions(results) == 3: 413*33de042dSApple OSS Distributions print_results_3D(results, testname) 414*33de042dSApple OSS Distributions elif dimensions(results) == 4: 415*33de042dSApple OSS Distributions print_results_4D(results) 416*33de042dSApple OSS Distributions else: 417*33de042dSApple OSS Distributions print(format_indent + 'too many dimensions') 418*33de042dSApple OSS Distributions 419*33de042dSApple OSS Distributions 420*33de042dSApple OSS Distributionsdef main(): 421*33de042dSApple OSS Distributions data = sys.stdin.readlines() 422*33de042dSApple OSS Distributions 423*33de042dSApple OSS Distributions 424*33de042dSApple OSS Distributions # remove any lines that don't start with "TESTNAME" or "TESTCONFIG" or "RESULT" 425*33de042dSApple OSS Distributions # (including darwintest output like "PASS" or "FAIL") 426*33de042dSApple OSS Distributions # and print them now 427*33de042dSApple OSS Distributions # Also verify that the counts of "TEST BEGIN" == "TEST END" 428*33de042dSApple OSS Distributions # (they will mismatch if a test suite crashed) 429*33de042dSApple OSS Distributions testbegincount = 0 430*33de042dSApple OSS Distributions testendcount = 0 431*33de042dSApple OSS Distributions testlines = [] 432*33de042dSApple OSS Distributions for line in data: 433*33de042dSApple OSS Distributions unmodified_line = line 434*33de042dSApple OSS Distributions # count TEST BEGIN and TEST END 435*33de042dSApple OSS Distributions if ('TEST BEGIN' in line): 436*33de042dSApple OSS Distributions testbegincount += 1 437*33de042dSApple OSS Distributions if ('TEST END' in line): 438*33de042dSApple OSS Distributions testendcount += 1 439*33de042dSApple OSS Distributions # remove any T_LOG() timestamp prefixes and KTEST prefixes 440*33de042dSApple OSS Distributions line = re.sub('^\s*\d+:\d+:\d+ ', '', line) 441*33de042dSApple OSS Distributions line = re.sub('^\[KTEST\]\s+[A-Z]+\s+\d+\s+(\d+\s+)?\S+\s+\d+\s+', '', line) 442*33de042dSApple OSS Distributions line = line.lstrip() 443*33de042dSApple OSS Distributions 444*33de042dSApple OSS Distributions if (line.startswith('TESTNAME') or line.startswith('RESULT') 445*33de042dSApple OSS Distributions or line.startswith('TESTCONFIG') or line.startswith('TESTCOMPAT')): 446*33de042dSApple OSS Distributions testlines.append(line) # line is test output 447*33de042dSApple OSS Distributions elif line == '': 448*33de042dSApple OSS Distributions pass # ignore empty lines 449*33de042dSApple OSS Distributions else: 450*33de042dSApple OSS Distributions print(unmodified_line, end='') # line is other output 451*33de042dSApple OSS Distributions 452*33de042dSApple OSS Distributions # parse test output into Test and Result objects 453*33de042dSApple OSS Distributions 454*33de042dSApple OSS Distributions testnum = 0 455*33de042dSApple OSS Distributions def group_by_test(line): 456*33de042dSApple OSS Distributions nonlocal testnum 457*33de042dSApple OSS Distributions if line.startswith('TESTNAME '): 458*33de042dSApple OSS Distributions testnum = testnum+1 459*33de042dSApple OSS Distributions return testnum 460*33de042dSApple OSS Distributions 461*33de042dSApple OSS Distributions tests = [] 462*33de042dSApple OSS Distributions for _, group in itertools.groupby(testlines, group_by_test): 463*33de042dSApple OSS Distributions lines = list(group) 464*33de042dSApple OSS Distributions 465*33de042dSApple OSS Distributions name = lines.pop(0).removeprefix('TESTNAME ').rstrip() 466*33de042dSApple OSS Distributions config = lines.pop(0).removeprefix('TESTCONFIG ').rstrip() 467*33de042dSApple OSS Distributions compat = [] 468*33de042dSApple OSS Distributions results = [] 469*33de042dSApple OSS Distributions for line in lines: 470*33de042dSApple OSS Distributions if line.startswith('RESULT'): 471*33de042dSApple OSS Distributions components = line.removeprefix('RESULT ').rstrip().split(', ') 472*33de042dSApple OSS Distributions ret = int(components.pop(0)) 473*33de042dSApple OSS Distributions results.append(Result(ret, components)) 474*33de042dSApple OSS Distributions 475*33de042dSApple OSS Distributions tests.append(Test(name, config, compat, results)) 476*33de042dSApple OSS Distributions 477*33de042dSApple OSS Distributions print('found %d tests' % (len(tests))) 478*33de042dSApple OSS Distributions 479*33de042dSApple OSS Distributions # stats to print at the end 480*33de042dSApple OSS Distributions test_count = len(tests) 481*33de042dSApple OSS Distributions all_configurations = set() 482*33de042dSApple OSS Distributions 483*33de042dSApple OSS Distributions # print test output 484*33de042dSApple OSS Distributions for test in tests: 485*33de042dSApple OSS Distributions # print test name and test config on separate lines 486*33de042dSApple OSS Distributions # `diff` handles this better than putting both on the same line 487*33de042dSApple OSS Distributions print('test ' + test.testname) 488*33de042dSApple OSS Distributions 489*33de042dSApple OSS Distributions print(format_indent + 'config ' + test.config) 490*33de042dSApple OSS Distributions all_configurations.add(test.config) 491*33de042dSApple OSS Distributions 492*33de042dSApple OSS Distributions if len(test.results) == 0: 493*33de042dSApple OSS Distributions print(format_indent + 'no results') 494*33de042dSApple OSS Distributions else: 495*33de042dSApple OSS Distributions print_legend(test) 496*33de042dSApple OSS Distributions print_results_nD(test.results, test.testname) 497*33de042dSApple OSS Distributions 498*33de042dSApple OSS Distributions 499*33de042dSApple OSS Distributions print('end ' + test.testname) 500*33de042dSApple OSS Distributions 501*33de042dSApple OSS Distributions print() 502*33de042dSApple OSS Distributions print(str(test_count) + ' test(s) performed') 503*33de042dSApple OSS Distributions 504*33de042dSApple OSS Distributions if (testbegincount != testendcount): 505*33de042dSApple OSS Distributions print('### error: %d TEST BEGINs, %d TEST ENDs - some tests may have crashed' 506*33de042dSApple OSS Distributions % (testbegincount, testendcount)) 507*33de042dSApple OSS Distributions 508*33de042dSApple OSS Distributions print(str(len(all_configurations)) + ' configuration(s) tested:') 509*33de042dSApple OSS Distributions for config in sorted(all_configurations): 510*33de042dSApple OSS Distributions print(format_indent + '[' + config + ']') 511*33de042dSApple OSS Distributions 512*33de042dSApple OSS Distributions 513*33de042dSApple OSS Distributionsmain() 514