<div dir="ltr">Hello,<br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Apr 20, 2015 at 3:59 AM, Christian Boltz <span dir="ltr"><<a href="mailto:apparmor@cboltz.de" target="_blank">apparmor@cboltz.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello,<br>
<br>
Am Sonntag, 19. April 2015 schrieb Kshitij Gupta:<br>
<span class="">> On Sat, Apr 18, 2015 at 2:51 AM, Christian Boltz wrote:<br>
> > Am Dienstag, 14. April 2015 schrieb Christian Boltz:<br>
> > > this patch adds utils/test/test-network.py with tests for<br>
> > > NetworkRule<br>
> > > and NetworkRuleset.<br>
> > ><br>
> > > The tests are hopefully self-explaining, so let me just mention<br>
> > > the<br>
> > > most important things:<br>
> > > - I started to play with namedtuple, which looks very useful (see<br>
><br>
> Interesting! Like a dictionary but without any overhead.<br>
<br>
</span>The important thing is that it allows to have named elements without the<br>
need to repeat the names all the time. And that's something really<br>
useful, especially when writing tests table-style to get sane line<br>
lengths ;-)<br>
<br>
That said - we have to thank Steve who gave a pointer to namedtuple some<br>
weeks ago.<br>
<span class=""><br>
> > +import unittest<br>
> > +from common_test import AATest, setup_all_loops<br>
> > +from collections import namedtuple<br>
><br>
> Nitpick: a non standard import surrounding apparmor specific import is<br>
> odd. Probably could re-use some shuffling around/separation.<br>
> quoting PEP 8 [1]:<br>
> "Imports should be grouped in the following order:<br>
><br>
</span>> 1. standard library imports<br>
> 2. related third party imports<br>
> 3. local application/library specific imports<br>
<span class="">><br>
> You should put a blank line between each group of imports."<br>
<br>
</span>Hmm, that's an interesting question.<br>
<br>
While I agree that those rules make sense for "normal" code, I'm not<br>
sure if they make sense for our testcases.<br>
<br>
Basically the order I'm using is:<br>
1. libraries needed to setup and run the tests (sooner or later, all<br>
tests will have those imports)<br>
2. the things we want to test<br>
3. additional libs needed for some tests (for example 're', even if<br>
that vanished by moving test_parse_profile_invalid() to<br>
test-baserule.py)<br>
<br></blockquote><div>I'm find with this reasoning for not following the PEP 8.<br></div><div>It'll be interesting to see what a pyflakes run says about it.<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Inside the first group, changing the order according to PEP 8 can't<br>
hurt, so I'm moving namedtuple a line upwards.<br>
<span class=""><br>
> > +from apparmor.rule.network import NetworkRule, NetworkRuleset<br>
> > +from apparmor.rule import BaseRule, parse_modifiers<br>
> > +from apparmor.common import AppArmorException, AppArmorBug<br>
> > +from apparmor.logparser import ReadLog<br>
> > +<br>
> > +import re<br>
> > +<br>
> > +exp = namedtuple('exp', ['audit', 'allow_keyword', 'deny',<br>
> > 'comment', + 'domain', 'all_domains', 'type_or_protocol',<br>
> > 'all_type_or_protocols'])<br>
><br>
> Didn't know about this. Pretty cool for readability.<br>
<br>
</span>Indeed :-) (as long as you add a comment as "headline" when using it)<br>
<span class=""><br>
> > +class NetworkTestParseFromLog(NetworkTest):<br>
> > + def test_net_from_log(self):<br>
> > + parser = ReadLog('', '', '', '', '')<br>
> > + event = 'type=AVC msg=audit(1428699242.551:386):<br>
> > apparmor="DENIED" operation="create" profile="/bin/ping" pid=10589<br>
> > comm="ping" family="inet" sock_type="raw" protocol=1'<br>
> > +<br>
> > + parsed_event = parser.parse_event(event)<br>
> > +<br>
> > + self.assertEqual(parsed_event, {<br>
> > + 'request_mask': None,<br>
> > + 'denied_mask': None,<br>
><br>
> you switched from set() to None between the two versions of this<br>
> patch?<br>
<br>
</span>Yes, that's caused by the logparser.py r3009 changes, which moved the<br>
code that parses request_mask and denied_mask to add_event_to_tree()<br>
(and does it only for file events).<br>
<br>
Sorry, I should have mentioned that in my v2 mail.<br>
<span class=""><br>
> > + self._compare_obj(obj, expected)<br>
> > +<br>
> > + self.assertEqual(obj.get_raw(1), ' network inet raw,')<br>
><br>
> why obj.get_raw(1) and not assertEqual on obj.raw_rule? The depth code<br>
> in get_raw() should be already be under tests elsewhere, seems<br>
> redundant? look below: comment about parse_modifiers<br>
<br>
</span>I prefer to test against the public functions - obj.raw_rule is just an<br>
implementation detail that could in theory change without breaking<br>
something.<br>
<br>
Besides that - in test_write_manually() obj.raw_rule is empty ;-)<br>
<span class=""><br>
> > +class InvalidNetworkInit(AATest):<br>
> > + tests = [<br>
<br>
</span>> > + ([dict(), 'tcp' ] , AppArmorBug), # wrong<br>
<span class="">> > type for domain<br>
> > + (['inet', dict() ] , AppArmorBug), # wrong<br>
> > type for type_or_protocol<br>
><br>
> Nitpick: would it be better/correct to use None instead of dict()<br>
> here? using dict() or list() seems arbitrary to me (I maybe wrong)?<br>
<br>
</span>Sounds like a philosophical question - what is a correct invalid value? ;-)<br>
<br>
Basically we can use everything that is not a string and not<br>
NetworkRule.ALL as invalid parameter, so I just picked one.<br>
Oh, and I just added the "None" variant as additional tests.<br>
<span class=""><br>
> > + def test_parse_modifiers_invalid(self):<br>
> > + regex =<br>
> > re.compile('^\s*(?P<audit>audit\s+)?(?P<allow>allow\s+|deny\s+|inval<br>
> > id\s+)?') + matches = regex.search('audit invalid ')<br>
> > +<br>
> > + with self.assertRaises(AppArmorBug):<br>
> > + parse_modifiers(matches)<br>
><br>
> This test is redundant as its already present in test-capability. Also<br>
> this test should instead be located somewhere where the tests for the<br>
> base classes are located as parse_modifiers is defined with them.<br>
<br>
</span>Indeed. I removed it from test-network.py (which also means to remove<br>
the import for parse_modifiers and re).<br>
<br>
I just sent a separate patch to move it from test-capability.py to<br>
test-baserule.py (the patch to add test-baserule.py is still pending,<br>
reviewing it should be easy ;-)<br>
<span class=""><br>
> > + def test_write_manually(self):<br>
> > + obj = NetworkRule('inet', 'stream', allow_keyword=True)<br>
> > +<br>
> > + expected = ' allow network inet stream,'<br>
> > +<br>
> > + self.assertEqual(expected, obj.get_clean(2), 'unexpected<br>
> > clean rule')<br>
> > + self.assertEqual(expected, obj.get_raw(2), 'unexpected raw<br>
> > rule')<br>
> As stated in rule/__init__.py, subclasses needed to implement<br>
> get_clean so its fair that get_clean should have tests here, however,<br>
> get_raw is not being implemented in capability or network rule<br>
> classes and it seems redundant to have tests for the same at both<br>
> places. I feel we can do away with tests for these methods in every<br>
> rule class and have them centralised place (tests for the __init__<br>
> stuff), unless a class overrides it. Opinions?<br>
<br>
</span>In theory, I agree - yes, it seems redundant.<br>
<br>
In practise, I want to keep that safety net - and I also want to test<br>
with all rule types to make sure we don't accidently break writing the<br>
raw rule somewhere.<br>
<span class=""><br></span></blockquote><div>Its okay I guess until we start having too much redundant tests(if there's such a thing) for safety.<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="">
> In general the above patch looks good specially given the 100%<br>
> coverage stat (will coverage % be effected if we move the get_raw<br>
> stuff to some other place?).<br>
<br>
</span>Probably not, but as I said, I prefer not to move it.<br>
<br>
BTW: Coverage stats are nice, but don't tell everything. Just as an<br>
example - if you test a complex regex with one example, you'll have<br>
100% coverage, but this doesn't mean that the regex is correct for all<br>
usecases.<br>
<span class=""><br>
> Note: I've used to the existing capability rule tests/classes for<br>
> reference given it went through many rounds of iteration before being<br>
> committed.<br>
<br>
</span>Then you probably also noticed that I've used test-capability.py as<br>
base for test-network.py - basically I started with<br></blockquote><div>Indeed. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
sed 's/^/# / ; s/capability/network/' < test-capability.py > test-network.py<br>
and then did some more changes and removed the # again.<br>
<br>
Of course, that's the simplified version - there are more differences<br>
besides those replacements, and also some improvements like using<br>
namedtuple.<br>
<span class=""><br>
> It wouldn't hurt to have second set of eyes look at this patch series.<br>
><br>
> However, I'm willing to ack this patch set once Christian responds on<br>
> the above queries.<br>
<br>
</span>:-)<br>
<span class=""><br>
> [1]- <a href="https://www.python.org/dev/peps/pep-0008/#imports" target="_blank">https://www.python.org/dev/peps/pep-0008/#imports</a><br>
><br>
> Follow-up read:<br>
> <a href="https://www.python.org/dev/peps/pep-0328/#guido-s-decision" target="_blank">https://www.python.org/dev/peps/pep-0328/#guido-s-decision</a><br>
<br>
</span>That sounds like another can of worms... ;-)<br>
<br></blockquote><div>;-) <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
That all said, here's the updated patch.<br>
<span class=""><br>
<br>
[ 45-add-tests-for-NetworkRule.diff ]<br>
<br>
=== added file utils/test/test-network.py<br>
</span>--- utils/test/test-network.py 2015-04-20 00:15:46.001752247 +0200<br>
+++ utils/test/test-network.py 2015-04-20 00:17:43.852948920 +0200<br>
@@ -0,0 +1,421 @@<br>
<span class="">+#!/usr/bin/env python<br>
+# ----------------------------------------------------------------------<br>
+# Copyright (C) 2015 Christian Boltz <<a href="mailto:apparmor@cboltz.de">apparmor@cboltz.de</a>><br>
+#<br>
+# This program is free software; you can redistribute it and/or<br>
+# modify it under the terms of version 2 of the GNU General Public<br>
+# License as published by the Free Software Foundation.<br>
+#<br>
+# This program is distributed in the hope that it will be useful,<br>
+# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+# GNU General Public License for more details.<br>
+#<br>
+# ----------------------------------------------------------------------<br>
+<br>
+import unittest<br>
</span>+from collections import namedtuple<br>
<span class="">+from common_test import AATest, setup_all_loops<br>
</span><span class="">+<br>
+from apparmor.rule.network import NetworkRule, NetworkRuleset<br>
+from apparmor.rule import BaseRule<br>
</span><span class="">+from apparmor.common import AppArmorException, AppArmorBug<br>
+from apparmor.logparser import ReadLog<br>
+<br>
</span><span class="">+exp = namedtuple('exp', ['audit', 'allow_keyword', 'deny', 'comment',<br>
+ 'domain', 'all_domains', 'type_or_protocol', 'all_type_or_protocols'])<br>
</span><div><div class="h5">+<br>
+# --- tests for single NetworkRule --- #<br>
+<br>
+class NetworkTest(AATest):<br>
+ def _compare_obj(self, obj, expected):<br>
+ self.assertEqual(expected.allow_keyword, obj.allow_keyword)<br>
+ self.assertEqual(expected.audit, obj.audit)<br>
+ self.assertEqual(expected.domain, obj.domain)<br>
+ self.assertEqual(expected.type_or_protocol, obj.type_or_protocol)<br>
+ self.assertEqual(expected.all_domains, obj.all_domains)<br>
+ self.assertEqual(expected.all_type_or_protocols, obj.all_type_or_protocols)<br>
+ self.assertEqual(expected.deny, obj.deny)<br>
+ self.assertEqual(expected.comment, obj.comment)<br>
+<br>
+class NetworkTestParse(NetworkTest):<br>
+ tests = [<br>
+ # rawrule audit allow deny comment domain all? type/proto all?<br>
+ ('network,' , exp(False, False, False, '' , None , True , None , True )),<br>
+ ('network inet,' , exp(False, False, False, '' , 'inet', False, None , True )),<br>
+ ('network inet stream,' , exp(False, False, False, '' , 'inet', False, 'stream' , False)),<br>
+ ('deny network inet stream, # comment' , exp(False, False, True , ' # comment' , 'inet', False, 'stream' , False)),<br>
+ ('audit allow network tcp,' , exp(True , True , False, '' , None , True , 'tcp' , False)),<br>
+ ]<br>
+<br>
+ def _run_test(self, rawrule, expected):<br>
+ obj = NetworkRule.parse(rawrule)<br>
+ self.assertEqual(rawrule.strip(), obj.raw_rule)<br>
+ self._compare_obj(obj, expected)<br>
+<br>
+class NetworkTestParseInvalid(NetworkTest):<br>
+ tests = [<br>
+ ('network stream,' , AppArmorException), # domain missing<br>
+ ('network foo,' , AppArmorException),<br>
+ ('network foo bar,' , AppArmorException),<br>
+ ('network foo tcp,' , AppArmorException),<br>
+ ('network inet bar,' , AppArmorException),<br>
+ ]<br>
+<br>
+ def _run_test(self, rawrule, expected):<br>
+ with self.assertRaises(expected):<br>
+ NetworkRule.parse(rawrule)<br>
+<br>
+class NetworkTestParseFromLog(NetworkTest):<br>
+ def test_net_from_log(self):<br>
+ parser = ReadLog('', '', '', '', '')<br>
+ event = 'type=AVC msg=audit(1428699242.551:386): apparmor="DENIED" operation="create" profile="/bin/ping" pid=10589 comm="ping" family="inet" sock_type="raw" protocol=1'<br>
+<br>
+ parsed_event = parser.parse_event(event)<br>
+<br>
+ self.assertEqual(parsed_event, {<br>
+ 'request_mask': None,<br>
+ 'denied_mask': None,<br>
</div></div><div><div class="h5">+ 'error_code': 0,<br>
+ 'family': 'inet',<br>
+ 'magic_token': 0,<br>
+ 'parent': 0,<br>
+ 'profile': '/bin/ping',<br>
+ 'protocol': 'icmp',<br>
+ 'sock_type': 'raw',<br>
+ 'operation': 'create',<br>
+ 'resource': None,<br>
+ 'info': None,<br>
+ 'aamode': 'REJECTING',<br>
+ 'time': 1428699242,<br>
+ 'active_hat': None,<br>
+ 'pid': 10589,<br>
+ 'task': 0,<br>
+ 'attr': None,<br>
+ 'name2': None,<br>
+ 'name': None,<br>
+ })<br>
+<br>
+ obj = NetworkRule(parsed_event['family'], parsed_event['sock_type'], log_event=parsed_event)<br>
+<br>
+ # audit allow deny comment domain all? type/proto all?<br>
+ expected = exp(False, False, False, '' , 'inet', False, 'raw' , False)<br>
+<br>
+ self._compare_obj(obj, expected)<br>
+<br>
+ self.assertEqual(obj.get_raw(1), ' network inet raw,')<br>
</div></div><div><div class="h5">+<br>
+<br>
+class NetworkFromInit(NetworkTest):<br>
+ tests = [<br>
+ # NetworkRule object audit allow deny comment domain all? type/proto all?<br>
+ (NetworkRule('inet', 'raw', deny=True) , exp(False, False, True , '' , 'inet', False, 'raw' , False)),<br>
+ (NetworkRule('inet', 'raw') , exp(False, False, False, '' , 'inet', False, 'raw' , False)),<br>
+ (NetworkRule('inet', NetworkRule.ALL) , exp(False, False, False, '' , 'inet', False, None , True )),<br>
+ (NetworkRule(NetworkRule.ALL, NetworkRule.ALL) , exp(False, False, False, '' , None , True , None , True )),<br>
+ (NetworkRule(NetworkRule.ALL, 'tcp') , exp(False, False, False, '' , None , True , 'tcp' , False)),<br>
+ ]<br>
+<br>
+ def _run_test(self, obj, expected):<br>
+ self._compare_obj(obj, expected)<br>
+<br>
+<br>
+class InvalidNetworkInit(AATest):<br>
+ tests = [<br>
+ # init params expected exception<br>
+ (['inet', '' ] , AppArmorBug), # empty type_or_protocol<br>
+ (['' , 'tcp' ] , AppArmorBug), # empty domain<br>
+ ([' ', 'tcp' ] , AppArmorBug), # whitespace domain<br>
+ (['inet', ' ' ] , AppArmorBug), # whitespace type_or_protocol<br>
+ (['xyxy', 'tcp' ] , AppArmorBug), # invalid domain<br>
+ (['inet', 'xyxy' ] , AppArmorBug), # invalid type_or_protocol<br>
+ ([dict(), 'tcp' ] , AppArmorBug), # wrong type for domain<br>
</div></div>+ ([None , 'tcp' ] , AppArmorBug), # wrong type for domain<br>
<span class="">+ (['inet', dict() ] , AppArmorBug), # wrong type for type_or_protocol<br>
</span>+ (['inet', None ] , AppArmorBug), # wrong type for type_or_protocol<br>
<div><div class="h5">+ ([NetworkRule.ALL, 'stream'] , AppArmorException), # stream requires a domain<br>
+ ]<br>
+<br>
+ def _run_test(self, params, expected):<br>
+ with self.assertRaises(expected):<br>
+ NetworkRule(params[0], params[1])<br>
+<br>
+ def test_missing_params_1(self):<br>
+ with self.assertRaises(TypeError):<br>
+ NetworkRule()<br>
+<br>
+ def test_missing_params_2(self):<br>
+ with self.assertRaises(TypeError):<br>
+ NetworkRule('inet')<br>
+<br>
+<br>
+class InvalidNetworkTest(AATest):<br>
+ def _check_invalid_rawrule(self, rawrule):<br>
+ obj = None<br>
+ with self.assertRaises(AppArmorException):<br>
+ obj = NetworkRule(NetworkRule.parse(rawrule))<br>
+<br>
+ self.assertIsNone(obj, 'NetworkRule handed back an object unexpectedly')<br>
+<br>
+ def test_invalid_net_missing_comma(self):<br>
+ self._check_invalid_rawrule('network') # missing comma<br>
+<br>
+ def test_invalid_net_non_NetworkRule(self):<br>
+ self._check_invalid_rawrule('dbus,') # not a network rule<br>
+<br>
</div></div>+ def test_empty_net_data_1(self):<br>
<div><div class="h5">+ obj = NetworkRule('inet', 'stream')<br>
+ obj.domain = ''<br>
+ # no domain set, and ALL not set<br>
+ with self.assertRaises(AppArmorBug):<br>
+ obj.get_clean(1)<br>
+<br>
+ def test_empty_net_data_2(self):<br>
+ obj = NetworkRule('inet', 'stream')<br>
+ obj.type_or_protocol = ''<br>
+ # no type_or_protocol set, and ALL not set<br>
+ with self.assertRaises(AppArmorBug):<br>
+ obj.get_clean(1)<br>
+<br>
+<br>
+class WriteNetworkTestAATest(AATest):<br>
+ def _run_test(self, rawrule, expected):<br>
+ obj = NetworkRule.parse(rawrule)<br>
+ clean = obj.get_clean()<br>
+ raw = obj.get_raw()<br>
+<br>
+ self.assertEqual(expected.strip(), clean, 'unexpected clean rule')<br>
+ self.assertEqual(rawrule.strip(), raw, 'unexpected raw rule')<br>
+<br>
+ tests = [<br>
+ # raw rule clean rule<br>
+ (' network , # foo ' , 'network, # foo'),<br>
+ (' audit network inet,' , 'audit network inet,'),<br>
+ (' deny network inet stream,# foo bar' , 'deny network inet stream, # foo bar'),<br>
+ (' deny network inet ,# foo bar' , 'deny network inet, # foo bar'),<br>
+ (' allow network tcp ,# foo bar' , 'allow network tcp, # foo bar'),<br>
+ ]<br>
+<br>
+ def test_write_manually(self):<br>
+ obj = NetworkRule('inet', 'stream', allow_keyword=True)<br>
+<br>
+ expected = ' allow network inet stream,'<br>
+<br>
+ self.assertEqual(expected, obj.get_clean(2), 'unexpected clean rule')<br>
+ self.assertEqual(expected, obj.get_raw(2), 'unexpected raw rule')<br>
</div></div><div><div class="h5">+<br>
+<br>
+class NetworkCoveredTest(AATest):<br>
+ def _run_test(self, param, expected):<br>
+ obj = NetworkRule.parse(self.rule)<br>
+ check_obj = NetworkRule.parse(param)<br>
+<br>
+ self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0])<br>
+ self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1])<br>
+<br>
+ self.assertEqual(obj.is_covered(check_obj), expected[2], 'Mismatch in is_covered, expected %s' % expected[2])<br>
+ self.assertEqual(obj.is_covered(check_obj, True, True), expected[3], 'Mismatch in is_covered/exact, expected %s' % expected[3])<br>
+<br>
+class NetworkCoveredTest_01(NetworkCoveredTest):<br>
+ rule = 'network inet,'<br>
+<br>
+ tests = [<br>
+ # rule equal strict equal covered covered exact<br>
+ ('network,' , [ False , False , False , False ]),<br>
+ ('network inet,' , [ True , True , True , True ]),<br>
+ ('network inet, # comment' , [ True , False , True , True ]),<br>
+ ('allow network inet,' , [ True , False , True , True ]),<br>
+ ('network inet,' , [ True , False , True , True ]),<br>
+ ('network inet stream,' , [ False , False , True , True ]),<br>
+ ('network inet tcp,' , [ False , False , True , True ]),<br>
+ ('audit network inet,' , [ False , False , False , False ]),<br>
+ ('audit network,' , [ False , False , False , False ]),<br>
+ ('network unix,' , [ False , False , False , False ]),<br>
+ ('network tcp,' , [ False , False , False , False ]),<br>
+ ('audit deny network inet,' , [ False , False , False , False ]),<br>
+ ('deny network inet,' , [ False , False , False , False ]),<br>
+ ]<br>
+<br>
+class NetworkCoveredTest_02(NetworkCoveredTest):<br>
+ rule = 'audit network inet,'<br>
+<br>
+ tests = [<br>
+ # rule equal strict equal covered covered exact<br>
+ ( 'network inet,' , [ False , False , True , False ]),<br>
+ ('audit network inet,' , [ True , True , True , True ]),<br>
+ ( 'network inet stream,' , [ False , False , True , False ]),<br>
+ ('audit network inet stream,' , [ False , False , True , True ]),<br>
+ ( 'network,' , [ False , False , False , False ]),<br>
+ ('audit network,' , [ False , False , False , False ]),<br>
+ ('network unix,' , [ False , False , False , False ]),<br>
+ ]<br>
+<br>
+<br>
+class NetworkCoveredTest_03(NetworkCoveredTest):<br>
+ rule = 'network inet stream,'<br>
+<br>
+ tests = [<br>
+ # rule equal strict equal covered covered exact<br>
+ ( 'network inet stream,' , [ True , True , True , True ]),<br>
+ ('allow network inet stream,' , [ True , False , True , True ]),<br>
+ ( 'network inet,' , [ False , False , False , False ]),<br>
+ ( 'network,' , [ False , False , False , False ]),<br>
+ ( 'network inet tcp,' , [ False , False , False , False ]),<br>
+ ('audit network,' , [ False , False , False , False ]),<br>
+ ('audit network inet stream,' , [ False , False , False , False ]),<br>
+ ( 'network unix,' , [ False , False , False , False ]),<br>
+ ( 'network,' , [ False , False , False , False ]),<br>
+ ]<br>
+<br>
+class NetworkCoveredTest_04(NetworkCoveredTest):<br>
+ rule = 'network,'<br>
+<br>
+ tests = [<br>
+ # rule equal strict equal covered covered exact<br>
+ ( 'network,' , [ True , True , True , True ]),<br>
+ ('allow network,' , [ True , False , True , True ]),<br>
+ ( 'network inet,' , [ False , False , True , True ]),<br>
+ ( 'network inet6 stream,' , [ False , False , True , True ]),<br>
+ ( 'network tcp,' , [ False , False , True , True ]),<br>
+ ( 'network inet raw,' , [ False , False , True , True ]),<br>
+ ('audit network,' , [ False , False , False , False ]),<br>
+ ('deny network,' , [ False , False , False , False ]),<br>
+ ]<br>
+<br>
+class NetworkCoveredTest_05(NetworkCoveredTest):<br>
+ rule = 'deny network inet,'<br>
+<br>
+ tests = [<br>
+ # rule equal strict equal covered covered exact<br>
+ ( 'deny network inet,' , [ True , True , True , True ]),<br>
+ ('audit deny network inet,' , [ False , False , False , False ]),<br>
+ ( 'network inet,' , [ False , False , False , False ]), # XXX should covered be true here?<br>
+ ( 'deny network unix,' , [ False , False , False , False ]),<br>
+ ( 'deny network,' , [ False , False , False , False ]),<br>
+ ]<br>
+<br>
+<br>
+class NetworkCoveredTest_Invalid(AATest):<br>
+ def test_borked_obj_is_covered_1(self):<br>
+ obj = NetworkRule.parse('network inet,')<br>
+<br>
+ testobj = NetworkRule('inet', 'stream')<br>
+ testobj.domain = ''<br>
+<br>
+ with self.assertRaises(AppArmorBug):<br>
+ obj.is_covered(testobj)<br>
+<br>
+ def test_borked_obj_is_covered_2(self):<br>
+ obj = NetworkRule.parse('network inet,')<br>
+<br>
+ testobj = NetworkRule('inet', 'stream')<br>
+ testobj.type_or_protocol = ''<br>
+<br>
+ with self.assertRaises(AppArmorBug):<br>
+ obj.is_covered(testobj)<br>
+<br>
+ def test_invalid_is_covered(self):<br>
+ obj = NetworkRule.parse('network inet,')<br>
+<br>
+ testobj = BaseRule() # different type<br>
+<br>
+ with self.assertRaises(AppArmorBug):<br>
+ obj.is_covered(testobj)<br>
+<br>
+ def test_invalid_is_equal(self):<br>
+ obj = NetworkRule.parse('network inet,')<br>
+<br>
+ testobj = BaseRule() # different type<br>
+<br>
+ with self.assertRaises(AppArmorBug):<br>
+ obj.is_equal(testobj)<br>
+<br>
+## --- tests for NetworkRuleset --- #<br>
+<br>
+class NetworkRulesTest(AATest):<br>
+ def test_empty_ruleset(self):<br>
+ ruleset = NetworkRuleset()<br>
+ ruleset_2 = NetworkRuleset()<br>
+ self.assertEqual([], ruleset.get_raw(2))<br>
+ self.assertEqual([], ruleset.get_clean(2))<br>
+ self.assertEqual([], ruleset_2.get_raw(2))<br>
+ self.assertEqual([], ruleset_2.get_clean(2))<br>
+<br>
+ def test_ruleset_1(self):<br>
+ ruleset = NetworkRuleset()<br>
+ rules = [<br>
+ 'network tcp,',<br>
+ 'network inet,',<br>
+ ]<br>
+<br>
+ expected_raw = [<br>
+ 'network tcp,',<br>
+ 'network inet,',<br>
+ '',<br>
+ ]<br>
+<br>
+ expected_clean = [<br>
+ 'network inet,',<br>
+ 'network tcp,',<br>
+ '',<br>
+ ]<br>
+<br>
+ for rule in rules:<br>
+ ruleset.add(NetworkRule.parse(rule))<br>
+<br>
+ self.assertEqual(expected_raw, ruleset.get_raw())<br>
+ self.assertEqual(expected_clean, ruleset.get_clean())<br>
+<br>
+ def test_ruleset_2(self):<br>
+ ruleset = NetworkRuleset()<br>
+ rules = [<br>
+ 'network inet6 raw,',<br>
+ 'allow network inet,',<br>
+ 'deny network udp, # example comment',<br>
+ ]<br>
+<br>
+ expected_raw = [<br>
+ ' network inet6 raw,',<br>
+ ' allow network inet,',<br>
+ ' deny network udp, # example comment',<br>
+ '',<br>
+ ]<br>
+<br>
+ expected_clean = [<br>
+ ' deny network udp, # example comment',<br>
+ '',<br>
+ ' allow network inet,',<br>
+ ' network inet6 raw,',<br>
+ '',<br>
+ ]<br>
+<br>
+ for rule in rules:<br>
+ ruleset.add(NetworkRule.parse(rule))<br>
+<br>
+ self.assertEqual(expected_raw, ruleset.get_raw(1))<br>
+ self.assertEqual(expected_clean, ruleset.get_clean(1))<br>
+<br>
+<br>
+class NetworkGlobTestAATest(AATest):<br>
+ def setUp(self):<br>
+ self.maxDiff = None<br>
+ self.ruleset = NetworkRuleset()<br>
+<br>
+ def test_glob_1(self):<br>
+ self.assertEqual(self.ruleset.get_glob('network inet,'), 'network,')<br>
+<br>
+ # not supported or used yet<br>
+ # def test_glob_2(self):<br>
+ # self.assertEqual(self.ruleset.get_glob('network inet raw,'), 'network inet,')<br>
+<br>
+ def test_glob_ext(self):<br>
+ with self.assertRaises(AppArmorBug):<br>
+ # get_glob_ext is not available for network rules<br>
+ self.ruleset.get_glob_ext('network inet raw,')<br>
+<br>
+class NetworkDeleteTestAATest(AATest):<br>
+ pass<br>
+<br>
+setup_all_loops(__name__)<br>
+if __name__ == '__main__':<br>
+ unittest.main(verbosity=2)<br>
<br>
<br></div></div></blockquote><div>Thank for the patch and follow-up.<br><br>Acked-by: Kshitij Gupta <<a href="mailto:kgupta8592@gmail.com" target="_blank">kgupta8592@gmail.com</a>>.<br><br></div><div>Regards,<br><br></div><div>Kshitij Gupta<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div class="h5">
<br>
<br>
</div></div>Regards,<br>
<br>
Christian Boltz<br>
<span class=""><font color="#888888">--<br>
[KDE3 vs. KDE4] My guess is the vocal minority will only be satisfied<br>
when KDE4 gets dropped. We need to let them know that might happen<br>
round about the release of KDE5.4 . [from a comment on<br>
<a href="http://blogs.warwick.ac.uk/bweber/entry/opensuse_110_kde4/" target="_blank">http://blogs.warwick.ac.uk/bweber/entry/opensuse_110_kde4/</a>]<br>
</font></span><div class=""><div class="h5"><br>
<br>
--<br>
AppArmor mailing list<br>
<a href="mailto:AppArmor@lists.ubuntu.com">AppArmor@lists.ubuntu.com</a><br>
Modify settings or unsubscribe at: <a href="https://lists.ubuntu.com/mailman/listinfo/apparmor" target="_blank">https://lists.ubuntu.com/mailman/listinfo/apparmor</a><br>
</div></div></blockquote></div><br></div></div>