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