~ubuntu-branches/ubuntu/wily/apparmor/wily

« back to all changes in this revision

Viewing changes to utils/test/test-regex_matches.py

  • Committer: Package Import Robot
  • Author(s): Steve Beattie
  • Date: 2015-05-11 22:03:04 UTC
  • mfrom: (1.1.31)
  • Revision ID: package-import@ubuntu.com-20150511220304-gcgk9ix2ui7wvyt0
Tags: 2.9.2-0ubuntu1
* Update to apparmor 2.9.2
  - Fix minitools to work with multiple profiles at once (LP: #1378095)
  - Parse mounts that have non-ascii UTF-8 chars (LP: #1310598)
  - Update dovecot profiles (LP: #1296667)
  - Allow ubuntu-helpers to build texlive fonts (LP: #1010909)
* dropped patches incorporated upstream:
  add-mir-abstraction-lp1422521.patch, systemd-dev-log-lp1413232.patch
  parser-fix_modifier_compilation_+_tests.patch,
  tests-fix_systemd_breakage_in_pivot_root-lp1436109.patch,
  GDM_X_authority-lp1432126.patch, and
  debian/patches/easyprof-framework-policy.patch
* Partial merge with debian apparmor package:
  - debian/rules: enable the bindnow hardening flag during build.
  - debian/upstream/signing-key.asc: add new upstream public
    signing key
  - debian/watch: fix watch file, add gpg signature checking
  - install libapparmor.so dev symlink under /usr not /lib
  - debian/patches/reproducible-pdf.patch: make techdoc.pdf
    reproducible even in face of timezone variations.
  - debian/control: sync fields
  - debian/debhelper/postrm-apparmor: remove
    /etc/apparmor.d/{disable,} on package purge
  - debian/libapache2-mod-apparmor.postrm: on package purge, delete
    /etc/apparmor.d/{,disable} if empty
  - debian/libapparmor1.symbols: Use Build-Depends-Package in the
    symbols file.
  - debian/copyright: sync

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
import apparmor.aa as aa
13
13
import unittest
14
 
 
15
 
 
16
 
class AARegexHasComma(unittest.TestCase):
 
14
from common_test import AATest, setup_all_loops
 
15
from apparmor.common import AppArmorBug
 
16
 
 
17
from apparmor.regex import strip_quotes, parse_profile_start_line, RE_PROFILE_START
 
18
 
 
19
 
 
20
class AARegexTest(AATest):
 
21
    def _run_test(self, params, expected):
 
22
        return _regex_test(self, params, expected)
 
23
 
 
24
class AANamedRegexTest(AATest):
 
25
    def _run_test(self, line, expected):
 
26
        '''Run a line through self.regex.search() and verify the result
 
27
 
 
28
        Keyword arguments:
 
29
        line -- the line to search
 
30
        expected -- False if the search isn't expected to match or, if the search
 
31
                    is expected to match, a tuple of expected match groups.
 
32
        '''
 
33
        matches = self.regex.search(line)
 
34
        if not expected:
 
35
            self.assertFalse(matches)
 
36
            return
 
37
 
 
38
        self.assertTrue(matches)
 
39
 
 
40
        for exp in expected:
 
41
            match = matches.group(exp)
 
42
            if match:
 
43
                match = match
 
44
            self.assertEqual(match, expected[exp], 'Group %s mismatch in rule %s' % (exp,line))
 
45
 
 
46
 
 
47
 
 
48
class AARegexHasComma(AATest):
17
49
    '''Tests for apparmor.aa.RE_RULE_HAS_COMMA'''
18
50
 
19
51
    def _check(self, line, expected=True):
93
125
        setattr(AARegexHasComma, 'test_comma_%d' % (i), stub_test_comma)
94
126
        setattr(AARegexHasComma, 'test_no_comma_%d' % (i), stub_test_no_comma)
95
127
 
96
 
class AARegexSplitComment(unittest.TestCase):
 
128
class AARegexSplitComment(AATest):
97
129
    '''Tests for RE_HAS_COMMENT_SPLIT'''
98
130
 
99
131
    def _check(self, line, expected, comment=None, not_comment=None):
141
173
        setattr(AARegexSplitComment, 'test_split_comment_%d' % (i), stub_test)
142
174
 
143
175
 
144
 
def regex_test(self, line, expected):
 
176
def _regex_test(self, line, expected):
145
177
    '''Run a line through self.regex.search() and verify the result
146
178
 
147
179
    Keyword arguments:
165
197
        self.assertEqual(group, expected[i], 'Group %d mismatch in rule %s' % (i,line))
166
198
 
167
199
 
168
 
def setup_regex_tests(test_class):
169
 
    '''Create tests in test_class using test_class.tests and regex_tests()
170
 
 
171
 
    test_class.tests should be tuples of (line, expected_results) where
172
 
    expected_results is False if test_class.regex.search(line) should not
173
 
    match. If the search should match, expected_results should be a tuple of
174
 
    the expected groups, with all of the strings stripped.
175
 
    '''
176
 
    for (i, (line, expected)) in enumerate(test_class.tests):
177
 
        def stub_test(self, line=line, expected=expected):
178
 
            regex_test(self, line, expected)
179
 
 
180
 
        stub_test.__doc__ = "test '%s'" % (line)
181
 
        setattr(test_class, 'test_%d' % (i), stub_test)
182
 
 
183
 
 
184
 
class AARegexCapability(unittest.TestCase):
 
200
 
 
201
 
 
202
 
 
203
class AARegexCapability(AARegexTest):
185
204
    '''Tests for RE_PROFILE_CAP'''
186
205
 
187
206
    def setUp(self):
196
215
    ]
197
216
 
198
217
 
199
 
class AARegexPath(unittest.TestCase):
 
218
class AARegexPath(AARegexTest):
200
219
    '''Tests for RE_PROFILE_PATH_ENTRY'''
201
220
 
202
221
    def setUp(self):
215
234
    ]
216
235
 
217
236
 
218
 
class AARegexBareFile(unittest.TestCase):
 
237
class AARegexBareFile(AARegexTest):
219
238
    '''Tests for RE_PROFILE_BARE_FILE_ENTRY'''
220
239
 
221
240
    def setUp(self):
233
252
    ]
234
253
 
235
254
 
236
 
class AARegexDbus(unittest.TestCase):
 
255
class AARegexDbus(AARegexTest):
237
256
    '''Tests for RE_PROFILE_DBUS'''
238
257
 
239
258
    def setUp(self):
249
268
        ('   audit dbusdriver,', False),
250
269
    ]
251
270
 
252
 
class AARegexMount(unittest.TestCase):
 
271
class AARegexMount(AARegexTest):
253
272
    '''Tests for RE_PROFILE_MOUNT'''
254
273
 
255
274
    def setUp(self):
273
292
 
274
293
 
275
294
 
276
 
class AARegexSignal(unittest.TestCase):
 
295
class AARegexSignal(AARegexTest):
277
296
    '''Tests for RE_PROFILE_SIGNAL'''
278
297
 
279
298
    def setUp(self):
299
318
    ]
300
319
 
301
320
 
302
 
class AARegexPtrace(unittest.TestCase):
 
321
class AARegexPtrace(AARegexTest):
303
322
    '''Tests for RE_PROFILE_PTRACE'''
304
323
 
305
324
    def setUp(self):
321
340
    ]
322
341
 
323
342
 
324
 
class AARegexPivotRoot(unittest.TestCase):
 
343
class AARegexPivotRoot(AARegexTest):
325
344
    '''Tests for RE_PROFILE_PIVOT_ROOT'''
326
345
 
327
346
    def setUp(self):
348
367
        ('pivot_rootbeer /new, # comment', False),
349
368
    ]
350
369
 
351
 
class AARegexUnix(unittest.TestCase):
 
370
class AARegexUnix(AARegexTest):
352
371
    '''Tests for RE_PROFILE_UNIX'''
353
372
 
354
373
    def setUp(self):
373
392
        ('deny unixlike,', False),
374
393
    ]
375
394
 
 
395
class AANamedRegexProfileStart_2(AANamedRegexTest):
 
396
    '''Tests for RE_PROFILE_START'''
 
397
 
 
398
    def setUp(self):
 
399
        self.regex = RE_PROFILE_START
 
400
 
 
401
    tests = [
 
402
        ('/bin/foo ', False), # no '{'
 
403
        ('/bin/foo /bin/bar', False), # missing 'profile' keyword
 
404
        ('profile {', False), # no attachment
 
405
        ('   profile foo bar /foo {', False), # missing quotes around "foo bar"
 
406
 
 
407
        ('   /foo {',                     { 'plainprofile': '/foo',    'namedprofile': None,          'attachment': None,     'flags': None,       'comment': None }),
 
408
        ('   "/foo" {',                   { 'plainprofile': '"/foo"',  'namedprofile': None,          'attachment': None,     'flags': None,       'comment': None }),
 
409
        ('   profile /foo {',             { 'plainprofile': None,      'namedprofile': '/foo',        'attachment': None,     'flags': None,       'comment': None }),
 
410
        ('   profile "/foo" {',           { 'plainprofile': None,      'namedprofile': '"/foo"',      'attachment': None,     'flags': None,       'comment': None }),
 
411
        ('   profile foo /foo {',         { 'plainprofile': None,      'namedprofile': 'foo',         'attachment': '/foo',   'flags': None,       'comment': None }),
 
412
        ('   profile foo /foo (audit) {', { 'plainprofile': None,      'namedprofile': 'foo',         'attachment': '/foo',   'flags': 'audit',    'comment': None }),
 
413
        ('   profile "foo" "/foo" {',     { 'plainprofile': None,      'namedprofile': '"foo"',       'attachment': '"/foo"', 'flags': None,       'comment': None }),
 
414
        ('   profile "foo bar" /foo {',   { 'plainprofile': None,      'namedprofile': '"foo bar"',   'attachment': '/foo',   'flags': None,       'comment': None }),
 
415
        ('   /foo (complain) {',          { 'plainprofile': '/foo',    'namedprofile': None,          'attachment': None,     'flags': 'complain', 'comment': None }),
 
416
        ('   /foo flags=(complain) {',    { 'plainprofile': '/foo',    'namedprofile': None,          'attachment': None,     'flags': 'complain', 'comment': None }),
 
417
        ('   /foo (complain) { # x',      { 'plainprofile': '/foo',    'namedprofile': None,          'attachment': None,     'flags': 'complain', 'comment': '# x'}),
 
418
 
 
419
        ('   /foo {',                     { 'plainprofile': '/foo',     'namedprofile': None,   'leadingspace': '   ' }),
 
420
        ('/foo {',                        { 'plainprofile': '/foo',     'namedprofile': None,   'leadingspace': ''    }),
 
421
        ('   profile foo {',              { 'plainprofile': None,       'namedprofile': 'foo',  'leadingspace': '   ' }),
 
422
        ('profile foo {',                 { 'plainprofile': None,       'namedprofile': 'foo',  'leadingspace': ''    }),
 
423
    ]
 
424
 
 
425
 
 
426
class Test_parse_profile_start_line(AATest):
 
427
    tests = [
 
428
        ('   /foo {',                     { 'profile': '/foo',    'profile_keyword': False, 'plainprofile': '/foo', 'namedprofile': None,   'attachment': None,   'flags': None,       'comment': None }),
 
429
        ('   "/foo" {',                   { 'profile': '/foo',    'profile_keyword': False, 'plainprofile': '/foo', 'namedprofile': None,   'attachment': None,   'flags': None,       'comment': None }),
 
430
        ('   profile /foo {',             { 'profile': '/foo',    'profile_keyword': True,  'plainprofile': None,   'namedprofile': '/foo', 'attachment': None,   'flags': None,       'comment': None }),
 
431
        ('   profile "/foo" {',           { 'profile': '/foo',    'profile_keyword': True,  'plainprofile': None,   'namedprofile': '/foo', 'attachment': None,   'flags': None,       'comment': None }),
 
432
        ('   profile foo /foo {',         { 'profile': 'foo',     'profile_keyword': True,  'plainprofile': None,   'namedprofile': 'foo',  'attachment': '/foo', 'flags': None,       'comment': None }),
 
433
        ('   profile foo /foo (audit) {', { 'profile': 'foo',     'profile_keyword': True,  'plainprofile': None,   'namedprofile': 'foo',  'attachment': '/foo', 'flags': 'audit',    'comment': None }),
 
434
        ('   profile "foo" "/foo" {',     { 'profile': 'foo',     'profile_keyword': True,  'plainprofile': None,   'namedprofile': 'foo',  'attachment': '/foo', 'flags': None,       'comment': None }),
 
435
        ('   profile "foo bar" /foo {',   { 'profile': 'foo bar', 'profile_keyword': True,  'plainprofile': None, 'namedprofile': 'foo bar','attachment': '/foo', 'flags': None,    'comment': None }),
 
436
        ('   /foo (complain) {',          { 'profile': '/foo',    'profile_keyword': False, 'plainprofile': '/foo', 'namedprofile': None,   'attachment': None,   'flags': 'complain', 'comment': None }),
 
437
        ('   /foo flags=(complain) {',    { 'profile': '/foo',    'profile_keyword': False, 'plainprofile': '/foo', 'namedprofile': None,   'attachment': None,   'flags': 'complain', 'comment': None }),
 
438
        ('   /foo (complain) { # x',      { 'profile': '/foo',    'profile_keyword': False, 'plainprofile': '/foo', 'namedprofile': None,   'attachment': None,   'flags': 'complain', 'comment': '# x'}),
 
439
 
 
440
        ('   /foo {',                     { 'profile': '/foo',    'plainprofile': '/foo', 'namedprofile': None,  'leadingspace': '   ' }),
 
441
        ('/foo {',                        { 'profile': '/foo',    'plainprofile': '/foo', 'namedprofile': None,  'leadingspace': None  }),
 
442
        ('   profile foo {',              { 'profile': 'foo',     'plainprofile': None,   'namedprofile': 'foo', 'leadingspace': '   ' }),
 
443
        ('profile foo {',                 { 'profile': 'foo',     'plainprofile': None,   'namedprofile': 'foo', 'leadingspace': None  }),
 
444
    ]
 
445
 
 
446
    def _run_test(self, line, expected):
 
447
        matches = parse_profile_start_line(line, 'somefile')
 
448
 
 
449
        self.assertTrue(matches)
 
450
 
 
451
        for exp in expected:
 
452
            self.assertEqual(matches[exp], expected[exp], 'Group %s mismatch in rule %s' % (exp,line))
 
453
 
 
454
class TestInvalid_parse_profile_start_line(AATest):
 
455
    tests = [
 
456
        ('/bin/foo ', False), # no '{'
 
457
        ('/bin/foo /bin/bar', False), # missing 'profile' keyword
 
458
        ('profile {', False), # no attachment
 
459
        ('   profile foo bar /foo {', False), # missing quotes around "foo bar"
 
460
    ]
 
461
 
 
462
    def _run_test(self, line, expected):
 
463
        with self.assertRaises(AppArmorBug):
 
464
            parse_profile_start_line(line, 'somefile')
 
465
 
 
466
 
 
467
class TestStripQuotes(AATest):
 
468
    def test_strip_quotes_01(self):
 
469
        self.assertEqual('foo', strip_quotes('foo'))
 
470
    def test_strip_quotes_02(self):
 
471
        self.assertEqual('foo', strip_quotes('"foo"'))
 
472
    def test_strip_quotes_03(self):
 
473
        self.assertEqual('"foo', strip_quotes('"foo'))
 
474
    def test_strip_quotes_04(self):
 
475
        self.assertEqual('foo"', strip_quotes('foo"'))
 
476
    def test_strip_quotes_05(self):
 
477
        self.assertEqual('', strip_quotes('""'))
 
478
    def test_strip_quotes_06(self):
 
479
        self.assertEqual('foo"bar', strip_quotes('foo"bar'))
 
480
    def test_strip_quotes_07(self):
 
481
        self.assertEqual('foo"bar', strip_quotes('"foo"bar"'))
 
482
    def test_strip_quotes_08(self):
 
483
        self.assertEqual('"""foo"bar"""', strip_quotes('""""foo"bar""""'))
 
484
 
 
485
 
 
486
 
 
487
setup_all_loops(__name__)
376
488
if __name__ == '__main__':
377
 
    verbosity = 2
378
 
 
 
489
    # these two are not converted to a tests[] loop yet
379
490
    setup_has_comma_testcases()
380
491
    setup_split_comment_testcases()
381
492
 
382
 
    test_suite = unittest.TestSuite()
383
 
    test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(AARegexHasComma))
384
 
    test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(AARegexSplitComment))
385
 
 
386
 
    for tests in (AARegexCapability, AARegexPath, AARegexBareFile,
387
 
                  AARegexDbus, AARegexMount, AARegexUnix,
388
 
                  AARegexSignal, AARegexPtrace, AARegexPivotRoot):
389
 
        setup_regex_tests(tests)
390
 
        test_suite.addTest(unittest.TestLoader().loadTestsFromTestCase(tests))
391
 
 
392
 
    result = unittest.TextTestRunner(verbosity=verbosity).run(test_suite)
393
 
    if not result.wasSuccessful():
394
 
        exit(1)
 
493
    unittest.main(verbosity=2)