test_preferences.py (13233B)
1 #!/usr/bin/env python 2 3 # This Source Code Form is subject to the terms of the Mozilla Public 4 # License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 # You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 import os 8 import shutil 9 import tempfile 10 11 import mozfile 12 import mozunit 13 import pytest 14 from mozprofile.cli import MozProfileCLI 15 from mozprofile.prefs import Preferences, PreferencesReadError 16 from mozprofile.profile import Profile 17 from wptserve import server 18 19 here = os.path.dirname(os.path.abspath(__file__)) 20 21 22 # preferences from files/prefs_with_comments.js 23 _prefs_with_comments = { 24 "browser.startup.homepage": "http://planet.mozilla.org", 25 "zoom.minPercent": 30, 26 "zoom.maxPercent": 300, 27 "webgl.verbose": "false", 28 } 29 30 31 @pytest.fixture 32 def run_command(): 33 """ 34 invokes mozprofile command line via the CLI factory 35 - args : command line arguments (equivalent of sys.argv[1:]) 36 """ 37 38 def inner(*args): 39 # instantiate the factory 40 cli = MozProfileCLI(list(args)) 41 42 # create the profile 43 profile = cli.profile() 44 45 # return path to profile 46 return profile.profile 47 48 return inner 49 50 51 @pytest.fixture 52 def compare_generated(run_command): 53 """ 54 writes out to a new profile with mozprofile command line 55 reads the generated preferences with prefs.py 56 compares the results 57 cleans up 58 """ 59 60 def inner(prefs, commandline): 61 profile = run_command(*commandline) 62 prefs_file = os.path.join(profile, "user.js") 63 assert os.path.exists(prefs_file) 64 read = Preferences.read_prefs(prefs_file) 65 if isinstance(prefs, dict): 66 read = dict(read) 67 assert prefs == read 68 shutil.rmtree(profile) 69 70 return inner 71 72 73 def test_basic_prefs(compare_generated): 74 """test setting a pref from the command line entry point""" 75 76 _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"} 77 commandline = [] 78 for pref, value in _prefs.items(): 79 commandline += ["--pref", "%s:%s" % (pref, value)] 80 compare_generated(_prefs, commandline) 81 82 83 def test_ordered_prefs(compare_generated): 84 """ensure the prefs stay in the right order""" 85 _prefs = [ 86 ("browser.startup.homepage", "http://planet.mozilla.org/"), 87 ("zoom.minPercent", 30), 88 ("zoom.maxPercent", 300), 89 ("webgl.verbose", "false"), 90 ] 91 commandline = [] 92 for pref, value in _prefs: 93 commandline += ["--pref", "%s:%s" % (pref, value)] 94 _prefs = [(i, Preferences.cast(j)) for i, j in _prefs] 95 compare_generated(_prefs, commandline) 96 97 98 def test_ini(compare_generated): 99 # write the .ini file 100 _ini = """[DEFAULT] 101 browser.startup.homepage = http://planet.mozilla.org/ 102 103 [foo] 104 browser.startup.homepage = http://github.com/ 105 """ 106 try: 107 fd, name = tempfile.mkstemp(suffix=".ini", text=True) 108 os.write(fd, _ini.encode()) 109 os.close(fd) 110 commandline = ["--preferences", name] 111 112 # test the [DEFAULT] section 113 _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"} 114 compare_generated(_prefs, commandline) 115 116 # test a specific section 117 _prefs = {"browser.startup.homepage": "http://github.com/"} 118 commandline[-1] = commandline[-1] + ":foo" 119 compare_generated(_prefs, commandline) 120 121 finally: 122 # cleanup 123 os.remove(name) 124 125 126 def test_ini_keep_case(compare_generated): 127 """ 128 Read a preferences config file with a preference in camel-case style. 129 Check that the read preference name has not been lower-cased 130 """ 131 # write the .ini file 132 _ini = """[DEFAULT] 133 network.dns.disableIPv6 = True 134 """ 135 try: 136 fd, name = tempfile.mkstemp(suffix=".ini", text=True) 137 os.write(fd, _ini.encode()) 138 os.close(fd) 139 commandline = ["--preferences", name] 140 141 # test the [DEFAULT] section 142 _prefs = {"network.dns.disableIPv6": "True"} 143 compare_generated(_prefs, commandline) 144 145 finally: 146 # cleanup 147 os.remove(name) 148 149 150 def test_reset_should_remove_added_prefs(): 151 """Check that when we call reset the items we expect are updated""" 152 profile = Profile() 153 prefs_file = os.path.join(profile.profile, "user.js") 154 155 # we shouldn't have any initial preferences 156 initial_prefs = Preferences.read_prefs(prefs_file) 157 assert not initial_prefs 158 initial_prefs = open(prefs_file).read().strip() 159 assert not initial_prefs 160 161 # add some preferences 162 prefs1 = [("mr.t.quotes", "i aint getting on no plane!")] 163 profile.set_preferences(prefs1) 164 assert prefs1 == Preferences.read_prefs(prefs_file) 165 lines = open(prefs_file).read().strip().splitlines() 166 assert any(line.startswith("#MozRunner Prefs Start") for line in lines) 167 assert any(line.startswith("#MozRunner Prefs End") for line in lines) 168 169 profile.reset() 170 assert prefs1 != Preferences.read_prefs(os.path.join(profile.profile, "user.js")) 171 172 173 def test_reset_should_keep_user_added_prefs(): 174 """Check that when we call reset the items we expect are updated""" 175 profile = Profile() 176 prefs_file = os.path.join(profile.profile, "user.js") 177 178 # we shouldn't have any initial preferences 179 initial_prefs = Preferences.read_prefs(prefs_file) 180 assert not initial_prefs 181 initial_prefs = open(prefs_file).read().strip() 182 assert not initial_prefs 183 184 # add some preferences 185 prefs1 = [("mr.t.quotes", "i aint getting on no plane!")] 186 profile.set_persistent_preferences(prefs1) 187 assert prefs1 == Preferences.read_prefs(prefs_file) 188 lines = open(prefs_file).read().strip().splitlines() 189 assert any(line.startswith("#MozRunner Prefs Start") for line in lines) 190 assert any(line.startswith("#MozRunner Prefs End") for line in lines) 191 192 profile.reset() 193 assert prefs1 == Preferences.read_prefs(os.path.join(profile.profile, "user.js")) 194 195 196 def test_magic_markers(): 197 """ensure our magic markers are working""" 198 199 profile = Profile() 200 prefs_file = os.path.join(profile.profile, "user.js") 201 202 # we shouldn't have any initial preferences 203 initial_prefs = Preferences.read_prefs(prefs_file) 204 assert not initial_prefs 205 initial_prefs = open(prefs_file).read().strip() 206 assert not initial_prefs 207 208 # add some preferences 209 prefs1 = [ 210 ("browser.startup.homepage", "http://planet.mozilla.org/"), 211 ("zoom.minPercent", 30), 212 ] 213 profile.set_preferences(prefs1) 214 assert prefs1 == Preferences.read_prefs(prefs_file) 215 lines = open(prefs_file).read().strip().splitlines() 216 assert bool([line for line in lines if line.startswith("#MozRunner Prefs Start")]) 217 assert bool([line for line in lines if line.startswith("#MozRunner Prefs End")]) 218 219 # add some more preferences 220 prefs2 = [("zoom.maxPercent", 300), ("webgl.verbose", "false")] 221 profile.set_preferences(prefs2) 222 assert prefs1 + prefs2 == Preferences.read_prefs(prefs_file) 223 lines = open(prefs_file).read().strip().splitlines() 224 assert ( 225 len([line for line in lines if line.startswith("#MozRunner Prefs Start")]) == 2 226 ) 227 assert len([line for line in lines if line.startswith("#MozRunner Prefs End")]) == 2 228 229 # now clean it up 230 profile.clean_preferences() 231 final_prefs = Preferences.read_prefs(prefs_file) 232 assert not final_prefs 233 lines = open(prefs_file).read().strip().splitlines() 234 assert "#MozRunner Prefs Start" not in lines 235 assert "#MozRunner Prefs End" not in lines 236 237 238 def test_preexisting_preferences(): 239 """ensure you don't clobber preexisting preferences""" 240 241 # make a pretend profile 242 tempdir = tempfile.mkdtemp() 243 244 try: 245 # make a user.js 246 contents = """ 247 user_pref("webgl.enabled_for_all_sites", true); 248 user_pref("webgl.force-enabled", true); 249 """ 250 user_js = os.path.join(tempdir, "user.js") 251 f = open(user_js, "w") 252 f.write(contents) 253 f.close() 254 255 # make sure you can read it 256 prefs = Preferences.read_prefs(user_js) 257 original_prefs = [ 258 ("webgl.enabled_for_all_sites", True), 259 ("webgl.force-enabled", True), 260 ] 261 assert prefs == original_prefs 262 263 # now read this as a profile 264 profile = Profile( 265 tempdir, preferences={"browser.download.dir": "/home/jhammel"} 266 ) 267 268 # make sure the new pref is now there 269 new_prefs = original_prefs[:] + [("browser.download.dir", "/home/jhammel")] 270 prefs = Preferences.read_prefs(user_js) 271 assert prefs == new_prefs 272 273 # clean up the added preferences 274 profile.cleanup() 275 del profile 276 277 # make sure you have the original preferences 278 prefs = Preferences.read_prefs(user_js) 279 assert prefs == original_prefs 280 finally: 281 shutil.rmtree(tempdir) 282 283 284 def test_can_read_prefs_with_multiline_comments(): 285 """ 286 Ensure that multiple comments in the file header do not break reading 287 the prefs (https://bugzilla.mozilla.org/show_bug.cgi?id=1233534). 288 """ 289 user_js = tempfile.NamedTemporaryFile(suffix=".js", delete=False) 290 try: 291 with user_js: 292 user_js.write( 293 b""" 294 # Mozilla User Preferences 295 296 /* Do not edit this file. 297 * 298 * If you make changes to this file while the application is running, 299 * the changes will be overwritten when the application exits. 300 * 301 * To make a manual change to preferences, you can visit the URL about:config 302 */ 303 304 user_pref("webgl.enabled_for_all_sites", true); 305 user_pref("webgl.force-enabled", true); 306 """ 307 ) 308 assert Preferences.read_prefs(user_js.name) == [ 309 ("webgl.enabled_for_all_sites", True), 310 ("webgl.force-enabled", True), 311 ] 312 finally: 313 mozfile.remove(user_js.name) 314 315 316 def test_json(compare_generated): 317 _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"} 318 json = '{"browser.startup.homepage": "http://planet.mozilla.org/"}' 319 320 # just repr it...could use the json module but we don't need it here 321 with mozfile.NamedTemporaryFile(suffix=".json") as f: 322 f.write(json.encode()) 323 f.flush() 324 325 commandline = ["--preferences", f.name] 326 compare_generated(_prefs, commandline) 327 328 329 def test_json_datatypes(): 330 # minPercent is at 30.1 to test if non-integer data raises an exception 331 json = """{"zoom.minPercent": 30.1, "zoom.maxPercent": 300}""" 332 333 with mozfile.NamedTemporaryFile(suffix=".json") as f: 334 f.write(json.encode()) 335 f.flush() 336 337 with pytest.raises(PreferencesReadError): 338 Preferences.read_json(f._path) 339 340 341 def test_prefs_write(): 342 """test that the Preferences.write() method correctly serializes preferences""" 343 344 _prefs = { 345 "browser.startup.homepage": "http://planet.mozilla.org", 346 "zoom.minPercent": 30, 347 "zoom.maxPercent": 300, 348 } 349 350 # make a Preferences manager with the testing preferences 351 preferences = Preferences(_prefs) 352 353 # write them to a temporary location 354 path = None 355 read_prefs = None 356 try: 357 with mozfile.NamedTemporaryFile(suffix=".js", delete=False, mode="w+t") as f: 358 path = f.name 359 preferences.write(f, _prefs) 360 361 # read them back and ensure we get what we put in 362 read_prefs = dict(Preferences.read_prefs(path)) 363 364 finally: 365 # cleanup 366 if path and os.path.exists(path): 367 os.remove(path) 368 369 assert read_prefs == _prefs 370 371 372 def test_read_prefs_with_comments(): 373 """test reading preferences from a prefs.js file that contains comments""" 374 375 path = os.path.join(here, "files", "prefs_with_comments.js") 376 assert dict(Preferences.read_prefs(path)) == _prefs_with_comments 377 378 379 def test_read_prefs_with_interpolation(): 380 """test reading preferences from a prefs.js file whose values 381 require interpolation""" 382 383 expected_prefs = { 384 "browser.foo": "http://server-name", 385 "zoom.minPercent": 30, 386 "webgl.verbose": "false", 387 "browser.bar": "somethingxyz", 388 } 389 values = {"server": "server-name", "abc": "something"} 390 path = os.path.join(here, "files", "prefs_with_interpolation.js") 391 read_prefs = Preferences.read_prefs(path, interpolation=values) 392 assert dict(read_prefs) == expected_prefs 393 394 395 def test_read_prefs_with_multiline(): 396 """test reading preferences from a prefs.js file that contains multiline prefs""" 397 398 path = os.path.join(here, "files", "prefs_with_multiline.js") 399 assert dict(Preferences.read_prefs(path)) == { 400 "browser.long.preference.name.that.causes.the.line.to.wrap": "itislong" 401 } 402 403 404 def test_read_prefs_ttw(): 405 """test reading preferences through the web via wptserve""" 406 407 # create a WebTestHttpd instance 408 docroot = os.path.join(here, "files") 409 host = "127.0.0.1" 410 port = 8888 411 httpd = server.WebTestHttpd(host=host, port=port, doc_root=docroot) 412 413 # create a preferences instance 414 prefs = Preferences() 415 416 try: 417 # start server 418 httpd.start() 419 420 # read preferences through the web 421 read = prefs.read_prefs("http://%s:%d/prefs_with_comments.js" % (host, port)) 422 assert dict(read) == _prefs_with_comments 423 finally: 424 httpd.stop() 425 426 427 if __name__ == "__main__": 428 mozunit.main()