2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00

Change string formatting method in Python tests

This commit is contained in:
Mark Grassi 2023-02-19 16:26:14 -05:00
parent d713f75086
commit 844a4dc393
36 changed files with 541 additions and 529 deletions

View File

@ -11,4 +11,4 @@ if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
identifier = sys.implementation.cache_tag identifier = sys.implementation.cache_tag
else: else:
identifier = "%d.%d" % sys.version_info[:2] identifier = "%d.%d" % sys.version_info[:2]
print("lib.%s-%s" % (sysconfig.get_platform(), identifier)) print("lib.{}-{}".format(sysconfig.get_platform(), identifier))

View File

@ -64,8 +64,8 @@ class AAPythonBindingsTests(unittest.TestCase):
self.maxDiff = None self.maxDiff = None
def _runtest(self, testname): def _runtest(self, testname):
infile = "%s.in" % (testname) infile = testname + ".in"
outfile = "%s.out" % (testname) outfile = testname + ".out"
# infile *should* only contain one line # infile *should* only contain one line
with open(os.path.join(TESTDIR, infile), 'r') as f: with open(os.path.join(TESTDIR, infile), 'r') as f:
line = f.read() line = f.read()
@ -78,7 +78,7 @@ class AAPythonBindingsTests(unittest.TestCase):
expected = self.parse_output_file(outfile) expected = self.parse_output_file(outfile)
self.assertEqual(expected, record, self.assertEqual(expected, record,
"expected records did not match\n" "expected records did not match\n"
"expected = %s\nactual = %s" % (expected, record)) "expected = {}\nactual = {}".format(expected, record))
def parse_output_file(self, outfile): def parse_output_file(self, outfile):
"""parse testcase .out file and return dict""" """parse testcase .out file and return dict"""
@ -93,7 +93,7 @@ class AAPythonBindingsTests(unittest.TestCase):
count += 1 count += 1
if line == "START": if line == "START":
self.assertEqual(count, 1, self.assertEqual(count, 1,
"Unexpected output format in %s" % (outfile)) "Unexpected output format in " + outfile)
continue continue
else: else:
key, value = line.split(": ", 1) key, value = line.split(": ", 1)
@ -141,8 +141,8 @@ def main():
for f in find_testcases(TESTDIR): for f in find_testcases(TESTDIR):
def stub_test(self, testname=f): def stub_test(self, testname=f):
self._runtest(testname) self._runtest(testname)
stub_test.__doc__ = "test %s" % (f) stub_test.__doc__ = "test " + f
setattr(AAPythonBindingsTests, 'test_%s' % (f), stub_test) setattr(AAPythonBindingsTests, 'test_' + f, stub_test)
return unittest.main(verbosity=2) return unittest.main(verbosity=2)

View File

@ -41,7 +41,7 @@ PROFILE_CONTENTS = '''
/bin/ping mixr, /bin/ping mixr,
/etc/modules.conf r, /etc/modules.conf r,
} }
''' % (ABSTRACTION) ''' % (ABSTRACTION,)
PROFILE = 'sbin.pingy' PROFILE = 'sbin.pingy'
config = None config = None
@ -91,7 +91,7 @@ class AAParserCachingCommon(testlib.AATestTemplate):
"""teardown for each test""" """teardown for each test"""
if not self.do_cleanup: if not self.do_cleanup:
print("\n===> Skipping cleanup, leaving testfiles behind in '%s'" % (self.tmp_dir)) print("\n===> Skipping cleanup, leaving testfiles behind in '{}'".format(self.tmp_dir))
else: else:
if os.path.exists(self.tmp_dir): if os.path.exists(self.tmp_dir):
shutil.rmtree(self.tmp_dir) shutil.rmtree(self.tmp_dir)
@ -102,7 +102,7 @@ class AAParserCachingCommon(testlib.AATestTemplate):
rc, report = self.run_cmd(cmd) rc, report = self.run_cmd(cmd)
if rc != 0: if rc != 0:
if "unrecognized option '--print-cache-dir'" not in report: if "unrecognized option '--print-cache-dir'" not in report:
self.fail('Unknown apparmor_parser error:\n%s' % report) self.fail('Unknown apparmor_parser error:\n' + report)
cache_dir = os.path.join(self.tmp_dir, 'cache') cache_dir = os.path.join(self.tmp_dir, 'cache')
else: else:
@ -116,10 +116,10 @@ class AAParserCachingCommon(testlib.AATestTemplate):
def assert_path_exists(self, path, expected=True): def assert_path_exists(self, path, expected=True):
if expected: if expected:
self.assertTrue(os.path.exists(path), self.assertTrue(os.path.exists(path),
'test did not create file %s, when it was expected to do so' % path) 'test did not create file {}, when it was expected to do so'.format(path))
else: else:
self.assertFalse(os.path.exists(path), self.assertFalse(os.path.exists(path),
'test created file %s, when it was not expected to do so' % path) 'test created file {}, when it was not expected to do so'.format(path))
def is_apparmorfs_mounted(self): def is_apparmorfs_mounted(self):
return os.path.exists("/sys/kernel/security/apparmor") return os.path.exists("/sys/kernel/security/apparmor")
@ -139,11 +139,11 @@ class AAParserCachingCommon(testlib.AATestTemplate):
if expected: if expected:
self.assertEqual( self.assertEqual(
expected_output, features, expected_output, features,
"features contents differ, expected:\n%s\nresult:\n%s" % (expected_output, features)) "features contents differ, expected:\n{}\nresult:\n{}".format(expected_output, features))
else: else:
self.assertNotEqual( self.assertNotEqual(
expected_output, features, expected_output, features,
"features contents equal, expected:\n%s\nresult:\n%s" % (expected_output, features)) "features contents equal, expected:\n{}\nresult:\n{}".format(expected_output, features))
class AAParserBasicCachingTests(AAParserCachingCommon): class AAParserBasicCachingTests(AAParserCachingCommon):
@ -210,7 +210,7 @@ class AAParserAltCacheBasicTests(AAParserBasicCachingTests):
def tearDown(self): def tearDown(self):
if os.listdir(self.unused_cache_loc): if os.listdir(self.unused_cache_loc):
self.fail("original cache dir '%s' not empty" % self.unused_cache_loc) self.fail("original cache dir '{}' not empty".format(self.unused_cache_loc))
super().tearDown() super().tearDown()
@ -517,7 +517,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
def tearDown(self): def tearDown(self):
if self.check_orig_cache and os.listdir(self.orig_cache_dir): if self.check_orig_cache and os.listdir(self.orig_cache_dir):
self.fail("original cache dir '%s' not empty" % self.orig_cache_dir) self.fail("original cache dir '{}' not empty".format(self.orig_cache_dir))
super().tearDown() super().tearDown()
def test_cache_purge_leaves_original_cache_alone(self): def test_cache_purge_leaves_original_cache_alone(self):
@ -534,7 +534,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
for f in filelist: for f in filelist:
if not os.path.exists(os.path.join(self.orig_cache_dir, f)): if not os.path.exists(os.path.join(self.orig_cache_dir, f)):
self.fail('cache purge removed %s, was not supposed to' % (os.path.join(self.orig_cache_dir, f))) self.fail('cache purge removed {}, was not supposed to'.format(os.path.join(self.orig_cache_dir, f)))
def main(): def main():

View File

@ -32,7 +32,7 @@ class AAErrorTests(testlib.AATestTemplate):
cmd = self.cmd_prefix + [profile] cmd = self.cmd_prefix + [profile]
(rc, out, outerr) = self._run_cmd(cmd, stdout=subprocess.DEVNULL) (rc, out, outerr) = self._run_cmd(cmd, stdout=subprocess.DEVNULL)
report = "\nCommand: %s\nExit value:%s\nSTDERR\n%s" % (" ".join(cmd), rc, outerr) report = "\nCommand: {}\nExit value:{}\nSTDERR\n{}".format(" ".join(cmd), rc, outerr)
if is_error: if is_error:
self.assertNotEqual(rc, 0, report) self.assertNotEqual(rc, 0, report)
else: else:

View File

@ -25,7 +25,7 @@ def get_rule(quantifier, perms, session, name, path, interface, member, peer):
for part in (quantifier, 'dbus', perms, session, name, path, interface, member, peer): for part in (quantifier, 'dbus', perms, session, name, path, interface, member, peer):
if part: if part:
result += ' %s' % part result += ' ' + part
result += ',\n' result += ',\n'
@ -37,14 +37,14 @@ def gen_file(test, xres, quantifier, perms, session, name, path, interface, memb
content = '' content = ''
content += '#\n' content += '#\n'
content += '#=DESCRIPTION %s\n' % test content += '#=DESCRIPTION {}\n'.format(test)
content += '#=EXRESULT %s\n' % xres content += '#=EXRESULT {}\n'.format(xres)
content += '#\n' content += '#\n'
content += '/usr/bin/foo {\n' content += '/usr/bin/foo {\n'
content += get_rule(quantifier, perms, session, name, path, interface, member, peer) content += get_rule(quantifier, perms, session, name, path, interface, member, peer)
content += '}\n' content += '}\n'
write_file('simple_tests/generated_dbus', '%s-%s.sd' % (test, count), content) write_file('simple_tests/generated_dbus', '{}-{}.sd'.format(test, count), content)
count += 1 count += 1
@ -158,4 +158,4 @@ gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(name=1) peer=(name=2)', '
gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(label=1) peer=(label=2)', '', '', '', '', '', '') gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(label=1) peer=(label=2)', '', '', '', '', '', '')
gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(name=1) peer=(label=2)', '', '', '', '', '', '') gen_file('duplicated-conditionals', 'FAIL', '', 'peer=(name=1) peer=(label=2)', '', '', '', '', '', '')
print('Generated %s dbus tests' % count) print('Generated {} dbus tests'.format(count))

View File

@ -66,9 +66,9 @@ def gen_list():
for trans in trans_types: for trans in trans_types:
if trans in trans_modifiers: if trans in trans_modifiers:
for mod in trans_modifiers[trans]: for mod in trans_modifiers[trans]:
output.append("%s%sx" % (trans, mod)) output.append("{}{}x".format(trans, mod))
output.append("%sx" % trans) output.append("{}x".format(trans))
return output return output
@ -80,19 +80,19 @@ def test_gen_list():
actual = gen_list() actual = gen_list()
if actual != expected: if actual != expected:
raise Exception("gen_list produced unexpected result, expected %s, got %s" % (expected, actual)) raise Exception("gen_list produced unexpected result, expected {}, got {}".format(expected, actual))
def build_rule(leading, qual, name, perm, target): def build_rule(leading, qual, name, perm, target):
rule = '' rule = ''
if leading: if leading:
rule += "\t%s %s %s" % (qual, perm, name) rule += "\t{} {} {}".format(qual, perm, name)
else: else:
rule += "\t%s %s %s" % (qual, name, perm) rule += "\t{} {} {}".format(qual, name, perm)
if target: if target:
rule += " -> %s" % target rule += " -> {}".format(target)
rule += ",\n" rule += ",\n"
@ -105,8 +105,8 @@ def gen_file(name, xres, leading1, qual1, rule1, perm1, target1, leading2, qual2
content = '' content = ''
content += "#\n" content += "#\n"
content += "#=DESCRIPTION %s\n" % name content += "#=DESCRIPTION {}\n".format(name)
content += "#=EXRESULT %s\n" % xres content += "#=EXRESULT {}\n".format(xres)
content += "#\n" content += "#\n"
content += "/usr/bin/foo {\n" content += "/usr/bin/foo {\n"
content += build_rule(leading1, qual1, rule1, perm1, target1) content += build_rule(leading1, qual1, rule1, perm1, target1)
@ -197,10 +197,10 @@ def gen_safe_perms(name, xres, invert, rule1, rule2):
if (not invert or qual): if (not invert or qual):
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + '-' + 'rule-' + i + t + '.sd' file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + '-' + 'rule-' + i + t + '.sd'
gen_file(file, xres, 0, '%s %s' % (q, qual), rule1, i, t, 1, q, rule2, i, t) gen_file(file, xres, 0, '{} {}'.format(q, qual), rule1, i, t, 1, q, rule2, i, t)
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + i + '-' + 'rule-' + t + '.sd' file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + i + '-' + 'rule-' + t + '.sd'
gen_file(file, xres, 0, q, rule1, i, t, 1, '%s %s' % (q, qual), rule2, i, t) gen_file(file, xres, 0, q, rule1, i, t, 1, '{} {}'.format(q, qual), rule2, i, t)
test_gen_list() test_gen_list()
@ -225,4 +225,4 @@ gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat")
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*") gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*")
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b") gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b")
print("Generated %s xtransition interaction tests" % count) print("Generated {} xtransition interaction tests".format(count))

View File

@ -27,7 +27,7 @@ def main():
config = p.parse_args() config = p.parse_args()
if not os.path.exists(config.fdir): if not os.path.exists(config.fdir):
print('Unable to find apparmor features directory "%s"' % config.fdir, file=sys.stderr) print('Unable to find apparmor features directory "{}"'.format(config.fdir), file=sys.stderr)
return 1 return 1
features = read_features_dir(config.fdir) features = read_features_dir(config.fdir)

View File

@ -70,9 +70,9 @@ class AATestTemplate(unittest.TestCase, metaclass=AANoCleanupMetaClass):
rc is as long as it's not a specific set of return codes, rc is as long as it's not a specific set of return codes,
so can't push the check directly into run_cmd().""" so can't push the check directly into run_cmd()."""
rc, report = self.run_cmd(command, input, stderr, stdout, stdin, timeout) rc, report = self.run_cmd(command, input, stderr, stdout, stdin, timeout)
self.assertEqual(rc, expected_rc, "Got return code %d, expected %d\nCommand run: %s\nOutput: %s" % (rc, expected_rc, (' '.join(command)), report)) self.assertEqual(rc, expected_rc, "Got return code {}, expected {}\nCommand run: {}\nOutput: {}".format(rc, expected_rc, ' '.join(command), report))
if expected_string: if expected_string:
self.assertIn(expected_string, report, 'Expected message "%s", got: \n%s' % (expected_string, report)) self.assertIn(expected_string, report, 'Expected message "{}", got: \n{}'.format(expected_string, report))
return report return report
def run_cmd(self, command, input=None, stderr=subprocess.PIPE, stdout=subprocess.PIPE, def run_cmd(self, command, input=None, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
@ -81,7 +81,7 @@ class AATestTemplate(unittest.TestCase, metaclass=AANoCleanupMetaClass):
return a textual error if it failed.""" return a textual error if it failed."""
if self.debug: if self.debug:
print("\n===> Running command: '%s'" % (' '.join(command))) print("\n===> Running command: '{}'".format(' '.join(command)))
(rc, out, outerr) = self._run_cmd(command, input, stderr, stdout, stdin, timeout) (rc, out, outerr) = self._run_cmd(command, input, stderr, stdout, stdin, timeout)
report = out + outerr report = out + outerr
@ -154,7 +154,7 @@ def filesystem_time_resolution():
for i in range(10): for i in range(10):
s = None s = None
with open(os.path.join(tmp_dir, 'test.%d' % i), 'w+') as f: with open(os.path.join(tmp_dir, 'test.{}'.format(i)), 'w+') as f:
s = os.fstat(f.fileno()) s = os.fstat(f.fileno())
if (s.st_mtime == last_stamp): if (s.st_mtime == last_stamp):
@ -181,13 +181,13 @@ def read_features_dir(path):
for name in sorted(os.listdir(path)): for name in sorted(os.listdir(path)):
entry = os.path.join(path, name) entry = os.path.join(path, name)
result += '%s {' % name result += name + ' {'
if os.path.isfile(entry): if os.path.isfile(entry):
with open(entry, 'r') as f: with open(entry, 'r') as f:
# don't need extra '\n' here as features file contains it # don't need extra '\n' here as features file contains it
result += '%s' % (f.read()) result += f.read()
elif os.path.isdir(entry): elif os.path.isdir(entry):
result += '%s' % (read_features_dir(entry)) result += read_features_dir(entry)
result += '}\n' result += '}\n'
return result return result

View File

@ -23,7 +23,9 @@ import testlib
DEFAULT_TESTDIR = "./simple_tests/vars" DEFAULT_TESTDIR = "./simple_tests/vars"
VALGRIND_ERROR_CODE = 151 VALGRIND_ERROR_CODE = 151
VALGRIND_ARGS = ['--leak-check=full', '--error-exitcode=%d' % (VALGRIND_ERROR_CODE)] VALGRIND_ARGS = [
'--leak-check=full', '--error-exitcode={}'.format(VALGRIND_ERROR_CODE)
]
VALGRIND_SUPPRESSIONS = ''' VALGRIND_SUPPRESSIONS = '''
{ {
@ -53,8 +55,8 @@ class AAParserValgrindTests(testlib.AATestTemplate):
rc, output = self.run_cmd(command, timeout=120) rc, output = self.run_cmd(command, timeout=120)
self.assertNotIn( self.assertNotIn(
rc, failure_rc, rc, failure_rc,
"valgrind returned error code %d, gave the following output\n%s\ncommand run: %s" "valgrind returned error code {}, gave the following output\n{}\ncommand run: {}".format(
% (rc, output, " ".join(command))) rc, output, " ".join(command)))
def find_testcases(testdir): def find_testcases(testdir):
@ -94,8 +96,10 @@ def main():
return rc return rc
if not os.path.exists(config.valgrind): if not os.path.exists(config.valgrind):
print("Unable to find valgrind at '%s', ensure that it is installed" % (config.valgrind), print(
file=sys.stderr) "Unable to find valgrind at '{}', ensure that it is installed".format(config.valgrind),
file=sys.stderr
)
sys.exit(1) sys.exit(1)
verbosity = 1 verbosity = 1
@ -106,13 +110,13 @@ def main():
suppression_file = None suppression_file = None
else: else:
suppression_file = create_suppressions() suppression_file = create_suppressions()
VALGRIND_ARGS.append('--suppressions=%s' % (suppression_file)) VALGRIND_ARGS.append('--suppressions=' + suppression_file)
for f in find_testcases(config.testdir): for f in find_testcases(config.testdir):
def stub_test(self, testname=f): def stub_test(self, testname=f):
self._runtest(testname, config) self._runtest(testname, config)
stub_test.__doc__ = "test %s" % (f) stub_test.__doc__ = "test " + f
setattr(AAParserValgrindTests, 'test_%s' % (f), stub_test) setattr(AAParserValgrindTests, 'test_' + f, stub_test)
test_suite = unittest.TestSuite() test_suite = unittest.TestSuite()
test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(AAParserValgrindTests)) test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(AAParserValgrindTests))

View File

@ -62,8 +62,8 @@ class AAParseTest(unittest.TestCase):
parsed = self.parse_function(rule) parsed = self.parse_function(rule)
self.assertEqual( self.assertEqual(
rule, parsed.serialize(), rule, parsed.serialize(),
'parse object %s returned "%s", expected "%s"' 'parse object {} returned "{}", expected "{}"'.format(
% (self.parse_function.__doc__, parsed.serialize(), rule)) self.parse_function.__doc__, parsed.serialize(), rule))
def setup_all_loops(module_name): def setup_all_loops(module_name):
@ -89,8 +89,8 @@ def setup_tests_loop(test_class):
def stub_test(self, test_data=test_data, expected=expected): def stub_test(self, test_data=test_data, expected=expected):
self._run_test(test_data, expected) self._run_test(test_data, expected)
stub_test.__doc__ = "test '%s'" % str(test_data) stub_test.__doc__ = "test '{}'".format(test_data)
setattr(test_class, 'test_%d' % (i), stub_test) setattr(test_class, 'test_{}'.format(i), stub_test)
def setup_regex_tests(test_class): def setup_regex_tests(test_class):
@ -102,8 +102,8 @@ def setup_regex_tests(test_class):
def stub_test(self, line=line): def stub_test(self, line=line):
self._test_parse_rule(line) self._test_parse_rule(line)
stub_test.__doc__ = "test '%s': %s" % (line, desc) stub_test.__doc__ = "test '{}': {}".format(line, desc)
setattr(test_class, 'test_%d' % (i), stub_test) setattr(test_class, 'test_{}'.format(i), stub_test)
def setup_aa(aa): def setup_aa(aa):

View File

@ -57,4 +57,4 @@ elif sys.argv[1] == 'TEMPLATE':
print('') print('')
else: else:
raise Exception('unknown parameter in fake_ldd: %s' % sys.argv[1]) raise Exception('unknown parameter in fake_ldd: ' + sys.argv[1])

View File

@ -66,7 +66,7 @@ class AADecodeTest(unittest.TestCase):
expected = 0 expected = 0
rc, report = cmd((aadecode_bin, "--help")) rc, report = cmd((aadecode_bin, "--help"))
result = 'Got exit code %d, expected %d\n' % (rc, expected) result = 'Got exit code {}, expected {}\n'.format(rc, expected)
self.assertEqual(expected, rc, result + report) self.assertEqual(expected, rc, result + report)
def _run_file_test(self, content, expected): def _run_file_test(self, content, expected):
@ -82,10 +82,10 @@ class AADecodeTest(unittest.TestCase):
temp_file.seek(0) temp_file.seek(0)
rc, report = cmd((aadecode_bin,), stdin=temp_file) rc, report = cmd((aadecode_bin,), stdin=temp_file)
result = 'Got exit code %d, expected %d\n' % (rc, expected_return_code) result = 'Got exit code {}, expected {}\n'.format(rc, expected_return_code)
self.assertEqual(expected_return_code, rc, result + report) self.assertEqual(expected_return_code, rc, result + report)
for expected_string in expected: for expected_string in expected:
result = 'could not find expected %s in output:\n' % (expected_string) result = 'could not find expected {} in output:\n'.format(expected_string)
self.assertIn(expected_string, report, result + report) self.assertIn(expected_string, report, result + report)
def test_simple_decode(self): def test_simple_decode(self):
@ -96,9 +96,9 @@ class AADecodeTest(unittest.TestCase):
test_code = '2F746D702F666F6F20626172' test_code = '2F746D702F666F6F20626172'
rc, report = cmd((aadecode_bin, test_code)) rc, report = cmd((aadecode_bin, test_code))
result = 'Got exit code %d, expected %d\n' % (rc, expected) result = 'Got exit code {}, expected {}\n'.format(rc, expected)
self.assertEqual(expected, rc, result + report) self.assertEqual(expected, rc, result + report)
result = 'Got output "%s", expected "%s"\n' % (report, expected_output) result = 'Got output "{}", expected "{}"\n'.format(report, expected_output)
self.assertIn(expected_output, report, result + report) self.assertIn(expected_output, report, result + report)
def test_simple_filter(self): def test_simple_filter(self):

File diff suppressed because it is too large Load Diff

View File

@ -138,9 +138,9 @@ Feb 4 13:40:38 XPS-13-9370 kernel: [128552.880347] audit: type=1400 audit({epoc
expected_output_has = 'usage: aa-notify' expected_output_has = 'usage: aa-notify'
return_code, output = cmd(aanotify_bin) return_code, output = cmd(aanotify_bin)
result = 'Got return code %d, expected %d\n' % (return_code, expected_return_code) result = 'Got return code {}, expected {}\n'.format(return_code, expected_return_code)
self.assertEqual(expected_return_code, return_code, result + output) self.assertEqual(expected_return_code, return_code, result + output)
result = 'Got output "%s", expected "%s"\n' % (output, expected_output_has) result = 'Got output "{}", expected "{}"\n'.format(output, expected_output_has)
self.assertIn(expected_output_has, output, result + output) self.assertIn(expected_output_has, output, result + output)
def test_help_contents(self): def test_help_contents(self):
@ -173,7 +173,7 @@ Display AppArmor notifications or messages for DENIED entries.
''' '''
return_code, output = cmd(aanotify_bin + ['--help']) return_code, output = cmd(aanotify_bin + ['--help'])
result = 'Got return code %d, expected %d\n' % (return_code, expected_return_code) result = 'Got return code {}, expected {}\n'.format(return_code, expected_return_code)
self.assertEqual(expected_return_code, return_code, result + output) self.assertEqual(expected_return_code, return_code, result + output)
self.assertIn(expected_output_1, output) self.assertIn(expected_output_1, output)
@ -186,9 +186,9 @@ Display AppArmor notifications or messages for DENIED entries.
expected_output_has = 'AppArmor denials: 20 (since' expected_output_has = 'AppArmor denials: 20 (since'
return_code, output = cmd(aanotify_bin + ['-f', self.test_logfile, '-s', '100']) return_code, output = cmd(aanotify_bin + ['-f', self.test_logfile, '-s', '100'])
result = 'Got return code %d, expected %d\n' % (return_code, expected_return_code) result = 'Got return code {}, expected {}\n'.format(return_code, expected_return_code)
self.assertEqual(expected_return_code, return_code, result + output) self.assertEqual(expected_return_code, return_code, result + output)
result = 'Got output "%s", expected "%s"\n' % (output, expected_output_has) result = 'Got output "{}", expected "{}"\n'.format(output, expected_output_has)
self.assertIn(expected_output_has, output, result + output) self.assertIn(expected_output_has, output, result + output)
@unittest.skipUnless(os.path.isfile('/var/log/wtmp'), 'Requires wtmp on system') @unittest.skipUnless(os.path.isfile('/var/log/wtmp'), 'Requires wtmp on system')
@ -201,9 +201,9 @@ Display AppArmor notifications or messages for DENIED entries.
return_code, output = cmd(aanotify_bin + ['-f', self.test_logfile, '-l']) return_code, output = cmd(aanotify_bin + ['-f', self.test_logfile, '-l'])
if "ERROR: Could not find last login" in output: if "ERROR: Could not find last login" in output:
self.skipTest('Could not find last login') self.skipTest('Could not find last login')
result = 'Got return code %d, expected %d\n' % (return_code, expected_return_code) result = 'Got return code {}, expected {}\n'.format(return_code, expected_return_code)
self.assertEqual(expected_return_code, return_code, result + output) self.assertEqual(expected_return_code, return_code, result + output)
result = 'Got output "%s", expected "%s"\n' % (output, expected_output_has) result = 'Got output "{}", expected "{}"\n'.format(output, expected_output_has)
self.assertIn(expected_output_has, output, result + output) self.assertIn(expected_output_has, output, result + output)
@unittest.skipUnless(os.path.isfile('/var/log/wtmp'), 'Requires wtmp on system') @unittest.skipUnless(os.path.isfile('/var/log/wtmp'), 'Requires wtmp on system')
@ -277,9 +277,9 @@ AppArmor denials: 10 (since'''.format(logfile=self.test_logfile)
return_code, output = cmd(aanotify_bin + ['-f', self.test_logfile, '-l', '-v']) return_code, output = cmd(aanotify_bin + ['-f', self.test_logfile, '-l', '-v'])
if "ERROR: Could not find last login" in output: if "ERROR: Could not find last login" in output:
self.skipTest('Could not find last login') self.skipTest('Could not find last login')
result = 'Got return code %d, expected %d\n' % (return_code, expected_return_code) result = 'Got return code {}, expected {}\n'.format(return_code, expected_return_code)
self.assertEqual(expected_return_code, return_code, result + output) self.assertEqual(expected_return_code, return_code, result + output)
result = 'Got output "%s", expected "%s"\n' % (output, expected_output_has) result = 'Got output "{}", expected "{}"\n'.format(output, expected_output_has)
self.assertIn(expected_output_has, output, result + output) self.assertIn(expected_output_has, output, result + output)

View File

@ -59,7 +59,7 @@ class AaTest_check_for_apparmor(AaTestWithTempdir):
def test_check_for_apparmor_securityfs_invalid_filesystems(self): def test_check_for_apparmor_securityfs_invalid_filesystems(self):
filesystems = '' filesystems = ''
mounts = write_file(self.tmpdir, 'mounts', self.MOUNTS_WITH_SECURITYFS % self.tmpdir) mounts = write_file(self.tmpdir, 'mounts', self.MOUNTS_WITH_SECURITYFS % (self.tmpdir,))
self.assertEqual(None, check_for_apparmor(filesystems, mounts)) self.assertEqual(None, check_for_apparmor(filesystems, mounts))
def test_check_for_apparmor_securityfs_invalid_mounts(self): def test_check_for_apparmor_securityfs_invalid_mounts(self):
@ -69,13 +69,13 @@ class AaTest_check_for_apparmor(AaTestWithTempdir):
def test_check_for_apparmor_invalid_securityfs_path(self): def test_check_for_apparmor_invalid_securityfs_path(self):
filesystems = write_file(self.tmpdir, 'filesystems', self.FILESYSTEMS_WITH_SECURITYFS) filesystems = write_file(self.tmpdir, 'filesystems', self.FILESYSTEMS_WITH_SECURITYFS)
mounts = write_file(self.tmpdir, 'mounts', self.MOUNTS_WITH_SECURITYFS % 'xxx') mounts = write_file(self.tmpdir, 'mounts', self.MOUNTS_WITH_SECURITYFS % ('xxx',))
self.assertEqual(None, check_for_apparmor(filesystems, mounts)) self.assertEqual(None, check_for_apparmor(filesystems, mounts))
def test_check_for_apparmor_securityfs_mounted(self): def test_check_for_apparmor_securityfs_mounted(self):
filesystems = write_file(self.tmpdir, 'filesystems', self.FILESYSTEMS_WITH_SECURITYFS) filesystems = write_file(self.tmpdir, 'filesystems', self.FILESYSTEMS_WITH_SECURITYFS)
mounts = write_file(self.tmpdir, 'mounts', self.MOUNTS_WITH_SECURITYFS % self.tmpdir) mounts = write_file(self.tmpdir, 'mounts', self.MOUNTS_WITH_SECURITYFS % (self.tmpdir,))
self.assertEqual('%s/security/apparmor' % self.tmpdir, check_for_apparmor(filesystems, mounts)) self.assertEqual(self.tmpdir + '/security/apparmor', check_for_apparmor(filesystems, mounts))
class AATest_get_output(AATest): class AATest_get_output(AATest):
@ -119,7 +119,7 @@ class AaTest_create_new_profile(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
# load the abstractions we need in the test # load the abstractions we need in the test
@ -139,22 +139,22 @@ class AaTest_create_new_profile(AATest):
expected_profiles = [] expected_profiles = []
for prof in exp_profiles: for prof in exp_profiles:
expected_profiles.append('%s/%s' % (self.tmpdir, prof)) # actual profile names start with tmpdir, prepend it to the expected profile names expected_profiles.append('{}/{}'.format(self.tmpdir, prof)) # actual profile names start with tmpdir, prepend it to the expected profile names
self.assertEqual(list(profile.keys()), expected_profiles) self.assertEqual(list(profile.keys()), expected_profiles)
if exp_interpreter_path: if exp_interpreter_path:
self.assertEqual( self.assertEqual(
set(profile[program]['file'].get_clean()), set(profile[program]['file'].get_clean()),
{'%s ix,' % exp_interpreter_path, '%s r,' % program, '', {'{} ix,'.format(exp_interpreter_path), '{} r,'.format(program), '',
'/AATest/lib64/libtinfo.so.* mr,', '/AATest/lib64/libc.so.* mr,', '/AATest/lib64/libtinfo.so.* mr,', '/AATest/lib64/libc.so.* mr,',
'/AATest/lib64/libdl.so.* mr,', '/AATest/lib64/libreadline.so.* mr,', '/AATest/lib64/libdl.so.* mr,', '/AATest/lib64/libreadline.so.* mr,',
'/AATest/lib64/ld-linux-x86-64.so.* mr,'}) '/AATest/lib64/ld-linux-x86-64.so.* mr,'})
else: else:
self.assertEqual(set(profile[program]['file'].get_clean()), {'%s mr,' % program, ''}) self.assertEqual(set(profile[program]['file'].get_clean()), {'{} mr,'.format(program), ''})
if exp_abstraction: if exp_abstraction:
self.assertEqual(profile[program]['inc_ie'].get_clean(), ['include <abstractions/base>', 'include <%s>' % exp_abstraction, '']) self.assertEqual(profile[program]['inc_ie'].get_clean(), ['include <abstractions/base>', 'include <{}>'.format(exp_abstraction), ''])
else: else:
self.assertEqual(profile[program]['inc_ie'].get_clean(), ['include <abstractions/base>', '']) self.assertEqual(profile[program]['inc_ie'].get_clean(), ['include <abstractions/base>', ''])
@ -183,7 +183,7 @@ class AaTest_get_interpreter_and_abstraction(AATest):
def _run_test(self, params, expected): def _run_test(self, params, expected):
exp_interpreter_path, exp_abstraction = expected exp_interpreter_path, exp_abstraction = expected
program = self.writeTmpfile('program', "%s\nfoo\nbar" % params) program = self.writeTmpfile('program', params + "\nfoo\nbar")
interpreter_path, abstraction = get_interpreter_and_abstraction(program) interpreter_path, abstraction = get_interpreter_and_abstraction(program)
# damn symlinks! # damn symlinks!
@ -198,12 +198,12 @@ class AaTest_get_interpreter_and_abstraction(AATest):
def test_file_not_found(self): def test_file_not_found(self):
self.createTmpdir() self.createTmpdir()
self.assertEqual((None, None), get_interpreter_and_abstraction('%s/file-not-found' % self.tmpdir)) self.assertEqual((None, None), get_interpreter_and_abstraction(self.tmpdir + '/file-not-found'))
class AaTest_get_profile_flags(AaTestWithTempdir): class AaTest_get_profile_flags(AaTestWithTempdir):
def _test_get_flags(self, profile_header, expected_flags): def _test_get_flags(self, profile_header, expected_flags):
file = write_file(self.tmpdir, 'profile', '%s {\n}\n' % profile_header) file = write_file(self.tmpdir, 'profile', profile_header + ' {\n}\n')
flags = get_profile_flags(file, '/foo') flags = get_profile_flags(file, '/foo')
self.assertEqual(flags, expected_flags) self.assertEqual(flags, expected_flags)
@ -238,10 +238,10 @@ class AaTest_change_profile_flags(AaTestWithTempdir):
self, profile, old_flags, flags_to_change, set_flag, expected_flags, whitespace='', self, profile, old_flags, flags_to_change, set_flag, expected_flags, whitespace='',
comment='', more_rules='', expected_more_rules='@-@-@', check_new_flags=True, profile_name='/foo'): comment='', more_rules='', expected_more_rules='@-@-@', check_new_flags=True, profile_name='/foo'):
if old_flags: if old_flags:
old_flags = ' %s' % old_flags old_flags = ' ' + old_flags
if expected_flags: if expected_flags:
expected_flags = ' flags=(%s)' % (expected_flags) expected_flags = ' flags=({})'.format(expected_flags)
else: else:
expected_flags = '' expected_flags = ''
@ -249,7 +249,7 @@ class AaTest_change_profile_flags(AaTestWithTempdir):
expected_more_rules = more_rules expected_more_rules = more_rules
if comment: if comment:
comment = ' %s' % comment comment = ' ' + comment
dummy_profile_content = ' #include <abstractions/base>\n capability chown,\n /bar r,' dummy_profile_content = ' #include <abstractions/base>\n capability chown,\n /bar r,'
prof_template = '%s%s%s {%s\n%s\n%s\n}\n' prof_template = '%s%s%s {%s\n%s\n%s\n}\n'
@ -406,7 +406,7 @@ class AaTest_change_profile_flags(AaTestWithTempdir):
def test_change_profile_flags_file_not_found(self): def test_change_profile_flags_file_not_found(self):
with self.assertRaises(IOError): with self.assertRaises(IOError):
change_profile_flags('%s/file-not-found' % self.tmpdir, '/foo', 'audit', True) change_profile_flags(self.tmpdir + '/file-not-found', '/foo', 'audit', True)
class AaTest_set_options_audit_mode(AATest): class AaTest_set_options_audit_mode(AATest):
@ -561,7 +561,7 @@ class AaTest_get_file_perms_1(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
profile = apparmor.aa.ProfileStorage('/test', '/test', 'test-aa.py') profile = apparmor.aa.ProfileStorage('/test', '/test', 'test-aa.py')
@ -590,7 +590,7 @@ class AaTest_get_file_perms_2(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
# load the abstractions we need in the test # load the abstractions we need in the test
@ -629,7 +629,7 @@ class AaTest_propose_file_rules(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
# load the abstractions we need in the test # load the abstractions we need in the test
@ -671,7 +671,7 @@ class AaTest_propose_file_rules_with_absolute_includes(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
# load the abstractions we need in the test # load the abstractions we need in the test
@ -689,9 +689,9 @@ class AaTest_propose_file_rules_with_absolute_includes(AATest):
profile = apparmor.aa.ProfileStorage('/test', '/test', 'test-aa.py') profile = apparmor.aa.ProfileStorage('/test', '/test', 'test-aa.py')
profile['inc_ie'].add(IncludeRule.create_instance('include <abstractions/base>')) profile['inc_ie'].add(IncludeRule.create_instance('include <abstractions/base>'))
profile['inc_ie'].add(IncludeRule.create_instance('include "%s"' % abs_include1)) profile['inc_ie'].add(IncludeRule.create_instance('include "{}"'.format(abs_include1)))
profile['inc_ie'].add(IncludeRule.create_instance('include "%s"' % abs_include2)) profile['inc_ie'].add(IncludeRule.create_instance('include "{}"'.format(abs_include2)))
profile['inc_ie'].add(IncludeRule.create_instance('include "%s"' % abs_include3)) profile['inc_ie'].add(IncludeRule.create_instance('include "{}"'.format(abs_include3)))
rule_obj = FileRule(params[0], params[1], None, FileRule.ALL, owner=False, log_event=True) rule_obj = FileRule(params[0], params[1], None, FileRule.ALL, owner=False, log_event=True)
proposals = propose_file_rules(profile, rule_obj) proposals = propose_file_rules(profile, rule_obj)

View File

@ -138,12 +138,12 @@ class TestConvert_regexpAndAAREMatch(AATest):
def _run_test(self, params, expected): def _run_test(self, params, expected):
regex, path = params regex, path = params
parsed_regex = re.compile(convert_regexp(regex)) parsed_regex = re.compile(convert_regexp(regex))
self.assertEqual(bool(parsed_regex.search(path)), expected, 'Incorrectly Parsed regex: %s' % regex) self.assertEqual(bool(parsed_regex.search(path)), expected, 'Incorrectly Parsed regex: ' + regex)
aare_obj = AARE(regex, True) aare_obj = AARE(regex, True)
self.assertEqual(aare_obj.match(path), expected, 'Incorrectly parsed AARE object: %s' % regex) self.assertEqual(aare_obj.match(path), expected, 'Incorrectly parsed AARE object: ' + regex)
if not ('*' in path or '{' in path or '}' in path or '?' in path): if not ('*' in path or '{' in path or '}' in path or '?' in path):
self.assertEqual(aare_obj.match(AARE(path, False)), expected, 'Incorrectly parsed AARE object: AARE(%s)' % regex) self.assertEqual(aare_obj.match(AARE(path, False)), expected, 'Incorrectly parsed AARE object: AARE({})'.format(regex))
def test_multi_usage(self): def test_multi_usage(self):
aare_obj = AARE('/foo/*', True) aare_obj = AARE('/foo/*', True)

View File

@ -199,11 +199,11 @@ class AbiCoveredTest(AATest):
self.assertTrue(AbiRule.match(param)) self.assertTrue(AbiRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class AbiCoveredTest_01(AbiCoveredTest): class AbiCoveredTest_01(AbiCoveredTest):

View File

@ -176,11 +176,11 @@ class AliasCoveredTest(AATest):
self.assertTrue(AliasRule.match(param)) self.assertTrue(AliasRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class AliasCoveredTest_01(AliasCoveredTest): class AliasCoveredTest_01(AliasCoveredTest):

View File

@ -181,11 +181,11 @@ class BooleanCoveredTest(AATest):
self.assertTrue(BooleanRule.match(param)) self.assertTrue(BooleanRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class BooleanCoveredTest_01(BooleanCoveredTest): class BooleanCoveredTest_01(BooleanCoveredTest):

View File

@ -252,11 +252,11 @@ class ChangeProfileCoveredTest(AATest):
self.assertTrue(ChangeProfileRule.match(param)) self.assertTrue(ChangeProfileRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class ChangeProfileCoveredTest_01(ChangeProfileCoveredTest): class ChangeProfileCoveredTest_01(ChangeProfileCoveredTest):

View File

@ -441,11 +441,11 @@ class DbusCoveredTest(AATest):
self.assertTrue(DbusRule.match(param)) self.assertTrue(DbusRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class DbusCoveredTest_01(DbusCoveredTest): class DbusCoveredTest_01(DbusCoveredTest):

View File

@ -464,11 +464,11 @@ class FileCoveredTest(AATest):
self.assertTrue(FileRule.match(param)) self.assertTrue(FileRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class FileCoveredTest_01(FileCoveredTest): class FileCoveredTest_01(FileCoveredTest):
@ -892,7 +892,7 @@ class FileValidateAndStoreEditTest(AATest):
self.assertEqual(rule_obj.validate_edit(params), expected) self.assertEqual(rule_obj.validate_edit(params), expected)
rule_obj.store_edit(params) rule_obj.store_edit(params)
self.assertEqual(rule_obj.get_raw(), '%s r,' % params) self.assertEqual(rule_obj.get_raw(), params + ' r,')
tests = ( tests = (
# edited path match # edited path match

View File

@ -249,11 +249,11 @@ class IncludeCoveredTest(AATest):
self.assertTrue(IncludeRule.match(param)) self.assertTrue(IncludeRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class IncludeCoveredTest_01(IncludeCoveredTest): class IncludeCoveredTest_01(IncludeCoveredTest):
@ -332,7 +332,7 @@ class IncludeFullPathsTest(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
inc_dir = os.path.join(self.profile_dir, 'abstractions/inc.d') inc_dir = os.path.join(self.profile_dir, 'abstractions/inc.d')
@ -374,7 +374,7 @@ class IncludeRulesTest(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
write_file(self.profile_dir, 'baz', '/baz r,') write_file(self.profile_dir, 'baz', '/baz r,')

View File

@ -33,12 +33,12 @@ class TestLibapparmorTestMulti(AATest):
expected = self._parse_libapparmor_test_multi(params) expected = self._parse_libapparmor_test_multi(params)
loglines = [] loglines = []
with open_file_read('%s.in' % params) as f_in: with open_file_read(params + '.in') as f_in:
for line in f_in: for line in f_in:
if line.strip(): if line.strip():
loglines.append(line) loglines.append(line)
self.assertEqual(len(loglines), 1, '%s.in should only contain one line!' % params) self.assertEqual(len(loglines), 1, params + '.in should only contain one line!')
parser = ReadLog('', '', '') parser = ReadLog('', '', '')
parsed_event = parser.parse_event(loglines[0]) parsed_event = parser.parse_event(loglines[0])
@ -72,11 +72,11 @@ class TestLibapparmorTestMulti(AATest):
elif parsed_items['operation'] == 'ptrace' and label == 'name2' and params.endswith('/ptrace_garbage_lp1689667_1'): elif parsed_items['operation'] == 'ptrace' and label == 'name2' and params.endswith('/ptrace_garbage_lp1689667_1'):
pass # libapparmor would better qualify this case as invalid event pass # libapparmor would better qualify this case as invalid event
elif not parsed_items.get(label, None): elif not parsed_items.get(label, None):
raise Exception('parsed_items[%s] not set' % label) raise Exception('parsed_items[{}] not set'.format(label))
elif not expected.get(label, None): elif not expected.get(label, None):
raise Exception('expected[%s] not set' % label) raise Exception('expected[{}] not set'.format(label))
else: else:
self.assertEqual(str(parsed_items[label]), expected[label], '%s differs' % label) self.assertEqual(str(parsed_items[label]), expected[label], label + ' differs')
elif expected: elif expected:
self.assertIsNone(parsed_event) # that's why we end up here self.assertIsNone(parsed_event) # that's why we end up here
self.assertEqual(dict(), expected, 'parsed_event is none') # effectively print the content of expected self.assertEqual(dict(), expected, 'parsed_event is none') # effectively print the content of expected
@ -109,12 +109,12 @@ class TestLibapparmorTestMulti(AATest):
def _parse_libapparmor_test_multi(self, file_with_path): def _parse_libapparmor_test_multi(self, file_with_path):
"""parse the libapparmor test_multi *.in tests and their expected result in *.out""" """parse the libapparmor test_multi *.in tests and their expected result in *.out"""
with open_file_read('%s.out' % file_with_path) as f_in: with open_file_read(file_with_path + '.out') as f_in:
expected = f_in.readlines() expected = f_in.readlines()
if expected[0].rstrip('\n') != 'START': if expected[0].rstrip('\n') != 'START':
raise Exception("%s.out doesn't have 'START' in its first line! (%s)" raise Exception("{}.out doesn't have 'START' in its first line! ({})".format(
% (file_with_path, expected[0])) file_with_path, expected[0]))
expected.pop(0) expected.pop(0)
@ -129,8 +129,8 @@ class TestLibapparmorTestMulti(AATest):
exresult[label] = value.strip() exresult[label] = value.strip()
if not exresult['event_type'].startswith('AA_RECORD_'): if not exresult['event_type'].startswith('AA_RECORD_'):
raise Exception("event_type doesn't start with AA_RECORD_: %s in file %s" raise Exception("event_type doesn't start with AA_RECORD_: {} in file {}".format(
% (exresult['event_type'], file_with_path)) exresult['event_type'], file_with_path))
exresult['aamode'] = exresult['event_type'].replace('AA_RECORD_', '') exresult['aamode'] = exresult['event_type'].replace('AA_RECORD_', '')
if exresult['aamode'] == 'ALLOWED': if exresult['aamode'] == 'ALLOWED':
@ -189,7 +189,7 @@ class TestLogToProfile(AATest):
tests = 'invalid' # filled by parse_test_profiles() tests = 'invalid' # filled by parse_test_profiles()
def _run_test(self, params, expected): def _run_test(self, params, expected):
logfile = '%s.in' % params logfile = params + '.in'
if params.split('/')[-1] in log_to_profile_skip: if params.split('/')[-1] in log_to_profile_skip:
return return
@ -198,7 +198,7 @@ class TestLogToProfile(AATest):
if profile is None: if profile is None:
return return
expected_profile = read_file('%s.profile' % params) expected_profile = read_file(params + '.profile')
if params.split('/')[-1] in log_to_profile_known_failures: if params.split('/')[-1] in log_to_profile_known_failures:
self.assertNotEqual(new_profile, expected_profile) # known failure self.assertNotEqual(new_profile, expected_profile) # known failure
@ -222,7 +222,7 @@ def logfile_to_profile(logfile):
return None, aamode return None, aamode
if aamode not in ('PERMITTING', 'REJECTING'): if aamode not in ('PERMITTING', 'REJECTING'):
raise Exception('Unexpected aamode %s' % parsed_event['aamode']) raise Exception('Unexpected aamode {}'.format(parsed_event['aamode']))
# cleanup apparmor.aa storage # cleanup apparmor.aa storage
apparmor.aa.log = dict() apparmor.aa.log = dict()
@ -249,7 +249,7 @@ def logfile_to_profile(logfile):
log_dict = apparmor.aa.collapse_log(hashlog, ignore_null_profiles=False) log_dict = apparmor.aa.collapse_log(hashlog, ignore_null_profiles=False)
if list(log_dict[aamode].keys()) != [parsed_event['profile']]: if list(log_dict[aamode].keys()) != [parsed_event['profile']]:
raise Exception('log_dict[%s] contains unexpected keys. Logfile: %s, keys %s' % (aamode, logfile, log_dict.keys())) raise Exception('log_dict[{}] contains unexpected keys. Logfile: {}, keys {}'.format(aamode, logfile, log_dict.keys()))
if '//' in parsed_event['profile']: if '//' in parsed_event['profile']:
# log event for a child profile means log_dict only contains the child profile # log event for a child profile means log_dict only contains the child profile
@ -272,10 +272,10 @@ def logfile_to_profile(logfile):
if logfile.split('/')[-1][:-3] in log_to_profile_known_empty_log: if logfile.split('/')[-1][:-3] in log_to_profile_known_empty_log:
# unfortunately this function might be called outside Unittest.TestCase, therefore we can't use assertEqual / assertNotEqual # unfortunately this function might be called outside Unittest.TestCase, therefore we can't use assertEqual / assertNotEqual
if not log_is_empty: if not log_is_empty:
raise Exception('got non-empty log for logfile in log_to_profile_known_empty_log: %s %s' % (logfile, hashlog)) raise Exception('got non-empty log for logfile in log_to_profile_known_empty_log: {} {}'.format(logfile, hashlog))
else: else:
if log_is_empty: if log_is_empty:
raise Exception('got empty log for logfile not in log_to_profile_known_empty_log: %s %s' % (logfile, hashlog)) raise Exception('got empty log for logfile not in log_to_profile_known_empty_log: {} {}'.format(logfile, hashlog))
new_profile = apparmor.aa.serialize_profile(log_dict[aamode], profile, {}) new_profile = apparmor.aa.serialize_profile(log_dict[aamode], profile, {})
@ -297,7 +297,7 @@ def find_test_multi(log_dir):
elif file.endswith('.out') or file.endswith('.err') or file.endswith('.profile'): elif file.endswith('.out') or file.endswith('.err') or file.endswith('.profile'):
pass pass
else: else:
raise Exception('Found unknown file %s in libapparmor test_multi' % file) raise Exception('Found unknown file {} in libapparmor test_multi'.format(file))
return tests return tests

View File

@ -29,7 +29,7 @@ class MinitoolsTest(AATest):
# copy the local profiles to the test directory # copy the local profiles to the test directory
# Should be the set of cleanprofile # Should be the set of cleanprofile
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
apparmor.profile_dir = self.profile_dir apparmor.profile_dir = self.profile_dir
@ -37,143 +37,152 @@ class MinitoolsTest(AATest):
# Path for the program # Path for the program
self.test_path = '/usr/sbin/winbindd' self.test_path = '/usr/sbin/winbindd'
# Path for the target file containing profile # Path for the target file containing profile
self.local_profilename = '%s/usr.sbin.winbindd' % self.profile_dir self.local_profilename = self.profile_dir + '/usr.sbin.winbindd'
def test_audit(self): def test_audit(self):
# Set test profile to audit mode and check if it was correctly set # Set test profile to audit mode and check if it was correctly set
str(subprocess.check_output( subprocess.check_output(
'%s ./../aa-audit --no-reload -d %s %s --configdir ./' '{} ./../aa-audit --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True)) python_interpreter, self.profile_dir, self.test_path),
shell=True)
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
'audit', 'audit',
'Audit flag could not be set in profile %s' % self.local_profilename) 'Audit flag could not be set in profile ' + self.local_profilename)
# Remove audit mode from test profile and check if it was correctly removed # Remove audit mode from test profile and check if it was correctly removed
subprocess.check_output( subprocess.check_output(
'%s ./../aa-audit --no-reload -d %s -r %s --configdir ./' '{} ./../aa-audit --no-reload -d {} -r {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path), shell=True)
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
None, None,
'Audit flag could not be removed in profile %s' % self.local_profilename) 'Audit flag could not be removed in profile ' + self.local_profilename)
def test_complain(self): def test_complain(self):
# Set test profile to complain mode and check if it was correctly set # Set test profile to complain mode and check if it was correctly set
subprocess.check_output( subprocess.check_output(
'%s ./../aa-complain --no-reload -d %s %s --configdir ./' '{} ./../aa-complain --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
# "manually" create a force-complain symlink (will be deleted by aa-enforce later) # "manually" create a force-complain symlink (will be deleted by aa-enforce later)
force_complain_dir = '%s/force-complain' % self.profile_dir force_complain_dir = self.profile_dir + '/force-complain'
if not os.path.isdir(force_complain_dir): if not os.path.isdir(force_complain_dir):
os.mkdir(force_complain_dir) os.mkdir(force_complain_dir)
os.symlink( os.symlink(
self.local_profilename, self.local_profilename,
'%s/%s' % (force_complain_dir, os.path.basename(self.local_profilename))) '{}/{}'.format(force_complain_dir, os.path.basename(self.local_profilename)))
self.assertEqual( self.assertEqual(
os.path.islink('%s/%s' % (force_complain_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/{}'.format(force_complain_dir, os.path.basename(self.local_profilename))),
True, True,
'Failed to create a symlink for %s in force-complain' % self.local_profilename) 'Failed to create a symlink for {} in force-complain'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
'complain', 'complain',
'Complain flag could not be set in profile %s' % self.local_profilename) 'Complain flag could not be set in profile ' + self.local_profilename)
# Set test profile to enforce mode and check if it was correctly set # Set test profile to enforce mode and check if it was correctly set
subprocess.check_output( subprocess.check_output(
'%s ./../aa-enforce --no-reload -d %s %s --configdir ./' '{} ./../aa-enforce --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
self.assertEqual( self.assertEqual(
os.path.islink('%s/%s' % (force_complain_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/{}'.format(force_complain_dir, os.path.basename(self.local_profilename))),
False, False,
'Failed to remove symlink for %s from force-complain' % self.local_profilename) 'Failed to remove symlink for {} from force-complain'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
os.path.islink('%s/disable/%s' % (self.profile_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/disable/{}'.format(self.profile_dir, os.path.basename(self.local_profilename))),
False, False,
'Failed to remove symlink for %s from disable' % self.local_profilename) 'Failed to remove symlink for {} from disable'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
None, None,
'Complain flag could not be removed in profile %s' % self.local_profilename) 'Complain flag could not be removed in profile ' + self.local_profilename)
# Set audit flag and then complain flag in a profile # Set audit flag and then complain flag in a profile
subprocess.check_output( subprocess.check_output(
'%s ./../aa-audit --no-reload -d %s %s --configdir ./' '{} ./../aa-audit --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
subprocess.check_output( subprocess.check_output(
'%s ./../aa-complain --no-reload -d %s %s --configdir ./' '{} ./../aa-complain --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
# "manually" create a force-complain symlink (will be deleted by aa-enforce later) # "manually" create a force-complain symlink (will be deleted by aa-enforce later)
os.symlink( os.symlink(
self.local_profilename, self.local_profilename,
'%s/%s' % (force_complain_dir, os.path.basename(self.local_profilename))) '{}/{}'.format(force_complain_dir, os.path.basename(self.local_profilename)))
self.assertEqual( self.assertEqual(
os.path.islink('%s/%s' % (force_complain_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/{}'.format(force_complain_dir, os.path.basename(self.local_profilename))),
True, True,
'Failed to create a symlink for %s in force-complain' % self.local_profilename) 'Failed to create a symlink for {} in force-complain'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
'audit, complain', 'audit, complain',
'Complain flag could not be set in profile %s' % self.local_profilename) 'Complain flag could not be set in profile ' + self.local_profilename)
# Remove complain flag first i.e. set to enforce mode # Remove complain flag first i.e. set to enforce mode
subprocess.check_output( subprocess.check_output(
'%s ./../aa-enforce --no-reload -d %s %s --configdir ./' '{} ./../aa-enforce --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
self.assertEqual( self.assertEqual(
os.path.islink('%s/%s' % (force_complain_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/{}'.format(force_complain_dir, os.path.basename(self.local_profilename))),
False, False,
'Failed to remove symlink for %s from force-complain' % self.local_profilename) 'Failed to remove symlink for {} from force-complain'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
os.path.islink('%s/disable/%s' % (self.profile_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/disable/{}'.format(self.profile_dir, os.path.basename(self.local_profilename))),
False, False,
'Failed to remove symlink for %s from disable' % self.local_profilename) 'Failed to remove symlink for {} from disable'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
'audit', 'audit',
'Complain flag could not be removed in profile %s' % self.local_profilename) 'Complain flag could not be removed in profile ' + self.local_profilename)
# Remove audit flag # Remove audit flag
subprocess.check_output( subprocess.check_output(
'%s ./../aa-audit --no-reload -d %s -r %s --configdir ./' '{} ./../aa-audit --no-reload -d {} -r {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
def test_enforce(self): def test_enforce(self):
# Set test profile to enforce mode and check if it was correctly set # Set test profile to enforce mode and check if it was correctly set
subprocess.check_output( subprocess.check_output(
'%s ./../aa-enforce --no-reload -d %s %s --configdir ./' '{} ./../aa-enforce --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
self.assertEqual( self.assertEqual(
os.path.islink('%s/force-complain/%s' % (self.profile_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/force-complain/{}'.format(self.profile_dir, os.path.basename(self.local_profilename))),
False, False,
'Failed to remove symlink for %s from force-complain' % self.local_profilename) 'Failed to remove symlink for {} from force-complain'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
os.path.islink('%s/disable/%s' % (self.profile_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/disable/{}'.format(self.profile_dir, os.path.basename(self.local_profilename))),
False, False,
'Failed to remove symlink for %s from disable' % self.local_profilename) 'Failed to remove symlink for {} from disable'.format(self.local_profilename))
self.assertEqual( self.assertEqual(
apparmor.get_profile_flags(self.local_profilename, self.test_path), apparmor.get_profile_flags(self.local_profilename, self.test_path),
None, None,
'Complain flag could not be removed in profile %s' % self.local_profilename) 'Complain flag could not be removed in profile {}'.format(self.local_profilename))
def test_disable(self): def test_disable(self):
# Disable the test profile and check if it was correctly disabled # Disable the test profile and check if it was correctly disabled
subprocess.check_output( subprocess.check_output(
'%s ./../aa-disable --no-reload -d %s %s --configdir ./' '{} ./../aa-disable --no-reload -d {} {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, self.test_path), shell=True) python_interpreter, self.profile_dir, self.test_path),
shell=True)
self.assertEqual( self.assertEqual(
os.path.islink('%s/disable/%s' % (self.profile_dir, os.path.basename(self.local_profilename))), os.path.islink('{}/disable/{}'.format(self.profile_dir, os.path.basename(self.local_profilename))),
True, True,
'Failed to create a symlink for %s in disable' % self.local_profilename) 'Failed to create a symlink for {} in disable'.format(self.local_profilename))
def test_autodep(self): def test_autodep(self):
pass pass
@ -181,10 +190,10 @@ class MinitoolsTest(AATest):
@unittest.skipIf(apparmor.check_for_apparmor() is None, "Securityfs not mounted or doesn't have the apparmor directory.") @unittest.skipIf(apparmor.check_for_apparmor() is None, "Securityfs not mounted or doesn't have the apparmor directory.")
def test_unconfined(self): def test_unconfined(self):
output = subprocess.check_output( output = subprocess.check_output(
'%s ./../aa-unconfined --configdir ./' % python_interpreter, shell=True) python_interpreter + ' ./../aa-unconfined --configdir ./', shell=True)
output_force = subprocess.check_output( output_force = subprocess.check_output(
'%s ./../aa-unconfined --paranoid --configdir ./' % python_interpreter, shell=True) python_interpreter + ' ./../aa-unconfined --paranoid --configdir ./', shell=True)
self.assertIsNot(output, '', 'Failed to run aa-unconfined') self.assertIsNot(output, '', 'Failed to run aa-unconfined')
@ -194,19 +203,20 @@ class MinitoolsTest(AATest):
input_file = 'cleanprof_test.in' input_file = 'cleanprof_test.in'
output_file = 'cleanprof_test.out' output_file = 'cleanprof_test.out'
# We position the local testfile # We position the local testfile
shutil.copy('./%s' % input_file, self.profile_dir) shutil.copy('./' + input_file, self.profile_dir)
# Our silly test program whose profile we wish to clean # Our silly test program whose profile we wish to clean
cleanprof_test = '/usr/bin/a/simple/cleanprof/test/profile' cleanprof_test = '/usr/bin/a/simple/cleanprof/test/profile'
subprocess.check_output( subprocess.check_output(
'%s ./../aa-cleanprof --no-reload -d %s -s %s --configdir ./' '{} ./../aa-cleanprof --no-reload -d {} -s {} --configdir ./'.format(
% (python_interpreter, self.profile_dir, cleanprof_test), shell=True) python_interpreter, self.profile_dir, cleanprof_test),
shell=True)
# Strip off the first line (#modified line) # Strip off the first line (#modified line)
subprocess.check_output('sed -i 1d %s/%s' % (self.profile_dir, input_file), shell=True) subprocess.check_output('sed -i 1d {}/{}'.format(self.profile_dir, input_file), shell=True)
exp_content = read_file('./%s' % output_file) exp_content = read_file('./' + output_file)
real_content = read_file('%s/%s' % (self.profile_dir, input_file)) real_content = read_file('{}/{}'.format(self.profile_dir, input_file))
self.maxDiff = None self.maxDiff = None
self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly') self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly')

View File

@ -254,17 +254,17 @@ class NetworkCoveredTest(AATest):
self.assertEqual( self.assertEqual(
obj.is_equal(check_obj), expected[0], obj.is_equal(check_obj), expected[0],
'Mismatch in is_equal, expected %s' % expected[0]) 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual( self.assertEqual(
obj.is_equal(check_obj, True), expected[1], obj.is_equal(check_obj, True), expected[1],
'Mismatch in is_equal/strict, expected %s' % expected[1]) 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual( self.assertEqual(
obj.is_covered(check_obj), expected[2], obj.is_covered(check_obj), expected[2],
'Mismatch in is_covered, expected %s' % expected[2]) 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual( self.assertEqual(
obj.is_covered(check_obj, True, True), expected[3], obj.is_covered(check_obj, True, True), expected[3],
'Mismatch in is_covered/exact, expected %s' % expected[3]) 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class NetworkCoveredTest_01(NetworkCoveredTest): class NetworkCoveredTest_01(NetworkCoveredTest):

View File

@ -42,7 +42,7 @@ class TestGet_last_login_timestamp(AATest):
def _run_test(self, params, expected): def _run_test(self, params, expected):
filename, user = params filename, user = params
filename = 'wtmp-examples/%s' % filename filename = 'wtmp-examples/' + filename
self.assertEqual(get_last_login_timestamp(user, filename), expected) self.assertEqual(get_last_login_timestamp(user, filename), expected)
def test_date_1999(self): def test_date_1999(self):

View File

@ -459,7 +459,7 @@ def parse_test_profiles(file_with_path):
exresult = False exresult = False
exresult_found = True exresult_found = True
else: else:
raise Exception('%s contains unknown EXRESULT %s' % (file_with_path, exresult)) raise Exception('{} contains unknown EXRESULT {}'.format(file_with_path, exresult))
elif line.upper().startswith('#=DESCRIPTION '): elif line.upper().startswith('#=DESCRIPTION '):
description = line.split()[1] description = line.split()[1]
@ -471,25 +471,25 @@ def parse_test_profiles(file_with_path):
disabled = True disabled = True
if not exresult_found: if not exresult_found:
raise Exception('%s does not contain EXRESULT' % file_with_path) raise Exception(file_with_path + ' does not contain EXRESULT')
if not description: if not description:
raise Exception('%s does not contain description' % file_with_path) raise Exception(file_with_path + ' does not contain description')
tools_wrong = False tools_wrong = False
if relfile in exception_not_raised: if relfile in exception_not_raised:
if exresult: if exresult:
raise Exception("%s listed in exception_not_raised, but has EXRESULT PASS" % file_with_path) raise Exception(file_with_path + " listed in exception_not_raised, but has EXRESULT PASS")
tools_wrong = 'EXCEPTION_NOT_RAISED' tools_wrong = 'EXCEPTION_NOT_RAISED'
elif relfile.startswith(skip_startswith): elif relfile.startswith(skip_startswith):
return 1 # XXX *** SKIP *** those tests return 1 # XXX *** SKIP *** those tests
elif relfile in unknown_line: elif relfile in unknown_line:
if not exresult: if not exresult:
raise Exception("%s listed in unknown_line, but has EXRESULT FAIL" % file_with_path) raise Exception(file_with_path + " listed in unknown_line, but has EXRESULT FAIL")
tools_wrong = 'UNKNOWN_LINE' tools_wrong = 'UNKNOWN_LINE'
elif relfile in syntax_failure: elif relfile in syntax_failure:
if not exresult: if not exresult:
raise Exception("%s listed in syntax_failure, but has EXRESULT FAIL" % file_with_path) raise Exception(file_with_path + " listed in syntax_failure, but has EXRESULT FAIL")
tools_wrong = 'SYNTAX_FAILURE' tools_wrong = 'SYNTAX_FAILURE'
params = { params = {
@ -534,9 +534,9 @@ def find_and_setup_test_profiles(profile_dir):
skipped += parse_test_profiles(file_with_path) skipped += parse_test_profiles(file_with_path)
if skipped: if skipped:
print('Skipping %s test profiles listed in skip_startswith.' % skipped) print('Skipping {} test profiles listed in skip_startswith.'.format(skipped))
print('Running %s parser simple_tests...' % len(TestParseParserTests.tests)) print('Running {} parser simple_tests...'.format(len(TestParseParserTests.tests)))
setup_aa(apparmor) setup_aa(apparmor)

View File

@ -33,28 +33,28 @@ class TestAdd_profile(AATest):
def testEmpty(self): def testEmpty(self):
self.assertEqual(self.pl.profile_names, {}) self.assertEqual(self.pl.profile_names, {})
self.assertEqual(self.pl.attachments, {}) self.assertEqual(self.pl.attachments, {})
self.assertEqual('%s' % self.pl, "\n".join(['', '<ProfileList>', '', '</ProfileList>', ''])) self.assertEqual(str(self.pl), "\n".join(['', '<ProfileList>', '', '</ProfileList>', '']))
def testAdd_profile_1(self): def testAdd_profile_1(self):
self.pl.add_profile('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo', self.dummy_profile) self.pl.add_profile('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo', self.dummy_profile)
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'}) self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'}) self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
self.assertEqual(self.pl.profiles_in_file('/etc/apparmor.d/bin.foo'), ['foo']) self.assertEqual(self.pl.profiles_in_file('/etc/apparmor.d/bin.foo'), ['foo'])
self.assertEqual('%s' % self.pl, '\n<ProfileList>\n/etc/apparmor.d/bin.foo\n</ProfileList>\n') self.assertEqual(str(self.pl), '\n<ProfileList>\n/etc/apparmor.d/bin.foo\n</ProfileList>\n')
def testAdd_profile_2(self): def testAdd_profile_2(self):
self.pl.add_profile('/etc/apparmor.d/bin.foo', None, '/bin/foo', self.dummy_profile) self.pl.add_profile('/etc/apparmor.d/bin.foo', None, '/bin/foo', self.dummy_profile)
self.assertEqual(self.pl.profile_names, {}) self.assertEqual(self.pl.profile_names, {})
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'}) self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
self.assertEqual(self.pl.profiles_in_file('/etc/apparmor.d/bin.foo'), ['/bin/foo']) self.assertEqual(self.pl.profiles_in_file('/etc/apparmor.d/bin.foo'), ['/bin/foo'])
self.assertEqual('%s' % self.pl, '\n<ProfileList>\n/etc/apparmor.d/bin.foo\n</ProfileList>\n') self.assertEqual(str(self.pl), '\n<ProfileList>\n/etc/apparmor.d/bin.foo\n</ProfileList>\n')
def testAdd_profile_3(self): def testAdd_profile_3(self):
self.pl.add_profile('/etc/apparmor.d/bin.foo', 'foo', None, self.dummy_profile) self.pl.add_profile('/etc/apparmor.d/bin.foo', 'foo', None, self.dummy_profile)
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'}) self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
self.assertEqual(self.pl.attachments, {}) self.assertEqual(self.pl.attachments, {})
self.assertEqual(self.pl.profiles_in_file('/etc/apparmor.d/bin.foo'), ['foo']) self.assertEqual(self.pl.profiles_in_file('/etc/apparmor.d/bin.foo'), ['foo'])
self.assertEqual('%s' % self.pl, '\n<ProfileList>\n/etc/apparmor.d/bin.foo\n</ProfileList>\n') self.assertEqual(str(self.pl), '\n<ProfileList>\n/etc/apparmor.d/bin.foo\n</ProfileList>\n')
def testAdd_profileError_1(self): def testAdd_profileError_1(self):
with self.assertRaises(AppArmorBug): with self.assertRaises(AppArmorBug):
@ -354,7 +354,7 @@ class AaTest_get_all_merged_variables(AATest):
self.createTmpdir() self.createTmpdir()
# copy the local profiles to the test directory # copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir self.profile_dir = self.tmpdir + '/profiles'
apparmor.aa.profile_dir = self.profile_dir apparmor.aa.profile_dir = self.profile_dir
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True) shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)

View File

@ -261,11 +261,11 @@ class PtraceCoveredTest(AATest):
self.assertTrue(PtraceRule.match(param)) self.assertTrue(PtraceRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class PtraceCoveredTest_01(PtraceCoveredTest): class PtraceCoveredTest_01(PtraceCoveredTest):
@ -511,8 +511,7 @@ class PtraceRulesTest(AATest):
self.assertEqual([], ruleset_2.get_clean(2)) self.assertEqual([], ruleset_2.get_clean(2))
# test __repr__() for empty ruleset # test __repr__() for empty ruleset
as_string = '%s' % ruleset self.assertEqual(str(ruleset), '<PtraceRuleset (empty) />')
self.assertEqual(as_string, '<PtraceRuleset (empty) />')
def test_ruleset_1(self): def test_ruleset_1(self):
ruleset = PtraceRuleset() ruleset = PtraceRuleset()
@ -540,9 +539,8 @@ class PtraceRulesTest(AATest):
self.assertEqual(expected_clean, ruleset.get_clean()) self.assertEqual(expected_clean, ruleset.get_clean())
# test __repr__() for non-empty ruleset # test __repr__() for non-empty ruleset
as_string = '%s' % ruleset
self.assertEqual( self.assertEqual(
as_string, '<PtraceRuleset>\n ptrace peer=/foo,\n ptrace read,\n</PtraceRuleset>') str(ruleset), '<PtraceRuleset>\n ptrace peer=/foo,\n ptrace read,\n</PtraceRuleset>')
def test_ruleset_2(self): def test_ruleset_2(self):
ruleset = PtraceRuleset() ruleset = PtraceRuleset()

View File

@ -45,7 +45,7 @@ class AANamedRegexTest(AATest):
match = matches.group(exp) match = matches.group(exp)
if match: if match:
match = match match = match
self.assertEqual(match, expected[exp], 'Group %s mismatch in rule %s' % (exp, line)) self.assertEqual(match, expected[exp], 'Group {} mismatch in rule {}'.format(exp, line))
class AARegexHasComma(AATest): class AARegexHasComma(AATest):
@ -54,9 +54,9 @@ class AARegexHasComma(AATest):
def _check(self, line, expected=True): def _check(self, line, expected=True):
result = aa.RE_RULE_HAS_COMMA.search(line) result = aa.RE_RULE_HAS_COMMA.search(line)
if expected: if expected:
self.assertTrue(result, 'Couldn\'t find a comma in "%s"' % line) self.assertTrue(result, 'Couldn\'t find a comma in "{}"'.format(line))
else: else:
self.assertEqual(None, result, 'Found an unexpected comma in "%s"' % line) self.assertEqual(None, result, 'Found an unexpected comma in "{}"'.format(line))
regex_has_comma_testcases = ( regex_has_comma_testcases = (
@ -128,10 +128,10 @@ def setup_has_comma_testcases():
def stub_test_no_comma(self, test_string=test_string): def stub_test_no_comma(self, test_string=test_string):
self._check(test_string % ' ', False) self._check(test_string % ' ', False)
stub_test_comma.__doc__ = "test %s (w/comma)" % (description) stub_test_comma.__doc__ = "test {} (w/comma)".format(description)
stub_test_no_comma.__doc__ = "test %s (no comma)" % (description) stub_test_no_comma.__doc__ = "test {} (no comma)".format(description)
setattr(AARegexHasComma, 'test_comma_%d' % (i), stub_test_comma) setattr(AARegexHasComma, 'test_comma_{}'.format(i), stub_test_comma)
setattr(AARegexHasComma, 'test_no_comma_%d' % (i), stub_test_no_comma) setattr(AARegexHasComma, 'test_no_comma_{}'.format(i), stub_test_no_comma)
class AARegexSplitComment(AATest): class AARegexSplitComment(AATest):
@ -140,16 +140,16 @@ class AARegexSplitComment(AATest):
def _check(self, line, expected, comment=None, not_comment=None): def _check(self, line, expected, comment=None, not_comment=None):
result = aa.RE_HAS_COMMENT_SPLIT.search(line) result = aa.RE_HAS_COMMENT_SPLIT.search(line)
if expected: if expected:
self.assertTrue(result, 'Couldn\'t find a comment in "%s"' % line) self.assertTrue(result, 'Couldn\'t find a comment in "{}"'.format(line))
self.assertEqual( self.assertEqual(
result.group('comment'), comment, result.group('comment'), comment,
'Expected comment "%s", got "%s"' % (comment, result.group('comment'))) 'Expected comment "{}", got "{}"'.format(comment, result.group('comment')))
self.assertEqual( self.assertEqual(
result.group('not_comment'), not_comment, result.group('not_comment'), not_comment,
'Expected not comment "%s", got "%s"' % (not_comment, result.group('not_comment'))) 'Expected not comment "{}", got "{}"'.format(not_comment, result.group('not_comment')))
else: else:
self.assertEqual(None, result, 'Found an unexpected comment "%s" in "%s"' self.assertEqual(None, result, 'Found an unexpected comment "{}" in "{}"'.format(
% ("" if result is None else result.group('comment'), line)) "" if result is None else result.group('comment'), line))
# Tuples of (string, expected result), where expected result is False if # Tuples of (string, expected result), where expected result is False if
@ -184,8 +184,8 @@ def setup_split_comment_testcases():
else: else:
self._check(test_string, True, not_comment=result[0], comment=result[1]) self._check(test_string, True, not_comment=result[0], comment=result[1])
stub_test.__doc__ = "test '%s'" % (test_string) stub_test.__doc__ = "test '{}'".format(test_string)
setattr(AARegexSplitComment, 'test_split_comment_%d' % (i), stub_test) setattr(AARegexSplitComment, 'test_split_comment_{}'.format(i), stub_test)
def _regex_test(self, line, expected): def _regex_test(self, line, expected):
@ -209,7 +209,7 @@ def _regex_test(self, line, expected):
for (i, group) in enumerate(groups): for (i, group) in enumerate(groups):
if group: if group:
group = group.strip() group = group.strip()
self.assertEqual(group, expected[i], 'Group %d mismatch in rule %s' % (i, line)) self.assertEqual(group, expected[i], 'Group {} mismatch in rule {}'.format(i, line))
class AARegexCapability(AARegexTest): class AARegexCapability(AARegexTest):
@ -428,7 +428,7 @@ class Test_parse_profile_start_line(AATest):
for exp in expected: for exp in expected:
self.assertEqual( self.assertEqual(
matches[exp], expected[exp], matches[exp], expected[exp],
'Group %s mismatch in rule %s' % (exp, line)) 'Group {} mismatch in rule {}'.format(exp, line))
class TestInvalid_parse_profile_start_line(AATest): class TestInvalid_parse_profile_start_line(AATest):

View File

@ -244,17 +244,17 @@ class RlimitCoveredTest(AATest):
self.assertEqual( self.assertEqual(
obj.is_equal(check_obj), expected[0], obj.is_equal(check_obj), expected[0],
'Mismatch in is_equal, expected %s' % expected[0]) 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual( self.assertEqual(
obj.is_equal(check_obj, True), expected[1], obj.is_equal(check_obj, True), expected[1],
'Mismatch in is_equal/strict, expected %s' % expected[1]) 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual( self.assertEqual(
obj.is_covered(check_obj), expected[2], obj.is_covered(check_obj), expected[2],
'Mismatch in is_covered, expected %s' % expected[2]) 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual( self.assertEqual(
obj.is_covered(check_obj, True, True), expected[3], obj.is_covered(check_obj, True, True), expected[3],
'Mismatch in is_covered/exact, expected %s' % expected[3]) 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class RlimitCoveredTest_01(RlimitCoveredTest): class RlimitCoveredTest_01(RlimitCoveredTest):

View File

@ -29,12 +29,12 @@ class SeverityBaseTest(AATest):
def _capability_severity_test(self, cap, expected_rank): def _capability_severity_test(self, cap, expected_rank):
rank = self.sev_db.rank_capability(cap) rank = self.sev_db.rank_capability(cap)
self.assertEqual(rank, expected_rank, self.assertEqual(rank, expected_rank,
'expected rank %s, got %s' % (expected_rank, rank)) 'expected rank {}, got {}'.format(expected_rank, rank))
def _simple_severity_w_perm(self, path, perm, expected_rank): def _simple_severity_w_perm(self, path, perm, expected_rank):
rank = self.sev_db.rank_path(path, perm) rank = self.sev_db.rank_path(path, perm)
self.assertEqual(rank, expected_rank, self.assertEqual(rank, expected_rank,
'expected rank %s, got %s' % (expected_rank, rank)) 'expected rank {}, got {}'.format(expected_rank, rank))
class SeverityTest(SeverityBaseTest): class SeverityTest(SeverityBaseTest):
@ -77,7 +77,7 @@ class SeverityTestCap(SeverityBaseTest):
self._capability_severity_test(params, expected) self._capability_severity_test(params, expected)
rank = self.sev_db.rank_capability(params) rank = self.sev_db.rank_capability(params)
self.assertEqual(rank, expected, 'expected rank %s, got %s' % (expected, rank)) self.assertEqual(rank, expected, 'expected rank {}, got {}'.format(expected, rank))
class SeverityVarsTest(SeverityBaseTest): class SeverityVarsTest(SeverityBaseTest):

View File

@ -279,17 +279,17 @@ class SignalCoveredTest(AATest):
self.assertEqual( self.assertEqual(
obj.is_equal(check_obj), expected[0], obj.is_equal(check_obj), expected[0],
'Mismatch in is_equal, expected %s' % expected[0]) 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual( self.assertEqual(
obj.is_equal(check_obj, True), expected[1], obj.is_equal(check_obj, True), expected[1],
'Mismatch in is_equal/strict, expected %s' % expected[1]) 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual( self.assertEqual(
obj.is_covered(check_obj), expected[2], obj.is_covered(check_obj), expected[2],
'Mismatch in is_covered, expected %s' % expected[2]) 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual( self.assertEqual(
obj.is_covered(check_obj, True, True), expected[3], obj.is_covered(check_obj, True, True), expected[3],
'Mismatch in is_covered/exact, expected %s' % expected[3]) 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class SignalCoveredTest_01(SignalCoveredTest): class SignalCoveredTest_01(SignalCoveredTest):

View File

@ -230,11 +230,11 @@ class VariableCoveredTest(AATest):
self.assertTrue(VariableRule.match(param)) self.assertTrue(VariableRule.match(param))
self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected {}'.format(expected[0]))
self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected {}'.format(expected[1]))
self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2]) self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected {}'.format(expected[2]))
self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3]) self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected {}'.format(expected[3]))
class VariableCoveredTest_01(VariableCoveredTest): class VariableCoveredTest_01(VariableCoveredTest):

View File

@ -173,7 +173,7 @@ sys.stdout.write('" do not edit this file - edit apparmor.vim.in or create-appar
with open("apparmor.vim.in") as template: with open("apparmor.vim.in") as template:
for line in template: for line in template:
line = re.sub(regex, my_repl, line.rstrip()) line = re.sub(regex, my_repl, line.rstrip())
sys.stdout.write('%s\n' % line) sys.stdout.write(line + '\n')
sys.stdout.write("\n\n\n\n") sys.stdout.write("\n\n\n\n")