2 run the command under test, under valgrind and collect memory leak info
10 from string
import Template
13 from TdcPlugin
import TdcPlugin
15 from tdc_config
import *
17 def vp_extract_num_from_string(num_as_string_maybe_with_commas
):
18 return int(num_as_string_maybe_with_commas
.replace(',',''))
20 class SubPlugin(TdcPlugin
):
22 self
.sub_class
= 'valgrind/SubPlugin'
26 def pre_suite(self
, testcount
, testidlist
):
27 '''run commands before test_runner goes into a test loop'''
28 super().pre_suite(testcount
, testidlist
)
29 if self
.args
.verbose
> 1:
30 print('{}.pre_suite'.format(self
.sub_class
))
31 if self
.args
.valgrind
:
32 self
._add
_to
_tap
('1..{}\n'.format(self
.testcount
))
34 def post_suite(self
, index
):
35 '''run commands after test_runner goes into a test loop'''
36 super().post_suite(index
)
37 self
._add
_to
_tap
('\n|---\n')
38 if self
.args
.verbose
> 1:
39 print('{}.post_suite'.format(self
.sub_class
))
40 print('{}'.format(self
.tap
))
41 if self
.args
.verbose
< 4:
42 subprocess
.check_output('rm -f vgnd-*.log', shell
=True)
44 def add_args(self
, parser
):
45 super().add_args(parser
)
46 self
.argparser_group
= self
.argparser
.add_argument_group(
48 'options for valgrindPlugin (run command under test under Valgrind)')
50 self
.argparser_group
.add_argument(
51 '-V', '--valgrind', action
='store_true',
52 help='Run commands under valgrind')
56 def adjust_command(self
, stage
, command
):
57 super().adjust_command(stage
, command
)
61 if not self
.args
.valgrind
:
64 if self
.args
.verbose
> 1:
65 print('{}.adjust_command'.format(self
.sub_class
))
67 if not isinstance(command
, list):
69 cmdlist
= command
.split()
73 if stage
== 'execute':
74 if self
.args
.verbose
> 1:
75 print('adjust_command: stage is {}; inserting valgrind stuff in command [{}] list [{}]'.
76 format(stage
, command
, cmdlist
))
77 cmdlist
.insert(0, '--track-origins=yes')
78 cmdlist
.insert(0, '--show-leak-kinds=definite,indirect')
79 cmdlist
.insert(0, '--leak-check=full')
80 cmdlist
.insert(0, '--log-file=vgnd-{}.log'.format(self
.args
.testid
))
81 cmdlist
.insert(0, '-v') # ask for summary of non-leak errors
82 cmdlist
.insert(0, ENVIR
['VALGRIND_BIN'])
87 command
= ' '.join(cmdlist
)
91 if self
.args
.verbose
> 1:
92 print('adjust_command: return command [{}]'.format(command
))
95 def post_execute(self
):
96 if not self
.args
.valgrind
:
99 self
.definitely_lost_re
= re
.compile(
100 r
'definitely lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\sblocks', re
.MULTILINE | re
.DOTALL
)
101 self
.indirectly_lost_re
= re
.compile(
102 r
'indirectly lost:\s+([,0-9]+)\s+bytes in\s+([,0-9]+)\s+blocks', re
.MULTILINE | re
.DOTALL
)
103 self
.possibly_lost_re
= re
.compile(
104 r
'possibly lost:\s+([,0-9]+)bytes in\s+([,0-9]+)\s+blocks', re
.MULTILINE | re
.DOTALL
)
105 self
.non_leak_error_re
= re
.compile(
106 r
'ERROR SUMMARY:\s+([,0-9]+) errors from\s+([,0-9]+)\s+contexts', re
.MULTILINE | re
.DOTALL
)
113 # what about concurrent test runs? Maybe force them to be in different directories?
114 with
open('vgnd-{}.log'.format(self
.args
.testid
)) as vfd
:
116 def_mo
= self
.definitely_lost_re
.search(content
)
117 ind_mo
= self
.indirectly_lost_re
.search(content
)
118 pos_mo
= self
.possibly_lost_re
.search(content
)
119 nle_mo
= self
.non_leak_error_re
.search(content
)
122 def_num
= int(def_mo
.group(2))
124 ind_num
= int(ind_mo
.group(2))
126 pos_num
= int(pos_mo
.group(2))
128 nle_num
= int(nle_mo
.group(1))
131 if (def_num
> 0) or (ind_num
> 0) or (pos_num
> 0) or (nle_num
> 0):
132 mem_results
+= 'not '
134 mem_results
+= 'ok {} - {}-mem # {}\n'.format(
135 self
.args
.test_ordinal
, self
.args
.testid
, 'memory leak check')
136 self
._add
_to
_tap
(mem_results
)
137 if mem_results
.startswith('not '):
138 print('{}'.format(content
))
139 self
._add
_to
_tap
(content
)
141 def _add_to_tap(self
, more_tap_output
):
142 self
.tap
+= more_tap_output