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/.
4
5from __future__ import absolute_import, print_function, unicode_literals
6
7import unittest
8import mozunit
9import os
10from mozpack.chrome.manifest import (
11    ManifestContent,
12    ManifestLocale,
13    ManifestSkin,
14    Manifest,
15    ManifestResource,
16    ManifestOverride,
17    ManifestComponent,
18    ManifestContract,
19    ManifestInterfaces,
20    ManifestBinaryComponent,
21    ManifestCategory,
22    ManifestStyle,
23    ManifestOverlay,
24    MANIFESTS_TYPES,
25    parse_manifest,
26    parse_manifest_line,
27)
28from mozpack.errors import errors, AccumulatedErrors
29from test_errors import TestErrors
30
31
32class TestManifest(unittest.TestCase):
33    def test_parse_manifest(self):
34        manifest = [
35            'content global content/global/',
36            'content global content/global/ application=foo application=bar' +
37            ' platform',
38            'locale global en-US content/en-US/',
39            'locale global en-US content/en-US/ application=foo',
40            'skin global classic/1.0 content/skin/classic/',
41            'skin global classic/1.0 content/skin/classic/ application=foo' +
42            ' os=WINNT',
43            '',
44            'manifest pdfjs/chrome.manifest',
45            'resource gre-resources toolkit/res/',
46            'override chrome://global/locale/netError.dtd' +
47            ' chrome://browser/locale/netError.dtd',
48            '# Comment',
49            'component {b2bba4df-057d-41ea-b6b1-94a10a8ede68} foo.js',
50            'contract @mozilla.org/foo;1' +
51            ' {b2bba4df-057d-41ea-b6b1-94a10a8ede68}',
52            'interfaces foo.xpt',
53            'binary-component bar.so',
54            'category command-line-handler m-browser' +
55            ' @mozilla.org/browser/clh;1' +
56            ' application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}',
57            'style chrome://global/content/viewSource.xul' +
58            ' chrome://browser/skin/',
59            'overlay chrome://global/content/viewSource.xul' +
60            ' chrome://browser/content/viewSourceOverlay.xul',
61        ]
62        other_manifest = [
63            'content global content/global/'
64        ]
65        expected_result = [
66            ManifestContent('', 'global', 'content/global/'),
67            ManifestContent('', 'global', 'content/global/', 'application=foo',
68                            'application=bar', 'platform'),
69            ManifestLocale('', 'global', 'en-US', 'content/en-US/'),
70            ManifestLocale('', 'global', 'en-US', 'content/en-US/',
71                           'application=foo'),
72            ManifestSkin('', 'global', 'classic/1.0', 'content/skin/classic/'),
73            ManifestSkin('', 'global', 'classic/1.0', 'content/skin/classic/',
74                         'application=foo', 'os=WINNT'),
75            Manifest('', 'pdfjs/chrome.manifest'),
76            ManifestResource('', 'gre-resources', 'toolkit/res/'),
77            ManifestOverride('', 'chrome://global/locale/netError.dtd',
78                             'chrome://browser/locale/netError.dtd'),
79            ManifestComponent('', '{b2bba4df-057d-41ea-b6b1-94a10a8ede68}',
80                              'foo.js'),
81            ManifestContract('', '@mozilla.org/foo;1',
82                             '{b2bba4df-057d-41ea-b6b1-94a10a8ede68}'),
83            ManifestInterfaces('', 'foo.xpt'),
84            ManifestBinaryComponent('', 'bar.so'),
85            ManifestCategory('', 'command-line-handler', 'm-browser',
86                             '@mozilla.org/browser/clh;1', 'application=' +
87                             '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}'),
88            ManifestStyle('', 'chrome://global/content/viewSource.xul',
89                          'chrome://browser/skin/'),
90            ManifestOverlay('', 'chrome://global/content/viewSource.xul',
91                            'chrome://browser/content/viewSourceOverlay.xul'),
92        ]
93        with mozunit.MockedOpen({'manifest': '\n'.join(manifest),
94                                 'other/manifest': '\n'.join(other_manifest)}):
95            # Ensure we have tests for all types of manifests.
96            self.assertEqual(set(type(e) for e in expected_result),
97                             set(MANIFESTS_TYPES.values()))
98            self.assertEqual(list(parse_manifest(os.curdir, 'manifest')),
99                             expected_result)
100            self.assertEqual(list(parse_manifest(os.curdir, 'other/manifest')),
101                             [ManifestContent('other', 'global',
102                                              'content/global/')])
103
104    def test_manifest_rebase(self):
105        m = parse_manifest_line('chrome', 'content global content/global/')
106        m = m.rebase('')
107        self.assertEqual(str(m), 'content global chrome/content/global/')
108        m = m.rebase('chrome')
109        self.assertEqual(str(m), 'content global content/global/')
110
111        m = parse_manifest_line('chrome/foo', 'content global content/global/')
112        m = m.rebase('chrome')
113        self.assertEqual(str(m), 'content global foo/content/global/')
114        m = m.rebase('chrome/foo')
115        self.assertEqual(str(m), 'content global content/global/')
116
117        m = parse_manifest_line('modules/foo', 'resource foo ./')
118        m = m.rebase('modules')
119        self.assertEqual(str(m), 'resource foo foo/')
120        m = m.rebase('modules/foo')
121        self.assertEqual(str(m), 'resource foo ./')
122
123        m = parse_manifest_line('chrome', 'content browser browser/content/')
124        m = m.rebase('chrome/browser').move('jar:browser.jar!').rebase('')
125        self.assertEqual(str(m), 'content browser jar:browser.jar!/content/')
126
127
128class TestManifestErrors(TestErrors, unittest.TestCase):
129    def test_parse_manifest_errors(self):
130        manifest = [
131            'skin global classic/1.0 content/skin/classic/ platform',
132            '',
133            'binary-component bar.so',
134            'unsupported foo',
135        ]
136        with mozunit.MockedOpen({'manifest': '\n'.join(manifest)}):
137            with self.assertRaises(AccumulatedErrors):
138                with errors.accumulate():
139                    list(parse_manifest(os.curdir, 'manifest'))
140            out = self.get_output()
141            # Expecting 2 errors
142            self.assertEqual(len(out), 2)
143            path = os.path.abspath('manifest')
144            # First on line 1
145            self.assertTrue(out[0].startswith('Error: %s:1: ' % path))
146            # Second on line 4
147            self.assertTrue(out[1].startswith('Error: %s:4: ' % path))
148
149
150if __name__ == '__main__':
151    mozunit.main()
152