#!/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/. import os import shutil import tempfile import mozfile import mozunit import pytest from mozprofile.cli import MozProfileCLI from mozprofile.prefs import Preferences, PreferencesReadError from mozprofile.profile import Profile from wptserve import server 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_with_multiline(): """test reading preferences from a prefs.js file that contains multiline prefs""" path = os.path.join(here, "files", "prefs_with_multiline.js") assert dict(Preferences.read_prefs(path)) == { "browser.long.preference.name.that.causes.the.line.to.wrap": "itislong" } 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() # 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()