mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
b860fe5648
--HG-- extra : rebase_source : 0db515433e1e5dacaf6be0c0921af060c3ad644d
510 lines
17 KiB
Python
510 lines
17 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
import mozunit
|
|
import unittest
|
|
from mozpack.packager.formats import (
|
|
FlatFormatter,
|
|
JarFormatter,
|
|
OmniJarFormatter,
|
|
)
|
|
from mozpack.copier import FileRegistry
|
|
from mozpack.files import (
|
|
GeneratedFile,
|
|
ManifestFile,
|
|
)
|
|
from mozpack.chrome.manifest import (
|
|
ManifestContent,
|
|
ManifestComponent,
|
|
ManifestResource,
|
|
ManifestBinaryComponent,
|
|
ManifestSkin,
|
|
ManifestLocale,
|
|
)
|
|
from mozpack.errors import (
|
|
errors,
|
|
ErrorMessage,
|
|
)
|
|
from mozpack.test.test_files import (
|
|
MockDest,
|
|
foo_xpt,
|
|
foo2_xpt,
|
|
bar_xpt,
|
|
read_interfaces,
|
|
)
|
|
import mozpack.path as mozpath
|
|
from test_errors import TestErrors
|
|
|
|
|
|
CONTENTS = {
|
|
'bases': {
|
|
# base_path: is_addon?
|
|
'': False,
|
|
'app': False,
|
|
'addon0': 'unpacked',
|
|
'addon1': True,
|
|
},
|
|
'manifests': [
|
|
ManifestContent('chrome/f', 'oo', 'oo/'),
|
|
ManifestContent('chrome/f', 'bar', 'oo/bar/'),
|
|
ManifestResource('chrome/f', 'foo', 'resource://bar/'),
|
|
ManifestBinaryComponent('components', 'foo.so'),
|
|
ManifestContent('app/chrome', 'content', 'foo/'),
|
|
ManifestComponent('app/components', '{foo-id}', 'foo.js'),
|
|
ManifestContent('addon0/chrome', 'content', 'foo/bar/'),
|
|
ManifestContent('addon1/chrome', 'content', 'foo/bar/'),
|
|
],
|
|
'files': {
|
|
'chrome/f/oo/bar/baz': GeneratedFile('foobarbaz'),
|
|
'chrome/f/oo/baz': GeneratedFile('foobaz'),
|
|
'chrome/f/oo/qux': GeneratedFile('fooqux'),
|
|
'components/foo.so': GeneratedFile('foo.so'),
|
|
'components/foo.xpt': foo_xpt,
|
|
'components/bar.xpt': bar_xpt,
|
|
'foo': GeneratedFile('foo'),
|
|
'app/chrome/foo/foo': GeneratedFile('appfoo'),
|
|
'app/components/foo.js': GeneratedFile('foo.js'),
|
|
'addon0/chrome/foo/bar/baz': GeneratedFile('foobarbaz'),
|
|
'addon0/components/foo.xpt': foo2_xpt,
|
|
'addon0/components/bar.xpt': bar_xpt,
|
|
'addon1/chrome/foo/bar/baz': GeneratedFile('foobarbaz'),
|
|
'addon1/components/foo.xpt': foo2_xpt,
|
|
'addon1/components/bar.xpt': bar_xpt,
|
|
},
|
|
}
|
|
|
|
FILES = CONTENTS['files']
|
|
|
|
RESULT_FLAT = {
|
|
'chrome.manifest': [
|
|
'manifest chrome/chrome.manifest',
|
|
'manifest components/components.manifest',
|
|
],
|
|
'chrome/chrome.manifest': [
|
|
'manifest f/f.manifest',
|
|
],
|
|
'chrome/f/f.manifest': [
|
|
'content oo oo/',
|
|
'content bar oo/bar/',
|
|
'resource foo resource://bar/',
|
|
],
|
|
'chrome/f/oo/bar/baz': FILES['chrome/f/oo/bar/baz'],
|
|
'chrome/f/oo/baz': FILES['chrome/f/oo/baz'],
|
|
'chrome/f/oo/qux': FILES['chrome/f/oo/qux'],
|
|
'components/components.manifest': [
|
|
'binary-component foo.so',
|
|
'interfaces interfaces.xpt',
|
|
],
|
|
'components/foo.so': FILES['components/foo.so'],
|
|
'components/interfaces.xpt': {
|
|
'foo': read_interfaces(foo_xpt.open())['foo'],
|
|
'bar': read_interfaces(bar_xpt.open())['bar'],
|
|
},
|
|
'foo': FILES['foo'],
|
|
'app/chrome.manifest': [
|
|
'manifest chrome/chrome.manifest',
|
|
'manifest components/components.manifest',
|
|
],
|
|
'app/chrome/chrome.manifest': [
|
|
'content content foo/',
|
|
],
|
|
'app/chrome/foo/foo': FILES['app/chrome/foo/foo'],
|
|
'app/components/components.manifest': [
|
|
'component {foo-id} foo.js',
|
|
],
|
|
'app/components/foo.js': FILES['app/components/foo.js'],
|
|
}
|
|
|
|
for addon in ('addon0', 'addon1'):
|
|
RESULT_FLAT.update({
|
|
mozpath.join(addon, p): f
|
|
for p, f in {
|
|
'chrome.manifest': [
|
|
'manifest chrome/chrome.manifest',
|
|
'manifest components/components.manifest',
|
|
],
|
|
'chrome/chrome.manifest': [
|
|
'content content foo/bar/',
|
|
],
|
|
'chrome/foo/bar/baz': FILES[mozpath.join(addon, 'chrome/foo/bar/baz')],
|
|
'components/components.manifest': [
|
|
'interfaces interfaces.xpt',
|
|
],
|
|
'components/interfaces.xpt': {
|
|
'foo': read_interfaces(foo2_xpt.open())['foo'],
|
|
'bar': read_interfaces(bar_xpt.open())['bar'],
|
|
},
|
|
}.iteritems()
|
|
})
|
|
|
|
RESULT_JAR = {
|
|
p: RESULT_FLAT[p]
|
|
for p in (
|
|
'chrome.manifest',
|
|
'chrome/chrome.manifest',
|
|
'components/components.manifest',
|
|
'components/foo.so',
|
|
'components/interfaces.xpt',
|
|
'foo',
|
|
'app/chrome.manifest',
|
|
'app/components/components.manifest',
|
|
'app/components/foo.js',
|
|
'addon0/chrome.manifest',
|
|
'addon0/components/components.manifest',
|
|
'addon0/components/interfaces.xpt',
|
|
)
|
|
}
|
|
|
|
RESULT_JAR.update({
|
|
'chrome/f/f.manifest': [
|
|
'content oo jar:oo.jar!/',
|
|
'content bar jar:oo.jar!/bar/',
|
|
'resource foo resource://bar/',
|
|
],
|
|
'chrome/f/oo.jar': {
|
|
'bar/baz': FILES['chrome/f/oo/bar/baz'],
|
|
'baz': FILES['chrome/f/oo/baz'],
|
|
'qux': FILES['chrome/f/oo/qux'],
|
|
},
|
|
'app/chrome/chrome.manifest': [
|
|
'content content jar:foo.jar!/',
|
|
],
|
|
'app/chrome/foo.jar': {
|
|
'foo': FILES['app/chrome/foo/foo'],
|
|
},
|
|
'addon0/chrome/chrome.manifest': [
|
|
'content content jar:foo.jar!/bar/',
|
|
],
|
|
'addon0/chrome/foo.jar': {
|
|
'bar/baz': FILES['addon0/chrome/foo/bar/baz'],
|
|
},
|
|
'addon1.xpi': {
|
|
mozpath.relpath(p, 'addon1'): f
|
|
for p, f in RESULT_FLAT.iteritems()
|
|
if p.startswith('addon1/')
|
|
},
|
|
})
|
|
|
|
RESULT_OMNIJAR = {
|
|
p: RESULT_FLAT[p]
|
|
for p in (
|
|
'components/foo.so',
|
|
'foo',
|
|
)
|
|
}
|
|
|
|
RESULT_OMNIJAR.update({
|
|
p: RESULT_JAR[p]
|
|
for p in RESULT_JAR
|
|
if p.startswith('addon')
|
|
})
|
|
|
|
RESULT_OMNIJAR.update({
|
|
'omni.foo': {
|
|
'components/components.manifest': [
|
|
'interfaces interfaces.xpt',
|
|
],
|
|
},
|
|
'chrome.manifest': [
|
|
'manifest components/components.manifest',
|
|
],
|
|
'components/components.manifest': [
|
|
'binary-component foo.so',
|
|
],
|
|
'app/omni.foo': {
|
|
p: RESULT_FLAT['app/' + p]
|
|
for p in (
|
|
'chrome.manifest',
|
|
'chrome/chrome.manifest',
|
|
'chrome/foo/foo',
|
|
'components/components.manifest',
|
|
'components/foo.js',
|
|
)
|
|
},
|
|
'app/chrome.manifest': [],
|
|
})
|
|
|
|
RESULT_OMNIJAR['omni.foo'].update({
|
|
p: RESULT_FLAT[p]
|
|
for p in (
|
|
'chrome.manifest',
|
|
'chrome/chrome.manifest',
|
|
'chrome/f/f.manifest',
|
|
'chrome/f/oo/bar/baz',
|
|
'chrome/f/oo/baz',
|
|
'chrome/f/oo/qux',
|
|
'components/interfaces.xpt',
|
|
)
|
|
})
|
|
|
|
CONTENTS_WITH_BASE = {
|
|
'bases': {
|
|
mozpath.join('base/root', b) if b else 'base/root': a
|
|
for b, a in CONTENTS['bases'].iteritems()
|
|
},
|
|
'manifests': [
|
|
m.move(mozpath.join('base/root', m.base))
|
|
for m in CONTENTS['manifests']
|
|
],
|
|
'files': {
|
|
mozpath.join('base/root', p): f
|
|
for p, f in CONTENTS['files'].iteritems()
|
|
},
|
|
}
|
|
|
|
EXTRA_CONTENTS = {
|
|
'extra/file': GeneratedFile('extra file'),
|
|
}
|
|
|
|
CONTENTS_WITH_BASE['files'].update(EXTRA_CONTENTS)
|
|
|
|
def result_with_base(results):
|
|
result = {
|
|
mozpath.join('base/root', p): v
|
|
for p, v in results.iteritems()
|
|
}
|
|
result.update(EXTRA_CONTENTS)
|
|
return result
|
|
|
|
RESULT_FLAT_WITH_BASE = result_with_base(RESULT_FLAT)
|
|
RESULT_JAR_WITH_BASE = result_with_base(RESULT_JAR)
|
|
RESULT_OMNIJAR_WITH_BASE = result_with_base(RESULT_OMNIJAR)
|
|
|
|
|
|
class MockDest(MockDest):
|
|
def exists(self):
|
|
return False
|
|
|
|
|
|
def fill_formatter(formatter, contents):
|
|
for base, is_addon in contents['bases'].items():
|
|
formatter.add_base(base, is_addon)
|
|
|
|
for manifest in contents['manifests']:
|
|
formatter.add_manifest(manifest)
|
|
|
|
for k, v in contents['files'].iteritems():
|
|
if k.endswith('.xpt'):
|
|
formatter.add_interfaces(k, v)
|
|
else:
|
|
formatter.add(k, v)
|
|
|
|
|
|
def get_contents(registry, read_all=False):
|
|
result = {}
|
|
for k, v in registry:
|
|
if k.endswith('.xpt'):
|
|
tmpfile = MockDest()
|
|
registry[k].copy(tmpfile)
|
|
result[k] = read_interfaces(tmpfile)
|
|
elif isinstance(v, FileRegistry):
|
|
result[k] = get_contents(v)
|
|
elif isinstance(v, ManifestFile) or read_all:
|
|
result[k] = v.open().read().splitlines()
|
|
else:
|
|
result[k] = v
|
|
return result
|
|
|
|
|
|
class TestFormatters(TestErrors, unittest.TestCase):
|
|
maxDiff = None
|
|
|
|
def test_bases(self):
|
|
formatter = FlatFormatter(FileRegistry())
|
|
formatter.add_base('')
|
|
formatter.add_base('browser')
|
|
formatter.add_base('addon0', addon=True)
|
|
self.assertEqual(formatter._get_base('platform.ini'),
|
|
('', 'platform.ini'))
|
|
self.assertEqual(formatter._get_base('browser/application.ini'),
|
|
('browser', 'application.ini'))
|
|
self.assertEqual(formatter._get_base('addon0/install.rdf'),
|
|
('addon0', 'install.rdf'))
|
|
|
|
def do_test_contents(self, formatter, contents):
|
|
for f in contents['files']:
|
|
# .xpt files are merged, so skip them.
|
|
if not f.endswith('.xpt'):
|
|
self.assertTrue(formatter.contains(f))
|
|
|
|
def test_flat_formatter(self):
|
|
registry = FileRegistry()
|
|
formatter = FlatFormatter(registry)
|
|
|
|
fill_formatter(formatter, CONTENTS)
|
|
self.assertEqual(get_contents(registry), RESULT_FLAT)
|
|
self.do_test_contents(formatter, CONTENTS)
|
|
|
|
def test_jar_formatter(self):
|
|
registry = FileRegistry()
|
|
formatter = JarFormatter(registry)
|
|
|
|
fill_formatter(formatter, CONTENTS)
|
|
self.assertEqual(get_contents(registry), RESULT_JAR)
|
|
self.do_test_contents(formatter, CONTENTS)
|
|
|
|
def test_omnijar_formatter(self):
|
|
registry = FileRegistry()
|
|
formatter = OmniJarFormatter(registry, 'omni.foo')
|
|
|
|
fill_formatter(formatter, CONTENTS)
|
|
self.assertEqual(get_contents(registry), RESULT_OMNIJAR)
|
|
self.do_test_contents(formatter, CONTENTS)
|
|
|
|
def test_flat_formatter_with_base(self):
|
|
registry = FileRegistry()
|
|
formatter = FlatFormatter(registry)
|
|
|
|
fill_formatter(formatter, CONTENTS_WITH_BASE)
|
|
self.assertEqual(get_contents(registry), RESULT_FLAT_WITH_BASE)
|
|
self.do_test_contents(formatter, CONTENTS_WITH_BASE)
|
|
|
|
def test_jar_formatter_with_base(self):
|
|
registry = FileRegistry()
|
|
formatter = JarFormatter(registry)
|
|
|
|
fill_formatter(formatter, CONTENTS_WITH_BASE)
|
|
self.assertEqual(get_contents(registry), RESULT_JAR_WITH_BASE)
|
|
self.do_test_contents(formatter, CONTENTS_WITH_BASE)
|
|
|
|
def test_omnijar_formatter_with_base(self):
|
|
registry = FileRegistry()
|
|
formatter = OmniJarFormatter(registry, 'omni.foo')
|
|
|
|
fill_formatter(formatter, CONTENTS_WITH_BASE)
|
|
self.assertEqual(get_contents(registry), RESULT_OMNIJAR_WITH_BASE)
|
|
self.do_test_contents(formatter, CONTENTS_WITH_BASE)
|
|
|
|
def test_omnijar_is_resource(self):
|
|
def is_resource(base, path):
|
|
registry = FileRegistry()
|
|
f = OmniJarFormatter(registry, 'omni.foo', non_resources=[
|
|
'defaults/messenger/mailViews.dat',
|
|
'defaults/foo/*',
|
|
'*/dummy',
|
|
])
|
|
f.add_base('')
|
|
f.add_base('app')
|
|
f.add(mozpath.join(base, path), GeneratedFile(''))
|
|
if f.copier.contains(mozpath.join(base, path)):
|
|
return False
|
|
self.assertTrue(f.copier.contains(mozpath.join(base, 'omni.foo')))
|
|
self.assertTrue(f.copier[mozpath.join(base, 'omni.foo')]
|
|
.contains(path))
|
|
return True
|
|
|
|
for base in ['', 'app/']:
|
|
self.assertTrue(is_resource(base, 'chrome'))
|
|
self.assertTrue(
|
|
is_resource(base, 'chrome/foo/bar/baz.properties'))
|
|
self.assertFalse(is_resource(base, 'chrome/icons/foo.png'))
|
|
self.assertTrue(is_resource(base, 'components/foo.js'))
|
|
self.assertFalse(is_resource(base, 'components/foo.so'))
|
|
self.assertTrue(is_resource(base, 'res/foo.css'))
|
|
self.assertFalse(is_resource(base, 'res/cursors/foo.png'))
|
|
self.assertFalse(is_resource(base, 'res/MainMenu.nib/foo'))
|
|
self.assertTrue(is_resource(base, 'defaults/pref/foo.js'))
|
|
self.assertFalse(
|
|
is_resource(base, 'defaults/pref/channel-prefs.js'))
|
|
self.assertTrue(
|
|
is_resource(base, 'defaults/preferences/foo.js'))
|
|
self.assertFalse(
|
|
is_resource(base, 'defaults/preferences/channel-prefs.js'))
|
|
self.assertTrue(is_resource(base, 'modules/foo.jsm'))
|
|
self.assertTrue(is_resource(base, 'greprefs.js'))
|
|
self.assertTrue(is_resource(base, 'hyphenation/foo'))
|
|
self.assertTrue(is_resource(base, 'update.locale'))
|
|
self.assertFalse(is_resource(base, 'foo'))
|
|
self.assertFalse(is_resource(base, 'foo/bar/greprefs.js'))
|
|
self.assertTrue(is_resource(base, 'defaults/messenger/foo.dat'))
|
|
self.assertFalse(
|
|
is_resource(base, 'defaults/messenger/mailViews.dat'))
|
|
self.assertTrue(is_resource(base, 'defaults/pref/foo.js'))
|
|
self.assertFalse(is_resource(base, 'defaults/foo/bar.dat'))
|
|
self.assertFalse(is_resource(base, 'defaults/foo/bar/baz.dat'))
|
|
self.assertTrue(is_resource(base, 'chrome/foo/bar/baz/dummy_'))
|
|
self.assertFalse(is_resource(base, 'chrome/foo/bar/baz/dummy'))
|
|
self.assertTrue(is_resource(base, 'chrome/foo/bar/dummy_'))
|
|
self.assertFalse(is_resource(base, 'chrome/foo/bar/dummy'))
|
|
|
|
def test_chrome_override(self):
|
|
registry = FileRegistry()
|
|
f = FlatFormatter(registry)
|
|
f.add_base('')
|
|
f.add_manifest(ManifestContent('chrome', 'foo', 'foo/unix'))
|
|
# A more specific entry for a given chrome name can override a more
|
|
# generic one.
|
|
f.add_manifest(ManifestContent('chrome', 'foo', 'foo/win', 'os=WINNT'))
|
|
f.add_manifest(ManifestContent('chrome', 'foo', 'foo/osx', 'os=Darwin'))
|
|
|
|
# Chrome with the same name overrides the previous registration.
|
|
with self.assertRaises(ErrorMessage) as e:
|
|
f.add_manifest(ManifestContent('chrome', 'foo', 'foo/'))
|
|
|
|
self.assertEqual(e.exception.message,
|
|
'Error: "content foo foo/" overrides '
|
|
'"content foo foo/unix"')
|
|
|
|
# Chrome with the same name and same flags overrides the previous
|
|
# registration.
|
|
with self.assertRaises(ErrorMessage) as e:
|
|
f.add_manifest(ManifestContent('chrome', 'foo', 'foo/', 'os=WINNT'))
|
|
|
|
self.assertEqual(e.exception.message,
|
|
'Error: "content foo foo/ os=WINNT" overrides '
|
|
'"content foo foo/win os=WINNT"')
|
|
|
|
# We may start with the more specific entry first
|
|
f.add_manifest(ManifestContent('chrome', 'bar', 'bar/win', 'os=WINNT'))
|
|
# Then adding a more generic one overrides it.
|
|
with self.assertRaises(ErrorMessage) as e:
|
|
f.add_manifest(ManifestContent('chrome', 'bar', 'bar/unix'))
|
|
|
|
self.assertEqual(e.exception.message,
|
|
'Error: "content bar bar/unix" overrides '
|
|
'"content bar bar/win os=WINNT"')
|
|
|
|
# Adding something more specific still works.
|
|
f.add_manifest(ManifestContent('chrome', 'bar', 'bar/win',
|
|
'os=WINNT osversion>=7.0'))
|
|
|
|
# Variations of skin/locales are allowed.
|
|
f.add_manifest(ManifestSkin('chrome', 'foo', 'classic/1.0',
|
|
'foo/skin/classic/'))
|
|
f.add_manifest(ManifestSkin('chrome', 'foo', 'modern/1.0',
|
|
'foo/skin/modern/'))
|
|
|
|
f.add_manifest(ManifestLocale('chrome', 'foo', 'en-US',
|
|
'foo/locale/en-US/'))
|
|
f.add_manifest(ManifestLocale('chrome', 'foo', 'ja-JP',
|
|
'foo/locale/ja-JP/'))
|
|
|
|
# But same-skin/locale still error out.
|
|
with self.assertRaises(ErrorMessage) as e:
|
|
f.add_manifest(ManifestSkin('chrome', 'foo', 'classic/1.0',
|
|
'foo/skin/classic/foo'))
|
|
|
|
self.assertEqual(e.exception.message,
|
|
'Error: "skin foo classic/1.0 foo/skin/classic/foo" overrides '
|
|
'"skin foo classic/1.0 foo/skin/classic/"')
|
|
|
|
with self.assertRaises(ErrorMessage) as e:
|
|
f.add_manifest(ManifestLocale('chrome', 'foo', 'en-US',
|
|
'foo/locale/en-US/foo'))
|
|
|
|
self.assertEqual(e.exception.message,
|
|
'Error: "locale foo en-US foo/locale/en-US/foo" overrides '
|
|
'"locale foo en-US foo/locale/en-US/"')
|
|
|
|
# Duplicating existing manifest entries is not an error.
|
|
f.add_manifest(ManifestContent('chrome', 'foo', 'foo/unix'))
|
|
|
|
self.assertEqual(self.get_output(), [
|
|
'Warning: "content foo foo/unix" is duplicated. Skipping.',
|
|
])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
mozunit.main()
|