Bug 1486971 - Test for dynamically change of the prefers-reduced-motion setting on MacOSX. r=froydnj,mstange
The framework to simulate the setting change works as following;
- nsIDOMWindowUtils.setPrefersReducedMotion() calls an IPC function which ends
up calling nsChildView::SetPrefersReducedMotion() in the parent process
- nsChildView::SetPrefersReducedMotion() sets the given value into
nsLookAndFeel::mPrefersReducedMotionCached just like we set the value queried
via NSWorkspace.accessibilityDisplayShouldReduceMotion in the parent process
and send a notification which is the same notification MacOSX sends when the
system setting changed
- Normally the cached value is cleared before quering new values since the
cache value is stale, but in this case the value is up-to-date one, so
nsChildView::SetPrefersReducedMotion() tells that we don't need to clear the
cache, and nsIDOMWindowUtils.resetPrefersReducedMotion() resets that state
of 'we don't need to clear the cache'
There are two test cases with the framework in this commit, one is just setting
the value and checking the value queried by window.matchMedia. The other one is
receiving 'change' event and checking the value of the event target.
Note that to make this test works the patch for bug 1478212 is necessary since
the test runs in an iframe.
Depends on D5003
Differential Revision: https://phabricator.services.mozilla.com/D5004

#!/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/.importosimportsysimportsubprocessfromzipfileimportZipFileimportruncppunittestsascppunittestsimportmozcrashimportmozfileimportmozinfoimportmozlogimportposixpathfrommozdeviceimportADBAndroid,ADBProcessError,ADBTimeoutErrortry:frommozbuild.baseimportMozbuildObjectbuild_obj=MozbuildObject.from_environment()exceptImportError:build_obj=NoneclassRemoteCPPUnitTests(cppunittests.CPPUnitTests):def__init__(self,options,progs):cppunittests.CPPUnitTests.__init__(self)self.options=optionsself.device=ADBAndroid(adb=options.adb_pathor'adb',device=options.device_serial,test_root=options.remote_test_root)self.remote_test_root=posixpath.join(self.device.test_root,"cppunittests")self.remote_bin_dir=posixpath.join(self.remote_test_root,"b")self.remote_tmp_dir=posixpath.join(self.remote_test_root,"tmp")self.remote_home_dir=posixpath.join(self.remote_test_root,"h")ifoptions.setup:self.setup_bin(progs)defsetup_bin(self,progs):self.device.rm(self.remote_test_root,force=True,recursive=True)self.device.mkdir(self.remote_home_dir,parents=True)self.device.mkdir(self.remote_tmp_dir)self.push_libs()self.push_progs(progs)self.device.chmod(self.remote_bin_dir,recursive=True,root=True)defpush_libs(self):ifself.options.local_apk:withmozfile.TemporaryDirectory()astmpdir:apk_contents=ZipFile(self.options.local_apk)forinfoinapk_contents.infolist():ifinfo.filename.endswith(".so"):print>>sys.stderr,"Pushing %s.."%info.filenameremote_file=posixpath.join(self.remote_bin_dir,os.path.basename(info.filename))apk_contents.extract(info,tmpdir)local_file=os.path.join(tmpdir,info.filename)withopen(local_file)asf:# Decompress xz-compressed file.iff.read(5)[1:]=='7zXZ':cmd=['xz','-df','--suffix','.so',local_file]subprocess.check_output(cmd)# xz strips the ".so" file suffix.os.rename(local_file[:-3],local_file)self.device.push(local_file,remote_file)elifself.options.local_lib:forfileinos.listdir(self.options.local_lib):iffile.endswith(".so"):print>>sys.stderr,"Pushing %s.."%fileremote_file=posixpath.join(self.remote_bin_dir,file)local_file=os.path.join(self.options.local_lib,file)self.device.push(local_file,remote_file)# Additional libraries may be found in a sub-directory such as# "lib/armeabi-v7a"forsubdirin["assets","lib"]:local_arm_lib=os.path.join(self.options.local_lib,subdir)ifos.path.isdir(local_arm_lib):forroot,dirs,filesinos.walk(local_arm_lib):forfileinfiles:if(file.endswith(".so")):print>>sys.stderr,"Pushing %s.."%fileremote_file=posixpath.join(self.remote_bin_dir,file)local_file=os.path.join(root,file)self.device.push(local_file,remote_file)defpush_progs(self,progs):forlocal_fileinprogs:remote_file=posixpath.join(self.remote_bin_dir,os.path.basename(local_file))self.device.push(local_file,remote_file)defbuild_environment(self):env=self.build_core_environment()env['LD_LIBRARY_PATH']=self.remote_bin_direnv["TMPDIR"]=self.remote_tmp_direnv["HOME"]=self.remote_home_direnv["MOZ_XRE_DIR"]=self.remote_bin_dirifself.options.add_env:forenvdefinself.options.add_env:envdef_parts=envdef.split("=",1)iflen(envdef_parts)==2:env[envdef_parts[0]]=envdef_parts[1]eliflen(envdef_parts)==1:env[envdef_parts[0]]=""else:self.log.warning("invalid --addEnv option skipped: %s"%envdef)returnenvdefrun_one_test(self,prog,env,symbols_path=None,interactive=False,timeout_factor=1):""" Run a single C++ unit test program remotely. Arguments: * prog: The path to the test program to run. * env: The environment to use for running the program. * symbols_path: A path to a directory containing Breakpad-formatted symbol files for producing stack traces on crash. * timeout_factor: An optional test-specific timeout multiplier. Return True if the program exits with a zero status, False otherwise. """basename=os.path.basename(prog)remote_bin=posixpath.join(self.remote_bin_dir,basename)self.log.test_start(basename)test_timeout=cppunittests.CPPUnitTests.TEST_PROC_TIMEOUT* \timeout_factortry:output=self.device.shell_output(remote_bin,env=env,cwd=self.remote_home_dir,timeout=test_timeout)returncode=0exceptADBTimeoutError:raiseexceptADBProcessErrorase:output=e.adb_process.stdoutreturncode=e.adb_process.exitcodeself.log.process_output(basename,"\n%s"%output,command=[remote_bin])withmozfile.TemporaryDirectory()astempdir:self.device.pull(self.remote_home_dir,tempdir)ifmozcrash.check_for_crashes(tempdir,symbols_path,test_name=basename):self.log.test_end(basename,status='CRASH',expected='PASS')returnFalseresult=returncode==0ifnotresult:self.log.test_end(basename,status='FAIL',expected='PASS',message=("test failed with return code %s"%returncode))else:self.log.test_end(basename,status='PASS',expected='PASS')returnresultclassRemoteCPPUnittestOptions(cppunittests.CPPUnittestOptions):def__init__(self):cppunittests.CPPUnittestOptions.__init__(self)defaults={}self.add_option("--deviceSerial",action="store",type="string",dest="device_serial",help="serial ID of device")defaults["device_serial"]=Noneself.add_option("--adbPath",action="store",type="string",dest="adb_path",help="Path to adb")defaults["adb_path"]=Noneself.add_option("--noSetup",action="store_false",dest="setup",help="do not copy any files to device (to be used only if ""device is already setup)")defaults["setup"]=Trueself.add_option("--localLib",action="store",type="string",dest="local_lib",help="location of libraries to push -- preferably stripped")defaults["local_lib"]=Noneself.add_option("--apk",action="store",type="string",dest="local_apk",help="local path to Fennec APK")defaults["local_apk"]=Noneself.add_option("--localBinDir",action="store",type="string",dest="local_bin",help="local path to bin directory")defaults["local_bin"]=build_obj.bindirifbuild_objisnotNoneelseNoneself.add_option("--remoteTestRoot",action="store",type="string",dest="remote_test_root",help="remote directory to use as test root (eg. /data/local/tests)")# /data/local/tests is used because it is usually not possible to set +x permissions# on binaries on /mnt/sdcarddefaults["remote_test_root"]="/data/local/tests"self.add_option("--addEnv",action="append",type="string",dest="add_env",help="additional remote environment variable definitions ""(eg. --addEnv \"somevar=something\")")defaults["add_env"]=Noneself.set_defaults(**defaults)defrun_test_harness(options,args):options.xre_path=os.path.abspath(options.xre_path)cppunittests.update_mozinfo()progs=cppunittests.extract_unittests_from_args(args,mozinfo.info,options.manifest_path)tester=RemoteCPPUnitTests(options,[item[0]foriteminprogs])result=tester.run_tests(progs,options.xre_path,options.symbols_path)returnresultdefmain():parser=RemoteCPPUnittestOptions()mozlog.commandline.add_logging_group(parser)options,args=parser.parse_args()ifnotargs:print>>sys.stderr,"""Usage: %s <test binary> [<test binary>...]"""%sys.argv[0]sys.exit(1)ifoptions.local_libisnotNoneandnotos.path.isdir(options.local_lib):print>>sys.stderr,"""Error: --localLib directory %s not found"""%options.local_libsys.exit(1)ifoptions.local_apkisnotNoneandnotos.path.isfile(options.local_apk):print>>sys.stderr,"""Error: --apk file %s not found"""%options.local_apksys.exit(1)ifnotoptions.xre_path:print>>sys.stderr,"""Error: --xre-path is required"""sys.exit(1)log=mozlog.commandline.setup_logging("remotecppunittests",options,{"tbpl":sys.stdout})try:result=run_test_harness(options,args)exceptExceptionase:log.error(str(e))result=Falsesys.exit(0ifresultelse1)if__name__=='__main__':main()