addon-sdk/source/python-lib/cuddlefish/tests/test_xpi.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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 os
     6 import unittest
     7 import zipfile
     8 import pprint
     9 import shutil
    11 import simplejson as json
    12 from cuddlefish import xpi, packaging, manifest, buildJID
    13 from cuddlefish.tests import test_packaging
    14 from test_linker import up
    16 import xml.etree.ElementTree as ElementTree
    18 xpi_template_path = os.path.join(test_packaging.static_files_path,
    19                                  'xpi-template')
    21 fake_manifest = '<RDF><!-- Extension metadata is here. --></RDF>'
    23 class PrefsTests(unittest.TestCase):
    24     def makexpi(self, pkg_name):
    25         self.xpiname = "%s.xpi" % pkg_name
    26         create_xpi(self.xpiname, pkg_name, 'preferences-files')
    27         self.xpi = zipfile.ZipFile(self.xpiname, 'r')
    28         options = self.xpi.read('harness-options.json')
    29         self.xpi_harness_options = json.loads(options)
    31     def setUp(self):
    32         self.xpiname = None
    33         self.xpi = None
    35     def tearDown(self):
    36         if self.xpi:
    37             self.xpi.close()
    38         if self.xpiname and os.path.exists(self.xpiname):
    39             os.remove(self.xpiname)
    41     def testPackageWithSimplePrefs(self):
    42         self.makexpi('simple-prefs')
    43         packageName = 'jid1-fZHqN9JfrDBa8A@jetpack'
    44         self.failUnless('options.xul' in self.xpi.namelist())
    45         optsxul = self.xpi.read('options.xul').decode("utf-8")
    46         self.failUnlessEqual(self.xpi_harness_options["jetpackID"], packageName)
    47         self.failUnlessEqual(self.xpi_harness_options["preferencesBranch"], packageName)
    49         root = ElementTree.XML(optsxul.encode('utf-8'))
    51         xulNamespacePrefix = \
    52             "{http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul}"
    54         settings = root.findall(xulNamespacePrefix + 'setting')
    56         def assertPref(setting, name, prefType, title):
    57             self.failUnlessEqual(setting.get('data-jetpack-id'), packageName)
    58             self.failUnlessEqual(setting.get('pref'),
    59                                  'extensions.' + packageName + '.' + name)
    60             self.failUnlessEqual(setting.get('pref-name'), name)
    61             self.failUnlessEqual(setting.get('type'), prefType)
    62             self.failUnlessEqual(setting.get('title'), title)
    64         assertPref(settings[0], 'test', 'bool', u't\u00EBst')
    65         assertPref(settings[1], 'test2', 'string', u't\u00EBst')
    66         assertPref(settings[2], 'test3', 'menulist', '"><test')
    67         assertPref(settings[3], 'test4', 'radio', u't\u00EBst')
    69         menuItems = settings[2].findall(
    70             '%(0)smenulist/%(0)smenupopup/%(0)smenuitem' % { "0": xulNamespacePrefix })
    71         radios = settings[3].findall(
    72             '%(0)sradiogroup/%(0)sradio' % { "0": xulNamespacePrefix })
    74         def assertOption(option, value, label):
    75             self.failUnlessEqual(option.get('value'), value)
    76             self.failUnlessEqual(option.get('label'), label)
    78         assertOption(menuItems[0], "0", "label1")
    79         assertOption(menuItems[1], "1", "label2")
    80         assertOption(radios[0], "red", "rouge")
    81         assertOption(radios[1], "blue", "bleu")
    83         prefsjs = self.xpi.read('defaults/preferences/prefs.js').decode("utf-8")
    84         exp = [u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test", false);',
    85                u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test2", "\u00FCnic\u00F8d\u00E9");',
    86                u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test3", "1");',
    87                u'pref("extensions.jid1-fZHqN9JfrDBa8A@jetpack.test4", "red");',
    88                ]
    89         self.failUnlessEqual(prefsjs, "\n".join(exp)+"\n")
    91     def testPackageWithPreferencesBranch(self):
    92         self.makexpi('preferences-branch')
    93         self.failUnless('options.xul' in self.xpi.namelist())
    94         optsxul = self.xpi.read('options.xul').decode("utf-8")
    95         self.failUnlessEqual(self.xpi_harness_options["preferencesBranch"], 
    96                              "human-readable")
    98         root = ElementTree.XML(optsxul.encode('utf-8'))
    99         xulNamespacePrefix = \
   100             "{http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul}"
   102         setting = root.find(xulNamespacePrefix + 'setting')
   103         self.failUnlessEqual(setting.get('pref'),
   104                              'extensions.human-readable.test42')
   106         prefsjs = self.xpi.read('defaults/preferences/prefs.js').decode("utf-8")
   107         self.failUnlessEqual(prefsjs, 
   108                             'pref("extensions.human-readable.test42", true);\n')
   110     def testPackageWithNoPrefs(self):
   111         self.makexpi('no-prefs')
   112         self.failIf('options.xul' in self.xpi.namelist())
   113         self.failUnlessEqual(self.xpi_harness_options["jetpackID"],
   114                              "jid1-fZHqN9JfrDBa8A@jetpack")
   115         prefsjs = self.xpi.read('defaults/preferences/prefs.js').decode("utf-8")
   116         self.failUnlessEqual(prefsjs, "")
   118     def testPackageWithInvalidPreferencesBranch(self):
   119         self.makexpi('curly-id')
   120         self.failIfEqual(self.xpi_harness_options["preferencesBranch"], 
   121                          "invalid^branch*name")
   122         self.failUnlessEqual(self.xpi_harness_options["preferencesBranch"], 
   123                              "{34a1eae1-c20a-464f-9b0e-000000000000}")
   125     def testPackageWithCurlyID(self):
   126         self.makexpi('curly-id')
   127         self.failUnlessEqual(self.xpi_harness_options["jetpackID"], 
   128                              "{34a1eae1-c20a-464f-9b0e-000000000000}")
   130         self.failUnless('options.xul' in self.xpi.namelist())
   131         optsxul = self.xpi.read('options.xul').decode("utf-8")
   133         root = ElementTree.XML(optsxul.encode('utf-8'))
   134         xulNamespacePrefix = \
   135             "{http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul}"
   137         setting = root.find(xulNamespacePrefix + 'setting')
   138         self.failUnlessEqual(setting.get('pref'),
   139                              'extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13')
   141         prefsjs = self.xpi.read('defaults/preferences/prefs.js').decode("utf-8")
   142         self.failUnlessEqual(prefsjs, 
   143                             'pref("extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13", 26);\n')
   146 class Bug588119Tests(unittest.TestCase):
   147     def makexpi(self, pkg_name):
   148         self.xpiname = "%s.xpi" % pkg_name
   149         create_xpi(self.xpiname, pkg_name, 'bug-588119-files')
   150         self.xpi = zipfile.ZipFile(self.xpiname, 'r')
   151         options = self.xpi.read('harness-options.json')
   152         self.xpi_harness_options = json.loads(options)
   154     def setUp(self):
   155         self.xpiname = None
   156         self.xpi = None
   158     def tearDown(self):
   159         if self.xpi:
   160             self.xpi.close()
   161         if self.xpiname and os.path.exists(self.xpiname):
   162             os.remove(self.xpiname)
   164     def testPackageWithImplicitIcon(self):
   165         self.makexpi('implicit-icon')
   166         assert 'icon.png' in self.xpi.namelist()
   168     def testPackageWithImplicitIcon64(self):
   169         self.makexpi('implicit-icon')
   170         assert 'icon64.png' in self.xpi.namelist()
   172     def testPackageWithExplicitIcon(self):
   173         self.makexpi('explicit-icon')
   174         assert 'icon.png' in self.xpi.namelist()
   176     def testPackageWithExplicitIcon64(self):
   177         self.makexpi('explicit-icon')
   178         assert 'icon64.png' in self.xpi.namelist()
   180     def testPackageWithNoIcon(self):
   181         self.makexpi('no-icon')
   182         assert 'icon.png' not in self.xpi.namelist()
   184     def testIconPathNotInHarnessOptions(self):
   185         self.makexpi('implicit-icon')
   186         assert 'icon' not in self.xpi_harness_options
   188     def testIcon64PathNotInHarnessOptions(self):
   189         self.makexpi('implicit-icon')
   190         assert 'icon64' not in self.xpi_harness_options
   192 class ExtraHarnessOptions(unittest.TestCase):
   193     def setUp(self):
   194         self.xpiname = None
   195         self.xpi = None
   197     def tearDown(self):
   198         if self.xpi:
   199             self.xpi.close()
   200         if self.xpiname and os.path.exists(self.xpiname):
   201             os.remove(self.xpiname)
   203     def testOptions(self):
   204         pkg_name = "extra-options"
   205         self.xpiname = "%s.xpi" % pkg_name
   206         create_xpi(self.xpiname, pkg_name, "bug-669274-files",
   207                    extra_harness_options={"builderVersion": "futuristic"})
   208         self.xpi = zipfile.ZipFile(self.xpiname, 'r')
   209         options = self.xpi.read('harness-options.json')
   210         hopts = json.loads(options)
   211         self.failUnless("builderVersion" in hopts)
   212         self.failUnlessEqual(hopts["builderVersion"], "futuristic")
   214     def testBadOptionName(self):
   215         pkg_name = "extra-options"
   216         self.xpiname = "%s.xpi" % pkg_name
   217         self.failUnlessRaises(xpi.HarnessOptionAlreadyDefinedError,
   218                               create_xpi,
   219                               self.xpiname, pkg_name, "bug-669274-files",
   220                               extra_harness_options={"main": "already in use"})
   222 class SmallXPI(unittest.TestCase):
   223     def setUp(self):
   224         self.root = up(os.path.abspath(__file__), 4)
   225     def get_linker_files_dir(self, name):
   226         return os.path.join(up(os.path.abspath(__file__)), "linker-files", name)
   227     def get_pkg(self, name):
   228         d = self.get_linker_files_dir(name)
   229         return packaging.get_config_in_dir(d)
   231     def get_basedir(self):
   232         return os.path.join(".test_tmp", self.id())
   233     def make_basedir(self):
   234         basedir = self.get_basedir()
   235         if os.path.isdir(basedir):
   236             here = os.path.abspath(os.getcwd())
   237             assert os.path.abspath(basedir).startswith(here) # safety
   238             shutil.rmtree(basedir)
   239         os.makedirs(basedir)
   240         return basedir
   242     def test_contents(self):
   243         target_cfg = self.get_pkg("three")
   244         package_path = [self.get_linker_files_dir("three-deps")]
   245         pkg_cfg = packaging.build_config(self.root, target_cfg,
   246                                          packagepath=package_path)
   247         deps = packaging.get_deps_for_targets(pkg_cfg,
   248                                               [target_cfg.name, "addon-sdk"])
   249         addon_sdk_dir = pkg_cfg.packages["addon-sdk"].lib[0]
   250         m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False)
   251         used_files = list(m.get_used_files(True))
   252         here = up(os.path.abspath(__file__))
   253         def absify(*parts):
   254             fn = os.path.join(here, "linker-files", *parts)
   255             return os.path.abspath(fn)
   256         expected = [absify(*parts) for parts in
   257                     [("three", "lib", "main.js"),
   258                      ("three-deps", "three-a", "lib", "main.js"),
   259                      ("three-deps", "three-a", "lib", "subdir", "subfile.js"),
   260                      ("three", "data", "msg.txt"),
   261                      ("three", "data", "subdir", "submsg.txt"),
   262                      ("three-deps", "three-b", "lib", "main.js"),
   263                      ("three-deps", "three-c", "lib", "main.js"),
   264                      ("three-deps", "three-c", "lib", "sub", "foo.js")
   265                      ]]
   267         add_addon_sdk= lambda path: os.path.join(addon_sdk_dir, path)
   268         expected.extend([add_addon_sdk(module) for module in [
   269             os.path.join("sdk", "self.js"),
   270             os.path.join("sdk", "core", "promise.js"),
   271             os.path.join("sdk", "net", "url.js"),
   272             os.path.join("sdk", "util", "object.js"),
   273             os.path.join("sdk", "util", "array.js")
   274             ]])
   276         missing = set(expected) - set(used_files)
   277         extra = set(used_files) - set(expected)
   279         self.failUnlessEqual(list(missing), [])
   280         self.failUnlessEqual(list(extra), [])
   281         used_deps = m.get_used_packages()
   283         build = packaging.generate_build_for_target(pkg_cfg, target_cfg.name,
   284                                                     used_deps,
   285                                                     include_tests=False)
   286         options = {'main': target_cfg.main}
   287         options.update(build)
   288         basedir = self.make_basedir()
   289         xpi_name = os.path.join(basedir, "contents.xpi")
   290         xpi.build_xpi(template_root_dir=xpi_template_path,
   291                       manifest=fake_manifest,
   292                       xpi_path=xpi_name,
   293                       harness_options=options,
   294                       limit_to=used_files)
   295         x = zipfile.ZipFile(xpi_name, "r")
   296         names = x.namelist()
   297         expected = ["components/",
   298                     "components/harness.js",
   299                     # the real template also has 'bootstrap.js', but the fake
   300                     # one in tests/static-files/xpi-template doesn't
   301                     "harness-options.json",
   302                     "install.rdf",
   303                     "defaults/preferences/prefs.js",
   304                     "resources/",
   305                     "resources/addon-sdk/",
   306                     "resources/addon-sdk/lib/",
   307                     "resources/addon-sdk/lib/sdk/",
   308                     "resources/addon-sdk/lib/sdk/self.js",
   309                     "resources/addon-sdk/lib/sdk/core/",
   310                     "resources/addon-sdk/lib/sdk/util/",
   311                     "resources/addon-sdk/lib/sdk/net/",
   312                     "resources/addon-sdk/lib/sdk/core/promise.js",
   313                     "resources/addon-sdk/lib/sdk/util/object.js",
   314                     "resources/addon-sdk/lib/sdk/util/array.js",
   315                     "resources/addon-sdk/lib/sdk/net/url.js",
   316                     "resources/three/",
   317                     "resources/three/lib/",
   318                     "resources/three/lib/main.js",
   319                     "resources/three/data/",
   320                     "resources/three/data/msg.txt",
   321                     "resources/three/data/subdir/",
   322                     "resources/three/data/subdir/submsg.txt",
   323                     "resources/three-a/",
   324                     "resources/three-a/lib/",
   325                     "resources/three-a/lib/main.js",
   326                     "resources/three-a/lib/subdir/",
   327                     "resources/three-a/lib/subdir/subfile.js",
   328                     "resources/three-b/",
   329                     "resources/three-b/lib/",
   330                     "resources/three-b/lib/main.js",
   331                     "resources/three-c/",
   332                     "resources/three-c/lib/",
   333                     "resources/three-c/lib/main.js",
   334                     "resources/three-c/lib/sub/",
   335                     "resources/three-c/lib/sub/foo.js",
   336                     # notably absent: three-a/lib/unused.js
   337                     "locale/",
   338                     "locale/fr-FR.json",
   339                     "locales.json",
   340                     ]
   341         # showing deltas makes failures easier to investigate
   342         missing = set(expected) - set(names)
   343         extra = set(names) - set(expected)
   344         self.failUnlessEqual((list(missing), list(extra)), ([], []))
   345         self.failUnlessEqual(sorted(names), sorted(expected))
   347         # check locale files
   348         localedata = json.loads(x.read("locales.json"))
   349         self.failUnlessEqual(sorted(localedata["locales"]), sorted(["fr-FR"]))
   350         content = x.read("locale/fr-FR.json")
   351         locales = json.loads(content)
   352         # Locale files are merged into one.
   353         # Conflicts are silently resolved by taking last package translation,
   354         # so that we get "No" translation from three-c instead of three-b one.
   355         self.failUnlessEqual(locales, json.loads(u'''
   356           {
   357             "No": "Nein",
   358             "one": "un",
   359             "What?": "Quoi?",
   360             "Yes": "Oui",
   361             "plural": {
   362               "other": "other",
   363               "one": "one"
   364             },
   365             "uft8_value": "\u00e9"
   366           }'''))
   368     def test_scantests(self):
   369         target_cfg = self.get_pkg("three")
   370         package_path = [self.get_linker_files_dir("three-deps")]
   371         pkg_cfg = packaging.build_config(self.root, target_cfg,
   372                                          packagepath=package_path)
   374         deps = packaging.get_deps_for_targets(pkg_cfg,
   375                                               [target_cfg.name, "addon-sdk"])
   376         m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=True)
   377         self.failUnlessEqual(sorted(m.get_all_test_modules()),
   378                              sorted(["three/tests/test-one", "three/tests/test-two"]))
   379         # the current __init__.py code omits limit_to=used_files for 'cfx
   380         # test', so all test files are included in the XPI. But the test
   381         # runner will only execute the tests that m.get_all_test_modules()
   382         # tells us about (which are put into the .allTestModules property of
   383         # harness-options.json).
   384         used_deps = m.get_used_packages()
   386         build = packaging.generate_build_for_target(pkg_cfg, target_cfg.name,
   387                                                     used_deps,
   388                                                     include_tests=True)
   389         options = {'main': target_cfg.main}
   390         options.update(build)
   391         basedir = self.make_basedir()
   392         xpi_name = os.path.join(basedir, "contents.xpi")
   393         xpi.build_xpi(template_root_dir=xpi_template_path,
   394                       manifest=fake_manifest,
   395                       xpi_path=xpi_name,
   396                       harness_options=options,
   397                       limit_to=None)
   398         x = zipfile.ZipFile(xpi_name, "r")
   399         names = x.namelist()
   400         self.failUnless("resources/addon-sdk/lib/sdk/deprecated/unit-test.js" in names, names)
   401         self.failUnless("resources/addon-sdk/lib/sdk/deprecated/unit-test-finder.js" in names, names)
   402         self.failUnless("resources/addon-sdk/lib/sdk/test/harness.js" in names, names)
   403         self.failUnless("resources/addon-sdk/lib/sdk/test/runner.js" in names, names)
   404         # all files are copied into the XPI, even the things that don't look
   405         # like tests.
   406         self.failUnless("resources/three/tests/test-one.js" in names, names)
   407         self.failUnless("resources/three/tests/test-two.js" in names, names)
   408         self.failUnless("resources/three/tests/nontest.js" in names, names)
   410     def test_scantests_filter(self):
   411         target_cfg = self.get_pkg("three")
   412         package_path = [self.get_linker_files_dir("three-deps")]
   413         pkg_cfg = packaging.build_config(self.root, target_cfg,
   414                                          packagepath=package_path)
   415         deps = packaging.get_deps_for_targets(pkg_cfg,
   416                                               [target_cfg.name, "addon-sdk"])
   417         FILTER = ".*one.*"
   418         m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=True,
   419                                     test_filter_re=FILTER)
   420         self.failUnlessEqual(sorted(m.get_all_test_modules()),
   421                              sorted(["three/tests/test-one"]))
   422         # the current __init__.py code omits limit_to=used_files for 'cfx
   423         # test', so all test files are included in the XPI. But the test
   424         # runner will only execute the tests that m.get_all_test_modules()
   425         # tells us about (which are put into the .allTestModules property of
   426         # harness-options.json).
   427         used_deps = m.get_used_packages()
   429         build = packaging.generate_build_for_target(pkg_cfg, target_cfg.name,
   430                                                     used_deps,
   431                                                     include_tests=True)
   432         options = {'main': target_cfg.main}
   433         options.update(build)
   434         basedir = self.make_basedir()
   435         xpi_name = os.path.join(basedir, "contents.xpi")
   436         xpi.build_xpi(template_root_dir=xpi_template_path,
   437                       manifest=fake_manifest,
   438                       xpi_path=xpi_name,
   439                       harness_options=options,
   440                       limit_to=None)
   441         x = zipfile.ZipFile(xpi_name, "r")
   442         names = x.namelist()
   443         self.failUnless("resources/addon-sdk/lib/sdk/deprecated/unit-test.js" in names, names)
   444         self.failUnless("resources/addon-sdk/lib/sdk/deprecated/unit-test-finder.js" in names, names)
   445         self.failUnless("resources/addon-sdk/lib/sdk/test/harness.js" in names, names)
   446         self.failUnless("resources/addon-sdk/lib/sdk/test/runner.js" in names, names)
   447         # get_all_test_modules() respects the filter. But all files are still
   448         # copied into the XPI.
   449         self.failUnless("resources/three/tests/test-one.js" in names, names)
   450         self.failUnless("resources/three/tests/test-two.js" in names, names)
   451         self.failUnless("resources/three/tests/nontest.js" in names, names)
   454 def document_dir(name):
   455     if name in ['packages', 'xpi-template']:
   456         dirname = os.path.join(test_packaging.static_files_path, name)
   457         document_dir_files(dirname)
   458     elif name == 'xpi-output':
   459         create_xpi('test-xpi.xpi')
   460         document_zip_file('test-xpi.xpi')
   461         os.remove('test-xpi.xpi')
   462     else:
   463         raise Exception('unknown dir: %s' % name)
   465 def normpath(path):
   466     """
   467     Make a platform-specific relative path use '/' as a separator.
   468     """
   470     return path.replace(os.path.sep, '/')
   472 def document_zip_file(path):
   473     zip = zipfile.ZipFile(path, 'r')
   474     for name in sorted(zip.namelist()):
   475         contents = zip.read(name)
   476         lines = contents.splitlines()
   477         if len(lines) == 1 and name.endswith('.json') and len(lines[0]) > 75:
   478             # Ideally we would json-decode this, but it results
   479             # in an annoying 'u' before every string literal,
   480             # since json decoding makes all strings unicode.
   481             contents = eval(contents)
   482             contents = pprint.pformat(contents)
   483             lines = contents.splitlines()
   484         contents = "\n  ".join(lines)
   485         print "%s:\n  %s" % (normpath(name), contents)
   486     zip.close()
   488 def document_dir_files(path):
   489     filename_contents_tuples = []
   490     for dirpath, dirnames, filenames in os.walk(path):
   491         relpath = dirpath[len(path)+1:]
   492         for filename in filenames:
   493             abspath = os.path.join(dirpath, filename)
   494             contents = open(abspath, 'r').read()
   495             contents = "\n  ".join(contents.splitlines())
   496             relfilename = os.path.join(relpath, filename)
   497             filename_contents_tuples.append((normpath(relfilename), contents))
   498     filename_contents_tuples.sort()
   499     for filename, contents in filename_contents_tuples:
   500         print "%s:" % filename
   501         print "  %s" % contents
   503 def create_xpi(xpiname, pkg_name='aardvark', dirname='static-files',
   504                extra_harness_options={}):
   505     configs = test_packaging.get_configs(pkg_name, dirname)
   506     options = {'main': configs.target_cfg.main,
   507                'jetpackID': buildJID(configs.target_cfg), }
   508     options.update(configs.build)
   509     xpi.build_xpi(template_root_dir=xpi_template_path,
   510                   manifest=fake_manifest,
   511                   xpi_path=xpiname,
   512                   harness_options=options,
   513                   extra_harness_options=extra_harness_options)
   515 if __name__ == '__main__':
   516     unittest.main()

mercurial