python/mozbuild/mozpack/test/test_packager.py

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 import unittest
     6 import mozunit
     7 import os
     8 from mozpack.packager import (
     9     preprocess_manifest,
    10     CallDeque,
    11     Component,
    12     SimplePackager,
    13     SimpleManifestSink,
    14 )
    15 from mozpack.files import GeneratedFile
    16 from mozpack.chrome.manifest import (
    17     ManifestResource,
    18     ManifestContent,
    19 )
    20 from mozunit import MockedOpen
    21 from mozbuild.preprocessor import Preprocessor
    22 from mozpack.errors import (
    23     errors,
    24     ErrorMessage,
    25 )
    26 import mozpack.path
    28 MANIFEST = '''
    29 bar/*
    30 [foo]
    31 foo/*
    32 -foo/bar
    33 chrome.manifest
    34 [zot destdir="destdir"]
    35 foo/zot
    36 ; comment
    37 #ifdef baz
    38 [baz]
    39 baz@SUFFIX@
    40 #endif
    41 '''
    44 class TestPreprocessManifest(unittest.TestCase):
    45     MANIFEST_PATH = os.path.join(os.path.abspath(os.curdir), 'manifest')
    47     EXPECTED_LOG = [
    48         ((MANIFEST_PATH, 2), 'add', '', 'bar/*'),
    49         ((MANIFEST_PATH, 4), 'add', 'foo', 'foo/*'),
    50         ((MANIFEST_PATH, 5), 'remove', 'foo', 'foo/bar'),
    51         ((MANIFEST_PATH, 6), 'add', 'foo', 'chrome.manifest'),
    52         ((MANIFEST_PATH, 8), 'add', 'zot destdir="destdir"', 'foo/zot'),
    53     ]
    55     def setUp(self):
    56         class MockSink(object):
    57             def __init__(self):
    58                 self.log = []
    60             def add(self, component, path):
    61                 self._log(errors.get_context(), 'add', repr(component), path)
    63             def remove(self, component, path):
    64                 self._log(errors.get_context(), 'remove', repr(component), path)
    66             def _log(self, *args):
    67                 self.log.append(args)
    69         self.sink = MockSink()
    71     def test_preprocess_manifest(self):
    72         with MockedOpen({'manifest': MANIFEST}):
    73             preprocess_manifest(self.sink, 'manifest')
    74         self.assertEqual(self.sink.log, self.EXPECTED_LOG)
    76     def test_preprocess_manifest_missing_define(self):
    77         with MockedOpen({'manifest': MANIFEST}):
    78             self.assertRaises(
    79                 Preprocessor.Error,
    80                 preprocess_manifest,
    81                 self.sink,
    82                 'manifest',
    83                 {'baz': 1}
    84             )
    86     def test_preprocess_manifest_defines(self):
    87         with MockedOpen({'manifest': MANIFEST}):
    88             preprocess_manifest(self.sink, 'manifest',
    89                                 {'baz': 1, 'SUFFIX': '.exe'})
    90         self.assertEqual(self.sink.log, self.EXPECTED_LOG +
    91                          [((self.MANIFEST_PATH, 12), 'add', 'baz', 'baz.exe')])
    94 class MockFinder(object):
    95     def __init__(self, files):
    96         self.files = files
    97         self.log = []
    99     def find(self, path):
   100         self.log.append(path)
   101         for f in sorted(self.files):
   102             if mozpack.path.match(f, path):
   103                 yield f, self.files[f]
   105     def __iter__(self):
   106         return self.find('')
   109 class MockFormatter(object):
   110     def __init__(self):
   111         self.log = []
   113     def add_base(self, *args):
   114         self._log(errors.get_context(), 'add_base', *args)
   116     def add_manifest(self, *args):
   117         self._log(errors.get_context(), 'add_manifest', *args)
   119     def add_interfaces(self, *args):
   120         self._log(errors.get_context(), 'add_interfaces', *args)
   122     def add(self, *args):
   123         self._log(errors.get_context(), 'add', *args)
   125     def _log(self, *args):
   126         self.log.append(args)
   129 class TestSimplePackager(unittest.TestCase):
   130     def test_simple_packager(self):
   131         class GeneratedFileWithPath(GeneratedFile):
   132             def __init__(self, path, content):
   133                 GeneratedFile.__init__(self, content)
   134                 self.path = path
   136         formatter = MockFormatter()
   137         packager = SimplePackager(formatter)
   138         curdir = os.path.abspath(os.curdir)
   139         file = GeneratedFileWithPath(os.path.join(curdir, 'foo',
   140                                                   'bar.manifest'),
   141                                      'resource bar bar/\ncontent bar bar/')
   142         with errors.context('manifest', 1):
   143             packager.add('foo/bar.manifest', file)
   145         file = GeneratedFileWithPath(os.path.join(curdir, 'foo',
   146                                                   'baz.manifest'),
   147                                      'resource baz baz/')
   148         with errors.context('manifest', 2):
   149             packager.add('bar/baz.manifest', file)
   151         with errors.context('manifest', 3):
   152             packager.add('qux/qux.manifest',
   153                          GeneratedFile('resource qux qux/'))
   154         bar_xpt = GeneratedFile('bar.xpt')
   155         qux_xpt = GeneratedFile('qux.xpt')
   156         foo_html = GeneratedFile('foo_html')
   157         bar_html = GeneratedFile('bar_html')
   158         with errors.context('manifest', 4):
   159             packager.add('foo/bar.xpt', bar_xpt)
   160         with errors.context('manifest', 5):
   161             packager.add('foo/bar/foo.html', foo_html)
   162             packager.add('foo/bar/bar.html', bar_html)
   164         file = GeneratedFileWithPath(os.path.join(curdir, 'foo.manifest'),
   165                                      ''.join([
   166                                          'manifest foo/bar.manifest\n',
   167                                          'manifest bar/baz.manifest\n',
   168                                      ]))
   169         with errors.context('manifest', 6):
   170             packager.add('foo.manifest', file)
   171         with errors.context('manifest', 7):
   172             packager.add('foo/qux.xpt', qux_xpt)
   174         self.assertEqual(formatter.log, [])
   176         with errors.context('dummy', 1):
   177             packager.close()
   178         self.maxDiff = None
   179         # The formatter is expected to reorder the manifest entries so that
   180         # chrome entries appear before the others.
   181         self.assertEqual(formatter.log, [
   182             (('dummy', 1), 'add_base', 'qux'),
   183             ((os.path.join(curdir, 'foo', 'bar.manifest'), 2),
   184              'add_manifest', ManifestContent('foo', 'bar', 'bar/')),
   185             ((os.path.join(curdir, 'foo', 'bar.manifest'), 1),
   186              'add_manifest', ManifestResource('foo', 'bar', 'bar/')),
   187             (('bar/baz.manifest', 1),
   188              'add_manifest', ManifestResource('bar', 'baz', 'baz/')),
   189             (('qux/qux.manifest', 1),
   190              'add_manifest', ManifestResource('qux', 'qux', 'qux/')),
   191             (('manifest', 4), 'add_interfaces', 'foo/bar.xpt', bar_xpt),
   192             (('manifest', 7), 'add_interfaces', 'foo/qux.xpt', qux_xpt),
   193             (('manifest', 5), 'add', 'foo/bar/foo.html', foo_html),
   194             (('manifest', 5), 'add', 'foo/bar/bar.html', bar_html),
   195         ])
   197         self.assertEqual(packager.get_bases(), set(['', 'qux']))
   200 class TestSimpleManifestSink(unittest.TestCase):
   201     def test_simple_manifest_parser(self):
   202         formatter = MockFormatter()
   203         foobar = GeneratedFile('foobar')
   204         foobaz = GeneratedFile('foobaz')
   205         fooqux = GeneratedFile('fooqux')
   206         foozot = GeneratedFile('foozot')
   207         finder = MockFinder({
   208             'bin/foo/bar': foobar,
   209             'bin/foo/baz': foobaz,
   210             'bin/foo/qux': fooqux,
   211             'bin/foo/zot': foozot,
   212             'bin/foo/chrome.manifest': GeneratedFile('resource foo foo/'),
   213             'bin/chrome.manifest':
   214             GeneratedFile('manifest foo/chrome.manifest'),
   215         })
   216         parser = SimpleManifestSink(finder, formatter)
   217         component0 = Component('component0')
   218         component1 = Component('component1')
   219         component2 = Component('component2', destdir='destdir')
   220         parser.add(component0, 'bin/foo/b*')
   221         parser.add(component1, 'bin/foo/qux')
   222         parser.add(component1, 'bin/foo/chrome.manifest')
   223         parser.add(component2, 'bin/foo/zot')
   224         self.assertRaises(ErrorMessage, parser.add, 'component1', 'bin/bar')
   226         self.assertEqual(formatter.log, [])
   227         parser.close()
   228         self.assertEqual(formatter.log, [
   229             (('foo/chrome.manifest', 1),
   230              'add_manifest', ManifestResource('foo', 'foo', 'foo/')),
   231             (None, 'add', 'foo/bar', foobar),
   232             (None, 'add', 'foo/baz', foobaz),
   233             (None, 'add', 'foo/qux', fooqux),
   234             (None, 'add', 'destdir/foo/zot', foozot),
   235         ])
   237         self.assertEqual(finder.log, [
   238             'bin/foo/b*',
   239             'bin/foo/qux',
   240             'bin/foo/chrome.manifest',
   241             'bin/foo/zot',
   242             'bin/bar',
   243             'bin/chrome.manifest'
   244         ])
   247 class TestCallDeque(unittest.TestCase):
   248     def test_call_deque(self):
   249         class Logger(object):
   250             def __init__(self):
   251                 self._log = []
   253             def log(self, str):
   254                 self._log.append(str)
   256             @staticmethod
   257             def staticlog(logger, str):
   258                 logger.log(str)
   260         def do_log(logger, str):
   261             logger.log(str)
   263         logger = Logger()
   264         d = CallDeque()
   265         d.append(logger.log, 'foo')
   266         d.append(logger.log, 'bar')
   267         d.append(logger.staticlog, logger, 'baz')
   268         d.append(do_log, logger, 'qux')
   269         self.assertEqual(logger._log, [])
   270         d.execute()
   271         self.assertEqual(logger._log, ['foo', 'bar', 'baz', 'qux'])
   274 class TestComponent(unittest.TestCase):
   275     def do_split(self, string, name, options):
   276         n, o = Component._split_component_and_options(string)
   277         self.assertEqual(name, n)
   278         self.assertEqual(options, o)
   280     def test_component_split_component_and_options(self):
   281         self.do_split('component', 'component', {})
   282         self.do_split('trailingspace ', 'trailingspace', {})
   283         self.do_split(' leadingspace', 'leadingspace', {})
   284         self.do_split(' trim ', 'trim', {})
   285         self.do_split(' trim key="value"', 'trim', {'key':'value'})
   286         self.do_split(' trim empty=""', 'trim', {'empty':''})
   287         self.do_split(' trim space=" "', 'trim', {'space':' '})
   288         self.do_split('component key="value"  key2="second" ',
   289                       'component', {'key':'value', 'key2':'second'})
   290         self.do_split( 'trim key="  value with spaces   "  key2="spaces again"',
   291                        'trim', {'key':'  value with spaces   ', 'key2': 'spaces again'})
   293     def do_split_error(self, string):
   294         self.assertRaises(ValueError, Component._split_component_and_options, string)
   296     def test_component_split_component_and_options_errors(self):
   297         self.do_split_error('"component')
   298         self.do_split_error('comp"onent')
   299         self.do_split_error('component"')
   300         self.do_split_error('"component"')
   301         self.do_split_error('=component')
   302         self.do_split_error('comp=onent')
   303         self.do_split_error('component=')
   304         self.do_split_error('key="val"')
   305         self.do_split_error('component key=')
   306         self.do_split_error('component key="val')
   307         self.do_split_error('component key=val"')
   308         self.do_split_error('component key="val" x')
   309         self.do_split_error('component x key="val"')
   310         self.do_split_error('component key1="val" x key2="val"')
   312     def do_from_string(self, string, name, destdir=''):
   313         component = Component.from_string(string)
   314         self.assertEqual(name, component.name)
   315         self.assertEqual(destdir, component.destdir)
   317     def test_component_from_string(self):
   318         self.do_from_string('component', 'component')
   319         self.do_from_string('component-with-hyphen', 'component-with-hyphen')
   320         self.do_from_string('component destdir="foo/bar"', 'component', 'foo/bar')
   321         self.do_from_string('component destdir="bar spc"', 'component', 'bar spc')
   322         self.assertRaises(ErrorMessage, Component.from_string, '')
   323         self.assertRaises(ErrorMessage, Component.from_string, 'component novalue=')
   324         self.assertRaises(ErrorMessage, Component.from_string, 'component badoption=badvalue')
   327 if __name__ == '__main__':
   328     mozunit.main()

mercurial