2
# ------------------------------------------------------------------
4
# Copyright (C) 2013 Canonical Ltd.
5
# Author: Steve Beattie <steve@nxnw.org>
7
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of version 2 of the GNU General Public
9
# License published by the Free Software Foundation.
11
# ------------------------------------------------------------------
16
import LibAppArmor as libapparmor
18
TESTDIR = "../../../testsuite/test_multi"
20
# map of testsuite .out entries that aren't a simple to_lower() and
21
# s/ /_/ of the field name
24
'Event type': 'event',
25
'Mask': 'requested_mask',
27
'Token': 'magic_token',
28
'ErrorCode': 'error_code',
29
'Network family': 'net_family',
30
'Socket type': 'net_sock_type',
31
'Protocol': 'net_protocol',
32
'Local addr': 'net_local_addr',
33
'Foreign addr': 'net_foreign_addr',
34
'Local port': 'net_local_port',
35
'Foreign port': 'net_foreign_port',
36
'Audit subid': 'audit_sub_id',
39
# FIXME: pull this automatically out of LibAppArmor, but swig
40
# classes aren't real enough. (Perhaps we're not using swig correctly)
42
libapparmor.AA_RECORD_ALLOWED: 'AA_RECORD_ALLOWED',
43
libapparmor.AA_RECORD_AUDIT: 'AA_RECORD_AUDIT',
44
libapparmor.AA_RECORD_DENIED: 'AA_RECORD_DENIED',
45
libapparmor.AA_RECORD_ERROR: 'AA_RECORD_ERROR',
46
libapparmor.AA_RECORD_HINT: 'AA_RECORD_HINT',
47
libapparmor.AA_RECORD_INVALID: 'AA_RECORD_INVALID',
48
libapparmor.AA_RECORD_STATUS: 'AA_RECORD_STATUS',
51
# default is None if not in this table
53
'fsuid': int(ctypes.c_ulong(-1).value),
54
'ouid': int(ctypes.c_ulong(-1).value),
58
class AAPythonBindingsTests(unittest.TestCase):
61
# REPORT ALL THE OUTPUT
64
def _runtest(self, testname):
65
infile = "%s.in" % (testname)
66
outfile = "%s.out" % (testname)
67
# infile *should* only contain one line
68
with open(os.path.join(TESTDIR, infile), 'r') as f:
70
swig_record = libapparmor.parse_record(line)
72
record = self.create_record_dict(swig_record)
73
record['file'] = infile
74
libapparmor.free_record(swig_record)
76
expected = self.parse_output_file(outfile)
77
self.assertEquals(expected, record,
78
"expected records did not match\n" +
79
"expected = %s\nactual = %s" % (expected, record))
81
def parse_output_file(self, outfile):
82
'''parse testcase .out file and return dict'''
85
with open(os.path.join(TESTDIR, outfile), 'r') as f:
93
self.assertEquals(count, 1,
94
"Unexpected output format in %s" % (outfile))
97
key, value = line.split(": ", 1)
99
newkey = OUTPUT_MAP[key]
101
newkey = key.lower().replace(' ', '_')
102
# check if entry already exists?
103
output[newkey] = value
107
def create_record_dict(self, record):
108
'''parse the swig created record and construct a dict from it'''
111
for key in [x for x in dir(record) if not (x.startswith('_') or x == 'this')]:
112
value = record.__getattr__(key)
113
if key == "event" and value in EVENT_MAP:
114
new_record[key] = EVENT_MAP[value]
115
elif key == "version":
116
# FIXME: out files should report log version?
117
# FIXME: or can we just deprecate v1 logs?
119
elif key in NO_VALUE_MAP:
120
if NO_VALUE_MAP[key] == value:
123
new_record[key] = str(value)
124
elif record.__getattr__(key):
125
new_record[key] = str(value)
130
def find_testcases(testdir):
131
'''dig testcases out of passed directory'''
133
for f in os.listdir(testdir):
134
if f.endswith(".in"):
139
for f in find_testcases(TESTDIR):
140
def stub_test(self, testname=f):
141
self._runtest(testname)
142
stub_test.__doc__ = "test %s" % (f)
143
setattr(AAPythonBindingsTests, 'test_%s' % (f), stub_test)
144
return unittest.main(verbosity=2)
146
if __name__ == "__main__":