2 run the command under test, under valgrind and collect memory leak info
10 from string
import Template
13 from TdcPlugin
import TdcPlugin
14 from TdcResults
import *
16 from tdc_config
import *
18 def vp_extract_num_from_string(num_as_string_maybe_with_commas
):
19 return int(num_as_string_maybe_with_commas
.replace(',',''))
21 class SubPlugin(TdcPlugin
):
23 self
.sub_class
= 'valgrind/SubPlugin'
25 self
._tsr
= TestSuiteReport()
28 def pre_suite(self
, testcount
, testidlist
):
29 '''run commands before test_runner goes into a test loop'''
30 super().pre_suite(testcount
, testidlist
)
31 if self
.args
.verbose
> 1:
32 print('{}.pre_suite'.format(self
.sub_class
))
33 if self
.args
.valgrind
:
34 self
._add
_to
_tap
('1..{}\n'.format(self
.testcount
))
36 def post_suite(self
, index
):
37 '''run commands after test_runner goes into a test loop'''
38 super().post_suite(index
)
39 if self
.args
.verbose
> 1:
40 print('{}.post_suite'.format(self
.sub_class
))
41 #print('{}'.format(self.tap))
42 for xx
in range(index
- 1, self
.testcount
):
43 res
= TestResult('{}-mem'.format(self
.testidlist
[xx
]), 'Test skipped')
44 res
.set_result(ResultState
.skip
)
45 res
.set_errormsg('Skipped because of prior setup/teardown failure')
46 self
._add
_results
(res
)
47 if self
.args
.verbose
< 4:
48 subprocess
.check_output('rm -f vgnd-*.log', shell
=True)
50 def add_args(self
, parser
):
51 super().add_args(parser
)
52 self
.argparser_group
= self
.argparser
.add_argument_group(
54 'options for valgrindPlugin (run command under test under Valgrind)')
56 self
.argparser_group
.add_argument(
57 '-V', '--valgrind', action
='store_true',
58 help='Run commands under valgrind')
62 def adjust_command(self
, stage
, command
):
63 super().adjust_command(stage
, command
)
67 if not self
.args
.valgrind
:
70 if self
.args
.verbose
> 1:
71 print('{}.adjust_command'.format(self
.sub_class
))
73 if not isinstance(command
, list):
75 cmdlist
= command
.split()
79 if stage
== 'execute':
80 if self
.args
.verbose
> 1:
81 print('adjust_command: stage is {}; inserting valgrind stuff in command [{}] list [{}]'.
82 format(stage
, command
, cmdlist
))
83 cmdlist
.insert(0, '--track-origins=yes')
84 cmdlist
.insert(0, '--show-leak-kinds=definite,indirect')
85 cmdlist
.insert(0, '--leak-check=full')
86 cmdlist
.insert(0, '--log-file=vgnd-{}.log'.format(self
.args
.testid
))
87 cmdlist
.insert(0, '-v') # ask for summary of non-leak errors
88 cmdlist
.insert(0, ENVIR
['VALGRIND_BIN'])
93 command
= ' '.join(cmdlist
)
97 if self
.args
.verbose
> 1:
98 print('adjust_command: return command [{}]'.format(command
))
101 def post_execute(self
):
102 if not self
.args
.valgrind
:
105 res
= TestResult('{}-mem'.format(self
.args
.testid
),
106 '{} memory leak check'.format(self
.args
.test_name
))
107 if self
.args
.test_skip
:
108 res
.set_result(ResultState
.skip
)
109 res
.set_errormsg('Test case designated as skipped.')
110 self
._add
_results
(res
)
113 self
.definitely_lost_re
= re
.compile(
114 r
'definitely lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\sblocks', re
.MULTILINE | re
.DOTALL
)
115 self
.indirectly_lost_re
= re
.compile(
116 r
'indirectly lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\s+blocks', re
.MULTILINE | re
.DOTALL
)
117 self
.possibly_lost_re
= re
.compile(
118 r
'possibly lost:\s+([,0-9]+)bytes in\s+([,0-9]+)\s+blocks', re
.MULTILINE | re
.DOTALL
)
119 self
.non_leak_error_re
= re
.compile(
120 r
'ERROR SUMMARY:\s+([,0-9]+) errors from\s+([,0-9]+)\s+contexts', re
.MULTILINE | re
.DOTALL
)
127 # what about concurrent test runs? Maybe force them to be in different directories?
128 with
open('vgnd-{}.log'.format(self
.args
.testid
)) as vfd
:
130 def_mo
= self
.definitely_lost_re
.search(content
)
131 ind_mo
= self
.indirectly_lost_re
.search(content
)
132 pos_mo
= self
.possibly_lost_re
.search(content
)
133 nle_mo
= self
.non_leak_error_re
.search(content
)
136 def_num
= int(def_mo
.group(2))
138 ind_num
= int(ind_mo
.group(2))
140 pos_num
= int(pos_mo
.group(2))
142 nle_num
= int(nle_mo
.group(1))
145 if (def_num
> 0) or (ind_num
> 0) or (pos_num
> 0) or (nle_num
> 0):
146 mem_results
+= 'not '
147 res
.set_result(ResultState
.fail
)
148 res
.set_failmsg('Memory leak detected')
149 res
.append_failmsg(content
)
151 res
.set_result(ResultState
.success
)
153 self
._add
_results
(res
)
156 def _add_results(self
, res
):
157 self
._tsr
.add_resultdata(res
)
159 def _add_to_tap(self
, more_tap_output
):
160 self
.tap
+= more_tap_output