Beispiel #1
0
    def test_server_locations_callback(self):
        class CallbackTest(object):
            last_locations = None

            def callback(self, locations):
                self.last_locations = locations

        c = CallbackTest()
        f = self.create_temp_file(self.locations)
        locations = ServerLocations(f.name, c.callback)

        # callback should be for all locations in file
        self.assertEqual(len(c.last_locations), 6)

        # validate arbitrary one
        self.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
        self.assertEqual(len(c.last_locations), 1)
        self.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 = self.create_temp_file(self.locations_no_primary)
        locations.read(f.name)
        self.assertEqual(len(c.last_locations), 2)
Beispiel #2
0
    def test_server_locations(self):
        # write a permissions file
        f = self.create_temp_file(self.locations)

        # read the locations
        locations = ServerLocations(f.name)

        # ensure that they're what we expect
        self.assertEqual(len(locations), 6)
        i = iter(locations)
        self.compare_location(i.next(), 'http', 'mochi.test', '8888',
                              ['primary', 'privileged'])
        self.compare_location(i.next(), 'http', '127.0.0.1', '80',
                              ['privileged'])
        self.compare_location(i.next(), 'http', '127.0.0.1', '8888',
                              ['privileged'])
        self.compare_location(i.next(), 'https', 'test', '80', ['privileged'])
        self.compare_location(i.next(), 'http', 'example.org', '80',
                              ['privileged'])
        self.compare_location(i.next(), 'http', 'test1.example.org', '8888',
                              ['privileged'])

        locations.add_host('mozilla.org')
        self.assertEqual(len(locations), 7)
        self.compare_location(i.next(), 'http', 'mozilla.org', '80',
                              ['privileged'])

        # test some errors
        self.assertRaises(MultiplePrimaryLocationsError, locations.add_host,
                          'primary.test', options='primary')

        # We no longer throw these DuplicateLocation Error
        try:
            locations.add_host('127.0.0.1')
        except DuplicateLocationError:
            self.assertTrue(False, "Should no longer throw DuplicateLocationError")

        self.assertRaises(BadPortLocationError, locations.add_host, '127.0.0.1',
                          port='abc')

        # test some errors in locations file
        f = self.create_temp_file(self.locations_no_primary)

        exc = None
        try:
            ServerLocations(f.name)
        except LocationsSyntaxError, e:
            exc = e
Beispiel #3
0
    def start(self):
        self.marionette_port = get_free_port(2828, exclude=self.used_ports)

        env = os.environ.copy()
        env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1"

        locations = ServerLocations(filename=os.path.join(here, "server-locations.txt"))

        preferences = self.load_prefs()

        self.profile = FirefoxProfile(locations=locations,
                                      preferences=preferences)
        self.profile.set_preferences({"marionette.defaultPrefs.enabled": True,
                                      "marionette.defaultPrefs.port": self.marionette_port,
                                      "dom.disable_open_during_load": False,
                                      "network.dns.localDomains": ",".join(hostnames)})

        if self.ca_certificate_path is not None:
            self.setup_ssl()

        debug_args, cmd = browser_command(self.binary, [cmd_arg("marionette"), "about:blank"],
                                          self.debug_info)

        self.runner = FirefoxRunner(profile=self.profile,
                                    binary=cmd[0],
                                    cmdargs=cmd[1:],
                                    env=env,
                                    process_class=ProcessHandler,
                                    process_args={"processOutputLine": [self.on_output]})

        self.logger.debug("Starting Firefox")

        self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive)
        self.logger.debug("Firefox Started")
Beispiel #4
0
    def start(self):
        self.marionette_port = get_free_port(2828, exclude=self.used_ports)

        env = os.environ.copy()
        env["MOZ_CRASHREPORTER"] = "1"
        env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1"
        env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
        env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1"

        locations = ServerLocations(
            filename=os.path.join(here, "server-locations.txt"))

        preferences = self.load_prefs()

        self.profile = FirefoxProfile(locations=locations,
                                      proxy=True,
                                      preferences=preferences)
        self.profile.set_preferences({
            "marionette.defaultPrefs.enabled": True,
            "marionette.defaultPrefs.port": self.marionette_port,
            "dom.disable_open_during_load": False
        })

        self.runner = FirefoxRunner(
            profile=self.profile,
            binary=self.binary,
            cmdargs=[cmd_arg("marionette"), "about:blank"],
            env=env,
            process_class=ProcessHandler,
            process_args={"processOutputLine": [self.on_output]})

        self.logger.debug("Starting Firefox")
        self.runner.start(debug_args=self.debug_args,
                          interactive=self.interactive)
        self.logger.debug("Firefox Started")
Beispiel #5
0
def writeCertspecForServerLocations(fd):
    locations = ServerLocations(
        os.path.join(build.topsrcdir, "build", "pgo", "server-locations.txt"))
    SAN = []
    for loc in [
            i for i in iter(locations)
            if i.scheme == "https" and "nocert" not in i.options
    ]:
        customCertOption = False
        customCertRE = re.compile("^cert=(?:\w+)")
        for _ in [i for i in loc.options if customCertRE.match(i)]:
            customCertOption = True
            break

        if "ipV4Address" in loc.options:
            loc.host = "ip4:" + loc.host

        if not customCertOption:
            SAN.append(loc.host)

    fd.write(
        "issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization\n"
    )  # NOQA: E501
    fd.write("subject:{}\n".format(SAN[0]))
    fd.write("extension:subjectAlternativeName:{}\n".format(",".join(SAN)))
    def start(self):
        self.marionette_port = get_free_port(2828, exclude=self.used_ports)
        self.used_ports.add(self.marionette_port)

        env = os.environ.copy()
        env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1"

        locations = ServerLocations(
            filename=os.path.join(here, "server-locations.txt"))

        preferences = self.load_prefs()

        self.profile = FirefoxProfile(locations=locations,
                                      preferences=preferences)
        self.profile.set_preferences({
            "marionette.enabled":
            True,
            "marionette.port":
            self.marionette_port,
            "dom.disable_open_during_load":
            False,
            "network.dns.localDomains":
            ",".join(hostnames),
            "network.proxy.type":
            0,
            "places.history.enabled":
            False
        })
        if self.e10s:
            self.profile.set_preferences(
                {"browser.tabs.remote.autostart": True})

        # Bug 1262954: winxp + e10s, disable hwaccel
        if (self.e10s and platform.system() in ("Windows", "Microsoft")
                and '5.1' in platform.version()):
            self.profile.set_preferences(
                {"layers.acceleration.disabled": True})

        if self.ca_certificate_path is not None:
            self.setup_ssl()

        debug_args, cmd = browser_command(
            self.binary, [cmd_arg("marionette"), "about:blank"],
            self.debug_info)

        self.runner = FirefoxRunner(
            profile=self.profile,
            binary=cmd[0],
            cmdargs=cmd[1:],
            env=env,
            process_class=ProcessHandler,
            process_args={"processOutputLine": [self.on_output]})

        self.logger.debug("Starting Firefox")

        self.runner.start(debug_args=debug_args,
                          interactive=self.debug_info
                          and self.debug_info.interactive)
        self.logger.debug("Firefox Started")
Beispiel #7
0
    def test_server_locations_callback(self):
        class CallbackTest(object):
            last_locations = None

            def callback(self, locations):
                self.last_locations = locations

        c = CallbackTest()
        f = self.create_temp_file(self.locations)
        locations = ServerLocations(f.name, c.callback)

        # callback should be for all locations in file
        self.assertEqual(len(c.last_locations), 6)

        # validate arbitrary one
        self.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
        self.assertEqual(len(c.last_locations), 1)
        self.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 = self.create_temp_file(self.locations_no_primary)
        locations.read(f.name)
        self.assertEqual(len(c.last_locations), 2)
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
Beispiel #9
0
    def test_server_locations(self):
        # write a permissions file
        f = self.create_temp_file(self.locations)

        # read the locations
        locations = ServerLocations(f.name)

        # ensure that they're what we expect
        self.assertEqual(len(locations), 6)
        i = iter(locations)
        self.compare_location(i.next(), 'http', 'mochi.test', '8888',
                              ['primary', 'privileged'])
        self.compare_location(i.next(), 'http', '127.0.0.1', '80',
                              ['privileged'])
        self.compare_location(i.next(), 'http', '127.0.0.1', '8888',
                              ['privileged'])
        self.compare_location(i.next(), 'https', 'test', '80', ['privileged'])
        self.compare_location(i.next(), 'http', 'example.org', '80',
                              ['privileged'])
        self.compare_location(i.next(), 'http', 'test1.example.org', '80',
                              ['privileged'])

        locations.add_host('mozilla.org')
        self.assertEqual(len(locations), 7)
        self.compare_location(i.next(), 'http', 'mozilla.org', '80',
                              ['privileged'])

        # test some errors
        self.assertRaises(MultiplePrimaryLocationsError,
                          locations.add_host,
                          'primary.test',
                          options='primary')

        # We no longer throw these DuplicateLocation Error
        try:
            locations.add_host('127.0.0.1')
        except DuplicateLocationError:
            self.assertTrue(False,
                            "Should no longer throw DuplicateLocationError")

        self.assertRaises(BadPortLocationError,
                          locations.add_host,
                          '127.0.0.1',
                          port='abc')

        # test some errors in locations file
        f = self.create_temp_file(self.locations_no_primary)

        exc = None
        try:
            ServerLocations(f.name)
        except LocationsSyntaxError, e:
            exc = e
Beispiel #10
0
    def valgrind_test(self, suppressions):

        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from six import string_types
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, 'build')

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            # TODO: refactor this into mozprofile
            profile_data_dir = os.path.join(self.topsrcdir, 'testing',
                                            'profiles')
            with open(os.path.join(profile_data_dir, 'profiles.json'),
                      'r') as fh:
                base_profiles = json.load(fh)['valgrind']

            prefpaths = [
                os.path.join(profile_data_dir, profile, 'user.js')
                for profile in base_profiles
            ]
            prefs = {}
            for path in prefpaths:
                prefs.update(Preferences.read_prefs(path))

            interpolation = {
                'server': '%s:%d' % httpd.httpd.server_address,
            }
            for k, v in prefs.items():
                if isinstance(v, string_types):
                    v = v.format(**interpolation)
                prefs[k] = Preferences.cast(v)

            quitter = os.path.join(self.topsrcdir, 'tools', 'quitter',
                                   '*****@*****.**')

            locations = ServerLocations()
            locations.add_host(host='127.0.0.1',
                               port=httpd.httpd.server_port,
                               options='primary')

            profile = FirefoxProfile(profile=profilePath,
                                     preferences=prefs,
                                     addons=[quitter],
                                     locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env['G_SLICE'] = 'always-malloc'
            env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
            env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
            env['XPCOM_DEBUG_BREAK'] = 'warn'

            env.update(self.extra_environment_variables)

            outputHandler = OutputHandler(self.log)
            kp_kwargs = {'processOutputLine': [outputHandler]}

            valgrind = 'valgrind'
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                '--sym-offsets=yes',
                '--smc-check=all-non-file',
                '--vex-iropt-register-updates=allregs-at-mem-access',
                '--gen-suppressions=all',
                '--num-callers=36',
                '--leak-check=full',
                '--show-possibly-lost=no',
                '--track-origins=yes',
                '--trace-children=yes',
                '-v',  # Enable verbosity to get the list of used suppressions
                # Avoid excessive delays in the presence of spinlocks.
                # See bug 1309851.
                '--fair-sched=yes',
                # Keep debuginfo after library unmap.  See bug 1382280.
                '--keep-debuginfo=yes',
                # Reduce noise level on rustc and/or LLVM compiled code.
                # See bug 1365915
                '--expensive-definedness-checks=yes',
            ]

            for s in suppressions:
                valgrind_args.append('--suppressions=' + s)

            supps_dir = os.path.join(build_dir, 'valgrind')
            supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
            valgrind_args.append('--suppressions=' + supps_file1)

            if mozinfo.os == 'linux':
                machtype = {
                    'x86_64': 'x86_64-pc-linux-gnu',
                    'x86': 'i386-pc-linux-gnu',
                }.get(mozinfo.processor)
                if machtype:
                    supps_file2 = os.path.join(supps_dir, machtype + '.sup')
                    if os.path.isfile(supps_file2):
                        valgrind_args.append('--suppressions=' + supps_file2)

            exitcode = None
            timeout = 1800
            try:
                runner = FirefoxRunner(profile=profile,
                                       binary=self.get_binary_path(),
                                       cmdargs=firefox_args,
                                       env=env,
                                       process_args=kp_kwargs)
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait(timeout=timeout)

            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    self.log(
                        logging.ERROR, 'valgrind-fail-parsing', {
                            'errs': errs,
                            'supps': supps
                        },
                        'TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors '
                        'seen, but {supps} generated suppressions seen')

                elif errs == 0:
                    status = 0
                    self.log(
                        logging.INFO, 'valgrind-pass', {},
                        'TEST-PASS | valgrind-test | valgrind found no errors')
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if exitcode is None:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR, 'valgrind-fail-timeout',
                        {'timeout': timeout},
                        'TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out '
                        '(reached {timeout} second limit)')
                elif exitcode != 0:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR, 'valgrind-fail-errors',
                        {'exitcode': exitcode},
                        'TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code '
                        'from Valgrind: {exitcode}')

                httpd.stop()

            return status
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
Beispiel #12
0
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
Beispiel #13
0
    def __init__(self, options, **kwargs):
        self.options = options
        self.server = None
        self.logger = mozlog.getLogger("PEP")

        # create the profile
        enable_proxy = False
        locations = ServerLocations()
        if self.options.proxyLocations:
            if not self.options.serverPath:
                self.logger.warning("Can't set up proxy without server path")
            else:
                enable_proxy = True
                locations.read(self.options.proxyLocations, False)
                locations.add_host(host="127.0.0.1", port=self.options.serverPort, options="primary,privileged")

        self.profile = self.profile_class(
            profile=self.options.profilePath,
            addons=[os.path.join(here, "extension")],
            locations=locations,
            proxy=enable_proxy,
        )

        # fork a server to serve the test related files
        if self.options.serverPath:
            self.runServer()

        tests = []
        # TODO is there a better way of doing this?
        if self.options.testPath.endswith(".js"):
            # a single test file was passed in
            testObj = {}
            testObj["path"] = os.path.realpath(self.options.testPath)
            testObj["name"] = os.path.basename(self.options.testPath)
            testObj["here"] = os.path.dirname(testObj["path"])
            tests.append(testObj)
        else:
            # a test manifest was passed in
            # open and convert the manifest to json
            manifest = TestManifest()
            manifest.read(self.options.testPath)
            tests = manifest.get()

        # create a manifest object to be read by the JS side
        manifestObj = {}
        manifestObj["tests"] = tests
        manifestObj["options"] = options.__dict__

        # write manifest to a JSON file
        jsonManifest = open(os.path.join(here, "manifest.json"), "w")
        jsonManifest.write(json.dumps(manifestObj))
        jsonManifest.close()

        # setup environment
        env = os.environ.copy()
        env["MOZ_INSTRUMENT_EVENT_LOOP"] = "1"
        env["MOZ_INSTRUMENT_EVENT_LOOP_THRESHOLD"] = str(options.tracerThreshold)
        env["MOZ_INSTRUMENT_EVENT_LOOP_INTERVAL"] = str(options.tracerInterval)
        env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"

        # construct the browser arguments
        cmdargs = []
        # TODO Make browserArgs a list
        cmdargs.extend(self.options.browserArgs)
        cmdargs.extend(["-pep-start", os.path.realpath(jsonManifest.name)])

        # run with managed process handler
        self.runner = self.runner_class(
            profile=self.profile, binary=self.options.binary, cmdargs=cmdargs, env=env, process_class=PepProcess
        )
Beispiel #14
0
    def run(self):
        if self.options.remote_webserver:
            httpd_host = self.options.remote_webserver.split(':')[0]
        else:
            httpd_host = self.httpd.host
        httpd_port = self.httpd.httpd.server_port

        locations = ServerLocations()
        locations.add_host(host=httpd_host,
                           port=httpd_port,
                           options='primary,privileged')

        #TODO: use Preferences.read when prefs_general.js has been updated
        prefpath = self.options.prefs
        prefs = {}
        prefs.update(Preferences.read_prefs(prefpath))
        interpolation = {
            "server": "%s:%d" % (httpd_host, httpd_port),
            "OOP": "false"
        }
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])
        prefs[
            "steeplechase.signalling_server"] = self.options.signalling_server
        prefs["steeplechase.signalling_room"] = str(uuid.uuid4())
        if self.options.timeout is None:
            prefs["steeplechase.timeout"] = 30000
        else:
            prefs["steeplechase.timeout"] = self.options.timeout
        prefs["media.navigator.permission.disabled"] = True
        prefs["media.navigator.streams.fake"] = True

        specialpowers_path = self.options.specialpowers
        threads = []
        results = []
        cond = threading.Condition()
        for info in self.remote_info:
            with mozfile.TemporaryDirectory() as profile_path:
                # Create and push profile
                print "Writing profile for %s..." % info['name']
                prefs["steeplechase.is_initiator"] = info['is_initiator']
                profile = FirefoxProfile(profile=profile_path,
                                         preferences=prefs,
                                         addons=[specialpowers_path],
                                         locations=locations)
                print "Pushing profile to %s..." % info['name']
                remote_profile_path = posixpath.join(info['test_root'],
                                                     "profile")
                info['dm'].mkDir(remote_profile_path)
                info['dm'].pushDir(profile_path, remote_profile_path)
                info['remote_profile_path'] = remote_profile_path

            env = {}
            env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
            env["XPCOM_DEBUG_BREAK"] = "warn"
            env["DISPLAY"] = self.options.remote_xdisplay

            cmd = [
                info['remote_app_path'], "-no-remote", "-profile",
                info['remote_profile_path'],
                'http://%s:%d/index.html' % (httpd_host, httpd_port)
            ]
            print "cmd: %s" % (cmd, )
            t = RunThread(name=info['name'],
                          args=(info['dm'], cmd, env, cond, results))
            threads.append(t)

        for t in threads:
            t.start()

        self.log.info("Waiting for results...")
        pass_count, fail_count = 0, 0
        outputs = {}
        while threads:
            cond.acquire()
            while not results:
                cond.wait()
            thread, result, output = results.pop(0)
            cond.release()
            outputs[thread.name] = output
            passes, failures = result
            #XXX: double-counting tests from both clients. Ok?
            pass_count += passes
            fail_count += failures
            if failures:
                self.log.error("Error in %s" % thread.name)
            threads.remove(thread)
        self.log.info("All clients finished")
        for info in self.remote_info:
            if self.options.log_dest:
                with open(
                        os.path.join(self.options.log_dest,
                                     "%s.log" % info['name']), "wb") as f:
                    f.write(outputs[info['name']])
            if fail_count:
                self.log.info("Log output for %s:", info["name"])
                self.log.info(">>>>>>>")
                for line in outputs[info['name']].splitlines():
                    #TODO: make structured log messages human-readable
                    self.log.info(line)
                self.log.info("<<<<<<<")
        return pass_count, fail_count
    def valgrind_test(self, suppressions):

        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from six import string_types
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, "build")

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo"))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            # TODO: refactor this into mozprofile
            profile_data_dir = os.path.join(self.topsrcdir, "testing",
                                            "profiles")
            with open(os.path.join(profile_data_dir, "profiles.json"),
                      "r") as fh:
                base_profiles = json.load(fh)["valgrind"]

            prefpaths = [
                os.path.join(profile_data_dir, profile, "user.js")
                for profile in base_profiles
            ]
            prefs = {}
            for path in prefpaths:
                prefs.update(Preferences.read_prefs(path))

            interpolation = {
                "server": "%s:%d" % httpd.httpd.server_address,
            }
            for k, v in prefs.items():
                if isinstance(v, string_types):
                    v = v.format(**interpolation)
                prefs[k] = Preferences.cast(v)

            quitter = os.path.join(self.topsrcdir, "tools", "quitter",
                                   "*****@*****.**")

            locations = ServerLocations()
            locations.add_host(host="127.0.0.1",
                               port=httpd.httpd.server_port,
                               options="primary")

            profile = FirefoxProfile(
                profile=profilePath,
                preferences=prefs,
                addons=[quitter],
                locations=locations,
            )

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env["G_SLICE"] = "always-malloc"
            env["MOZ_CC_RUN_DURING_SHUTDOWN"] = "1"
            env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
            env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1"
            env["XPCOM_DEBUG_BREAK"] = "warn"

            outputHandler = OutputHandler(self.log)
            kp_kwargs = {
                "processOutputLine": [outputHandler],
                "universal_newlines": True,
            }

            valgrind = "valgrind"
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                "--sym-offsets=yes",
                "--smc-check=all-non-file",
                "--vex-iropt-register-updates=allregs-at-mem-access",
                "--gen-suppressions=all",
                "--num-callers=36",
                "--leak-check=full",
                "--show-possibly-lost=no",
                "--track-origins=yes",
                "--trace-children=yes",
                "-v",  # Enable verbosity to get the list of used suppressions
                # Avoid excessive delays in the presence of spinlocks.
                # See bug 1309851.
                "--fair-sched=yes",
                # Keep debuginfo after library unmap.  See bug 1382280.
                "--keep-debuginfo=yes",
                # Reduce noise level on rustc and/or LLVM compiled code.
                # See bug 1365915
                "--expensive-definedness-checks=yes",
                # Compensate for the compiler inlining `new` but not `delete`
                # or vice versa.
                "--show-mismatched-frees=no",
            ]

            for s in suppressions:
                valgrind_args.append("--suppressions=" + s)

            supps_dir = os.path.join(build_dir, "valgrind")
            supps_file1 = os.path.join(supps_dir, "cross-architecture.sup")
            valgrind_args.append("--suppressions=" + supps_file1)

            if mozinfo.os == "linux":
                machtype = {
                    "x86_64": "x86_64-pc-linux-gnu",
                    "x86": "i386-pc-linux-gnu",
                }.get(mozinfo.processor)
                if machtype:
                    supps_file2 = os.path.join(supps_dir, machtype + ".sup")
                    if os.path.isfile(supps_file2):
                        valgrind_args.append("--suppressions=" + supps_file2)

            exitcode = None
            timeout = 1800
            binary_not_found_exception = None
            try:
                runner = FirefoxRunner(
                    profile=profile,
                    binary=self.get_binary_path(),
                    cmdargs=firefox_args,
                    env=env,
                    process_args=kp_kwargs,
                )
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait(timeout=timeout)
            except BinaryNotFoundException as e:
                binary_not_found_exception = e
            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-parsing",
                        {
                            "errs": errs,
                            "supps": supps
                        },
                        "TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors "
                        "seen, but {supps} generated suppressions seen",
                    )

                elif errs == 0:
                    status = 0
                    self.log(
                        logging.INFO,
                        "valgrind-pass",
                        {},
                        "TEST-PASS | valgrind-test | valgrind found no errors",
                    )
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if binary_not_found_exception:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-errors",
                        {"error": str(binary_not_found_exception)},
                        "TEST-UNEXPECTED-FAIL | valgrind-test | {error}",
                    )
                    self.log(
                        logging.INFO,
                        "valgrind-fail-errors",
                        {"help": binary_not_found_exception.help()},
                        "{help}",
                    )
                elif exitcode is None:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-timeout",
                        {"timeout": timeout},
                        "TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out "
                        "(reached {timeout} second limit)",
                    )
                elif exitcode != 0:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-errors",
                        {"exitcode": exitcode},
                        "TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code "
                        "from Valgrind: {exitcode}",
                    )

                httpd.stop()

            return status
Beispiel #16
0
    def __init__(self, options, **kwargs):
        self.options = options
        self.server = None
        self.logger = mozlog.getLogger('PEP')

        # create the profile
        enable_proxy = False
        locations = ServerLocations()
        if self.options.proxyLocations:
            if not self.options.serverPath:
                self.logger.warning('Can\'t set up proxy without server path')
            else:
                enable_proxy = True
                for proxyLocation in self.options.proxyLocations:
                    locations.read(proxyLocation, False)
                locations.add_host(host='127.0.0.1',
                                   port=self.options.serverPort,
                                   options='primary,privileged')

        self.profile = self.profile_class(profile=self.options.profilePath,
                                          addons=[os.path.join(here, 'extension')],
                                          locations=locations,
                                          proxy=enable_proxy)

        # fork a server to serve the test related files
        if self.options.serverPath:
            self.runServer()

        tests = []
        # TODO is there a better way of doing this?
        if self.options.testPath.endswith('.js'):
            # a single test file was passed in
            testObj = {}
            testObj['path'] = os.path.realpath(self.options.testPath)
            testObj['name'] = os.path.basename(self.options.testPath)
            testObj['here'] = os.path.dirname(testObj['path'])
            tests.append(testObj)
        else:
            # a test manifest was passed in
            # open and convert the manifest to json
            manifest = TestManifest()
            manifest.read(self.options.testPath)
            tests = manifest.get()

        # create a manifest object to be read by the JS side
        manifestObj = {}
        manifestObj['tests'] = tests
        manifestObj['options'] = options.__dict__

        # write manifest to a JSON file
        jsonManifest = open(os.path.join(here, 'manifest.json'), 'w')
        jsonManifest.write(json.dumps(manifestObj))
        jsonManifest.close()

        # setup environment
        env = os.environ.copy()
        env['MOZ_INSTRUMENT_EVENT_LOOP'] = '1'
        env['MOZ_INSTRUMENT_EVENT_LOOP_THRESHOLD'] = str(options.tracerThreshold)
        env['MOZ_INSTRUMENT_EVENT_LOOP_INTERVAL'] = str(options.tracerInterval)
        env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'

        # construct the browser arguments
        cmdargs = []
        # TODO Make browserArgs a list
        cmdargs.extend(self.options.browserArgs)
        cmdargs.extend(['-pep-start', os.path.realpath(jsonManifest.name)])

        # run with managed process handler
        self.runner = self.runner_class(profile=self.profile,
                                        binary=self.options.binary,
                                        cmdargs=cmdargs,
                                        env=env,
                                        process_class=PepProcess)
Beispiel #17
0
    def valgrind_test(self, suppressions):
        import json
        import re
        import sys
        import tempfile

        from mozbuild.base import MozbuildObject
        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath

        build_dir = os.path.join(self.topsrcdir, "build")

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo"))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            # TODO: refactor this into mozprofile
            prefpath = os.path.join(self.topsrcdir, "testing", "profiles", "prefs_general.js")
            prefs = {}
            prefs.update(Preferences.read_prefs(prefpath))
            interpolation = {"server": "%s:%d" % httpd.httpd.server_address, "OOP": "false"}
            prefs = json.loads(json.dumps(prefs) % interpolation)
            for pref in prefs:
                prefs[pref] = Preferences.cast(prefs[pref])

            quitter = os.path.join(self.distdir, "xpi-stage", "quitter")

            locations = ServerLocations()
            locations.add_host(host="127.0.0.1", port=httpd.httpd.server_port, options="primary")

            profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env["G_SLICE"] = "always-malloc"
            env["XPCOM_CC_RUN_DURING_SHUTDOWN"] = "1"
            env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
            env["XPCOM_DEBUG_BREAK"] = "warn"

            class OutputHandler(object):
                def __init__(self):
                    self.found_errors = False

                def __call__(self, line):
                    print(line)
                    m = re.match(r".*ERROR SUMMARY: [1-9]\d* errors from \d+ contexts", line)
                    if m:
                        self.found_errors = True

            outputHandler = OutputHandler()
            kp_kwargs = {"processOutputLine": [outputHandler]}

            valgrind = "valgrind"
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                "--smc-check=all-non-file",
                "--vex-iropt-register-updates=allregs-at-mem-access",
                "--gen-suppressions=all",
                "--num-callers=20",
                "--leak-check=full",
                "--show-possibly-lost=no",
                "--track-origins=yes",
            ]

            for s in suppressions:
                valgrind_args.append("--suppressions=" + s)

            supps_dir = os.path.join(build_dir, "valgrind")
            supps_file1 = os.path.join(supps_dir, "cross-architecture.sup")
            valgrind_args.append("--suppressions=" + supps_file1)

            # MACHTYPE is an odd bash-only environment variable that doesn't
            # show up in os.environ, so we have to get it another way.
            machtype = subprocess.check_output(["bash", "-c", "echo $MACHTYPE"]).rstrip()
            supps_file2 = os.path.join(supps_dir, machtype + ".sup")
            if os.path.isfile(supps_file2):
                valgrind_args.append("--suppressions=" + supps_file2)

            exitcode = None
            try:
                runner = FirefoxRunner(
                    profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, kp_kwargs=kp_kwargs
                )
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait()

            finally:
                if not outputHandler.found_errors:
                    status = 0
                    print("TEST-PASS | valgrind-test | valgrind found no errors")
                else:
                    status = 1  # turns the TBPL job orange
                    print("TEST-UNEXPECTED-FAIL | valgrind-test | valgrind found errors")

                if exitcode != 0:
                    status = 2  # turns the TBPL job red
                    print("TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind")

                httpd.stop()

            return status
Beispiel #18
0
    def valgrind_test(self, suppressions):
        import json
        import sys
        import tempfile

        from mozbuild.base import MozbuildObject
        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, 'build')

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            #TODO: refactor this into mozprofile
            prefpath = os.path.join(self.topsrcdir, 'testing', 'profiles', 'prefs_general.js')
            prefs = {}
            prefs.update(Preferences.read_prefs(prefpath))
            interpolation = { 'server': '%s:%d' % httpd.httpd.server_address,
                              'OOP': 'false'}
            prefs = json.loads(json.dumps(prefs) % interpolation)
            for pref in prefs:
                prefs[pref] = Preferences.cast(prefs[pref])

            quitter = os.path.join(self.topsrcdir, 'tools', 'quitter', '*****@*****.**')

            locations = ServerLocations()
            locations.add_host(host='127.0.0.1',
                               port=httpd.httpd.server_port,
                               options='primary')

            profile = FirefoxProfile(profile=profilePath,
                                     preferences=prefs,
                                     addons=[quitter],
                                     locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env['G_SLICE'] = 'always-malloc'
            env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
            env['XPCOM_DEBUG_BREAK'] = 'warn'

            env.update(self.extra_environment_variables)

            outputHandler = OutputHandler(self.log)
            kp_kwargs = {'processOutputLine': [outputHandler]}

            valgrind = 'valgrind'
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                '--smc-check=all-non-file',
                '--vex-iropt-register-updates=allregs-at-mem-access',
                '--gen-suppressions=all',
                '--num-callers=36',
                '--leak-check=full',
                '--show-possibly-lost=no',
                '--track-origins=yes',
                '--trace-children=yes',
                '-v',  # Enable verbosity to get the list of used suppressions
            ]

            for s in suppressions:
                valgrind_args.append('--suppressions=' + s)

            supps_dir = os.path.join(build_dir, 'valgrind')
            supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
            valgrind_args.append('--suppressions=' + supps_file1)

            # MACHTYPE is an odd bash-only environment variable that doesn't
            # show up in os.environ, so we have to get it another way.
            machtype = subprocess.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip()
            supps_file2 = os.path.join(supps_dir, machtype + '.sup')
            if os.path.isfile(supps_file2):
                valgrind_args.append('--suppressions=' + supps_file2)

            exitcode = None
            timeout = 1800
            try:
                runner = FirefoxRunner(profile=profile,
                                       binary=self.get_binary_path(),
                                       cmdargs=firefox_args,
                                       env=env,
                                       process_args=kp_kwargs)
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait(timeout=timeout)

            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    self.log(logging.ERROR, 'valgrind-fail-parsing',
                             {'errs': errs, 'supps': supps},
                             'TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors seen, but {supps} generated suppressions seen')

                elif errs == 0:
                    status = 0
                    self.log(logging.INFO, 'valgrind-pass', {},
                             'TEST-PASS | valgrind-test | valgrind found no errors')
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if exitcode == None:
                    status = 2  # turns the TBPL job red
                    self.log(logging.ERROR, 'valgrind-fail-timeout',
                             {'timeout': timeout},
                             'TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out (reached {timeout} second limit)')
                elif exitcode != 0:
                    status = 2  # turns the TBPL job red
                    self.log(logging.ERROR, 'valgrind-fail-errors', {},
                             'TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind')

                httpd.stop()

            return status
Beispiel #19
0
    def valgrind_test(self, suppressions):
        import json
        import sys
        import tempfile

        from mozbuild.base import MozbuildObject
        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, 'build')

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            #TODO: refactor this into mozprofile
            prefpath = os.path.join(self.topsrcdir, 'testing', 'profiles', 'prefs_general.js')
            prefs = {}
            prefs.update(Preferences.read_prefs(prefpath))
            interpolation = { 'server': '%s:%d' % httpd.httpd.server_address,
                              'OOP': 'false'}
            prefs = json.loads(json.dumps(prefs) % interpolation)
            for pref in prefs:
                prefs[pref] = Preferences.cast(prefs[pref])

            quitter = os.path.join(self.distdir, 'xpi-stage', 'quitter')

            locations = ServerLocations()
            locations.add_host(host='127.0.0.1',
                               port=httpd.httpd.server_port,
                               options='primary')

            profile = FirefoxProfile(profile=profilePath,
                                     preferences=prefs,
                                     addons=[quitter],
                                     locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env['G_SLICE'] = 'always-malloc'
            env['XPCOM_CC_RUN_DURING_SHUTDOWN'] = '1'
            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
            env['XPCOM_DEBUG_BREAK'] = 'warn'

            outputHandler = OutputHandler()
            kp_kwargs = {'processOutputLine': [outputHandler]}

            valgrind = 'valgrind'
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                '--smc-check=all-non-file',
                '--vex-iropt-register-updates=allregs-at-mem-access',
                '--gen-suppressions=all',
                '--num-callers=20',
                '--leak-check=full',
                '--show-possibly-lost=no',
                '--track-origins=yes'
            ]

            for s in suppressions:
                valgrind_args.append('--suppressions=' + s)

            supps_dir = os.path.join(build_dir, 'valgrind')
            supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
            valgrind_args.append('--suppressions=' + supps_file1)

            # MACHTYPE is an odd bash-only environment variable that doesn't
            # show up in os.environ, so we have to get it another way.
            machtype = subprocess.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip()
            supps_file2 = os.path.join(supps_dir, machtype + '.sup')
            if os.path.isfile(supps_file2):
                valgrind_args.append('--suppressions=' + supps_file2)

            exitcode = None
            try:
                runner = FirefoxRunner(profile=profile,
                                       binary=self.get_binary_path(),
                                       cmdargs=firefox_args,
                                       env=env,
                                       kp_kwargs=kp_kwargs)
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait()

            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    print('TEST-UNEXPECTED-FAILURE | valgrind-test | error parsing:', errs, "errors seen, but", supps, "generated suppressions seen")

                elif errs == 0:
                    status = 0
                    print('TEST-PASS | valgrind-test | valgrind found no errors')
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if exitcode != 0:
                    status = 2  # turns the TBPL job red
                    print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind')

                httpd.stop()

            return status
Beispiel #20
0
    def valgrind_test(self, suppressions):
        import json
        import sys
        import tempfile

        from mozbuild.base import MozbuildObject
        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, "build")

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo"))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            # TODO: refactor this into mozprofile
            prefpath = os.path.join(self.topsrcdir, "testing", "profiles", "prefs_general.js")
            prefs = {}
            prefs.update(Preferences.read_prefs(prefpath))
            interpolation = {"server": "%s:%d" % httpd.httpd.server_address, "OOP": "false"}
            prefs = json.loads(json.dumps(prefs) % interpolation)
            for pref in prefs:
                prefs[pref] = Preferences.cast(prefs[pref])

            quitter = os.path.join(self.topsrcdir, "tools", "quitter", "*****@*****.**")

            locations = ServerLocations()
            locations.add_host(host="127.0.0.1", port=httpd.httpd.server_port, options="primary")

            profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env["G_SLICE"] = "always-malloc"
            env["MOZ_CC_RUN_DURING_SHUTDOWN"] = "1"
            env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
            env["XPCOM_DEBUG_BREAK"] = "warn"

            env.update(self.extra_environment_variables)

            outputHandler = OutputHandler(self.log)
            kp_kwargs = {"processOutputLine": [outputHandler]}

            valgrind = "valgrind"
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                "--smc-check=all-non-file",
                "--vex-iropt-register-updates=allregs-at-mem-access",
                "--gen-suppressions=all",
                "--num-callers=36",
                "--leak-check=full",
                "--show-possibly-lost=no",
                "--track-origins=yes",
                "--trace-children=yes",
                "-v",  # Enable verbosity to get the list of used suppressions
            ]

            for s in suppressions:
                valgrind_args.append("--suppressions=" + s)

            supps_dir = os.path.join(build_dir, "valgrind")
            supps_file1 = os.path.join(supps_dir, "cross-architecture.sup")
            valgrind_args.append("--suppressions=" + supps_file1)

            # MACHTYPE is an odd bash-only environment variable that doesn't
            # show up in os.environ, so we have to get it another way.
            machtype = subprocess.check_output(["bash", "-c", "echo $MACHTYPE"]).rstrip()
            supps_file2 = os.path.join(supps_dir, machtype + ".sup")
            if os.path.isfile(supps_file2):
                valgrind_args.append("--suppressions=" + supps_file2)

            exitcode = None
            timeout = 1800
            try:
                runner = FirefoxRunner(
                    profile=profile,
                    binary=self.get_binary_path(),
                    cmdargs=firefox_args,
                    env=env,
                    process_args=kp_kwargs,
                )
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait(timeout=timeout)

            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-parsing",
                        {"errs": errs, "supps": supps},
                        "TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors seen, but {supps} generated suppressions seen",
                    )

                elif errs == 0:
                    status = 0
                    self.log(logging.INFO, "valgrind-pass", {}, "TEST-PASS | valgrind-test | valgrind found no errors")
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if exitcode == None:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-timeout",
                        {"timeout": timeout},
                        "TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out (reached {timeout} second limit)",
                    )
                elif exitcode != 0:
                    status = 2  # turns the TBPL job red
                    self.log(
                        logging.ERROR,
                        "valgrind-fail-errors",
                        {},
                        "TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind",
                    )

                httpd.stop()

            return status
Beispiel #21
0
    def start(self, **kwargs):
        if self.marionette_port is None:
            self.marionette_port = get_free_port(2828, exclude=self.used_ports)
            self.used_ports.add(self.marionette_port)

        env = os.environ.copy()
        env["MOZ_CRASHREPORTER"] = "1"
        env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1"
        env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1"
        env["STYLO_THREADS"] = str(self.stylo_threads)
        if self.chaos_mode_flags is not None:
            env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags)

        locations = ServerLocations(
            filename=os.path.join(here, "server-locations.txt"))

        preferences = self.load_prefs()

        self.profile = FirefoxProfile(locations=locations,
                                      preferences=preferences)
        self.profile.set_preferences({
            "marionette.port":
            self.marionette_port,
            "dom.disable_open_during_load":
            False,
            "network.dns.localDomains":
            ",".join(hostnames),
            "network.proxy.type":
            0,
            "places.history.enabled":
            False,
            "dom.send_after_paint_to_content":
            True,
            "network.preload":
            True
        })
        if self.e10s:
            self.profile.set_preferences(
                {"browser.tabs.remote.autostart": True})

        if self.test_type == "reftest":
            self.profile.set_preferences(
                {"layout.interruptible-reflow.enabled": False})

        if self.leak_check and kwargs.get("check_leaks", True):
            self.leak_report_file = os.path.join(self.profile.profile,
                                                 "runtests_leaks.log")
            if os.path.exists(self.leak_report_file):
                os.remove(self.leak_report_file)
            env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file
        else:
            self.leak_report_file = None

        # Bug 1262954: winxp + e10s, disable hwaccel
        if (self.e10s and platform.system() in ("Windows", "Microsoft")
                and '5.1' in platform.version()):
            self.profile.set_preferences(
                {"layers.acceleration.disabled": True})

        if self.ca_certificate_path is not None:
            self.setup_ssl()

        debug_args, cmd = browser_command(
            self.binary, self.binary_args if self.binary_args else [] +
            [cmd_arg("marionette"), "about:blank"], self.debug_info)

        self.runner = FirefoxRunner(
            profile=self.profile,
            binary=cmd[0],
            cmdargs=cmd[1:],
            env=env,
            process_class=ProcessHandler,
            process_args={"processOutputLine": [self.on_output]})

        self.logger.debug("Starting Firefox")

        self.runner.start(debug_args=debug_args,
                          interactive=self.debug_info
                          and self.debug_info.interactive)
        self.logger.debug("Firefox Started")
Beispiel #22
0
class ServerLocationsTest(unittest.TestCase):
    """test server locations"""

    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(self, location, scheme, host, port, options):
        self.assertEqual(location.scheme, scheme)
        self.assertEqual(location.host, host)
        self.assertEqual(location.port, port)
        self.assertEqual(location.options, options)

    def create_temp_file(self, contents):
        f = tempfile.NamedTemporaryFile()
        f.write(contents)
        f.flush()
        return f

    def test_server_locations(self):
        # write a permissions file
        f = self.create_temp_file(self.locations)

        # read the locations
        locations = ServerLocations(f.name)

        # ensure that they're what we expect
        self.assertEqual(len(locations), 6)
        i = iter(locations)
        self.compare_location(i.next(), 'http', 'mochi.test', '8888',
                              ['primary', 'privileged'])
        self.compare_location(i.next(), 'http', '127.0.0.1', '80',
                              ['privileged'])
        self.compare_location(i.next(), 'http', '127.0.0.1', '8888',
                              ['privileged'])
        self.compare_location(i.next(), 'https', 'test', '80', ['privileged'])
        self.compare_location(i.next(), 'http', 'example.org', '80',
                              ['privileged'])
        self.compare_location(i.next(), 'http', 'test1.example.org', '80',
                              ['privileged'])

        locations.add_host('mozilla.org')
        self.assertEqual(len(locations), 7)
        self.compare_location(i.next(), 'http', 'mozilla.org', '80',
                              ['privileged'])

        # test some errors
        self.assertRaises(MultiplePrimaryLocationsError,
                          locations.add_host,
                          'primary.test',
                          options='primary')

        # We no longer throw these DuplicateLocation Error
        try:
            locations.add_host('127.0.0.1')
        except DuplicateLocationError:
            self.assertTrue(False,
                            "Should no longer throw DuplicateLocationError")

        self.assertRaises(BadPortLocationError,
                          locations.add_host,
                          '127.0.0.1',
                          port='abc')

        # test some errors in locations file
        f = self.create_temp_file(self.locations_no_primary)

        exc = None
        try:
            ServerLocations(f.name)
        except LocationsSyntaxError, e:
            exc = e
        self.assertNotEqual(exc, None)
        self.assertEqual(exc.err.__class__, MissingPrimaryLocationError)
        self.assertEqual(exc.lineno, 3)

        # test bad port in a locations file to ensure lineno calculated
        # properly.
        f = self.create_temp_file(self.locations_bad_port)

        exc = None
        try:
            ServerLocations(f.name)
        except LocationsSyntaxError, e:
            exc = e
from datetime import datetime
from mozbuild.base import MozbuildObject
from buildconfig import substs

PORT = 8888

if __name__ == '__main__':
  cli = CLI()
  debug_args, interactive = cli.debugger_arguments()

  build = MozbuildObject.from_environment()
  httpd = MozHttpd(port=PORT,
                   docroot=os.path.join(build.topsrcdir, "build", "pgo"))
  httpd.start(block=False)

  locations = ServerLocations()
  locations.add_host(host='127.0.0.1',
                     port=PORT,
                     options='primary,privileged')

  #TODO: mozfile.TemporaryDirectory
  profilePath = tempfile.mkdtemp()
  try:
    #TODO: refactor this into mozprofile
    prefpath = os.path.join(build.topsrcdir, "testing", "profiles", "prefs_general.js")
    prefs = {}
    prefs.update(Preferences.read_prefs(prefpath))
    interpolation = { "server": "%s:%d" % httpd.httpd.server_address,
                      "OOP": "false"}
    prefs = json.loads(json.dumps(prefs) % interpolation)
    for pref in prefs:
Beispiel #24
0
    def valgrind_test(self, suppressions):

        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from six import string_types
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, 'build')

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            # TODO: refactor this into mozprofile
            profile_data_dir = os.path.join(
                self.topsrcdir, 'testing', 'profiles')
            with open(os.path.join(profile_data_dir, 'profiles.json'), 'r') as fh:
                base_profiles = json.load(fh)['valgrind']

            prefpaths = [os.path.join(profile_data_dir, profile, 'user.js')
                         for profile in base_profiles]
            prefs = {}
            for path in prefpaths:
                prefs.update(Preferences.read_prefs(path))

            interpolation = {
                'server': '%s:%d' % httpd.httpd.server_address,
            }
            for k, v in prefs.items():
                if isinstance(v, string_types):
                    v = v.format(**interpolation)
                prefs[k] = Preferences.cast(v)

            quitter = os.path.join(
                self.topsrcdir, 'tools', 'quitter', '*****@*****.**')

            locations = ServerLocations()
            locations.add_host(host='127.0.0.1',
                               port=httpd.httpd.server_port,
                               options='primary')

            profile = FirefoxProfile(profile=profilePath,
                                     preferences=prefs,
                                     addons=[quitter],
                                     locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env['G_SLICE'] = 'always-malloc'
            env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
            env['XPCOM_DEBUG_BREAK'] = 'warn'

            env.update(self.extra_environment_variables)

            outputHandler = OutputHandler(self.log)
            kp_kwargs = {'processOutputLine': [outputHandler]}

            valgrind = 'valgrind'
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                '--smc-check=all-non-file',
                '--vex-iropt-register-updates=allregs-at-mem-access',
                '--gen-suppressions=all',
                '--num-callers=36',
                '--leak-check=full',
                '--show-possibly-lost=no',
                '--track-origins=yes',
                '--trace-children=yes',
                '-v',  # Enable verbosity to get the list of used suppressions
                # Avoid excessive delays in the presence of spinlocks.
                # See bug 1309851.
                '--fair-sched=yes',
                # Keep debuginfo after library unmap.  See bug 1382280.
                '--keep-debuginfo=yes',
                # Reduce noise level on rustc and/or LLVM compiled code.
                # See bug 1365915
                '--expensive-definedness-checks=yes',
            ]

            for s in suppressions:
                valgrind_args.append('--suppressions=' + s)

            supps_dir = os.path.join(build_dir, 'valgrind')
            supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
            valgrind_args.append('--suppressions=' + supps_file1)

            if mozinfo.os == 'linux':
                machtype = {
                    'x86_64': 'x86_64-pc-linux-gnu',
                    'x86': 'i386-pc-linux-gnu',
                }.get(mozinfo.processor)
                if machtype:
                    supps_file2 = os.path.join(supps_dir, machtype + '.sup')
                    if os.path.isfile(supps_file2):
                        valgrind_args.append('--suppressions=' + supps_file2)

            exitcode = None
            timeout = 1800
            try:
                runner = FirefoxRunner(profile=profile,
                                       binary=self.get_binary_path(),
                                       cmdargs=firefox_args,
                                       env=env,
                                       process_args=kp_kwargs)
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait(timeout=timeout)

            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    self.log(logging.ERROR, 'valgrind-fail-parsing',
                             {'errs': errs, 'supps': supps},
                             'TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors '
                             'seen, but {supps} generated suppressions seen')

                elif errs == 0:
                    status = 0
                    self.log(logging.INFO, 'valgrind-pass', {},
                             'TEST-PASS | valgrind-test | valgrind found no errors')
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if exitcode is None:
                    status = 2  # turns the TBPL job red
                    self.log(logging.ERROR, 'valgrind-fail-timeout',
                             {'timeout': timeout},
                             'TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out '
                             '(reached {timeout} second limit)')
                elif exitcode != 0:
                    status = 2  # turns the TBPL job red
                    self.log(logging.ERROR, 'valgrind-fail-errors', {},
                             'TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code'
                             'from Valgrind')

                httpd.stop()

            return status
    def run(self):
        if self.options.remote_webserver:
            httpd_host = self.options.remote_webserver.split(':')[0]
        else:
            httpd_host = self.httpd.host
        httpd_port = self.httpd.httpd.server_port

        locations = ServerLocations()
        locations.add_host(host=httpd_host,
                           port=httpd_port,
                           options='primary,privileged')

        #TODO: use Preferences.read when prefs_general.js has been updated
        prefpath = self.options.prefs
        prefs = {}
        prefs.update(Preferences.read_prefs(prefpath))
        interpolation = { "server": "%s:%d" % (httpd_host, httpd_port),
                          "OOP": "false"}
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
          prefs[pref] = Preferences.cast(prefs[pref])
        prefs["steeplechase.signalling_server"] = self.options.signalling_server
        prefs["steeplechase.signalling_room"] = str(uuid.uuid4())
        prefs["media.navigator.permission.disabled"] = True
        prefs["media.navigator.streams.fake"] = True

        specialpowers_path = self.options.specialpowers
        threads = []
        results = []
        cond = threading.Condition()
        for info in self.remote_info:
            with mozfile.TemporaryDirectory() as profile_path:
                # Create and push profile
                print "Writing profile for %s..." % info['name']
                prefs["steeplechase.is_initiator"] = info['is_initiator']
                profile = FirefoxProfile(profile=profile_path,
                                         preferences=prefs,
                                         addons=[specialpowers_path],
                                         locations=locations)
                print "Pushing profile to %s..." % info['name']
                remote_profile_path = posixpath.join(info['test_root'], "profile")
                info['dm'].mkDir(remote_profile_path)
                info['dm'].pushDir(profile_path, remote_profile_path)
                info['remote_profile_path'] = remote_profile_path

            env = {}
            env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
            env["XPCOM_DEBUG_BREAK"] = "warn"
            env["DISPLAY"] = self.options.remote_xdisplay

            cmd = [info['remote_app_path'], "-no-remote",
                   "-profile", info['remote_profile_path'],
                   'http://%s:%d/index.html' % (httpd_host, httpd_port)]
            print "cmd: %s" % (cmd, )
            t = RunThread(name=info['name'],
                          args=(info['dm'], cmd, env, cond, results))
            threads.append(t)

        for t in threads:
            t.start()

        self.log.info("Waiting for results...")
        pass_count, fail_count = 0, 0
        outputs = {}
        while threads:
            cond.acquire()
            while not results:
                cond.wait()
            thread, result, output = results.pop(0)
            cond.release()
            outputs[thread.name] = output
            passes, failures = result
            #XXX: double-counting tests from both clients. Ok?
            pass_count += passes
            fail_count += failures
            if failures:
                self.log.error("Error in %s" % thread.name)
            threads.remove(thread)
        self.log.info("All clients finished")
        for info in self.remote_info:
            if self.options.log_dest:
                with open(os.path.join(self.options.log_dest,
                                       "%s.log" % info['name']), "wb") as f:
                    f.write(outputs[info['name']])
            if fail_count:
                self.log.info("Log output for %s:", info["name"])
                self.log.info(">>>>>>>")
                for line in outputs[info['name']].splitlines():
                    #TODO: make structured log messages human-readable
                    self.log.info(line)
                self.log.info("<<<<<<<")
        return pass_count, fail_count
Beispiel #26
0
def createSSLServerCertificate(build, srcDir):
    certutil = build.get_binary_path(what="certutil")
    pk12util = build.get_binary_path(what="pk12util")

    with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
        pgoCAPath = os.path.join(srcDir, "pgoca.p12")

        pwfile.write("\n")

        if not dbFilesExist(srcDir):
            # Make sure all DB files from src are really deleted
            unlinkDbFiles(srcDir)

            # Create certification database for ssltunnel
            status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
            if status:
                return status

            status = runUtil(pk12util, [
                "-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k",
                pwfile.name
            ])
            if status:
                return status

        # Generate automatic certificate
        locations = ServerLocations(
            os.path.join(build.topsrcdir, "build", "pgo",
                         "server-locations.txt"))
        iterator = iter(locations)

        # Skips the first entry, I don't know why: bug 879740
        iterator.next()

        locationsParam = ""
        firstLocation = ""
        for loc in iterator:
            if loc.scheme == "https" and "nocert" not in loc.options:
                customCertOption = False
                customCertRE = re.compile("^cert=(?:\w+)")
                for option in loc.options:
                    match = customCertRE.match(option)
                    if match:
                        customCertOption = True
                        break

                if not customCertOption:
                    if len(locationsParam) > 0:
                        locationsParam += ","
                    locationsParam += loc.host

                    if firstLocation == "":
                        firstLocation = loc.host

        if not firstLocation:
            print "Nothing to generate, no automatic secure hosts specified"
        else:
            createRandomFile(rndfile)

            runUtil(certutil, [
                "-D", "-n", "pgo server certificate", "-d", srcDir, "-z",
                rndfile.name, "-f", pwfile.name
            ])
            # Ignore the result, the certificate may not be present when new database is being built

            status = runUtil(certutil, [
                "-S", "-s",
                "CN=%s" % firstLocation, "-t", "Pu,,", "-c",
                "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v",
                "120", "-n", "pgo server certificate", "-d", srcDir, "-z",
                rndfile.name, "-f", pwfile.name
            ])
            if status:
                return status

            status = runUtil(certutil, [
                "-S", "-s", "CN=Imminently Distrusted End Entity", "-t", "P,,",
                "-c", "pgo temporary ca", "-k", "rsa", "-g", "2048", "-Z",
                "SHA256", "-m", "1519140221", "-n", "imminently_distrusted",
                "-v", "120", "-8", "imminently-distrusted.example.com", "-d",
                srcDir, "-z", rndfile.name, "-f", pwfile.name
            ])
            if status:
                return status
        """
    As of February 2018, there are 15 more certificates which are not created by
    this script. See bug 1441338:

    selfsigned                                                   Pu,u,u
    Unknown CA                                                   Cu,u,u
    escapeattack1                                                Pu,u,u
    untrustedandexpired                                          Pu,u,u
    alternateTrustedAuthority                                    Cu,u,u
    dynamicPinningGood                                           Pu,u,u
    staticPinningBad                                             Pu,u,u
    sha1_end_entity                                              Pu,u,u
    bug413909cert                                                u,u,u
    untrusted                                                    Pu,u,u
    escapeattack2                                                Pu,u,u
    expired                                                      Pu,u,u
    dynamicPinningBad                                            Pu,u,u
    sha256_end_entity                                            Pu,u,u
    """

    return 0
Beispiel #27
0
            print("{}\n\n{}\n".format(e, e.help()))
            sys.exit(1)
    binary = os.path.normpath(os.path.abspath(binary))

    path_mappings = {
        k: os.path.join(build.topsrcdir, v)
        for k, v in PATH_MAPPINGS.items()
    }
    httpd = MozHttpd(
        port=PORT,
        docroot=os.path.join(build.topsrcdir, "build", "pgo"),
        path_mappings=path_mappings,
    )
    httpd.start(block=False)

    locations = ServerLocations()
    locations.add_host(host="127.0.0.1",
                       port=PORT,
                       options="primary,privileged")

    old_profraw_files = glob.glob("*.profraw")
    for f in old_profraw_files:
        os.remove(f)

    with TemporaryDirectory() as profilePath:
        # TODO: refactor this into mozprofile
        profile_data_dir = os.path.join(build.topsrcdir, "testing", "profiles")
        with open(os.path.join(profile_data_dir, "profiles.json"), "r") as fh:
            base_profiles = json.load(fh)["profileserver"]

        prefpaths = [
Beispiel #28
0
    def __init__(self, options, **kwargs):
        self.options = options
        self.server = None
        self.logger = mozlog.getLogger('PEP')

        # create the profile
        enable_proxy = False
        locations = ServerLocations()
        if self.options.proxyLocations:
            if not self.options.serverPath:
                self.logger.warning('Can\'t set up proxy without server path')
            else:
                enable_proxy = True
                for proxyLocation in self.options.proxyLocations:
                    locations.read(proxyLocation, False)
                locations.add_host(host='127.0.0.1',
                                   port=self.options.serverPort,
                                   options='primary,privileged')

        self.profile = self.profile_class(
            profile=self.options.profilePath,
            addons=[os.path.join(here, 'extension')],
            locations=locations,
            proxy=enable_proxy)

        # fork a server to serve the test related files
        if self.options.serverPath:
            self.runServer()

        tests = []
        # TODO is there a better way of doing this?
        if self.options.testPath.endswith('.js'):
            # a single test file was passed in
            testObj = {}
            testObj['path'] = os.path.realpath(self.options.testPath)
            testObj['name'] = os.path.basename(self.options.testPath)
            testObj['here'] = os.path.dirname(testObj['path'])
            tests.append(testObj)
        else:
            # a test manifest was passed in
            # open and convert the manifest to json
            manifest = TestManifest()
            manifest.read(self.options.testPath)
            tests = manifest.get()

        # create a manifest object to be read by the JS side
        manifestObj = {}
        manifestObj['tests'] = tests
        manifestObj['options'] = options.__dict__

        # write manifest to a JSON file
        jsonManifest = open(os.path.join(here, 'manifest.json'), 'w')
        jsonManifest.write(json.dumps(manifestObj))
        jsonManifest.close()

        # setup environment
        env = os.environ.copy()
        env['MOZ_INSTRUMENT_EVENT_LOOP'] = '1'
        env['MOZ_INSTRUMENT_EVENT_LOOP_THRESHOLD'] = str(
            options.tracerThreshold)
        env['MOZ_INSTRUMENT_EVENT_LOOP_INTERVAL'] = str(options.tracerInterval)
        env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'

        # construct the browser arguments
        cmdargs = []
        # TODO Make browserArgs a list
        cmdargs.extend(self.options.browserArgs)
        cmdargs.extend(['-pep-start', os.path.realpath(jsonManifest.name)])

        # run with managed process handler
        self.runner = self.runner_class(profile=self.profile,
                                        binary=self.options.binary,
                                        cmdargs=cmdargs,
                                        env=env,
                                        process_class=PepProcess)
Beispiel #29
0
    def valgrind_test(self, suppressions):
        import json
        import re
        import sys
        import tempfile

        from mozbuild.base import MozbuildObject
        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath

        build_dir = os.path.join(self.topsrcdir, 'build')

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            #TODO: refactor this into mozprofile
            prefpath = os.path.join(self.topsrcdir, 'testing', 'profiles',
                                    'prefs_general.js')
            prefs = {}
            prefs.update(Preferences.read_prefs(prefpath))
            interpolation = {
                'server': '%s:%d' % httpd.httpd.server_address,
                'OOP': 'false'
            }
            prefs = json.loads(json.dumps(prefs) % interpolation)
            for pref in prefs:
                prefs[pref] = Preferences.cast(prefs[pref])

            quitter = os.path.join(self.distdir, 'xpi-stage', 'quitter')

            locations = ServerLocations()
            locations.add_host(host='127.0.0.1',
                               port=httpd.httpd.server_port,
                               options='primary')

            profile = FirefoxProfile(profile=profilePath,
                                     preferences=prefs,
                                     addons=[quitter],
                                     locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env['G_SLICE'] = 'always-malloc'
            env['XPCOM_CC_RUN_DURING_SHUTDOWN'] = '1'
            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
            env['XPCOM_DEBUG_BREAK'] = 'warn'

            class OutputHandler(object):
                def __init__(self):
                    self.found_errors = False

                def __call__(self, line):
                    print(line)
                    m = re.match(
                        r'.*ERROR SUMMARY: [1-9]\d* errors from \d+ contexts',
                        line)
                    if m:
                        self.found_errors = True

            outputHandler = OutputHandler()
            kp_kwargs = {'processOutputLine': [outputHandler]}

            valgrind = 'valgrind'
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind, '--smc-check=all-non-file',
                '--vex-iropt-register-updates=allregs-at-mem-access',
                '--gen-suppressions=all', '--num-callers=20',
                '--leak-check=full', '--show-possibly-lost=no',
                '--track-origins=yes'
            ]

            for s in suppressions:
                valgrind_args.append('--suppressions=' + s)

            supps_dir = os.path.join(build_dir, 'valgrind')
            supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
            valgrind_args.append('--suppressions=' + supps_file1)

            # MACHTYPE is an odd bash-only environment variable that doesn't
            # show up in os.environ, so we have to get it another way.
            machtype = subprocess.check_output(
                ['bash', '-c', 'echo $MACHTYPE']).rstrip()
            supps_file2 = os.path.join(supps_dir, machtype + '.sup')
            if os.path.isfile(supps_file2):
                valgrind_args.append('--suppressions=' + supps_file2)

            exitcode = None
            try:
                runner = FirefoxRunner(profile=profile,
                                       binary=self.get_binary_path(),
                                       cmdargs=firefox_args,
                                       env=env,
                                       kp_kwargs=kp_kwargs)
                runner.start(debug_args=valgrind_args)
                exitcode = runner.wait()

            finally:
                if not outputHandler.found_errors:
                    status = 0
                    print(
                        'TEST-PASS | valgrind-test | valgrind found no errors')
                else:
                    status = 1  # turns the TBPL job orange
                    print(
                        'TEST-UNEXPECTED-FAIL | valgrind-test | valgrind found errors'
                    )

                if exitcode != 0:
                    status = 2  # turns the TBPL job red
                    print(
                        'TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind'
                    )

                httpd.stop()

            return status
    build = MozbuildObject.from_environment()

    binary = runner_args.get('binary')
    if not binary:
        binary = build.get_binary_path(where="staged-package")

    path_mappings = {
        k: os.path.join(build.topsrcdir, v)
        for k, v in PATH_MAPPINGS.items()
    }
    httpd = MozHttpd(port=PORT,
                     docroot=os.path.join(build.topsrcdir, "build", "pgo"),
                     path_mappings=path_mappings)
    httpd.start(block=False)

    locations = ServerLocations()
    locations.add_host(host='127.0.0.1',
                       port=PORT,
                       options='primary,privileged')

    with TemporaryDirectory() as profilePath:
        # TODO: refactor this into mozprofile
        profile_data_dir = os.path.join(build.topsrcdir, 'testing', 'profiles')
        with open(os.path.join(profile_data_dir, 'profiles.json'), 'r') as fh:
            base_profiles = json.load(fh)['profileserver']

        prefpaths = [os.path.join(profile_data_dir, profile, 'user.js')
                     for profile in base_profiles]

        prefs = {}
        for path in prefpaths:
Beispiel #31
0
 def locations(self):
     if self._locations is not None:
         return self._locations
     locations_file = os.path.join(here, "server-locations.txt")
     self._locations = ServerLocations(locations_file)
     return self._locations
Beispiel #32
0
    def valgrind_test(self, suppressions):
        import json
        import sys
        import tempfile

        from mozbuild.base import MozbuildObject
        from mozfile import TemporaryDirectory
        from mozhttpd import MozHttpd
        from mozprofile import FirefoxProfile, Preferences
        from mozprofile.permissions import ServerLocations
        from mozrunner import FirefoxRunner
        from mozrunner.utils import findInPath
        from valgrind.output_handler import OutputHandler

        build_dir = os.path.join(self.topsrcdir, 'build')

        # XXX: currently we just use the PGO inputs for Valgrind runs.  This may
        # change in the future.
        httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo'))
        httpd.start(block=False)

        with TemporaryDirectory() as profilePath:
            #TODO: refactor this into mozprofile
            prefpath = os.path.join(self.topsrcdir, 'testing', 'profiles', 'prefs_general.js')
            prefs = {}
            prefs.update(Preferences.read_prefs(prefpath))
            interpolation = { 'server': '%s:%d' % httpd.httpd.server_address,
                              'OOP': 'false'}
            prefs = json.loads(json.dumps(prefs) % interpolation)
            for pref in prefs:
                prefs[pref] = Preferences.cast(prefs[pref])

            quitter = os.path.join(self.distdir, 'xpi-stage', 'quitter')

            locations = ServerLocations()
            locations.add_host(host='127.0.0.1',
                               port=httpd.httpd.server_port,
                               options='primary')

            profile = FirefoxProfile(profile=profilePath,
                                     preferences=prefs,
                                     addons=[quitter],
                                     locations=locations)

            firefox_args = [httpd.get_url()]

            env = os.environ.copy()
            env['G_SLICE'] = 'always-malloc'
            env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
            env['XPCOM_DEBUG_BREAK'] = 'warn'

            env.update(self.extra_environment_variables)

            outputHandler = OutputHandler()
            kp_kwargs = {'processOutputLine': [outputHandler]}

            valgrind = 'valgrind'
            if not os.path.exists(valgrind):
                valgrind = findInPath(valgrind)

            valgrind_args = [
                valgrind,
                '--smc-check=all-non-file',
                '--vex-iropt-register-updates=allregs-at-mem-access',
                '--gen-suppressions=all',
                '--num-callers=36',
                '--leak-check=full',
                '--show-possibly-lost=no',
                '--track-origins=yes',
                '--trace-children=yes',
                # The gstreamer plugin scanner can run as part of executing
                # firefox, but is an external program. In some weird cases,
                # valgrind finds errors while executing __libc_freeres when
                # it runs, but those are not relevant, as it's related to
                # executing third party code. So don't trace
                # gst-plugin-scanner.
                '--trace-children-skip=*/gst-plugin-scanner',
                '-v',  # Enable verbosity to get the list of used suppressions
            ]

            for s in suppressions:
                valgrind_args.append('--suppressions=' + s)

            supps_dir = os.path.join(build_dir, 'valgrind')
            supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
            valgrind_args.append('--suppressions=' + supps_file1)

            # MACHTYPE is an odd bash-only environment variable that doesn't
            # show up in os.environ, so we have to get it another way.
            machtype = subprocess.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip()
            supps_file2 = os.path.join(supps_dir, machtype + '.sup')
            if os.path.isfile(supps_file2):
                valgrind_args.append('--suppressions=' + supps_file2)

            exitcode = None
            timeout = 1100
            try:
                runner = FirefoxRunner(profile=profile,
                                       binary=self.get_binary_path(),
                                       cmdargs=firefox_args,
                                       env=env,
                                       process_args=kp_kwargs)
                runner.start(debug_args=valgrind_args)
                # This timeout is slightly less than the no-output timeout on
                # TBPL, so we'll timeout here first and give an informative
                # message.
                exitcode = runner.wait(timeout=timeout)

            finally:
                errs = outputHandler.error_count
                supps = outputHandler.suppression_count
                if errs != supps:
                    status = 1  # turns the TBPL job orange
                    print('TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {} errors seen, but {} generated suppressions seen'.format(errs, supps))

                elif errs == 0:
                    status = 0
                    print('TEST-PASS | valgrind-test | valgrind found no errors')
                else:
                    status = 1  # turns the TBPL job orange
                    # We've already printed details of the errors.

                if exitcode == None:
                    status = 2  # turns the TBPL job red
                    print('TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out (reached {} second limit)'.format(timeout))
                elif exitcode != 0:
                    status = 2  # turns the TBPL job red
                    print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind')

                httpd.stop()

            return status
Beispiel #33
0
def createSSLServerCertificate(build, srcDir):
    certutil = build.get_binary_path(what="certutil")
    pk12util = build.get_binary_path(what="pk12util")

    with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
        pgoCAPath = os.path.join(srcDir, "pgoca.p12")

        pwfile.write("\n")

        if not dbFilesExist(srcDir):
            # Make sure all DB files from src are really deleted
            unlinkDbFiles(srcDir)

            # Create certification database for ssltunnel
            status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
            if status:
                return status

            status = runUtil(pk12util, [
                "-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k",
                pwfile.name
            ])
            if status:
                return status

        # Generate automatic certificate
        locations = ServerLocations(
            os.path.join(build.topsrcdir, "build", "pgo",
                         "server-locations.txt"))
        iterator = iter(locations)

        # Skips the first entry, I don't know why: bug 879740
        iterator.next()

        locationsParam = ""
        firstLocation = ""
        for loc in iterator:
            if loc.scheme == "https" and "nocert" not in loc.options:
                customCertOption = False
                customCertRE = re.compile("^cert=(?:\w+)")
                for option in loc.options:
                    match = customCertRE.match(option)
                    if match:
                        customCertOption = True
                        break

                if not customCertOption:
                    if len(locationsParam) > 0:
                        locationsParam += ","
                    locationsParam += loc.host

                    if firstLocation == "":
                        firstLocation = loc.host

        if not firstLocation:
            print "Nothing to generate, no automatic secure hosts specified"
        else:
            createRandomFile(rndfile)

            runUtil(certutil, [
                "-D", "-n", "pgo server certificate", "-d", srcDir, "-z",
                rndfile.name, "-f", pwfile.name
            ])
            # Ignore the result, the certificate may not be present when new database is being built

            status = runUtil(certutil, [
                "-S", "-s",
                "CN=%s" % firstLocation, "-t", "Pu,,", "-c",
                "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v",
                "120", "-n", "pgo server certificate", "-d", srcDir, "-z",
                rndfile.name, "-f", pwfile.name
            ])
            if status:
                return status

    return 0