[apparmor] [2/3] add testsuite for capability rule class

Steve Beattie steve at nxnw.org
Thu Nov 20 22:14:52 UTC 2014


On Sat, Nov 15, 2014 at 11:44:15PM +0100, Christian Boltz wrote:
> Hello,
> 
> this patch adds a testsuite for the capability rule class (including the 
> base class). Since I'm writing these classes test-driven, the testsuite 
> covers 100% of the rule/*.py code :-)
> 
> Note that the testsuite also documents two known issues (commented out):
> 
> a) 
> If you use covered_raw('capability foo bar,') and your profile has 
> "capability foo, capability bar,", covered_raw will not detect it. The 
> reason for this is that "capability foo, capability bar," is split over 
> two capability_rule objects internally.
> 
> However it works the other way round - if the profile has "capability 
> foo bar", covered_raw("capability foo") and covered_raw("capability foo 
> bar",) and even "covered_raw("capability bar foo,") will find it.
> 
> That's a corner case and the only problem it can cause is a superfluous 
> line in a (hand-modified, we don't write multi-capability lines) 
> profile, so I'm not sure if it's worth fixing it

There's also the bit I raised in the earlier patch, that asking to
delete 'capability foo' will delete the entire 'capability foo bar'
rule. Or a 'capability,' rule.

> b)
> When deleting duplicates, "capability," will delete all "capability 
> foo," rules. However it doesn't delete "allow capability foo," rules. 
> (I didn't check the reason for this yet.)
> 
> (The included good news is that "capability," is now recogniced as "all 
> capabilities" :-)
> 
> 
> Regards,
> 
> Christian Boltz
> -- 
> [SuSE 9.1] Und utf-8 saugt tote Hamster durch Strohhalme, selbst wenn
> es funktioniert. [...] Und das alles nur, damit ich Klingonisch native
> verarbeiten kann in meinem Rechner.
> [http://blog.koehntopp.de/archives/317_Die+schlimmste+aller+Susen.html]

> === added file 'utils/test/test-capability.py'
> --- utils/test/test-capability.py	1970-01-01 00:00:00 +0000
> +++ utils/test/test-capability.py	2014-11-15 21:48:16 +0000
> @@ -0,0 +1,657 @@
> +#!/usr/bin/env python
> +# ----------------------------------------------------------------------
> +#    Copyright (C) 2014 Christian Boltz <apparmor at cboltz.de>
> +#
> +#    This program is free software; you can redistribute it and/or
> +#    modify it under the terms of version 2 of the GNU General Public
> +#    License as published by the Free Software Foundation.
> +#
> +#    This program is distributed in the hope that it will be useful,
> +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
> +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +#    GNU General Public License for more details.
> +#
> +# ----------------------------------------------------------------------
> +
> +import unittest
> +
> +from apparmor.rule.capability import capability_rule, capability_rules
> +from apparmor.aa import ALL
> +from apparmor.common import AppArmorException, AppArmorBug, hasher
> +from apparmor.logparser import ReadLog
> +
> +import re
> +
> +# --- tests for single capability_rule --- #

Can you add:

    def setUp(self):
        self.maxDiff = None

to each of the classes. so that when the comparison of two large
objects fails, we see the entire diff in the failure output?

> +class CapabilityTest(unittest.TestCase):
> +    def _compare_obj_with_rawrule(self, rawrule, expected):
> +
> +        obj = capability_rule()
> +        obj.set_raw(rawrule)
> +
> +        self.assertEqual(rawrule.strip(), obj.rawrule)
> +
> +        self._compare_obj(obj, expected)
> +
> +    def _compare_obj(self, obj, expected):
> +        self.assertEqual(expected['allow_keyword'], obj.allow_keyword)
> +        self.assertEqual(expected['audit'], obj.audit)
> +        self.assertEqual(expected['capability'], obj.capability)
> +        self.assertEqual(expected['deny'], obj.deny)
> +        self.assertEqual(expected['inlinecomment'], obj.inlinecomment)
> +
> +    def test_cap_allow_all(self):
> +        self._compare_obj_with_rawrule("capability,", {
> +            'allow_keyword':    False,
> +            'deny':             False,
> +            'audit':            False,
> +            'capability':       [ ALL ],
> +            'inlinecomment':    "",
> +        })
> +
> +    def test_cap_allow_sys_admin(self):
> +        self._compare_obj_with_rawrule("capability sys_admin,", {
> +            'allow_keyword':    False,
> +            'deny':             False,
> +            'audit':            False,
> +            'capability':       [ 'sys_admin' ],
> +            'inlinecomment':    "",
> +        })
> +
> +    def test_cap_deny_sys_admin(self):
> +        self._compare_obj_with_rawrule("     deny capability sys_admin,  # some comment", {
> +            'allow_keyword':    False,
> +            'deny':             True,
> +            'audit':            False,
> +            'capability':       [ 'sys_admin' ],
> +            'inlinecomment':    " # some comment",
> +        })

Don't you want a test for something like
'capability sys_admin dac_override,'?

> +    # Template for test_cap_* functions
> +    #    def test_cap_(self):
> +    #        self._compare_obj_with_rawrule("capability", {
> +    #            'allow_keyword':    False,
> +    #            'deny':             False,
> +    #            'audit':            False,
> +    #            'capability':       [],
> +    #            'inlinecomment':    "",
> +    #        })
> +
> +    def test_cap_from_log(self):
> +        parser = ReadLog('', '', '', '', '')

Blech to the ReadLog() interface. But that's a different patch set,
hopefully.

> +        event = 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/bin/ping" pid=15454 comm="ping" capability=13  capname="net_raw"'
> +
> +        parsed_event = parser.parse_event(event)
> +
> +        self.assertEqual(parsed_event, {
> +            'request_mask': set(),
> +            'denied_mask': set(),
> +            'magic_token': 0,
> +            'parent': 0,
> +            'profile': '/bin/ping',
> +            'operation': 'capable',
> +            'resource': None,
> +            'info': None,
> +            'aamode': 'PERMITTING',
> +            'time': 1415403814,
> +            'active_hat': None,
> +            'pid': 15454,
> +            'task': 0,
> +            'attr': None,
> +            'name2': None,
> +            'name': 'net_raw'
> +        })
> +
> +        obj = capability_rule()
> +        obj.set_log(parsed_event)
> +
> +        self._compare_obj(obj, {
> +            'allow_keyword':    False,
> +            'deny':             False,
> +            'audit':            False,
> +            'capability':       ['net_raw'],
> +            'inlinecomment':    "",
> +        })
> +
> +        self.assertEqual(obj.get_raw(1), '  capability net_raw,')
> +
> +    def test_cap_from_invalid_log(self):
> +        parser = ReadLog('', '', '', '', '')
> +        # invalid log entry, name= should contain the capability name
> +        event = 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/bin/ping" pid=15454 comm="ping" capability=13  capname=""'
> +
> +        parsed_event = parser.parse_event(event)
> +
> +        obj = capability_rule()
> +
> +        with self.assertRaises(AppArmorBug):
> +            obj.set_log(parsed_event)
> +
> +        with self.assertRaises(AppArmorBug):
> +            obj.get_raw(1)
> +
> +    def test_cap_from_non_cap_log(self):
> +        parser = ReadLog('', '', '', '', '')
> +        # log entry for different rule type
> +        event = 'type=AVC msg=audit(1415403814.973:667): apparmor="ALLOWED" operation="setsockopt" profile="/home/sys-tmp/ping" pid=15454 comm="ping" lport=1 family="inet" sock_type="raw" protocol=1'
> +
> +        parsed_event = parser.parse_event(event)
> +
> +        obj = capability_rule()
> +
> +        with self.assertRaises(AppArmorBug):
> +            obj.set_log(parsed_event)
> +
> +        with self.assertRaises(AppArmorBug):
> +            obj.get_raw(1)
> +
> +
> +class InvalidCapabilityTest(unittest.TestCase):
> +    def _check_invalid_rawrule(self, rawrule):
> +        obj = capability_rule()
> +        with self.assertRaises(AppArmorException):
> +            obj.set_raw(rawrule)
> +
> +    def test_invalid_cap_missing_comma(self):
> +        self._check_invalid_rawrule('capability')  # missing comma
> +
> +    def test_invalid_cap_non_capability_rule(self):
> +        self._check_invalid_rawrule('network,')  # not a capability rule
> +
> +    def test_empty_cap_list(self):
> +        obj = capability_rule()
> +        # no capability set, and ALL not set
> +        with self.assertRaises(AppArmorBug):
> +            obj.get_clean(1)
> +
> +    def test_space_cap(self):
> +        obj = capability_rule()
> +        obj.capability.append('  ')  # the whitespace capability ;-)
> +        with self.assertRaises(AppArmorBug):
> +            obj.get_clean(1)
> +
> +    def test_parse_audit_allow_invalid(self):
> +        obj = capability_rule()
> +
> +        regex = re.compile('^\s*(?P<audit>audit\s+)?(?P<allow>allow\s+|deny\s+|invalid\s+)?')
> +        matches = regex.search('audit invalid ')
> +
> +        with self.assertRaises(AppArmorBug):
> +            obj.parse_audit_allow(matches)
> +
> +
> +class WriteCapabilityTest(unittest.TestCase):
> +    def _check_write_rule(self, rawrule, cleanrule):
> +        obj = capability_rule()
> +        obj.set_raw(rawrule)
> +        clean = obj.get_clean(0)
> +        raw = obj.get_raw(0)
> +
> +        self.assertEqual(cleanrule.strip(), clean, 'unexpected clean rule')
> +        self.assertEqual(rawrule.strip(), raw, 'unexpected raw rule')
> +
> +    def test_write_all(self):
> +        self._check_write_rule('     capability      ,    # foo        ', 'capability, # foo')
> +
> +    def test_write_sys_admin(self):
> +        self._check_write_rule('    audit     capability sys_admin,', 'audit capability sys_admin,')
> +
> +    def test_write_sys_multi(self):
> +        self._check_write_rule('   deny capability      sys_admin      audit_write,# foo bar', 'deny capability audit_write sys_admin, # foo bar')
> +
> +    def test_write_manually(self):
> +        obj = capability_rule()
> +        obj.capability = ['ptrace', 'audit_write']
> +        obj.allow_keyword = True
> +
> +        expected = '    allow capability audit_write ptrace,'
> +
> +        self.assertEqual(expected, obj.get_clean(2), 'unexpected clean rule')
> +        self.assertEqual(expected, obj.get_raw(2), 'unexpected raw rule')
> +
> +class CapabilityCoveredTest(unittest.TestCase):
> +    def _init_obj_with_rawrule(self, rawrule):
> +        obj = capability_rule()
> +        obj.set_raw(rawrule)
> +        return obj
> +
> +    def _is_covered(self, obj, rule_to_test):
> +        return obj.covered(self._init_obj_with_rawrule(rule_to_test))
> +
> +    def _is_covered_exact(self, obj, rule_to_test):
> +        return obj.covered(self._init_obj_with_rawrule(rule_to_test), True, True)
> +
> +    def test_covered_single(self):
> +        obj = self._init_obj_with_rawrule('capability sys_admin,')
> +
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin,'))
> +
> +        self.assertFalse(self._is_covered(obj, 'audit capability sys_admin,'))
> +        self.assertFalse(self._is_covered(obj, 'audit capability,'))
> +        self.assertFalse(self._is_covered(obj, 'capability chown,'))
> +        self.assertFalse(self._is_covered(obj, 'capability,'))
> +
> +    def test_covered_audit(self):
> +        obj = self._init_obj_with_rawrule('audit capability sys_admin,')
> +
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin,'))
> +        self.assertTrue(self._is_covered(obj, 'audit capability sys_admin,'))
> +
> +        self.assertFalse(self._is_covered(obj, 'audit capability,'))
> +        self.assertFalse(self._is_covered(obj, 'capability chown,'))
> +        self.assertFalse(self._is_covered(obj, 'capability,'))
> +
> +    def test_covered_check_audit(self):
> +        obj = self._init_obj_with_rawrule('audit capability sys_admin,')
> +
> +        self.assertFalse(self._is_covered_exact(obj, 'capability sys_admin,'))
> +        self.assertTrue(self._is_covered_exact(obj, 'audit capability sys_admin,'))
> +
> +        self.assertFalse(self._is_covered_exact(obj, 'audit capability,'))
> +        self.assertFalse(self._is_covered_exact(obj, 'capability chown,'))
> +        self.assertFalse(self._is_covered_exact(obj, 'capability,'))
> +
> +
> +    def test_covered_multi(self):
> +        obj = self._init_obj_with_rawrule('capability audit_write sys_admin,')
> +
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin,'))
> +        self.assertTrue(self._is_covered(obj, 'capability audit_write,'))
> +        self.assertTrue(self._is_covered(obj, 'capability audit_write sys_admin,'))
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin audit_write,'))
> +
> +        self.assertFalse(self._is_covered(obj, 'audit capability,'))
> +        self.assertFalse(self._is_covered(obj, 'capability chown,'))
> +        self.assertFalse(self._is_covered(obj, 'capability,'))
> +
> +    def test_covered_all(self):
> +        obj = self._init_obj_with_rawrule('capability,')
> +
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin,'))
> +        self.assertTrue(self._is_covered(obj, 'capability audit_write,'))
> +        self.assertTrue(self._is_covered(obj, 'capability audit_write sys_admin,'))
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin audit_write,'))
> +        self.assertTrue(self._is_covered(obj, 'capability,'))
> +
> +        self.assertFalse(self._is_covered(obj, 'audit capability,'))
> +
> +    def test_covered_deny(self):
> +        obj = self._init_obj_with_rawrule('capability sys_admin,')
> +
> +        self.assertTrue(self._is_covered(obj, 'capability sys_admin,'))
> +
> +        self.assertFalse(self._is_covered(obj, 'audit deny capability sys_admin,'))
> +        self.assertFalse(self._is_covered(obj, 'deny capability sys_admin,'))
> +        self.assertFalse(self._is_covered(obj, 'capability chown,'))
> +        self.assertFalse(self._is_covered(obj, 'capability,'))
> +
> +    def test_covered_deny_2(self):
> +        obj = self._init_obj_with_rawrule('deny capability sys_admin,')
> +
> +        self.assertTrue(self._is_covered(obj, 'deny capability sys_admin,'))
> +
> +        self.assertFalse(self._is_covered(obj, 'audit deny capability sys_admin,'))
> +        self.assertFalse(self._is_covered(obj, 'capability sys_admin,'))
> +        self.assertFalse(self._is_covered(obj, 'deny capability chown,'))
> +        self.assertFalse(self._is_covered(obj, 'deny capability,'))
> +
> +    def test_invalid_covered_obj(self):
> +        obj = self._init_obj_with_rawrule('capability sys_admin,')
> +
> +        testobj = capability_rule()  # no capability set
> +
> +        with self.assertRaises(AppArmorBug):
> +            obj.covered(testobj)
> +
> +    def test_empty_init(self):
> +        obj = capability_rule()
> +        obj.capability.append('sys_admin')
> +
> +        obj2 = capability_rule()
> +        obj2.capability.append('ptrace')
> +
> +        self.assertFalse(self._is_covered(obj2, 'capability sys_admin,'))
> +        self.assertTrue(self._is_covered(obj2, 'capability ptrace,'))
> +
> +# --- tests for capability_rules --- #
> +
> +class CapabilityRulesTest(unittest.TestCase):
> +    def test_empty_collection(self):
> +        col = capability_rules()
> +        col2 = capability_rules()
> +        self.assertEqual([], col.get_raw(2))
> +        self.assertEqual([], col.get_clean(2))
> +        self.assertEqual([], col2.get_raw(2))
> +        self.assertEqual([], col2.get_clean(2))
> +
> +    def test_collection_1(self):
> +        col = capability_rules()
> +        rules = [
> +            'capability sys_admin,',
> +            'capability chown,',
> +        ]
> +
> +        expected_raw = [
> +            'capability sys_admin,',
> +            'capability chown,',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            'capability chown,',
> +            'capability sys_admin,',
> +            '',
> +        ]
> +
> +        for rule in rules:
> +            col.add_raw(rule)
> +
> +        self.assertEqual(expected_raw, col.get_raw(0))
> +        self.assertEqual(expected_clean, col.get_clean(0))
> +
> +    def test_collection_2(self):
> +        col = capability_rules()
> +        rules = [
> +            'capability chown,',
> +            'allow capability sys_admin,',
> +            'deny capability chgrp, # example comment',
> +        ]
> +
> +        expected_raw = [
> +            '  capability chown,',
> +            '  allow capability sys_admin,',
> +            '  deny capability chgrp, # example comment',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  allow capability sys_admin,',
> +            '  capability chown,',
> +            '',
> +        ]
> +
> +        for rule in rules:
> +            col.add_raw(rule)
> +
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +class CapabilityRulesCoveredTest(unittest.TestCase):
> +    def test_collection_covered_raw(self):
> +        col = capability_rules()
> +        rules = [
> +            'capability chown,',
> +            'capability setuid setgid,',
> +            'allow capability sys_admin,',
> +            'audit capability kill,',
> +            'deny capability chgrp, # example comment',
> +        ]
> +
> +        for rule in rules:
> +            col.add_raw(rule)
> +
> +        self.assertTrue(col.covered_raw('capability chown,'))
> +        self.assertTrue(col.covered_raw('capability sys_admin,'))
> +        self.assertTrue(col.covered_raw('allow capability sys_admin,'))
> +        self.assertTrue(col.covered_raw('capability setuid,'))
> +        self.assertTrue(col.covered_raw('allow capability setgid,'))
> +        self.assertTrue(col.covered_raw('capability setgid setuid,'))
> +        # self.assertTrue(col.covered_raw('capability sys_admin chown,'))  # fails because it is split over two rule objects internally
> +        self.assertTrue(col.covered_raw('capability kill,'))
> +
> +        self.assertFalse(col.covered_raw('deny capability chown,'))
> +        self.assertFalse(col.covered_raw('deny capability sys_admin,'))
> +        self.assertFalse(col.covered_raw('deny capability sys_admin chown,'))
> +        self.assertFalse(col.covered_raw('deny capability setgid,'))
> +        self.assertFalse(col.covered_raw('deny capability kill,'))
> +
> +        self.assertFalse(col.covered_raw('audit capability chown,'))
> +        self.assertFalse(col.covered_raw('audit capability sys_admin,'))
> +        self.assertFalse(col.covered_raw('audit capability sys_admin chown,'))
> +        self.assertFalse(col.covered_raw('audit capability setgid,'))
> +        self.assertTrue(col.covered_raw('audit capability kill,'))
> +
> +        self.assertTrue(col.covered_raw('deny capability chgrp,'))
> +        self.assertFalse(col.covered_raw('audit deny capability chgrp,'))
> +        self.assertFalse(col.covered_raw('audit capability chgrp,'))

Since they're all independent, can you break these apart into
individual test functions, and move the set up of 'col' into the setUp
function (especially since its the same between the covered_raw and
covered_raw_2 tests)? That way, if something changes in the capability
ruleset implementation that causes breakage, you'll know which if
the asserts that are triggered, not just the first one to get hit.

(If you're concerned about the time cost of setting up col
for each test case, you could use setUpClass and tearDownClass
https://docs.python.org/2.7/library/unittest.html#setupclass-and-teardownclass
but it removes some of the independence between the testcases.)

> +
> +    def test_collection_covered_raw_2(self):
> +        col = capability_rules()
> +        rules = [
> +            'capability chown,',
> +            'capability setuid setgid,',
> +            'allow capability sys_admin,',
> +            'audit capability kill,',
> +            'deny capability chgrp, # example comment',
> +        ]
> +
> +        for rule in rules:
> +            col.add_raw(rule)
> +
> +        event_base = 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/bin/ping" pid=15454 comm="ping" capability=13  capname="%s"'
> +
> +        parser = ReadLog('', '', '', '', '')
> +
> +        self.assertFalse(col.covered_log(parser.parse_event(event_base%'net_raw')))
> +        self.assertTrue(col.covered_log(parser.parse_event(event_base%'chown')))
> +        self.assertTrue(col.covered_log(parser.parse_event(event_base%'sys_admin')))
> +        self.assertTrue(col.covered_log(parser.parse_event(event_base%'kill')))
> +        self.assertFalse(col.covered_log(parser.parse_event(event_base%'chgrp')))
> +        self.assertTrue(col.covered_log(parser.parse_event(event_base%'chgrp'), False))  # ignores allow/deny

And similarly split up here.

Shouldn't there also be a set of tests for col.covered_obj?

> +class CapabilityGlobTest(unittest.TestCase):
> +    def test_glob(self):
> +        col = capability_rules()
nit: move 'col = capability_rules()' into setUp().

> +        self.assertEqual(col.get_glob('capability net_raw,'), 'capability,')
> +
> +    def test_glob_ext(self):
> +        col = capability_rules()
> +
> +        with self.assertRaises(AppArmorBug):
> +            col.get_glob_ext('capability net_raw,')
> +
> +class CapabilityDeleteTest(unittest.TestCase):
> +    def _setup_testcol(self):

This should just be setUp(). You'll need to convert all references of
col to self.col, but then you won't need to manually call the setup
function at the beginning of each testcase.

> +        col = capability_rules()
> +        rules = [
> +            'capability chown,',
> +            'allow capability sys_admin,',
> +            'deny capability chgrp, # example comment',
> +        ]
> +
> +        for rule in rules:
> +            col.add_raw(rule)
> +
> +        return col
> +
> +    def test_delete_raw(self):
> +        expected_raw = [
> +            '  capability chown,',
> +            '  deny capability chgrp, # example comment',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  capability chown,',
> +            '',
> +        ]
> +
> +        col = self._setup_testcol()
> +        col.delete_raw('capability sys_admin,')
> +
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +    def test_delete_raw_notfound(self):
> +        col = self._setup_testcol()
> +
> +        with self.assertRaises(AppArmorBug):
> +            col.delete_raw('capability audit_write,')
> +
> +    def test_delete_duplicates(self):
> +        col = self._setup_testcol()
> +
> +        inc = capability_rules()
> +        rules = [
> +            'capability chown,',
> +            'deny capability chgrp, # example comment',
> +        ]
> +
> +        for rule in rules:
> +            inc.add_raw(rule)

Seeing stuff like the above makes me want to have the __init__ function
for rulesets take an option raw_ruleset argument (perhaps obj_ and log_
as well), that automatically adds the rules for you, so that you'd just
write something like:

        inc = CapabilityRuleset(raw_ruleset=[
            'capability chown,',
            'deny capability chgrp, # example comment',
        ])

> +
> +        expected_raw = [
> +            '  allow capability sys_admin,',
> +            '',
> +        ]
> +
> +        expected_clean = expected_raw
> +
> +        self.assertEqual(col.delete_duplicates(inc), 2)
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +    def test_delete_duplicates_2(self):
> +        col = self._setup_testcol()
> +
> +        inc = capability_rules()
> +        rules = [
> +            'capability audit_write,',
> +            'capability chgrp, # example comment',
> +        ]
> +
> +        for rule in rules:
> +            inc.add_raw(rule)
> +
> +        expected_raw = [
> +            '  capability chown,',
> +            '  allow capability sys_admin,',
> +            '  deny capability chgrp, # example comment',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  allow capability sys_admin,',
> +            '  capability chown,',
> +            '',
> +        ]
> +
> +        self.assertEqual(col.delete_duplicates(inc), 0)
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +    def test_delete_duplicates_3(self):
> +        col = self._setup_testcol()
> +        col.add_raw('audit capability dac_override,')
> +
> +        inc = capability_rules()
> +        rules = [
> +            'capability dac_override,',
> +        ]
> +
> +        for rule in rules:
> +            inc.add_raw(rule)
> +
> +        expected_raw = [
> +            '  capability chown,',
> +            '  allow capability sys_admin,',
> +            '  deny capability chgrp, # example comment',
> +            '  audit capability dac_override,',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  allow capability sys_admin,',
> +            '  audit capability dac_override,',
> +            '  capability chown,',
> +            '',
> +        ]
> +
> +        self.assertEqual(col.delete_duplicates(inc), 0)
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +    def test_delete_duplicates_4(self):
> +        col = self._setup_testcol()
> +
> +        inc = capability_rules()
> +        rules = [
> +            'capability,',
> +        ]
> +
> +        for rule in rules:
> +            inc.add_raw(rule)
> +
> +        expected_raw = [
> +            '  allow capability sys_admin,',  # XXX huh? should be deleted!
> +            '  deny capability chgrp, # example comment',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  allow capability sys_admin,',  # XXX huh? should be deleted!
> +            '',
> +        ]
> +
> +        self.assertEqual(col.delete_duplicates(inc), 1)
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +    def test_delete_duplicates_none(self):
> +        col = self._setup_testcol()
> +
> +        expected_raw = [
> +            '  capability chown,',
> +            '  allow capability sys_admin,',
> +            '  deny capability chgrp, # example comment',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  allow capability sys_admin,',
> +            '  capability chown,',
> +            '',
> +        ]
> +
> +        self.assertEqual(col.delete_duplicates(None), 0)
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +    def test_delete_duplicates_hasher(self):
> +        col = self._setup_testcol()
> +
> +        expected_raw = [
> +            '  capability chown,',
> +            '  allow capability sys_admin,',
> +            '  deny capability chgrp, # example comment',
> +            '',
> +        ]
> +
> +        expected_clean = [
> +            '  deny capability chgrp, # example comment',
> +            '',
> +            '  allow capability sys_admin,',
> +            '  capability chown,',
> +            '',
> +        ]
> +
> +        self.assertEqual(col.delete_duplicates(hasher()), 0)
> +        self.assertEqual(expected_raw, col.get_raw(1))
> +        self.assertEqual(expected_clean, col.get_clean(1))
> +
> +
> +if __name__ == "__main__":
> +    unittest.main(verbosity=2)

-- 
Steve Beattie
<sbeattie at ubuntu.com>
http://NxNW.org/~steve/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20141120/caec6d01/attachment-0001.pgp>


More information about the AppArmor mailing list