1*c25e4736SBrenda J. Butler''' 2*c25e4736SBrenda J. Butlerrun the command under test, under valgrind and collect memory leak info 3*c25e4736SBrenda J. Butleras a separate test. 4*c25e4736SBrenda J. Butler''' 5*c25e4736SBrenda J. Butler 6*c25e4736SBrenda J. Butler 7*c25e4736SBrenda J. Butlerimport os 8*c25e4736SBrenda J. Butlerimport re 9*c25e4736SBrenda J. Butlerimport signal 10*c25e4736SBrenda J. Butlerfrom string import Template 11*c25e4736SBrenda J. Butlerimport subprocess 12*c25e4736SBrenda J. Butlerimport time 13*c25e4736SBrenda J. Butlerfrom TdcPlugin import TdcPlugin 14*c25e4736SBrenda J. Butler 15*c25e4736SBrenda J. Butlerfrom tdc_config import * 16*c25e4736SBrenda J. Butler 17*c25e4736SBrenda J. Butlerdef vp_extract_num_from_string(num_as_string_maybe_with_commas): 18*c25e4736SBrenda J. Butler return int(num_as_string_maybe_with_commas.replace(',','')) 19*c25e4736SBrenda J. Butler 20*c25e4736SBrenda J. Butlerclass SubPlugin(TdcPlugin): 21*c25e4736SBrenda J. Butler def __init__(self): 22*c25e4736SBrenda J. Butler self.sub_class = 'valgrind/SubPlugin' 23*c25e4736SBrenda J. Butler self.tap = '' 24*c25e4736SBrenda J. Butler super().__init__() 25*c25e4736SBrenda J. Butler 26*c25e4736SBrenda J. Butler def pre_suite(self, testcount, testidlist): 27*c25e4736SBrenda J. Butler '''run commands before test_runner goes into a test loop''' 28*c25e4736SBrenda J. Butler super().pre_suite(testcount, testidlist) 29*c25e4736SBrenda J. Butler if self.args.verbose > 1: 30*c25e4736SBrenda J. Butler print('{}.pre_suite'.format(self.sub_class)) 31*c25e4736SBrenda J. Butler if self.args.valgrind: 32*c25e4736SBrenda J. Butler self._add_to_tap('1..{}\n'.format(self.testcount)) 33*c25e4736SBrenda J. Butler 34*c25e4736SBrenda J. Butler def post_suite(self, index): 35*c25e4736SBrenda J. Butler '''run commands after test_runner goes into a test loop''' 36*c25e4736SBrenda J. Butler super().post_suite(index) 37*c25e4736SBrenda J. Butler self._add_to_tap('\n|---\n') 38*c25e4736SBrenda J. Butler if self.args.verbose > 1: 39*c25e4736SBrenda J. Butler print('{}.post_suite'.format(self.sub_class)) 40*c25e4736SBrenda J. Butler print('{}'.format(self.tap)) 41*c25e4736SBrenda J. Butler if self.args.verbose < 4: 42*c25e4736SBrenda J. Butler subprocess.check_output('rm -f vgnd-*.log', shell=True) 43*c25e4736SBrenda J. Butler 44*c25e4736SBrenda J. Butler def add_args(self, parser): 45*c25e4736SBrenda J. Butler super().add_args(parser) 46*c25e4736SBrenda J. Butler self.argparser_group = self.argparser.add_argument_group( 47*c25e4736SBrenda J. Butler 'valgrind', 48*c25e4736SBrenda J. Butler 'options for valgrindPlugin (run command under test under Valgrind)') 49*c25e4736SBrenda J. Butler 50*c25e4736SBrenda J. Butler self.argparser_group.add_argument( 51*c25e4736SBrenda J. Butler '-V', '--valgrind', action='store_true', 52*c25e4736SBrenda J. Butler help='Run commands under valgrind') 53*c25e4736SBrenda J. Butler 54*c25e4736SBrenda J. Butler return self.argparser 55*c25e4736SBrenda J. Butler 56*c25e4736SBrenda J. Butler def adjust_command(self, stage, command): 57*c25e4736SBrenda J. Butler super().adjust_command(stage, command) 58*c25e4736SBrenda J. Butler cmdform = 'list' 59*c25e4736SBrenda J. Butler cmdlist = list() 60*c25e4736SBrenda J. Butler 61*c25e4736SBrenda J. Butler if not self.args.valgrind: 62*c25e4736SBrenda J. Butler return command 63*c25e4736SBrenda J. Butler 64*c25e4736SBrenda J. Butler if self.args.verbose > 1: 65*c25e4736SBrenda J. Butler print('{}.adjust_command'.format(self.sub_class)) 66*c25e4736SBrenda J. Butler 67*c25e4736SBrenda J. Butler if not isinstance(command, list): 68*c25e4736SBrenda J. Butler cmdform = 'str' 69*c25e4736SBrenda J. Butler cmdlist = command.split() 70*c25e4736SBrenda J. Butler else: 71*c25e4736SBrenda J. Butler cmdlist = command 72*c25e4736SBrenda J. Butler 73*c25e4736SBrenda J. Butler if stage == 'execute': 74*c25e4736SBrenda J. Butler if self.args.verbose > 1: 75*c25e4736SBrenda J. Butler print('adjust_command: stage is {}; inserting valgrind stuff in command [{}] list [{}]'. 76*c25e4736SBrenda J. Butler format(stage, command, cmdlist)) 77*c25e4736SBrenda J. Butler cmdlist.insert(0, '--track-origins=yes') 78*c25e4736SBrenda J. Butler cmdlist.insert(0, '--show-leak-kinds=definite,indirect') 79*c25e4736SBrenda J. Butler cmdlist.insert(0, '--leak-check=full') 80*c25e4736SBrenda J. Butler cmdlist.insert(0, '--log-file=vgnd-{}.log'.format(self.args.testid)) 81*c25e4736SBrenda J. Butler cmdlist.insert(0, '-v') # ask for summary of non-leak errors 82*c25e4736SBrenda J. Butler cmdlist.insert(0, ENVIR['VALGRIND_BIN']) 83*c25e4736SBrenda J. Butler else: 84*c25e4736SBrenda J. Butler pass 85*c25e4736SBrenda J. Butler 86*c25e4736SBrenda J. Butler if cmdform == 'str': 87*c25e4736SBrenda J. Butler command = ' '.join(cmdlist) 88*c25e4736SBrenda J. Butler else: 89*c25e4736SBrenda J. Butler command = cmdlist 90*c25e4736SBrenda J. Butler 91*c25e4736SBrenda J. Butler if self.args.verbose > 1: 92*c25e4736SBrenda J. Butler print('adjust_command: return command [{}]'.format(command)) 93*c25e4736SBrenda J. Butler return command 94*c25e4736SBrenda J. Butler 95*c25e4736SBrenda J. Butler def post_execute(self): 96*c25e4736SBrenda J. Butler if not self.args.valgrind: 97*c25e4736SBrenda J. Butler return 98*c25e4736SBrenda J. Butler 99*c25e4736SBrenda J. Butler self.definitely_lost_re = re.compile( 100*c25e4736SBrenda J. Butler r'definitely lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\sblocks', re.MULTILINE | re.DOTALL) 101*c25e4736SBrenda J. Butler self.indirectly_lost_re = re.compile( 102*c25e4736SBrenda J. Butler r'indirectly lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\s+blocks', re.MULTILINE | re.DOTALL) 103*c25e4736SBrenda J. Butler self.possibly_lost_re = re.compile( 104*c25e4736SBrenda J. Butler r'possibly lost:\s+([,0-9]+)bytes in\s+([,0-9]+)\s+blocks', re.MULTILINE | re.DOTALL) 105*c25e4736SBrenda J. Butler self.non_leak_error_re = re.compile( 106*c25e4736SBrenda J. Butler r'ERROR SUMMARY:\s+([,0-9]+) errors from\s+([,0-9]+)\s+contexts', re.MULTILINE | re.DOTALL) 107*c25e4736SBrenda J. Butler 108*c25e4736SBrenda J. Butler def_num = 0 109*c25e4736SBrenda J. Butler ind_num = 0 110*c25e4736SBrenda J. Butler pos_num = 0 111*c25e4736SBrenda J. Butler nle_num = 0 112*c25e4736SBrenda J. Butler 113*c25e4736SBrenda J. Butler # what about concurrent test runs? Maybe force them to be in different directories? 114*c25e4736SBrenda J. Butler with open('vgnd-{}.log'.format(self.args.testid)) as vfd: 115*c25e4736SBrenda J. Butler content = vfd.read() 116*c25e4736SBrenda J. Butler def_mo = self.definitely_lost_re.search(content) 117*c25e4736SBrenda J. Butler ind_mo = self.indirectly_lost_re.search(content) 118*c25e4736SBrenda J. Butler pos_mo = self.possibly_lost_re.search(content) 119*c25e4736SBrenda J. Butler nle_mo = self.non_leak_error_re.search(content) 120*c25e4736SBrenda J. Butler 121*c25e4736SBrenda J. Butler if def_mo: 122*c25e4736SBrenda J. Butler def_num = int(def_mo.group(2)) 123*c25e4736SBrenda J. Butler if ind_mo: 124*c25e4736SBrenda J. Butler ind_num = int(ind_mo.group(2)) 125*c25e4736SBrenda J. Butler if pos_mo: 126*c25e4736SBrenda J. Butler pos_num = int(pos_mo.group(2)) 127*c25e4736SBrenda J. Butler if nle_mo: 128*c25e4736SBrenda J. Butler nle_num = int(nle_mo.group(1)) 129*c25e4736SBrenda J. Butler 130*c25e4736SBrenda J. Butler mem_results = '' 131*c25e4736SBrenda J. Butler if (def_num > 0) or (ind_num > 0) or (pos_num > 0) or (nle_num > 0): 132*c25e4736SBrenda J. Butler mem_results += 'not ' 133*c25e4736SBrenda J. Butler 134*c25e4736SBrenda J. Butler mem_results += 'ok {} - {}-mem # {}\n'.format( 135*c25e4736SBrenda J. Butler self.args.test_ordinal, self.args.testid, 'memory leak check') 136*c25e4736SBrenda J. Butler self._add_to_tap(mem_results) 137*c25e4736SBrenda J. Butler if mem_results.startswith('not '): 138*c25e4736SBrenda J. Butler print('{}'.format(content)) 139*c25e4736SBrenda J. Butler self._add_to_tap(content) 140*c25e4736SBrenda J. Butler 141*c25e4736SBrenda J. Butler def _add_to_tap(self, more_tap_output): 142*c25e4736SBrenda J. Butler self.tap += more_tap_output 143