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