def _set_fetch_config(self, index): app_name = str(self.ui.app_combo.currentText()) bits = int(self.ui.bits_combo.currentText()) self.fetch_config = create_config(app_name, mozinfo.os, bits, mozinfo.processor) self.build_type_model = QStringListModel( self.fetch_config.available_build_types()) self.ui.build_type.setModel(self.build_type_model) if not self.fetch_config.available_bits(): self.ui.bits_combo.hide() self.ui.label_4.hide() else: self.ui.bits_combo.show() self.ui.label_4.show() # URL doesn't make sense for Thunderbird if app_name == "thunderbird": self.ui.url.hide() self.ui.url_label.hide() else: self.ui.url.show() self.ui.url_label.show()
def setUp(self): good_date = datetime.date(2014, 11, 10) bad_date = datetime.date(2014, 11, 20) fetch_config = fetch_configs.create_config('firefox', 'linux', 64) self.build_data = build_data.NightlyBuildData(fetch_config, good_date, bad_date)
def test_runner_started_multiple_times(): class Worker(QObject): def __init__(self, *args): QObject.__init__(self) class BuildRunner(build_runner.AbstractBuildRunner): worker_class = Worker def init_worker(self, fetch_config, options): build_runner.AbstractBuildRunner.init_worker( self, fetch_config, options) return lambda: 1 fetch_config = create_config('firefox', 'linux', 64, 'x86_64') options = { 'addons': (), 'profile': '/path/to/profile', 'profile_persistence': 'clone' } runner = BuildRunner(Mock(persist='.')) assert not runner.stopped runner.start(fetch_config, options) assert not runner.stopped runner.stop() assert runner.stopped runner.start(fetch_config, options) assert not runner.stopped runner.stop() assert runner.stopped
def test_get_default_date_range(app, os, bits, processor, build_type, expected_range): fetch_config = create_config(app, os, bits, processor) if build_type: fetch_config.set_build_type(build_type) assert expected_range == cli.get_default_date_range(fetch_config)
def setUp(self): self.conf = create_config(self.app_name, self.os, self.bits, self.processor) self.conf.BUILD_TYPES = ( "excluded[win64]", "included[win64-aarch64]", "default", )
def test_set_firefox_build_type_pgo(os, bits, processor, tc_suffix): conf = create_config("firefox", os, bits, processor) if type(tc_suffix) is not str: with pytest.raises(tc_suffix): conf.set_build_type("pgo") else: conf.set_build_type("pgo") assert conf.tk_route(create_push(CHSET, TIMESTAMP_TEST)).endswith("." + tc_suffix)
def cli(argv=None): """ main entry point of mozregression command line. """ options = parse_args(argv) logger = commandline.setup_logging("mozregression", options, {"mach": sys.stdout}) check_mozregression_version(logger) if options.list_releases: print(formatted_valid_release_dates()) sys.exit() cache_session = limitedfilecache.get_cache( options.http_cache_dir, limitedfilecache.ONE_GIGABYTE, logger=get_default_logger('Limited File Cache')) set_http_cache_session(cache_session, get_defaults={"timeout": options.http_timeout}) fetch_config = create_config(options.app, mozinfo.os, options.bits) if options.command is None: launcher_kwargs = dict( addons=options.addons, profile=options.profile, cmdargs=options.cmdargs, preferences=preference(options.prefs_files, options.prefs), ) test_runner = ManualTestRunner(launcher_kwargs=launcher_kwargs) else: test_runner = CommandTestRunner(options.command) runner = ResumeInfoBisectRunner(fetch_config, test_runner, options) if fetch_config.is_inbound(): # this can be useful for both inbound and nightly, because we # can go to inbound from nightly. fetch_config.set_inbound_branch(options.inbound_branch) # bisect inbound if last good revision or first bad revision are set if options.first_bad_revision or options.last_good_revision: bisect = bisect_inbound else: bisect = bisect_nightlies try: launcher_class = APP_REGISTRY.get(fetch_config.app_name) launcher_class.check_is_runnable() sys.exit(bisect(runner, logger)) except KeyboardInterrupt: sys.exit("\nInterrupted.") except UnavailableRelease as exc: sys.exit("%s\n%s" % (exc, formatted_valid_release_dates())) except (MozRegressionError, RequestException) as exc: sys.exit(str(exc))
def __init__(self, good, bad, platform, warning, warning_limit, warning_re, ignore_lines, required_test): init_logger() self.use_nightly = True try: self.good = parse_date(good) self.bad = parse_date(bad) except DateFormatError: # This hopefully a revision range. We can bypass nightly and # go directly to InboundHandler. That itself is a bit of a misnomer, # it will still bisect m-c builds, but by changeset range, not date # range. self.use_nightly = False self.good = good self.bad = bad self.ignore_lines = ignore_lines self.test_runner = WarningTestRunner(warning, platform, ignore_lines=ignore_lines, warning_re=warning_re, warning_limit=warning_limit, required_test=required_test) # Convert the platform to a mozregression friendly version. # Also avoid overwriting the os module by *not* using |os| for a # variable name. (_os, bits) = re.match(r'([a-zA-Z]+)-?([0-9]+)?', platform).groups() if not bits or bits not in (32, 64): bits = 32 # windows7-32 # windows7-32-vm # win32 # win64 if '64' in platform: bits = 64 if _os.startswith('win'): _os = 'win' print("_os = %s bits = %s" % (_os, bits)) # TODO(ER): We might be able to ditch this. self.fetch_config = create_config('firefox', _os, int(bits)) # Hardcode to m-c for now. self.fetch_config.set_repo('mozilla-central') self.fetch_config.set_build_type('debug') class FakeDownloadManager: def focus_download(self, foo): pass dm = FakeDownloadManager() self.bisector = Bisector(self.fetch_config, self.test_runner, dm, False, None)
def create_build_info(klass, **attrs): defaults = dict( fetch_config=create_config('firefox', 'linux', 64), build_url='http://build/url', build_date=date(2015, 9, 1), changeset='12ab' * 10, repo_url='http://repo:url', ) defaults.update(attrs) return klass(**defaults)
def create_build_info(klass, **attrs): defaults = dict( fetch_config=create_config("firefox", "linux", 64, "x86_64"), build_url="http://build/url", build_date=date(2015, 9, 1), changeset="12ab" * 10, repo_url="http://repo:url", ) defaults.update(attrs) return klass(**defaults)
def test_set_firefox_build_type_pgo(os, bits, tc_suffix): conf = create_config('firefox', os, bits) if type(tc_suffix) is not str: with pytest.raises(tc_suffix): conf.set_build_type('pgo') else: conf.set_build_type('pgo') assert conf.tk_inbound_route( create_push(CHSET, TIMESTAMP_GECKO_V2)) \ .endswith('.' + tc_suffix)
def test_range_for_nightlies(): fetch_config = create_config('firefox', 'linux', 64, 'x86_64') b_range = build_range.range_for_nightlies(fetch_config, date(2015, 01, 01), date(2015, 01, 03)) assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == 3 b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == date(2015, 01, 01) assert b_range[1] == date(2015, 01, 02) assert b_range[2] == date(2015, 01, 03)
def test_build_infos(self): fetch_config = create_config('firefox', 'linux', 64) fetch_config.set_inbound_branch('my-branch') self.handler.set_build_data([{'changeset': '1', 'repository': 'my'}]) result = self.handler.build_infos(0, fetch_config) self.assertEqual(result, { 'changeset': '1', 'repository': 'my', 'build_type': 'inbound', 'app_name': 'firefox', 'repo': 'my-branch', })
def test_get_nightly_range(): fetch_config = create_config("firefox", "linux", 64, "x86_64") b_range = build_range.get_nightly_range(fetch_config, date(2015, 1, 1), date(2015, 1, 3)) assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == 3 b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == date(2015, 1, 1) assert b_range[1] == date(2015, 1, 2) assert b_range[2] == date(2015, 1, 3)
def create_inbound_build_data(self, good, bad, get_pushlogs, url_links): fetch_config = fetch_configs.create_config('firefox', 'linux', 64) # create fake pushlog returns pushlogs = [ {'date': d, 'changesets': ['c' + str(d)]} for d in xrange(int(good[1:]), int(bad[1:])) ] get_pushlogs.return_value = pushlogs # returns 100 possible build folders def inbound_links(url, regex=None): return ['%i/' % i for i in xrange(100)] url_links.side_effect = inbound_links return build_data.InboundBuildData(fetch_config, good, bad, range=5)
def test_range_for_inbounds_with_dates(mocker, start_date, end_date, start_call, end_call): fetch_config = create_config('firefox', 'linux', 64, 'x86_64') jpush_class = mocker.patch('mozregression.fetch_build_info.JsonPushes') jpush = mocker.Mock(pushes_within_changes=mocker.Mock(return_value=[]), spec=JsonPushes) jpush_class.return_value = jpush build_range.range_for_inbounds(fetch_config, start_date, end_date, time_limit=DATE_YEAR_BEFORE) jpush.pushes_within_changes.assert_called_once_with(start_call, end_call)
def test_get_integration_range_with_dates(mocker, start_date, end_date, start_call, end_call): fetch_config = create_config("firefox", "linux", 64, "x86_64") jpush_class = mocker.patch("mozregression.fetch_build_info.JsonPushes") jpush = mocker.Mock(pushes_within_changes=mocker.Mock(return_value=[]), spec=JsonPushes) jpush_class.return_value = jpush build_range.get_integration_range(fetch_config, start_date, end_date, time_limit=DATE_YEAR_BEFORE) jpush.pushes_within_changes.assert_called_once_with(start_call, end_call)
def test_range_for_nightlies_datetime(start, end, range_size): fetch_config = create_config('firefox', 'linux', 64, 'x86_64') b_range = build_range.range_for_nightlies(fetch_config, start, end) assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == range_size b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == start assert b_range[-1] == end # between, we only have date instances for i in range(1, range_size - 1): assert isinstance(b_range[i], date)
def test_get_nightly_range_datetime(start, end, range_size): fetch_config = create_config("firefox", "linux", 64, "x86_64") b_range = build_range.get_nightly_range(fetch_config, start, end) assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == range_size b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == start assert b_range[-1] == end # between, we only have date instances for i in range(1, range_size - 1): assert isinstance(b_range[i], date)
def test_build_infos(self): fetch_config = create_config('fennec-2.3', 'linux', 64) fetch_config.set_nightly_repo('my-repo') def get_associated_data(index): return index new_data = MagicMock(get_associated_data=get_associated_data) self.handler.set_build_data(new_data) result = self.handler.build_infos(1, fetch_config) self.assertEqual(result, { 'build_type': 'nightly', 'build_date': 1, 'app_name': 'fennec', 'repo': 'my-repo' })
def _set_fetch_config(self, index): app_name = str(self.ui.app_combo.currentText()) bits = int(self.ui.bits_combo.currentText()) self.fetch_config = create_config(app_name, mozinfo.os, bits) self.build_type_model = QStringListModel( [i for i in REGISTRY.get(app_name).BUILD_TYPES]) self.ui.build_type.setModel(self.build_type_model) if not self.fetch_config.available_bits(): self.ui.bits_combo.hide() self.ui.label_4.hide() else: self.ui.bits_combo.show() self.ui.label_4.show()
def test_get_integration_range_with_expand(mocker): fetch_config = create_config("firefox", "linux", 64, "x86_64") jpush_class = mocker.patch("mozregression.fetch_build_info.JsonPushes") pushes = [create_push("b", 1), create_push("d", 2), create_push("f", 3)] jpush = mocker.Mock(pushes_within_changes=mocker.Mock(return_value=pushes), spec=JsonPushes) jpush_class.return_value = jpush check_expand = mocker.patch( "mozregression.build_range.BuildRange.check_expand") build_range.get_integration_range(fetch_config, "a", "e", expand=10) check_expand.assert_called_once_with(10, build_range.tc_range_before, build_range.tc_range_after, interrupt=None)
def test_range_for_inbounds_with_expand(mocker): fetch_config = create_config('firefox', 'linux', 64, 'x86_64') jpush_class = mocker.patch('mozregression.fetch_build_info.JsonPushes') pushes = [create_push('b', 1), create_push('d', 2), create_push('f', 3)] jpush = mocker.Mock(pushes_within_changes=mocker.Mock(return_value=pushes), spec=JsonPushes) jpush_class.return_value = jpush check_expand = mocker.patch( 'mozregression.build_range.BuildRange.check_expand') build_range.range_for_inbounds(fetch_config, 'a', 'e', expand=10) check_expand.assert_called_once_with(10, build_range.tc_range_before, build_range.tc_range_after, interrupt=None)
def test_abstract_build_runner(qtbot): main_thread = QThread.currentThread() class Worker(QObject): call_started = Signal() def __init__(self, *args): QObject.__init__(self) @Slot() def my_slot(self): assert main_thread != self.thread() self.call_started.emit() class BuildRunner(build_runner.AbstractBuildRunner): call_started = Signal() thread_finished = Signal() worker_class = Worker def init_worker(self, fetch_config, options): build_runner.AbstractBuildRunner.init_worker( self, fetch_config, options) self.thread.finished.connect(self.thread_finished) self.worker.call_started.connect(self.call_started) return self.worker.my_slot # instantiate the runner runner = BuildRunner(Mock(persist='.')) assert not runner.thread with qtbot.waitSignal(runner.thread_finished, raising=True): with qtbot.waitSignal(runner.call_started, raising=True): runner.start( create_config('firefox', 'linux', 64, 'x86_64'), { 'addons': (), 'profile': '/path/to/profile', 'profile_persistence': 'clone' }, ) runner.stop(True) assert not runner.pending_threads
def _set_fetch_config(self, index): app_name = str(self.ui.app_combo.currentText()) bits = int(self.ui.bits_combo.currentText()) self.fetch_config = create_config(app_name, mozinfo.os, bits, mozinfo.processor) self.arch_model = QStringListModel(self.fetch_config.available_archs()) self.ui.arch_combo.setModel(self.arch_model) if not self.arch_model.stringList(): self.ui.arch_label.setDisabled(True) self.ui.arch_combo.setDisabled(True) else: self.ui.arch_label.setEnabled(True) self.ui.arch_combo.setEnabled(True) self.build_type_model = QStringListModel(self.fetch_config.available_build_types()) self.ui.build_type.setModel(self.build_type_model) if not self.fetch_config.available_bits(): self.ui.bits_combo.setDisabled(True) self.ui.label_4.setDisabled(True) else: self.ui.bits_combo.setEnabled(True) self.ui.label_4.setEnabled(True) # URL doesn't make sense for Thunderbird if app_name == "thunderbird": self.ui.url.setDisabled(True) self.ui.url_label.setDisabled(True) else: self.ui.url.setEnabled(True) self.ui.url_label.setEnabled(True) # lang only makes sense for firefox-l10n, and repo doesn't if app_name == "firefox-l10n": self.ui.lang.setEnabled(True) self.ui.lang_label.setEnabled(True) self.ui.repository.setDisabled(True) self.ui.repository_label.setDisabled(True) else: self.ui.lang.setDisabled(True) self.ui.lang_label.setDisabled(True) self.ui.repository.setEnabled(True) self.ui.repository_label.setEnabled(True)
def cli(args=sys.argv[1:]): from mozregression.fetch_configs import create_config parser = OptionParser() parser.add_option("--start-rev", dest="start_rev", help="start revision") parser.add_option("--end-rev", dest="end_rev", help="end revision") parser.add_option("--os", dest="os", help="override operating system " "autodetection (mac, linux, win)", default=mozinfo.os) parser.add_option("--bits", dest="bits", help="override operating system " "bits autodetection", default=mozinfo.bits) parser.add_option("-n", "--app", dest="app", help="application name " "(firefox, fennec or b2g)", metavar="[firefox|fennec|b2g]", default="firefox") parser.add_option("--inbound-branch", dest="inbound_branch", help="inbound branch name on ftp.mozilla.org", metavar="[tracemonkey|mozilla-1.9.2]", default=None) options, args = parser.parse_args(args) if not options.start_rev or not options.end_rev: sys.exit("start revision and end revision must be specified") fetch_config = create_config(options.app, options.os, options.bits) build_finder = BuildsFinder(fetch_config) revisions = build_finder.get_build_infos(options.start_rev, options.end_rev, range=60 * 60 * 12) print("Revision, Timestamp") for revision in revisions: print("%s %s" % (revision['revision'], revision['timestamp']))
def _set_fetch_config(self, index): # limit bisection type given the application bits = int(self.ui.bits_combo.currentText()) old_bisect_index = self.ui.bisect_combo.currentIndex() self.fetch_config = create_config( str(self.ui.app_combo.itemText(index)), mozinfo.os, bits) bisect_types = ['nightlies'] if self.fetch_config.is_inbound(): bisect_types.append('inbound') self.bisect_model.setStringList(bisect_types) bisect_index = 0 if old_bisect_index == 1 and len(bisect_types) == 2: bisect_index = 1 self.ui.bisect_combo.setCurrentIndex(bisect_index) available_bits = self.fetch_config.available_bits() if not available_bits: self.ui.bits_combo.hide() self.ui.label_4.hide() else: self.ui.bits_combo.show() self.ui.label_4.show()
def test_get_integration_range(mocker): fetch_config = create_config("firefox", "linux", 64, "x86_64") jpush_class = mocker.patch("mozregression.fetch_build_info.JsonPushes") pushes = [create_push("b", 1), create_push("d", 2), create_push("f", 3)] jpush = mocker.Mock(pushes_within_changes=mocker.Mock(return_value=pushes), spec=JsonPushes) jpush_class.return_value = jpush b_range = build_range.get_integration_range(fetch_config, "a", "e") jpush_class.assert_called_once_with(branch="mozilla-central") jpush.pushes_within_changes.assert_called_once_with("a", "e") assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == 3 b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == pushes[0] assert b_range[1] == pushes[1] assert b_range[2] == pushes[2] b_range.future_build_infos[0].date_or_changeset() == "b"
def test_range_for_inbounds(mocker): fetch_config = create_config('firefox', 'linux', 64, 'x86_64') jpush_class = mocker.patch('mozregression.fetch_build_info.JsonPushes') pushes = [create_push('b', 1), create_push('d', 2), create_push('f', 3)] jpush = mocker.Mock(pushes_within_changes=mocker.Mock(return_value=pushes), spec=JsonPushes) jpush_class.return_value = jpush b_range = build_range.range_for_inbounds(fetch_config, 'a', 'e') jpush_class.assert_called_once_with(branch='mozilla-inbound') jpush.pushes_within_changes.assert_called_once_with('a', 'e') assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == 3 b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == pushes[0] assert b_range[1] == pushes[1] assert b_range[2] == pushes[2] b_range.future_build_infos[0].date_or_changeset() == 'b'
def test_range_for_inbounds(mocker): fetch_config = create_config('firefox', 'linux', 64) jpush_class = mocker.patch('mozregression.fetch_build_info.JsonPushes') jpush = mocker.Mock(pushlog_within_changes=mocker.Mock(return_value=[{ 'changesets': ['a', 'b'] }, { 'changesets': ['c', 'd'] }, { 'changesets': ['e', 'f'] }]), spec=JsonPushes) jpush_class.return_value = jpush b_range = build_range.range_for_inbounds(fetch_config, 'a', 'e') jpush_class.assert_called_once_with(branch='mozilla-inbound') jpush.pushlog_within_changes.assert_called_once_with('a', 'e') assert isinstance(b_range, build_range.BuildRange) assert len(b_range) == 3 b_range.build_info_fetcher.find_build_info = lambda v: v assert b_range[0] == 'b' assert b_range[1] == 'd' assert b_range[2] == 'f'