1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
#!/usr/bin/env python3
# ------------------------------------------------------------------
#
# Copyright (C) 2013 Canonical Ltd.
# Author: Steve Beattie <steve@nxnw.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# TODO
# - finish adding suppressions for valgrind false positives
import os
import sys
import unittest
from argparse import ArgumentParser
from tempfile import NamedTemporaryFile
import testlib
DEFAULT_TESTDIR = "./simple_tests/vars"
VALGRIND_ERROR_CODE = 151
VALGRIND_ARGS = [
'--leak-check=full', '--error-exitcode={}'.format(VALGRIND_ERROR_CODE)
]
VALGRIND_SUPPRESSIONS = '''
{
valgrind-serialize_profile-obsessive-overreads
Memcheck:Addr4
fun:_Z*sd_serialize_profile*
...
fun:_Z*__sd_serialize_profile*
fun:_Z*load_profile*
fun:_Z*load_policy_list*
}'''
class AAParserValgrindTests(testlib.AATestTemplate):
def setUp(self):
# REPORT ALL THE OUTPUT
self.maxDiff = None
def _runtest(self, testname, config):
parser_args = ('-Q', '-I', config.testdir, '-M', './features_files/features.all')
failure_rc = (VALGRIND_ERROR_CODE, testlib.TIMEOUT_ERROR_CODE)
command = [config.valgrind]
command.extend(VALGRIND_ARGS)
command.append(config.parser)
command.extend(parser_args)
command.append(testname)
rc, output = self.run_cmd(command, timeout=120)
self.assertNotIn(
rc, failure_rc,
"valgrind returned error code {}, gave the following output\n{}\ncommand run: {}".format(
rc, output, " ".join(command)))
def find_testcases(testdir):
"""dig testcases out of passed directory"""
for (fdir, direntries, files) in os.walk(testdir):
for f in files:
if f.endswith(".sd"):
yield os.path.join(fdir, f)
def create_suppressions():
"""generate valgrind suppressions file"""
with NamedTemporaryFile("w+", suffix='.suppressions', prefix='aa-parser-valgrind', delete=False) as temp_file:
temp_file.write(VALGRIND_SUPPRESSIONS)
return temp_file.name
def main():
rc = 0
p = ArgumentParser()
p.add_argument('-p', '--parser', default=testlib.DEFAULT_PARSER, action="store", dest='parser',
help="Specify path of apparmor parser to use [default = %(default)s]")
p.add_argument('-v', '--verbose', action="store_true", dest="verbose")
p.add_argument('-V', '--valgrind', default='/usr/bin/valgrind', action="store", dest="valgrind",
help="Specify path of valgrind to use [default = %(default)s]")
p.add_argument('-s', '--skip-suppressions', action="store_true", dest="skip_suppressions",
help="Don't use valgrind suppressions to skip false positives")
p.add_argument('--dump-suppressions', action="store_true", dest="dump_suppressions",
help="Dump valgrind suppressions to stdout")
p.add_argument('testdir', action="store", default=DEFAULT_TESTDIR, nargs='?', metavar='dir',
help="run tests on alternate directory [default = %(default)s]")
config = p.parse_args()
if config.dump_suppressions:
print(VALGRIND_SUPPRESSIONS)
return rc
if not os.path.exists(config.valgrind):
print(
"Unable to find valgrind at '{}', ensure that it is installed".format(config.valgrind),
file=sys.stderr
)
sys.exit(1)
verbosity = 1
if config.verbose:
verbosity = 2
if config.skip_suppressions:
suppression_file = None
else:
suppression_file = create_suppressions()
VALGRIND_ARGS.append('--suppressions=' + suppression_file)
for f in find_testcases(config.testdir):
def stub_test(self, testname=f):
self._runtest(testname, config)
stub_test.__doc__ = "test " + f
setattr(AAParserValgrindTests, 'test_' + f, stub_test)
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(AAParserValgrindTests))
try:
result = unittest.TextTestRunner(verbosity=verbosity).run(test_suite)
except Exception:
rc = 1
else:
if not result.wasSuccessful():
rc = 1
finally:
if suppression_file:
os.remove(suppression_file)
return rc
if __name__ == "__main__":
sys.exit(main())
|