def run_job(self):
        is_test_completed = False
        custom_addons = ['pageloader.xpi']

        if not self.install_local_pages():
            self.add_failure(
                self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                'Aborting test - Could not install local pages on phone.',
                TreeherderStatus.EXCEPTION)
            return is_test_completed

        if not self.create_profile(custom_addons=custom_addons):
            self.add_failure(self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                             'Aborting test - Could not run Fennec.',
                             TreeherderStatus.BUSTED)
            return is_test_completed

        perfherder_options = PerfherderOptions(self.perfherder_options,
                                               self.build.tree)
        is_test_completed = True
        testcount = len(self._test_args.keys())
        test_items = enumerate(self._test_args.iteritems(), 1)
        for testnum, (testname, test_args) in test_items:
            self.loggerdeco = self.loggerdeco.clone(
                extradict={
                    'repo': self.build.tree,
                    'buildid': self.build.id,
                    'buildtype': self.build.type,
                    'sdk': self.phone.sdk,
                    'platform': self.build.platform,
                    'testname': testname
                },
                extraformat=
                'TalosTestJob %(repo)s %(buildid)s %(buildtype)s %(sdk)s %(platform)s %(testname)s %(message)s'
            )
            self.dm._logger = self.loggerdeco
            self.loggerdeco.info('Running test (%d/%d)', testnum, testcount)

            # success == False indicates that none of the attempts
            # were successful in getting any measurement. This is
            # typically due to a regression in the brower which should
            # be reported.
            success = False

            command = self.worker_subprocess.process_autophone_cmd(
                test=self, require_ip_address=testname.startswith('remote'))

            if command['interrupt']:
                self.handle_test_interrupt(command['reason'],
                                           command['test_result'])
                break

            self.update_status(message='Test %d/%d, for test_args %s' %
                               (testnum, testcount, test_args))

            if not self.create_profile(custom_addons=custom_addons):
                self.add_failure(self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                                 'Failed to create profile',
                                 TreeherderStatus.TESTFAILED)
            else:
                measurement = self.runtest(test_args)
                if measurement:
                    if not self.perfherder_artifact:
                        self.perfherder_artifact = PerfherderArtifact()
                    suite = self.create_suite(measurement['pageload_metric'],
                                              testname,
                                              options=perfherder_options)
                    self.perfherder_artifact.add_suite(suite)
                    self.add_pass(test_args)
                    success = True
                else:
                    self.add_failure(self.name,
                                     TestStatus.TEST_UNEXPECTED_FAIL,
                                     'Failed to get measurement.',
                                     TreeherderStatus.TESTFAILED)

            if not success:
                # If we have not gotten a single measurement at this point,
                # just bail and report the failure rather than wasting time
                # continuing more attempts.
                self.loggerdeco.info('Failed to get measurements for test %s',
                                     testname)
                self.worker_subprocess.mailer.send(
                    '%s %s failed for Build %s %s on %s %s' %
                    (self.__class__.__name__, testname, self.build.tree,
                     self.build.id, host(), self.phone.id),
                    'No measurements were detected for test %s.\n\n'
                    'Job        %s\n'
                    'Host       %s\n'
                    'Phone      %s\n'
                    'Repository %s\n'
                    'Build      %s\n'
                    'Revision   %s\n' %
                    (testname, self.job_url, host(), self.phone.id,
                     self.build.tree, self.build.id, self.build.changeset))
                self.add_failure(self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                                 'No measurements detected.',
                                 TreeherderStatus.BUSTED)

                self.loggerdeco.debug('publishing results')

            if command and command['interrupt']:
                break
            elif not success:
                break

        return is_test_completed
Beispiel #2
0
    def run_job(self):
        is_test_completed = False

        if not self.install_local_pages():
            self.add_failure(
                self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                'Aborting test - Could not install local pages on phone.',
                TreeherderStatus.EXCEPTION)
            return is_test_completed

        if not self.create_profile():
            self.add_failure(self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                             'Aborting test - Could not run Fennec.',
                             TreeherderStatus.BUSTED)
            return is_test_completed

        perfherder_options = PerfherderOptions(self.perfherder_options,
                                               repo=self.build.tree)
        is_test_completed = True
        testcount = len(self._urls.keys())
        for testnum, (testname, url) in enumerate(self._urls.iteritems(), 1):
            self.loggerdeco = self.loggerdeco.clone(
                extradict={
                    'phoneid': self.phone.id,
                    'buildid': self.build.id,
                    'testname': testname
                },
                extraformat=
                'S1S2TestJob|%(phoneid)s|%(buildid)s|%(testname)s|%(message)s')
            self.dm._logger = self.loggerdeco
            self.loggerdeco.info('Running test (%d/%d) for %d iterations',
                                 testnum, testcount, self._iterations)

            command = None
            for attempt in range(1, self.stderrp_attempts + 1):
                # dataset is a list of the measurements made for the
                # iterations for this test.
                #
                # An empty item in the dataset list represents a
                # failure to obtain any measurement for that
                # iteration.
                #
                # It is possible for an item in the dataset to have an
                # uncached value and not have a corresponding cached
                # value if the cached test failed to record the
                # values.

                iteration = 0
                dataset = []
                for iteration in range(1, self._iterations + 1):
                    # Calling svc power stayon true will turn on the
                    # display for at least some devices if it has
                    # turned off.
                    self.dm.power_on()
                    command = self.worker_subprocess.process_autophone_cmd(
                        test=self, require_ip_address=url.startswith('http'))
                    if command['interrupt']:
                        self.handle_test_interrupt(command['reason'],
                                                   command['test_result'])
                        break
                    self.update_status(message='Attempt %d/%d for Test %d/%d, '
                                       'run %d, for url %s' %
                                       (attempt, self.stderrp_attempts,
                                        testnum, testcount, iteration, url))

                    if not self.create_profile():
                        self.add_failure(self.name,
                                         TestStatus.TEST_UNEXPECTED_FAIL,
                                         'Failed to create profile',
                                         TreeherderStatus.TESTFAILED)
                        continue

                    measurement = self.runtest(url)
                    if not measurement:
                        self.loggerdeco.warning(
                            '%s %s Attempt %s Failed to get uncached measurement.',
                            testname, url, attempt)
                        continue

                    self.add_pass(url)
                    dataset.append({'uncached': measurement})

                    measurement = self.runtest(url)
                    if not measurement:
                        self.loggerdeco.warning(
                            '%s %s Attempt %s Failed to get cached measurement.',
                            testname, url, attempt)
                        continue

                    self.add_pass(url)
                    dataset[-1]['cached'] = measurement

                    if self.is_stderr_below_threshold(
                        ('throbberstart', 'throbberstop'), dataset,
                            self.stderrp_accept):
                        self.loggerdeco.info(
                            'Accepted test (%d/%d) after %d of %d iterations',
                            testnum, testcount, iteration, self._iterations)
                        break

                if command and command['interrupt']:
                    break
                measurements = len(dataset)
                if measurements > 0 and self._iterations != measurements:
                    self.add_failure(self.name,
                                     TestStatus.TEST_UNEXPECTED_FAIL,
                                     'Failed to get all measurements',
                                     TreeherderStatus.TESTFAILED)
                elif measurements == 0:
                    # If we have not gotten a single measurement at this point,
                    # just bail and report the failure rather than wasting time
                    # continuing more attempts.
                    self.add_failure(self.name,
                                     TestStatus.TEST_UNEXPECTED_FAIL,
                                     'No measurements detected.',
                                     TreeherderStatus.BUSTED)
                    self.loggerdeco.info(
                        'Failed to get measurements for test %s after %d/%d attempt '
                        'of %d iterations', testname, attempt,
                        self.stderrp_attempts, self._iterations)
                    self.worker_subprocess.mailer.send(
                        '%s %s failed for Build %s %s on %s %s' %
                        (self.__class__.__name__, testname, self.build.tree,
                         self.build.id, utils.host(), self.phone.id),
                        'No measurements were detected for test %s.\n\n'
                        'Job        %s\n'
                        'Host       %s\n'
                        'Phone      %s\n'
                        'Repository %s\n'
                        'Build      %s\n'
                        'Revision   %s\n' %
                        (testname, self.job_url, utils.host(), self.phone.id,
                         self.build.tree, self.build.id, self.build.changeset))
                    break

                if self.is_stderr_below_threshold(
                    ('throbberstart', 'throbberstop'), dataset,
                        self.stderrp_reject):
                    rejected = False
                else:
                    rejected = True
                    self.loggerdeco.info(
                        'Rejected test (%d/%d) after %d/%d iterations',
                        testnum, testcount, iteration, self._iterations)

                self.loggerdeco.debug('publishing results')

                perfherder_values = {'geometric_mean': 0}
                metric_keys = ['throbberstart', 'throbberstop', 'throbbertime']
                cache_names = {'uncached': 'first', 'cached': 'second'}
                cache_keys = cache_names.keys()

                for metric_key in metric_keys:
                    perfherder_values[metric_key] = {'geometric_mean': 0}
                    for cache_key in cache_keys:
                        perfherder_values[metric_key][cache_key] = {
                            'median': 0,
                            'values': []
                        }

                for datapoint in dataset:
                    for cache_key in datapoint:
                        starttime = datapoint[cache_key]['starttime']
                        throbberstart = datapoint[cache_key]['throbberstart']
                        throbberstop = datapoint[cache_key]['throbberstop']
                        self.report_results(
                            starttime=starttime,
                            tstrt=throbberstart,
                            tstop=throbberstop,
                            testname=testname,
                            cache_enabled=(cache_key == 'cached'),
                            rejected=rejected)
                        perfherder_values['throbberstart'][cache_key][
                            'values'].append(throbberstart - starttime)
                        perfherder_values['throbberstop'][cache_key][
                            'values'].append(throbberstop - starttime)
                        perfherder_values['throbbertime'][cache_key][
                            'values'].append(throbberstop - throbberstart)

                test_values = []
                for metric_key in metric_keys:
                    for cache_key in cache_keys:
                        perfherder_values[metric_key][cache_key][
                            'median'] = utils.median(
                                perfherder_values[metric_key][cache_key]
                                ['values'])
                    perfherder_values[metric_key][
                        'geometric_mean'] = utils.geometric_mean([
                            perfherder_values[metric_key]['uncached']
                            ['median'],
                            perfherder_values[metric_key]['cached']['median']
                        ])
                    test_values.append(
                        perfherder_values[metric_key]['geometric_mean'])

                perfherder_suite = PerfherderSuite(
                    name=testname,
                    value=utils.geometric_mean(test_values),
                    options=perfherder_options)
                for metric_key in metric_keys:
                    for cache_key in cache_keys:
                        cache_name = cache_names[cache_key]
                        subtest_name = "%s %s" % (metric_key, cache_name)
                        perfherder_suite.add_subtest(
                            subtest_name,
                            perfherder_values[metric_key][cache_key]['median'],
                            options=perfherder_options)

                self.perfherder_artifact = PerfherderArtifact()
                self.perfherder_artifact.add_suite(perfherder_suite)
                self.loggerdeco.debug("PerfherderArtifact: %s",
                                      self.perfherder_artifact)

                if not rejected:
                    break

            if command and command['interrupt']:
                break

        return is_test_completed