1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 from __future__
import print_function
, unicode_literals
10 from mach
.decorators
import (
14 from mozbuild
.base
import (
16 MachCommandConditions
as conditions
,
20 def is_valgrind_build(cls
):
21 """Must be a build with --enable-valgrind and --disable-jemalloc."""
22 defines
= cls
.config_environment
.defines
23 return 'MOZ_VALGRIND' in defines
and 'MOZ_MEMORY' not in defines
27 class MachCommands(MachCommandBase
):
31 def __init__(self
, context
):
32 MachCommandBase
.__init
__(self
, context
)
34 @Command('valgrind-test', category
='testing',
35 conditions
=[conditions
.is_firefox
, is_valgrind_build
],
36 description
='Run the Valgrind test job.')
37 def valgrind_test(self
):
42 from mozbuild
.base
import MozbuildObject
43 from mozfile
import TemporaryDirectory
44 from mozhttpd
import MozHttpd
45 from mozprofile
import FirefoxProfile
, Preferences
46 from mozprofile
.permissions
import ServerLocations
47 from mozrunner
import FirefoxRunner
48 from mozrunner
.utils
import findInPath
50 build_dir
= os
.path
.join(self
.topsrcdir
, 'build')
52 # XXX: currently we just use the PGO inputs for Valgrind runs. This may
53 # change in the future.
54 httpd
= MozHttpd(docroot
=os
.path
.join(build_dir
, 'pgo'))
55 httpd
.start(block
=False)
57 with
TemporaryDirectory() as profilePath
:
58 #TODO: refactor this into mozprofile
59 prefpath
= os
.path
.join(self
.topsrcdir
, 'testing', 'profiles', 'prefs_general.js')
61 prefs
.update(Preferences
.read_prefs(prefpath
))
62 interpolation
= { 'server': '%s:%d' % httpd
.httpd
.server_address
,
64 prefs
= json
.loads(json
.dumps(prefs
) % interpolation
)
66 prefs
[pref
] = Preferences
.cast(prefs
[pref
])
68 quitter
= os
.path
.join(self
.distdir
, 'xpi-stage', 'quitter')
70 locations
= ServerLocations()
71 locations
.add_host(host
='127.0.0.1',
72 port
=httpd
.httpd
.server_port
,
75 profile
= FirefoxProfile(profile
=profilePath
,
80 firefox_args
= [httpd
.get_url()]
82 env
= os
.environ
.copy()
83 env
['G_SLICE'] = 'always-malloc'
84 env
['XPCOM_CC_RUN_DURING_SHUTDOWN'] = '1'
85 env
['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
86 env
['XPCOM_DEBUG_BREAK'] = 'warn'
89 if not os
.path
.exists(valgrind
):
90 valgrind
= findInPath(valgrind
)
95 '--smc-check=all-non-file',
96 '--vex-iropt-register-updates=allregs-at-mem-access',
97 '--gen-suppressions=all',
100 '--show-possibly-lost=no',
101 '--track-origins=yes'
104 supps_dir
= os
.path
.join(build_dir
, 'valgrind')
105 supps_file1
= os
.path
.join(supps_dir
, 'cross-architecture.sup')
106 valgrind_args
.append('--suppressions=' + supps_file1
)
108 # MACHTYPE is an odd bash-only environment variable that doesn't
109 # show up in os.environ, so we have to get it another way.
110 machtype
= subprocess
.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip()
111 supps_file2
= os
.path
.join(supps_dir
, machtype
+ '.sup')
112 if os
.path
.isfile(supps_file2
):
113 valgrind_args
.append('--suppressions=' + supps_file2
)
116 runner
= FirefoxRunner(profile
=profile
,
117 binary
=self
.get_binary_path(),
118 cmdargs
=firefox_args
,
120 runner
.start(debug_args
=valgrind_args
)
121 status
= runner
.wait()
126 status
= 1 # normalize status, in case it's larger than 127
127 print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code')