fune/python/mozbuild/mozpack/test/test_packager_formats.py
Cristian Tuns c1b52fd95e Backed out 5 changesets (bug 1811850) for causing linting bustages(bugzilla) CLOSED TREE
Backed out changeset e8fcfc7f8108 (bug 1811850)
Backed out changeset f8950d716c9e (bug 1811850)
Backed out changeset f650123cc188 (bug 1811850)
Backed out changeset d96f90c2c58b (bug 1811850)
Backed out changeset c3b0f9666183 (bug 1811850)
2023-03-16 22:16:30 -04:00

536 lines
19 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 unittest
from itertools import chain
import mozpack.path as mozpath
import mozunit
import six
from mozpack.chrome.manifest import (
ManifestBinaryComponent,
ManifestComponent,
ManifestContent,
ManifestLocale,
ManifestResource,
ManifestSkin,
)
from mozpack.copier import FileRegistry
from mozpack.errors import ErrorMessage
from mozpack.files import GeneratedFile, ManifestFile
from mozpack.packager.formats import FlatFormatter, JarFormatter, OmniJarFormatter
from mozpack.test.test_files import bar_xpt, foo2_xpt, foo_xpt
from test_errors import TestErrors
CONTENTS = {
"bases": {
# base_path: is_addon?
"": False,
"app": False,
"addon0": "unpacked",
"addon1": True,
"app/chrome/addons/addon2": 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", "addon0", "foo/bar/"),
ManifestContent("addon1/chrome", "addon1", "foo/bar/"),
ManifestContent("app/chrome/addons/addon2/chrome", "addon2", "foo/bar/"),
],
"files": {
"chrome/f/oo/bar/baz": GeneratedFile(b"foobarbaz"),
"chrome/f/oo/baz": GeneratedFile(b"foobaz"),
"chrome/f/oo/qux": GeneratedFile(b"fooqux"),
"components/foo.so": GeneratedFile(b"foo.so"),
"components/foo.xpt": foo_xpt,
"components/bar.xpt": bar_xpt,
"foo": GeneratedFile(b"foo"),
"app/chrome/foo/foo": GeneratedFile(b"appfoo"),
"app/components/foo.js": GeneratedFile(b"foo.js"),
"addon0/chrome/foo/bar/baz": GeneratedFile(b"foobarbaz"),
"addon0/components/foo.xpt": foo2_xpt,
"addon0/components/bar.xpt": bar_xpt,
"addon1/chrome/foo/bar/baz": GeneratedFile(b"foobarbaz"),
"addon1/components/foo.xpt": foo2_xpt,
"addon1/components/bar.xpt": bar_xpt,
"app/chrome/addons/addon2/chrome/foo/bar/baz": GeneratedFile(b"foobarbaz"),
"app/chrome/addons/addon2/components/foo.xpt": foo2_xpt,
"app/chrome/addons/addon2/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 bar.xpt",
"interfaces foo.xpt",
],
"components/foo.so": FILES["components/foo.so"],
"components/foo.xpt": foo_xpt,
"components/bar.xpt": bar_xpt,
"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", "app/chrome/addons/addon2"):
RESULT_FLAT.update(
{
mozpath.join(addon, p): f
for p, f in six.iteritems(
{
"chrome.manifest": [
"manifest chrome/chrome.manifest",
"manifest components/components.manifest",
],
"chrome/chrome.manifest": [
"content %s foo/bar/" % mozpath.basename(addon),
],
"chrome/foo/bar/baz": FILES[
mozpath.join(addon, "chrome/foo/bar/baz")
],
"components/components.manifest": [
"interfaces bar.xpt",
"interfaces foo.xpt",
],
"components/bar.xpt": bar_xpt,
"components/foo.xpt": foo2_xpt,
}
)
}
)
RESULT_JAR = {
p: RESULT_FLAT[p]
for p in (
"chrome.manifest",
"chrome/chrome.manifest",
"components/components.manifest",
"components/foo.so",
"components/foo.xpt",
"components/bar.xpt",
"foo",
"app/chrome.manifest",
"app/components/components.manifest",
"app/components/foo.js",
"addon0/chrome.manifest",
"addon0/components/components.manifest",
"addon0/components/foo.xpt",
"addon0/components/bar.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 addon0 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 six.iteritems(RESULT_FLAT)
if p.startswith("addon1/")
},
"app/chrome/addons/addon2.xpi": {
mozpath.relpath(p, "app/chrome/addons/addon2"): f
for p, f in six.iteritems(RESULT_FLAT)
if p.startswith("app/chrome/addons/addon2/")
},
}
)
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 bar.xpt",
"interfaces foo.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 chain(
(
"chrome.manifest",
"chrome/chrome.manifest",
"chrome/foo/foo",
"components/components.manifest",
"components/foo.js",
),
(
mozpath.relpath(p, "app")
for p in six.iterkeys(RESULT_FLAT)
if p.startswith("app/chrome/addons/addon2/")
),
)
},
}
)
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/foo.xpt",
"components/bar.xpt",
)
}
)
RESULT_OMNIJAR_WITH_SUBPATH = {
k.replace("omni.foo", "bar/omni.foo"): v for k, v in RESULT_OMNIJAR.items()
}
CONTENTS_WITH_BASE = {
"bases": {
mozpath.join("base/root", b) if b else "base/root": a
for b, a in six.iteritems(CONTENTS["bases"])
},
"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 six.iteritems(CONTENTS["files"])
},
}
EXTRA_CONTENTS = {
"extra/file": GeneratedFile(b"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 six.iteritems(results)}
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)
def fill_formatter(formatter, contents):
for base, is_addon in sorted(contents["bases"].items()):
formatter.add_base(base, is_addon)
for manifest in contents["manifests"]:
formatter.add_manifest(manifest)
for k, v in sorted(six.iteritems(contents["files"])):
if k.endswith(".xpt"):
formatter.add_interfaces(k, v)
else:
formatter.add(k, v)
def get_contents(registry, read_all=False, mode="rt"):
result = {}
for k, v in registry:
if isinstance(v, FileRegistry):
result[k] = get_contents(v)
elif isinstance(v, ManifestFile) or read_all:
if "b" in mode:
result[k] = v.open().read()
else:
result[k] = six.ensure_text(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("addon0", addon=True)
formatter.add_base("browser")
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_formatter_with_subpath(self):
registry = FileRegistry()
formatter = OmniJarFormatter(registry, "bar/omni.foo")
fill_formatter(formatter, CONTENTS)
self.assertEqual(get_contents(registry), RESULT_OMNIJAR_WITH_SUBPATH)
self.do_test_contents(formatter, CONTENTS)
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(b""))
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(
str(e.exception),
'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(
str(e.exception),
'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(
str(e.exception),
'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(
str(e.exception),
'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(
str(e.exception),
'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()