diff options
Diffstat (limited to 'testing/mozbase/mozprofile/tests')
35 files changed, 2073 insertions, 0 deletions
diff --git a/testing/mozbase/mozprofile/tests/addon_stubs.py b/testing/mozbase/mozprofile/tests/addon_stubs.py new file mode 100644 index 0000000000..32b64070ea --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addon_stubs.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +from __future__ import absolute_import + +import os +import tempfile +import zipfile + +import mozfile + + +here = os.path.dirname(os.path.abspath(__file__)) + +# stubs is a dict of the form {'addon id': 'install manifest content'} +stubs = { + "test-addon-1@mozilla.org": "test_addon_1.rdf", + "test-addon-2@mozilla.org": "test_addon_2.rdf", + "test-addon-3@mozilla.org": "test_addon_3.rdf", + "test-addon-4@mozilla.org": "test_addon_4.rdf", + "test-addon-invalid-no-id@mozilla.org": "test_addon_invalid_no_id.rdf", + "test-addon-invalid-version@mozilla.org": "test_addon_invalid_version.rdf", + "test-addon-invalid-no-manifest@mozilla.org": None, + "test-addon-invalid-not-wellformed@mozilla.org": "test_addon_invalid_not_wellformed.rdf", + "test-addon-unpack@mozilla.org": "test_addon_unpack.rdf", +} + + +def generate_addon(addon_id, path=None, name=None, xpi=True): + """ + Method to generate a single addon. + + :param addon_id: id of an addon to generate from the stubs dictionary + :param path: path where addon and .xpi should be generated + :param name: name for the addon folder or .xpi file + :param xpi: Flag if an XPI or folder should be generated + + Returns the file-path of the addon's .xpi file + """ + + if addon_id not in stubs: + raise IOError('Requested addon stub "%s" does not exist' % addon_id) + + # Generate directory structure for addon + try: + tmpdir = path or tempfile.mkdtemp() + addon_dir = os.path.join(tmpdir, name or addon_id) + os.mkdir(addon_dir) + except IOError: + raise IOError("Could not generate directory structure for addon stub.") + + # Write install.rdf for addon + if stubs[addon_id]: + install_rdf = os.path.join(addon_dir, "install.rdf") + with open(install_rdf, "w") as f: + manifest = os.path.join(here, "install_manifests", stubs[addon_id]) + f.write(open(manifest, "r").read()) + + if not xpi: + return addon_dir + + # Generate the .xpi for the addon + xpi_file = os.path.join(tmpdir, (name or addon_id) + ".xpi") + with zipfile.ZipFile(xpi_file, "w") as x: + x.write(install_rdf, install_rdf[len(addon_dir) :]) + + # Ensure we remove the temporary folder to not install the addon twice + mozfile.rmtree(addon_dir) + + return xpi_file diff --git a/testing/mozbase/mozprofile/tests/addons/apply-css-id-via-browser-specific-settings.xpi b/testing/mozbase/mozprofile/tests/addons/apply-css-id-via-browser-specific-settings.xpi Binary files differnew file mode 100644 index 0000000000..c9ad38f63b --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addons/apply-css-id-via-browser-specific-settings.xpi diff --git a/testing/mozbase/mozprofile/tests/addons/apply-css-sans-id.xpi b/testing/mozbase/mozprofile/tests/addons/apply-css-sans-id.xpi Binary files differnew file mode 100644 index 0000000000..fa721a4f76 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addons/apply-css-sans-id.xpi diff --git a/testing/mozbase/mozprofile/tests/addons/apply-css.xpi b/testing/mozbase/mozprofile/tests/addons/apply-css.xpi Binary files differnew file mode 100644 index 0000000000..0ed64f79ac --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addons/apply-css.xpi diff --git a/testing/mozbase/mozprofile/tests/addons/empty.xpi b/testing/mozbase/mozprofile/tests/addons/empty.xpi Binary files differnew file mode 100644 index 0000000000..26f28f099d --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addons/empty.xpi diff --git a/testing/mozbase/mozprofile/tests/addons/empty/install.rdf b/testing/mozbase/mozprofile/tests/addons/empty/install.rdf new file mode 100644 index 0000000000..70b9e13e44 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addons/empty/install.rdf @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-empty@quality.mozilla.org</em:id> + <em:version>0.1</em:version> + <em:name>Test Extension (empty)</em:name> + <em:creator>Mozilla QA</em:creator> + <em:homepageURL>http://quality.mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/addons/invalid.xpi b/testing/mozbase/mozprofile/tests/addons/invalid.xpi Binary files differnew file mode 100644 index 0000000000..2f222c7637 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/addons/invalid.xpi diff --git a/testing/mozbase/mozprofile/tests/files/dummy-profile/.eslintrc.js b/testing/mozbase/mozprofile/tests/files/dummy-profile/.eslintrc.js new file mode 100644 index 0000000000..8d36cca287 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/dummy-profile/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + globals: { + user_pref: true, + }, +}; diff --git a/testing/mozbase/mozprofile/tests/files/dummy-profile/Preferences b/testing/mozbase/mozprofile/tests/files/dummy-profile/Preferences new file mode 100644 index 0000000000..697201c687 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/dummy-profile/Preferences @@ -0,0 +1 @@ +{"Preferences": 1} diff --git a/testing/mozbase/mozprofile/tests/files/dummy-profile/extensions/empty.xpi b/testing/mozbase/mozprofile/tests/files/dummy-profile/extensions/empty.xpi Binary files differnew file mode 100644 index 0000000000..26f28f099d --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/dummy-profile/extensions/empty.xpi diff --git a/testing/mozbase/mozprofile/tests/files/dummy-profile/prefs.js b/testing/mozbase/mozprofile/tests/files/dummy-profile/prefs.js new file mode 100644 index 0000000000..c2e18261a8 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/dummy-profile/prefs.js @@ -0,0 +1 @@ +user_pref("prefs.js", 1); diff --git a/testing/mozbase/mozprofile/tests/files/dummy-profile/user.js b/testing/mozbase/mozprofile/tests/files/dummy-profile/user.js new file mode 100644 index 0000000000..66752d6397 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/dummy-profile/user.js @@ -0,0 +1 @@ +user_pref("user.js", 1); diff --git a/testing/mozbase/mozprofile/tests/files/not_an_addon.txt b/testing/mozbase/mozprofile/tests/files/not_an_addon.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/not_an_addon.txt diff --git a/testing/mozbase/mozprofile/tests/files/prefs_with_comments.js b/testing/mozbase/mozprofile/tests/files/prefs_with_comments.js new file mode 100644 index 0000000000..06a56f2138 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/prefs_with_comments.js @@ -0,0 +1,6 @@ +# A leading comment +user_pref("browser.startup.homepage", "http://planet.mozilla.org"); # A trailing comment +user_pref("zoom.minPercent", 30); +// Another leading comment +user_pref("zoom.maxPercent", 300); // Another trailing comment +user_pref("webgl.verbose", "false"); diff --git a/testing/mozbase/mozprofile/tests/files/prefs_with_interpolation.js b/testing/mozbase/mozprofile/tests/files/prefs_with_interpolation.js new file mode 100644 index 0000000000..52700df6d8 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/files/prefs_with_interpolation.js @@ -0,0 +1,5 @@ +/* globals user_pref */ +user_pref("browser.foo", "http://{server}"); +user_pref("zoom.minPercent", 30); +user_pref("webgl.verbose", "false"); +user_pref("browser.bar", "{abc}xyz"); diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_1.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_1.rdf new file mode 100644 index 0000000000..839ea9fbd5 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_1.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-addon-1@mozilla.org</em:id> + <em:version>0.1</em:version> + <em:name>Test Add-on 1</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_2.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_2.rdf new file mode 100644 index 0000000000..8303e862fc --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_2.rdf @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-addon-2@mozilla.org</em:id> + <em:version>0.2</em:version> + <em:name>Test Add-on 2</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_3.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_3.rdf new file mode 100644 index 0000000000..5bd6d38043 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_3.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-addon-3@mozilla.org</em:id> + <em:version>0.1</em:version> + <em:name>Test Add-on 3</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> + diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_4.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_4.rdf new file mode 100644 index 0000000000..e0f99d3133 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_4.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-addon-4@mozilla.org</em:id> + <em:version>0.1</em:version> + <em:name>Test Add-on 4</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> + diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_no_id.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_no_id.rdf new file mode 100644 index 0000000000..23f60fece1 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_no_id.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <!-- Invalid because of a missing add-on id --> + <em:version>0.1</em:version> + <em:name>Test Invalid Extension (no id)</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <!-- Invalid target application string --> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_not_wellformed.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_not_wellformed.rdf new file mode 100644 index 0000000000..690ec406cc --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_not_wellformed.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <!-- Invalid because it's not well-formed --> + <em:id>test-addon-invalid-not-wellformed@mozilla.org</em:id + <em:version>0.1</em:version> + <em:name>Test Invalid Extension (no id)</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <!-- Invalid target application string --> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_version.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_version.rdf new file mode 100644 index 0000000000..c854bfcdb5 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_invalid_version.rdf @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-addon-invalid-version@mozilla.org</em:id> + <!-- Invalid addon version --> + <em:version>0.NOPE</em:version> + <em:name>Test Invalid Extension (invalid version)</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <!-- Invalid target application string --> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/install_manifests/test_addon_unpack.rdf b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_unpack.rdf new file mode 100644 index 0000000000..cc85ea560f --- /dev/null +++ b/testing/mozbase/mozprofile/tests/install_manifests/test_addon_unpack.rdf @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>test-addon-unpack@mozilla.org</em:id> + <em:version>0.1</em:version> + <em:name>Test Add-on (unpack)</em:name> + <em:creator>Mozilla</em:creator> + <em:homepageURL>http://mozilla.org</em:homepageURL> + <em:type>2</em:type> + <em:unpack>true</em:unpack> + + <!-- Firefox --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5.*</em:minVersion> + <em:maxVersion>*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF> diff --git a/testing/mozbase/mozprofile/tests/manifest.ini b/testing/mozbase/mozprofile/tests/manifest.ini new file mode 100644 index 0000000000..d69f4649ce --- /dev/null +++ b/testing/mozbase/mozprofile/tests/manifest.ini @@ -0,0 +1,13 @@ +[DEFAULT] +subsuite = mozbase +[test_addonid.py] +[test_server_locations.py] +[test_preferences.py] +[test_permissions.py] +[test_bug758250.py] +[test_nonce.py] +[test_clone_cleanup.py] +[test_profile.py] +[test_profile_view.py] +[test_addons.py] +[test_chrome_profile.py] diff --git a/testing/mozbase/mozprofile/tests/test_addonid.py b/testing/mozbase/mozprofile/tests/test_addonid.py new file mode 100755 index 0000000000..2390acf114 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_addonid.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python + +from __future__ import absolute_import + +import os + +import mozunit +import pytest + +from mozprofile import addons + + +here = os.path.dirname(os.path.abspath(__file__)) + + +"""Test finding the addon id in a variety of install.rdf styles""" + + +ADDON_ID_TESTS = [ + """ +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:id>winning</em:id> + <em:name>MozMill</em:name> + <em:version>2.0a</em:version> + <em:creator>Adam Christian</em:creator> + <em:description>A testing extension based on the + Windmill Testing Framework client source</em:description> + <em:unpack>true</em:unpack> + <em:targetApplication> + <!-- Firefox --> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5</em:minVersion> + <em:maxVersion>8.*</em:maxVersion> + </Description> + </em:targetApplication> + <em:targetApplication> + <!-- Thunderbird --> + <Description> + <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id> + <em:minVersion>3.0a1pre</em:minVersion> + <em:maxVersion>3.2*</em:maxVersion> + </Description> + </em:targetApplication> + <em:targetApplication> + <!-- Sunbird --> + <Description> + <em:id>{718e30fb-e89b-41dd-9da7-e25a45638b28}</em:id> + <em:minVersion>0.6a1</em:minVersion> + <em:maxVersion>1.0pre</em:maxVersion> + </Description> + </em:targetApplication> + <em:targetApplication> + <!-- SeaMonkey --> + <Description> + <em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id> + <em:minVersion>2.0a1</em:minVersion> + <em:maxVersion>2.1*</em:maxVersion> + </Description> + </em:targetApplication> + <em:targetApplication> + <!-- Songbird --> + <Description> + <em:id>songbird@songbirdnest.com</em:id> + <em:minVersion>0.3pre</em:minVersion> + <em:maxVersion>1.3.0a</em:maxVersion> + </Description> + </em:targetApplication> + <em:targetApplication> + <Description> + <em:id>toolkit@mozilla.org</em:id> + <em:minVersion>1.9.1</em:minVersion> + <em:maxVersion>2.0*</em:maxVersion> + </Description> + </em:targetApplication> + </Description> +</RDF>""", + """ +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <em:targetApplication> + <!-- Firefox --> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.5</em:minVersion> + <em:maxVersion>8.*</em:maxVersion> + </Description> + </em:targetApplication> + <em:id>winning</em:id> + <em:name>MozMill</em:name> + <em:version>2.0a</em:version> + <em:creator>Adam Christian</em:creator> + <em:description>A testing extension based on the + Windmill Testing Framework client source</em:description> + <em:unpack>true</em:unpack> + </Description> + </RDF>""", + """ +<RDF xmlns="http://www.mozilla.org/2004/em-rdf#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description about="urn:mozilla:install-manifest"> + <id>winning</id> + <name>foo</name> + <version>42</version> + <description>A testing extension based on the + Windmill Testing Framework client source</description> + </rdf:Description> +</RDF>""", + """ +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:foobar="http://www.mozilla.org/2004/em-rdf#"> + <Description about="urn:mozilla:install-manifest"> + <foobar:targetApplication> + <!-- Firefox --> + <Description> + <foobar:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</foobar:id> + <foobar:minVersion>3.5</foobar:minVersion> + <foobar:maxVersion>8.*</foobar:maxVersion> + </Description> + </foobar:targetApplication> + <foobar:id>winning</foobar:id> + <foobar:name>MozMill</foobar:name> + <foobar:version>2.0a</foobar:version> + <foobar:creator>Adam Christian</foobar:creator> + <foobar:description>A testing extension based on the + Windmill Testing Framework client source</foobar:description> + <foobar:unpack>true</foobar:unpack> + </Description> + </RDF>""", +] + + +@pytest.fixture( + params=ADDON_ID_TESTS, ids=[str(i) for i in range(0, len(ADDON_ID_TESTS))] +) +def profile(request, tmpdir): + test = request.param + path = tmpdir.mkdtemp().strpath + + with open(os.path.join(path, "install.rdf"), "w") as fh: + fh.write(test) + return path + + +def test_addonID(profile): + a = addons.AddonManager(os.path.join(profile, "profile")) + addon_id = a.addon_details(profile)["id"] + assert addon_id == "winning" + + +def test_addonID_xpi(): + a = addons.AddonManager("profile") + addon = a.addon_details(os.path.join(here, "addons", "empty.xpi")) + assert addon["id"] == "test-empty@quality.mozilla.org" + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_addons.py b/testing/mozbase/mozprofile/tests/test_addons.py new file mode 100644 index 0000000000..bcff62f724 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_addons.py @@ -0,0 +1,376 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import, unicode_literals + +import os +import zipfile + +import mozunit +import pytest + +import mozprofile +from addon_stubs import generate_addon + +here = os.path.dirname(os.path.abspath(__file__)) + + +@pytest.fixture +def profile(): + return mozprofile.Profile() + + +@pytest.fixture +def am(profile): + return profile.addons + + +def test_install_multiple_same_source(tmpdir, am): + path = tmpdir.strpath + + # Generate installer stubs for all possible types of addons + addon_xpi = generate_addon("test-addon-1@mozilla.org", path=path) + addon_folder = generate_addon("test-addon-1@mozilla.org", path=path, xpi=False) + + # The same folder should not be installed twice + am.install([addon_folder, addon_folder]) + assert am.installed_addons == [addon_folder] + am.clean() + + # The same XPI file should not be installed twice + am.install([addon_xpi, addon_xpi]) + assert am.installed_addons == [addon_xpi] + am.clean() + + # Even if it is the same id the add-on should be installed twice, if + # specified via XPI and folder + am.install([addon_folder, addon_xpi]) + assert len(am.installed_addons) == 2 + assert addon_folder in am.installed_addons + assert addon_xpi in am.installed_addons + am.clean() + + +def test_install_webextension_from_dir(tmpdir, am): + tmpdir = tmpdir.strpath + + addon = os.path.join(here, "addons", "apply-css.xpi") + zipped = zipfile.ZipFile(addon) + try: + zipped.extractall(tmpdir) + finally: + zipped.close() + am.install(tmpdir) + assert len(am.installed_addons) == 1 + assert os.path.isdir(am.installed_addons[0]) + + +def test_install_webextension(am): + addon = os.path.join(here, "addons", "apply-css.xpi") + + am.install(addon) + assert len(am.installed_addons) == 1 + assert os.path.isfile(am.installed_addons[0]) + assert "apply-css.xpi" == os.path.basename(am.installed_addons[0]) + + details = am.addon_details(am.installed_addons[0]) + assert "test-webext@quality.mozilla.org" == details["id"] + + +def test_install_webextension_id_via_browser_specific_settings(am): + # See Bug 1572404 + addon = os.path.join( + here, "addons", "apply-css-id-via-browser-specific-settings.xpi" + ) + am.install(addon) + assert len(am.installed_addons) == 1 + assert os.path.isfile(am.installed_addons[0]) + assert "apply-css-id-via-browser-specific-settings.xpi" == os.path.basename( + am.installed_addons[0] + ) + + details = am.addon_details(am.installed_addons[0]) + assert "test-webext@quality.mozilla.org" == details["id"] + + +def test_install_webextension_sans_id(am): + addon = os.path.join(here, "addons", "apply-css-sans-id.xpi") + am.install(addon) + + assert len(am.installed_addons) == 1 + assert os.path.isfile(am.installed_addons[0]) + assert "apply-css-sans-id.xpi" == os.path.basename(am.installed_addons[0]) + + details = am.addon_details(am.installed_addons[0]) + assert "@temporary-addon" in details["id"] + + +def test_install_xpi(tmpdir, am): + tmpdir = tmpdir.strpath + + addons_to_install = [] + addons_installed = [] + + # Generate installer stubs and install them + for ext in ["test-addon-1@mozilla.org", "test-addon-2@mozilla.org"]: + temp_addon = generate_addon(ext, path=tmpdir) + addons_to_install.append(am.addon_details(temp_addon)["id"]) + am.install(temp_addon) + + # Generate a list of addons installed in the profile + addons_installed = [ + str(x[: -len(".xpi")]) + for x in os.listdir(os.path.join(am.profile, "extensions")) + ] + assert addons_to_install.sort() == addons_installed.sort() + + +def test_install_folder(tmpdir, am): + tmpdir = tmpdir.strpath + + # Generate installer stubs for all possible types of addons + addons = [] + addons.append(generate_addon("test-addon-1@mozilla.org", path=tmpdir)) + addons.append(generate_addon("test-addon-2@mozilla.org", path=tmpdir, xpi=False)) + addons.append( + generate_addon("test-addon-3@mozilla.org", path=tmpdir, name="addon-3") + ) + addons.append( + generate_addon( + "test-addon-4@mozilla.org", path=tmpdir, name="addon-4", xpi=False + ) + ) + addons.sort() + + am.install(tmpdir) + + assert am.installed_addons == addons + + +def test_install_unpack(tmpdir, am): + tmpdir = tmpdir.strpath + + # Generate installer stubs for all possible types of addons + addon_xpi = generate_addon("test-addon-unpack@mozilla.org", path=tmpdir) + addon_folder = generate_addon( + "test-addon-unpack@mozilla.org", path=tmpdir, xpi=False + ) + addon_no_unpack = generate_addon("test-addon-1@mozilla.org", path=tmpdir) + + # Test unpack flag for add-on as XPI + am.install(addon_xpi) + assert am.installed_addons == [addon_xpi] + am.clean() + + # Test unpack flag for add-on as folder + am.install(addon_folder) + assert am.installed_addons == [addon_folder] + am.clean() + + # Test forcing unpack an add-on + am.install(addon_no_unpack, unpack=True) + assert am.installed_addons == [addon_no_unpack] + am.clean() + + +def test_install_after_reset(tmpdir, profile): + tmpdir = tmpdir.strpath + am = profile.addons + + # Installing the same add-on after a reset should not cause a failure + addon = generate_addon("test-addon-1@mozilla.org", path=tmpdir, xpi=False) + + # We cannot use am because profile.reset() creates a new instance + am.install(addon) + profile.reset() + + am.install(addon) + assert am.installed_addons == [addon] + + +def test_install_backup(tmpdir, am): + tmpdir = tmpdir.strpath + + staged_path = os.path.join(am.profile, "extensions") + + # Generate installer stubs for all possible types of addons + addon_xpi = generate_addon("test-addon-1@mozilla.org", path=tmpdir) + addon_folder = generate_addon("test-addon-1@mozilla.org", path=tmpdir, xpi=False) + addon_name = generate_addon( + "test-addon-1@mozilla.org", path=tmpdir, name="test-addon-1-dupe@mozilla.org" + ) + + # Test backup of xpi files + am.install(addon_xpi) + assert am.backup_dir is None + + am.install(addon_xpi) + assert am.backup_dir is not None + assert os.listdir(am.backup_dir) == ["test-addon-1@mozilla.org.xpi"] + + am.clean() + assert os.listdir(staged_path) == ["test-addon-1@mozilla.org.xpi"] + am.clean() + + # Test backup of folders + am.install(addon_folder) + assert am.backup_dir is None + + am.install(addon_folder) + assert am.backup_dir is not None + assert os.listdir(am.backup_dir) == ["test-addon-1@mozilla.org"] + + am.clean() + assert os.listdir(staged_path) == ["test-addon-1@mozilla.org"] + am.clean() + + # Test backup of xpi files with another file name + am.install(addon_name) + assert am.backup_dir is None + + am.install(addon_xpi) + assert am.backup_dir is not None + assert os.listdir(am.backup_dir) == ["test-addon-1@mozilla.org.xpi"] + + am.clean() + assert os.listdir(staged_path) == ["test-addon-1@mozilla.org.xpi"] + am.clean() + + +def test_install_invalid_addons(tmpdir, am): + tmpdir = tmpdir.strpath + + # Generate installer stubs for all possible types of addons + addons = [] + addons.append( + generate_addon( + "test-addon-invalid-no-manifest@mozilla.org", path=tmpdir, xpi=False + ) + ) + addons.append(generate_addon("test-addon-invalid-no-id@mozilla.org", path=tmpdir)) + + am.install(tmpdir) + + assert am.installed_addons == [] + + +@pytest.mark.xfail(reason="feature not implemented as part of AddonManger") +def test_install_error(am): + """ Check install raises an error with an invalid addon""" + temp_addon = generate_addon("test-addon-invalid-version@mozilla.org") + # This should raise an error here + with pytest.raises(Exception): + am.install(temp_addon) + + +def test_addon_details(tmpdir, am): + tmpdir = tmpdir.strpath + + # Generate installer stubs for a valid and invalid add-on manifest + valid_addon = generate_addon("test-addon-1@mozilla.org", path=tmpdir) + invalid_addon = generate_addon( + "test-addon-invalid-not-wellformed@mozilla.org", path=tmpdir + ) + + # Check valid add-on + details = am.addon_details(valid_addon) + assert details["id"] == "test-addon-1@mozilla.org" + assert details["name"] == "Test Add-on 1" + assert not details["unpack"] + assert details["version"] == "0.1" + + # Check invalid add-on + with pytest.raises(mozprofile.addons.AddonFormatError): + am.addon_details(invalid_addon) + + # Check invalid path + with pytest.raises(IOError): + am.addon_details("") + + # Check invalid add-on format + addon_path = os.path.join(os.path.join(here, "files"), "not_an_addon.txt") + with pytest.raises(mozprofile.addons.AddonFormatError): + am.addon_details(addon_path) + + +def test_clean_addons(am): + addon_one = generate_addon("test-addon-1@mozilla.org") + addon_two = generate_addon("test-addon-2@mozilla.org") + + am.install(addon_one) + installed_addons = [ + str(x[: -len(".xpi")]) + for x in os.listdir(os.path.join(am.profile, "extensions")) + ] + + # Create a new profile based on an existing profile + # Install an extra addon in the new profile + # Cleanup addons + duplicate_profile = mozprofile.profile.Profile(profile=am.profile, addons=addon_two) + duplicate_profile.addons.clean() + + addons_after_cleanup = [ + str(x[: -len(".xpi")]) + for x in os.listdir(os.path.join(duplicate_profile.profile, "extensions")) + ] + # New addons installed should be removed by clean_addons() + assert installed_addons == addons_after_cleanup + + +def test_noclean(tmpdir): + """test `restore=True/False` functionality""" + profile = tmpdir.mkdtemp().strpath + tmpdir = tmpdir.mkdtemp().strpath + + # empty initially + assert not bool(os.listdir(profile)) + + # make an addon + addons = [ + generate_addon("test-addon-1@mozilla.org", path=tmpdir), + os.path.join(here, "addons", "empty.xpi"), + ] + + # install it with a restore=True AddonManager + am = mozprofile.addons.AddonManager(profile, restore=True) + + for addon in addons: + am.install(addon) + + # now its there + assert os.listdir(profile) == ["extensions"] + staging_folder = os.path.join(profile, "extensions") + assert os.path.exists(staging_folder) + assert len(os.listdir(staging_folder)) == 2 + + del am + + assert os.listdir(profile) == ["extensions"] + assert os.path.exists(staging_folder) + assert os.listdir(staging_folder) == [] + + +def test_remove_addon(tmpdir, am): + tmpdir = tmpdir.strpath + + addons = [] + addons.append(generate_addon("test-addon-1@mozilla.org", path=tmpdir)) + addons.append(generate_addon("test-addon-2@mozilla.org", path=tmpdir)) + + am.install(tmpdir) + + extensions_path = os.path.join(am.profile, "extensions") + staging_path = os.path.join(extensions_path) + + for addon in am._addons: + am.remove_addon(addon) + + assert os.listdir(staging_path) == [] + assert os.listdir(extensions_path) == [] + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_bug758250.py b/testing/mozbase/mozprofile/tests/test_bug758250.py new file mode 100755 index 0000000000..e9d7862bd5 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_bug758250.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +from __future__ import absolute_import + +import mozprofile +import os +import shutil + +import mozunit + +here = os.path.dirname(os.path.abspath(__file__)) + +""" +use of --profile in mozrunner just blows away addon sources: +https://bugzilla.mozilla.org/show_bug.cgi?id=758250 +""" + + +def test_profile_addon_cleanup(tmpdir): + tmpdir = tmpdir.mkdtemp().strpath + addon = os.path.join(here, "addons", "empty") + + # sanity check: the empty addon should be here + assert os.path.exists(addon) + assert os.path.isdir(addon) + assert os.path.exists(os.path.join(addon, "install.rdf")) + + # because we are testing data loss, let's make sure we make a copy + shutil.rmtree(tmpdir) + shutil.copytree(addon, tmpdir) + assert os.path.exists(os.path.join(tmpdir, "install.rdf")) + + # make a starter profile + profile = mozprofile.FirefoxProfile() + path = profile.profile + + # make a new profile based on the old + newprofile = mozprofile.FirefoxProfile(profile=path, addons=[tmpdir]) + newprofile.cleanup() + + # the source addon *should* still exist + assert os.path.exists(tmpdir) + assert os.path.exists(os.path.join(tmpdir, "install.rdf")) + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_chrome_profile.py b/testing/mozbase/mozprofile/tests/test_chrome_profile.py new file mode 100644 index 0000000000..95f3b01baa --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_chrome_profile.py @@ -0,0 +1,75 @@ +# 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/. + +from __future__ import absolute_import + +import json +import os + +import mozunit + +from mozprofile import ChromeProfile + + +def test_chrome_profile_pre_existing(tmpdir): + path = tmpdir.strpath + profile = ChromeProfile(profile=path) + assert not profile.create_new + assert os.path.isdir(profile.profile) + assert profile.profile == path + + +def test_chrome_profile_create_new(): + profile = ChromeProfile() + assert profile.create_new + assert os.path.isdir(profile.profile) + assert profile.profile.endswith("Default") + + +def test_chrome_preferences(tmpdir): + prefs = {"foo": "bar"} + profile = ChromeProfile(preferences=prefs) + prefs_file = os.path.join(profile.profile, "Preferences") + + assert os.path.isfile(prefs_file) + + with open(prefs_file) as fh: + assert json.load(fh) == prefs + + # test with existing prefs + prefs_file = tmpdir.join("Preferences").strpath + with open(prefs_file, "w") as fh: + json.dump({"num": "1"}, fh) + + profile = ChromeProfile(profile=tmpdir.strpath, preferences=prefs) + + def assert_prefs(): + with open(prefs_file) as fh: + data = json.load(fh) + + assert len(data) == 2 + assert data.get("foo") == "bar" + assert data.get("num") == "1" + + assert_prefs() + profile.reset() + assert_prefs() + + +def test_chrome_addons(): + addons = ["foo", "bar"] + profile = ChromeProfile(addons=addons) + + assert isinstance(profile.addons, list) + assert profile.addons == addons + + profile.addons.install("baz") + assert profile.addons == addons + ["baz"] + + profile.reset() + assert profile.addons == addons + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_clone_cleanup.py b/testing/mozbase/mozprofile/tests/test_clone_cleanup.py new file mode 100644 index 0000000000..40b00175d5 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_clone_cleanup.py @@ -0,0 +1,81 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import + +import os +import mozfile + +import mozunit +import pytest + +from mozprofile.profile import Profile + +""" +test cleanup logic for the clone functionality +see https://bugzilla.mozilla.org/show_bug.cgi?id=642843 +""" + + +@pytest.fixture +def profile(tmpdir): + # make a profile with one preference + path = tmpdir.mkdtemp().strpath + profile = Profile(path, preferences={"foo": "bar"}, restore=False) + user_js = os.path.join(profile.profile, "user.js") + assert os.path.exists(user_js) + return profile + + +def test_restore_true(profile): + counter = [0] + + def _feedback(dir, content): + # Called by shutil.copytree on each visited directory. + # Used here to display info. + # + # Returns the items that should be ignored by + # shutil.copytree when copying the tree, so always returns + # an empty list. + counter[0] += 1 + return [] + + # make a clone of this profile with restore=True + clone = Profile.clone(profile.profile, restore=True, ignore=_feedback) + try: + clone.cleanup() + + # clone should be deleted + assert not os.path.exists(clone.profile) + assert counter[0] > 0 + finally: + mozfile.remove(clone.profile) + + +def test_restore_false(profile): + # make a clone of this profile with restore=False + clone = Profile.clone(profile.profile, restore=False) + try: + clone.cleanup() + + # clone should still be around on the filesystem + assert os.path.exists(clone.profile) + finally: + mozfile.remove(clone.profile) + + +def test_cleanup_on_garbage_collected(profile): + clone = Profile.clone(profile.profile) + profile_dir = clone.profile + assert os.path.exists(profile_dir) + del clone + + # clone should be deleted + assert not os.path.exists(profile_dir) + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_nonce.py b/testing/mozbase/mozprofile/tests/test_nonce.py new file mode 100755 index 0000000000..1d412d079e --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_nonce.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +""" +test nonce in prefs delimeters +see https://bugzilla.mozilla.org/show_bug.cgi?id=722804 +""" + +from __future__ import absolute_import + +import os + +import mozunit + +from mozprofile.prefs import Preferences +from mozprofile.profile import Profile + + +def test_nonce(tmpdir): + # make a profile with one preference + path = tmpdir.strpath + profile = Profile(path, preferences={"foo": "bar"}, restore=False) + user_js = os.path.join(profile.profile, "user.js") + assert os.path.exists(user_js) + + # ensure the preference is correct + prefs = Preferences.read_prefs(user_js) + assert dict(prefs) == {"foo": "bar"} + + del profile + + # augment the profile with a second preference + profile = Profile(path, preferences={"fleem": "baz"}, restore=True) + prefs = Preferences.read_prefs(user_js) + assert dict(prefs) == {"foo": "bar", "fleem": "baz"} + + # cleanup the profile; + # this should remove the new preferences but not the old + profile.cleanup() + prefs = Preferences.read_prefs(user_js) + assert dict(prefs) == {"foo": "bar"} + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_permissions.py b/testing/mozbase/mozprofile/tests/test_permissions.py new file mode 100755 index 0000000000..d943bab66e --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_permissions.py @@ -0,0 +1,225 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import + +import os +import sqlite3 + +import mozunit +import pytest + +from mozprofile.permissions import Permissions + +LOCATIONS = """http://mochi.test:8888 primary,privileged +http://127.0.0.1:80 noxul +http://127.0.0.1:8888 privileged +""" + + +@pytest.fixture +def locations_file(tmpdir): + locations_file = tmpdir.join("locations.txt") + locations_file.write(LOCATIONS) + return locations_file.strpath + + +@pytest.fixture +def perms(tmpdir, locations_file): + return Permissions(tmpdir.mkdir("profile").strpath, locations_file) + + +def test_create_permissions_db(perms): + profile_dir = perms._profileDir + perms_db_filename = os.path.join(profile_dir, "permissions.sqlite") + + select_stmt = "select origin, type, permission from moz_hosts" + + con = sqlite3.connect(perms_db_filename) + cur = con.cursor() + cur.execute(select_stmt) + entries = cur.fetchall() + + assert len(entries) == 3 + + assert entries[0][0] == "http://mochi.test:8888" + assert entries[0][1] == "allowXULXBL" + assert entries[0][2] == 1 + + assert entries[1][0] == "http://127.0.0.1" + assert entries[1][1] == "allowXULXBL" + assert entries[1][2] == 2 + + assert entries[2][0] == "http://127.0.0.1:8888" + assert entries[2][1] == "allowXULXBL" + assert entries[2][2] == 1 + + perms._locations.add_host("a.b.c", port="8081", scheme="https", options="noxul") + + cur.execute(select_stmt) + entries = cur.fetchall() + + assert len(entries) == 4 + assert entries[3][0] == "https://a.b.c:8081" + assert entries[3][1] == "allowXULXBL" + assert entries[3][2] == 2 + + # when creating a DB we should default to user_version==5 + cur.execute("PRAGMA user_version") + entries = cur.fetchall() + assert entries[0][0] == 5 + + perms.clean_db() + # table should be removed + cur.execute("select * from sqlite_master where type='table'") + entries = cur.fetchall() + assert len(entries) == 0 + + +def test_nw_prefs(perms): + prefs, user_prefs = perms.network_prefs(False) + + assert len(user_prefs) == 0 + assert len(prefs) == 0 + + prefs, user_prefs = perms.network_prefs(True) + assert len(user_prefs) == 2 + assert user_prefs[0] == ("network.proxy.type", 2) + assert user_prefs[1][0] == "network.proxy.autoconfig_url" + + origins_decl = ( + "var knownOrigins = (function () { return ['http://mochi.test:8888', " + "'http://127.0.0.1:80', 'http://127.0.0.1:8888'].reduce" + ) + assert origins_decl in user_prefs[1][1] + + proxy_check = ( + "'http': 'PROXY mochi.test:8888'", + "'https': 'PROXY mochi.test:4443'", + "'ws': 'PROXY mochi.test:4443'", + "'wss': 'PROXY mochi.test:4443'", + ) + assert all(c in user_prefs[1][1] for c in proxy_check) + + +@pytest.fixture +def perms_db_filename(tmpdir): + return tmpdir.join("permissions.sqlite").strpath + + +@pytest.fixture +def permDB(perms_db_filename): + permDB = sqlite3.connect(perms_db_filename) + yield permDB + permDB.cursor().close() + + +# pylint: disable=W1638 +@pytest.fixture(params=range(2, 6)) +def version(request, perms_db_filename, permDB, locations_file): + version = request.param + + cursor = permDB.cursor() + cursor.execute("PRAGMA user_version=%d;" % version) + + if version == 5: + cursor.execute( + """CREATE TABLE IF NOT EXISTS moz_hosts ( + id INTEGER PRIMARY KEY, + origin TEXT, + type TEXT, + permission INTEGER, + expireType INTEGER, + expireTime INTEGER, + modificationTime INTEGER)""" + ) + elif version == 4: + cursor.execute( + """CREATE TABLE IF NOT EXISTS moz_hosts ( + id INTEGER PRIMARY KEY, + host TEXT, + type TEXT, + permission INTEGER, + expireType INTEGER, + expireTime INTEGER, + modificationTime INTEGER, + appId INTEGER, + isInBrowserElement INTEGER)""" + ) + elif version == 3: + cursor.execute( + """CREATE TABLE IF NOT EXISTS moz_hosts ( + id INTEGER PRIMARY KEY, + host TEXT, + type TEXT, + permission INTEGER, + expireType INTEGER, + expireTime INTEGER, + appId INTEGER, + isInBrowserElement INTEGER)""" + ) + elif version == 2: + cursor.execute( + """CREATE TABLE IF NOT EXISTS moz_hosts ( + id INTEGER PRIMARY KEY, + host TEXT, + type TEXT, + permission INTEGER, + expireType INTEGER, + expireTime INTEGER)""" + ) + else: + raise Exception("version must be 2, 3, 4 or 5") + permDB.commit() + + # Create a permissions object to read the db + Permissions(os.path.dirname(perms_db_filename), locations_file) + return version + + +def test_verify_user_version(version, permDB): + """Verifies that we call INSERT statements using the correct number + of columns for existing databases. + """ + select_stmt = "select * from moz_hosts" + + cur = permDB.cursor() + cur.execute(select_stmt) + entries = cur.fetchall() + + assert len(entries) == 3 + + columns = { + 1: 6, + 2: 6, + 3: 8, + 4: 9, + 5: 7, + }[version] + + assert len(entries[0]) == columns + for x in range(4, columns): + assert entries[0][x] == 0 + + +def test_schema_version(perms, locations_file): + profile_dir = perms._profileDir + perms_db_filename = os.path.join(profile_dir, "permissions.sqlite") + perms.write_db(open(locations_file, "w+b")) + + stmt = "PRAGMA user_version;" + + con = sqlite3.connect(perms_db_filename) + cur = con.cursor() + cur.execute(stmt) + entries = cur.fetchall() + + schema_version = entries[0][0] + assert schema_version == 5 + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_preferences.py b/testing/mozbase/mozprofile/tests/test_preferences.py new file mode 100755 index 0000000000..261fe6f2a0 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_preferences.py @@ -0,0 +1,422 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import + +import mozfile +import os +import shutil +import tempfile + +import mozunit +import pytest +from wptserve import server + +from mozprofile.cli import MozProfileCLI +from mozprofile.prefs import Preferences, PreferencesReadError +from mozprofile.profile import Profile + +here = os.path.dirname(os.path.abspath(__file__)) + + +# preferences from files/prefs_with_comments.js +_prefs_with_comments = { + "browser.startup.homepage": "http://planet.mozilla.org", + "zoom.minPercent": 30, + "zoom.maxPercent": 300, + "webgl.verbose": "false", +} + + +@pytest.fixture +def run_command(): + """ + invokes mozprofile command line via the CLI factory + - args : command line arguments (equivalent of sys.argv[1:]) + """ + + def inner(*args): + # instantiate the factory + cli = MozProfileCLI(list(args)) + + # create the profile + profile = cli.profile() + + # return path to profile + return profile.profile + + return inner + + +@pytest.fixture +def compare_generated(run_command): + """ + writes out to a new profile with mozprofile command line + reads the generated preferences with prefs.py + compares the results + cleans up + """ + + def inner(prefs, commandline): + profile = run_command(*commandline) + prefs_file = os.path.join(profile, "user.js") + assert os.path.exists(prefs_file) + read = Preferences.read_prefs(prefs_file) + if isinstance(prefs, dict): + read = dict(read) + assert prefs == read + shutil.rmtree(profile) + + return inner + + +def test_basic_prefs(compare_generated): + """test setting a pref from the command line entry point""" + + _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"} + commandline = [] + for pref, value in _prefs.items(): + commandline += ["--pref", "%s:%s" % (pref, value)] + compare_generated(_prefs, commandline) + + +def test_ordered_prefs(compare_generated): + """ensure the prefs stay in the right order""" + _prefs = [ + ("browser.startup.homepage", "http://planet.mozilla.org/"), + ("zoom.minPercent", 30), + ("zoom.maxPercent", 300), + ("webgl.verbose", "false"), + ] + commandline = [] + for pref, value in _prefs: + commandline += ["--pref", "%s:%s" % (pref, value)] + _prefs = [(i, Preferences.cast(j)) for i, j in _prefs] + compare_generated(_prefs, commandline) + + +def test_ini(compare_generated): + # write the .ini file + _ini = """[DEFAULT] +browser.startup.homepage = http://planet.mozilla.org/ + +[foo] +browser.startup.homepage = http://github.com/ +""" + try: + fd, name = tempfile.mkstemp(suffix=".ini", text=True) + os.write(fd, _ini.encode()) + os.close(fd) + commandline = ["--preferences", name] + + # test the [DEFAULT] section + _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"} + compare_generated(_prefs, commandline) + + # test a specific section + _prefs = {"browser.startup.homepage": "http://github.com/"} + commandline[-1] = commandline[-1] + ":foo" + compare_generated(_prefs, commandline) + + finally: + # cleanup + os.remove(name) + + +def test_ini_keep_case(compare_generated): + """ + Read a preferences config file with a preference in camel-case style. + Check that the read preference name has not been lower-cased + """ + # write the .ini file + _ini = """[DEFAULT] +network.dns.disableIPv6 = True +""" + try: + fd, name = tempfile.mkstemp(suffix=".ini", text=True) + os.write(fd, _ini.encode()) + os.close(fd) + commandline = ["--preferences", name] + + # test the [DEFAULT] section + _prefs = {"network.dns.disableIPv6": "True"} + compare_generated(_prefs, commandline) + + finally: + # cleanup + os.remove(name) + + +def test_reset_should_remove_added_prefs(): + """Check that when we call reset the items we expect are updated""" + profile = Profile() + prefs_file = os.path.join(profile.profile, "user.js") + + # we shouldn't have any initial preferences + initial_prefs = Preferences.read_prefs(prefs_file) + assert not initial_prefs + initial_prefs = open(prefs_file).read().strip() + assert not initial_prefs + + # add some preferences + prefs1 = [("mr.t.quotes", "i aint getting on no plane!")] + profile.set_preferences(prefs1) + assert prefs1 == Preferences.read_prefs(prefs_file) + lines = open(prefs_file).read().strip().splitlines() + assert any(line.startswith("#MozRunner Prefs Start") for line in lines) + assert any(line.startswith("#MozRunner Prefs End") for line in lines) + + profile.reset() + assert prefs1 != Preferences.read_prefs(os.path.join(profile.profile, "user.js")) + + +def test_reset_should_keep_user_added_prefs(): + """Check that when we call reset the items we expect are updated""" + profile = Profile() + prefs_file = os.path.join(profile.profile, "user.js") + + # we shouldn't have any initial preferences + initial_prefs = Preferences.read_prefs(prefs_file) + assert not initial_prefs + initial_prefs = open(prefs_file).read().strip() + assert not initial_prefs + + # add some preferences + prefs1 = [("mr.t.quotes", "i aint getting on no plane!")] + profile.set_persistent_preferences(prefs1) + assert prefs1 == Preferences.read_prefs(prefs_file) + lines = open(prefs_file).read().strip().splitlines() + assert any(line.startswith("#MozRunner Prefs Start") for line in lines) + assert any(line.startswith("#MozRunner Prefs End") for line in lines) + + profile.reset() + assert prefs1 == Preferences.read_prefs(os.path.join(profile.profile, "user.js")) + + +def test_magic_markers(): + """ensure our magic markers are working""" + + profile = Profile() + prefs_file = os.path.join(profile.profile, "user.js") + + # we shouldn't have any initial preferences + initial_prefs = Preferences.read_prefs(prefs_file) + assert not initial_prefs + initial_prefs = open(prefs_file).read().strip() + assert not initial_prefs + + # add some preferences + prefs1 = [ + ("browser.startup.homepage", "http://planet.mozilla.org/"), + ("zoom.minPercent", 30), + ] + profile.set_preferences(prefs1) + assert prefs1 == Preferences.read_prefs(prefs_file) + lines = open(prefs_file).read().strip().splitlines() + assert bool([line for line in lines if line.startswith("#MozRunner Prefs Start")]) + assert bool([line for line in lines if line.startswith("#MozRunner Prefs End")]) + + # add some more preferences + prefs2 = [("zoom.maxPercent", 300), ("webgl.verbose", "false")] + profile.set_preferences(prefs2) + assert prefs1 + prefs2 == Preferences.read_prefs(prefs_file) + lines = open(prefs_file).read().strip().splitlines() + assert ( + len([line for line in lines if line.startswith("#MozRunner Prefs Start")]) == 2 + ) + assert len([line for line in lines if line.startswith("#MozRunner Prefs End")]) == 2 + + # now clean it up + profile.clean_preferences() + final_prefs = Preferences.read_prefs(prefs_file) + assert not final_prefs + lines = open(prefs_file).read().strip().splitlines() + assert "#MozRunner Prefs Start" not in lines + assert "#MozRunner Prefs End" not in lines + + +def test_preexisting_preferences(): + """ensure you don't clobber preexisting preferences""" + + # make a pretend profile + tempdir = tempfile.mkdtemp() + + try: + # make a user.js + contents = """ +user_pref("webgl.enabled_for_all_sites", true); +user_pref("webgl.force-enabled", true); +""" + user_js = os.path.join(tempdir, "user.js") + f = open(user_js, "w") + f.write(contents) + f.close() + + # make sure you can read it + prefs = Preferences.read_prefs(user_js) + original_prefs = [ + ("webgl.enabled_for_all_sites", True), + ("webgl.force-enabled", True), + ] + assert prefs == original_prefs + + # now read this as a profile + profile = Profile( + tempdir, preferences={"browser.download.dir": "/home/jhammel"} + ) + + # make sure the new pref is now there + new_prefs = original_prefs[:] + [("browser.download.dir", "/home/jhammel")] + prefs = Preferences.read_prefs(user_js) + assert prefs == new_prefs + + # clean up the added preferences + profile.cleanup() + del profile + + # make sure you have the original preferences + prefs = Preferences.read_prefs(user_js) + assert prefs == original_prefs + finally: + shutil.rmtree(tempdir) + + +def test_can_read_prefs_with_multiline_comments(): + """ + Ensure that multiple comments in the file header do not break reading + the prefs (https://bugzilla.mozilla.org/show_bug.cgi?id=1233534). + """ + user_js = tempfile.NamedTemporaryFile(suffix=".js", delete=False) + try: + with user_js: + user_js.write( + """ +# Mozilla User Preferences + +/* Do not edit this file. +* +* If you make changes to this file while the application is running, +* the changes will be overwritten when the application exits. +* +* To make a manual change to preferences, you can visit the URL about:config +*/ + +user_pref("webgl.enabled_for_all_sites", true); +user_pref("webgl.force-enabled", true); +""".encode() + ) + assert Preferences.read_prefs(user_js.name) == [ + ("webgl.enabled_for_all_sites", True), + ("webgl.force-enabled", True), + ] + finally: + mozfile.remove(user_js.name) + + +def test_json(compare_generated): + _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"} + json = '{"browser.startup.homepage": "http://planet.mozilla.org/"}' + + # just repr it...could use the json module but we don't need it here + with mozfile.NamedTemporaryFile(suffix=".json") as f: + f.write(json.encode()) + f.flush() + + commandline = ["--preferences", f.name] + compare_generated(_prefs, commandline) + + +def test_json_datatypes(): + # minPercent is at 30.1 to test if non-integer data raises an exception + json = """{"zoom.minPercent": 30.1, "zoom.maxPercent": 300}""" + + with mozfile.NamedTemporaryFile(suffix=".json") as f: + f.write(json.encode()) + f.flush() + + with pytest.raises(PreferencesReadError): + Preferences.read_json(f._path) + + +def test_prefs_write(): + """test that the Preferences.write() method correctly serializes preferences""" + + _prefs = { + "browser.startup.homepage": "http://planet.mozilla.org", + "zoom.minPercent": 30, + "zoom.maxPercent": 300, + } + + # make a Preferences manager with the testing preferences + preferences = Preferences(_prefs) + + # write them to a temporary location + path = None + read_prefs = None + try: + with mozfile.NamedTemporaryFile(suffix=".js", delete=False, mode="w+t") as f: + path = f.name + preferences.write(f, _prefs) + + # read them back and ensure we get what we put in + read_prefs = dict(Preferences.read_prefs(path)) + + finally: + # cleanup + if path and os.path.exists(path): + os.remove(path) + + assert read_prefs == _prefs + + +def test_read_prefs_with_comments(): + """test reading preferences from a prefs.js file that contains comments""" + + path = os.path.join(here, "files", "prefs_with_comments.js") + assert dict(Preferences.read_prefs(path)) == _prefs_with_comments + + +def test_read_prefs_with_interpolation(): + """test reading preferences from a prefs.js file whose values + require interpolation""" + + expected_prefs = { + "browser.foo": "http://server-name", + "zoom.minPercent": 30, + "webgl.verbose": "false", + "browser.bar": "somethingxyz", + } + values = {"server": "server-name", "abc": "something"} + path = os.path.join(here, "files", "prefs_with_interpolation.js") + read_prefs = Preferences.read_prefs(path, interpolation=values) + assert dict(read_prefs) == expected_prefs + + +def test_read_prefs_ttw(): + """test reading preferences through the web via wptserve""" + + # create a WebTestHttpd instance + docroot = os.path.join(here, "files") + host = "127.0.0.1" + port = 8888 + httpd = server.WebTestHttpd(host=host, port=port, doc_root=docroot) + + # create a preferences instance + prefs = Preferences() + + try: + # start server + httpd.start(block=False) + + # read preferences through the web + read = prefs.read_prefs("http://%s:%d/prefs_with_comments.js" % (host, port)) + assert dict(read) == _prefs_with_comments + finally: + httpd.stop() + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_profile.py b/testing/mozbase/mozprofile/tests/test_profile.py new file mode 100644 index 0000000000..20aaf959de --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_profile.py @@ -0,0 +1,114 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import, division + +import os + +import mozunit +import pytest + +from mozprofile.prefs import Preferences +from mozprofile import ( + BaseProfile, + Profile, + ChromeProfile, + ChromiumProfile, + FirefoxProfile, + ThunderbirdProfile, + create_profile, +) + +here = os.path.abspath(os.path.dirname(__file__)) + + +def test_with_profile_should_cleanup(): + with Profile() as profile: + assert os.path.exists(profile.profile) + + # profile is cleaned + assert not os.path.exists(profile.profile) + + +def test_with_profile_should_cleanup_even_on_exception(): + with pytest.raises(ZeroDivisionError): + # pylint --py3k W1619 + with Profile() as profile: + assert os.path.exists(profile.profile) + 1 / 0 # will raise ZeroDivisionError + + # profile is cleaned + assert not os.path.exists(profile.profile) + + +@pytest.mark.parametrize( + "app,cls", + [ + ("chrome", ChromeProfile), + ("chromium", ChromiumProfile), + ("firefox", FirefoxProfile), + ("thunderbird", ThunderbirdProfile), + ("unknown", None), + ], +) +def test_create_profile(tmpdir, app, cls): + path = tmpdir.strpath + + if cls is None: + with pytest.raises(NotImplementedError): + create_profile(app) + return + + profile = create_profile(app, profile=path) + assert isinstance(profile, BaseProfile) + assert profile.__class__ == cls + assert profile.profile == path + + +@pytest.mark.parametrize( + "cls", + [ + Profile, + ChromeProfile, + ChromiumProfile, + ], +) +def test_merge_profile(cls): + profile = cls(preferences={"foo": "bar"}) + assert profile._addons == [] + assert os.path.isfile( + os.path.join(profile.profile, profile.preference_file_names[0]) + ) + + other_profile = os.path.join(here, "files", "dummy-profile") + profile.merge(other_profile) + + # make sure to add a pref file for each preference_file_names in the dummy-profile + prefs = {} + for name in profile.preference_file_names: + path = os.path.join(profile.profile, name) + assert os.path.isfile(path) + + try: + prefs.update(Preferences.read_json(path)) + except ValueError: + prefs.update(Preferences.read_prefs(path)) + + assert "foo" in prefs + assert len(prefs) == len(profile.preference_file_names) + 1 + assert all(name in prefs for name in profile.preference_file_names) + + # for Google Chrome currently we ignore webext in profile prefs + if cls == Profile: + assert len(profile._addons) == 1 + assert profile._addons[0].endswith("empty.xpi") + assert os.path.exists(profile._addons[0]) + else: + assert len(profile._addons) == 0 + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_profile_view.py b/testing/mozbase/mozprofile/tests/test_profile_view.py new file mode 100644 index 0000000000..948491c140 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_profile_view.py @@ -0,0 +1,78 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import + +import mozprofile +import os +import sys +import pytest + +import mozunit +from six import text_type + +here = os.path.dirname(os.path.abspath(__file__)) + + +def test_profileprint(tmpdir): + """Test the summary function.""" + keys = set(["Files", "Path"]) + + tmpdir = tmpdir.strpath + profile = mozprofile.FirefoxProfile(tmpdir) + parts = profile.summary(return_parts=True) + parts = dict(parts) + + assert parts["Path"] == tmpdir + assert set(parts.keys()) == keys + + +def test_str_cast(): + """Test casting to a string.""" + profile = mozprofile.Profile() + if sys.version_info[0] >= 3: + assert str(profile) == profile.summary() + else: + assert str(profile) == profile.summary().encode("utf-8") + + +@pytest.mark.skipif( + sys.version_info[0] >= 3, reason="no unicode() operator starting from python3" +) +def test_unicode_cast(): + """Test casting to a unicode string.""" + profile = mozprofile.Profile() + assert text_type(profile) == profile.summary() + + +def test_profile_diff(): + profile1 = mozprofile.Profile() + profile2 = mozprofile.Profile(preferences=dict(foo="bar")) + + # diff a profile against itself; no difference + assert mozprofile.diff(profile1, profile1) == [] + + # diff two profiles + diff = dict(mozprofile.diff(profile1, profile2)) + assert list(diff.keys()) == ["user.js"] + lines = [line.strip() for line in diff["user.js"].splitlines()] + assert "+foo: bar" in lines + + # diff a blank vs FirefoxProfile + ff_profile = mozprofile.FirefoxProfile() + diff = dict(mozprofile.diff(profile2, ff_profile)) + assert list(diff.keys()) == ["user.js"] + lines = [line.strip() for line in diff["user.js"].splitlines()] + assert "-foo: bar" in lines + ff_pref_lines = [ + "+%s: %s" % (key, value) + for key, value in mozprofile.FirefoxProfile.preferences.items() + ] + assert set(ff_pref_lines).issubset(lines) + + +if __name__ == "__main__": + mozunit.main() diff --git a/testing/mozbase/mozprofile/tests/test_server_locations.py b/testing/mozbase/mozprofile/tests/test_server_locations.py new file mode 100644 index 0000000000..caa07196c5 --- /dev/null +++ b/testing/mozbase/mozprofile/tests/test_server_locations.py @@ -0,0 +1,151 @@ +#!/usr/bin/env 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/. + +from __future__ import absolute_import + +import mozunit +import pytest + +from mozprofile.permissions import ( + ServerLocations, + MissingPrimaryLocationError, + MultiplePrimaryLocationsError, + BadPortLocationError, + LocationsSyntaxError, +) + + +LOCATIONS = """# This is the primary location from which tests run. +# +http://mochi.test:8888 primary,privileged + +# a few test locations +http://127.0.0.1:80 privileged +http://127.0.0.1:8888 privileged +https://test:80 privileged +http://example.org:80 privileged +http://test1.example.org privileged + +""" + +LOCATIONS_NO_PRIMARY = """http://secondary.test:80 privileged +http://tertiary.test:8888 privileged +""" + +LOCATIONS_BAD_PORT = """http://mochi.test:8888 primary,privileged +http://127.0.0.1:80 privileged +http://127.0.0.1:8888 privileged +http://test:badport privileged +http://example.org:80 privileged +""" + + +def compare_location(location, scheme, host, port, options): + assert location.scheme == scheme + assert location.host == host + assert location.port == port + assert location.options == options + + +@pytest.fixture +def create_temp_file(tmpdir): + def inner(contents): + f = tmpdir.mkdtemp().join("locations.txt") + f.write(contents) + return f.strpath + + return inner + + +def test_server_locations(create_temp_file): + # write a permissions file + f = create_temp_file(LOCATIONS) + + # read the locations + locations = ServerLocations(f) + + # ensure that they're what we expect + assert len(locations) == 6 + i = iter(locations) + compare_location(next(i), "http", "mochi.test", "8888", ["primary", "privileged"]) + compare_location(next(i), "http", "127.0.0.1", "80", ["privileged"]) + compare_location(next(i), "http", "127.0.0.1", "8888", ["privileged"]) + compare_location(next(i), "https", "test", "80", ["privileged"]) + compare_location(next(i), "http", "example.org", "80", ["privileged"]) + compare_location(next(i), "http", "test1.example.org", "8888", ["privileged"]) + + locations.add_host("mozilla.org") + assert len(locations) == 7 + compare_location(next(i), "http", "mozilla.org", "80", ["privileged"]) + + # test some errors + with pytest.raises(MultiplePrimaryLocationsError): + locations.add_host("primary.test", options="primary") + + # assert we don't throw DuplicateLocationError + locations.add_host("127.0.0.1") + + with pytest.raises(BadPortLocationError): + locations.add_host("127.0.0.1", port="abc") + + # test some errors in locations file + f = create_temp_file(LOCATIONS_NO_PRIMARY) + + exc = None + try: + ServerLocations(f) + except LocationsSyntaxError as e: + exc = e + assert exc is not None + assert exc.err.__class__ == MissingPrimaryLocationError + assert exc.lineno == 3 + + # test bad port in a locations file to ensure lineno calculated + # properly. + f = create_temp_file(LOCATIONS_BAD_PORT) + + exc = None + try: + ServerLocations(f) + except LocationsSyntaxError as e: + exc = e + assert exc is not None + assert exc.err.__class__ == BadPortLocationError + assert exc.lineno == 4 + + +def test_server_locations_callback(create_temp_file): + class CallbackTest(object): + last_locations = None + + def callback(self, locations): + self.last_locations = locations + + c = CallbackTest() + f = create_temp_file(LOCATIONS) + locations = ServerLocations(f, c.callback) + + # callback should be for all locations in file + assert len(c.last_locations) == 6 + + # validate arbitrary one + compare_location(c.last_locations[2], "http", "127.0.0.1", "8888", ["privileged"]) + + locations.add_host("a.b.c") + + # callback should be just for one location + assert len(c.last_locations) == 1 + compare_location(c.last_locations[0], "http", "a.b.c", "80", ["privileged"]) + + # read a second file, which should generate a callback with both + # locations. + f = create_temp_file(LOCATIONS_NO_PRIMARY) + locations.read(f) + assert len(c.last_locations) == 2 + + +if __name__ == "__main__": + mozunit.main() |