def testAddCacheTime(self): cache = WfTryBotCache.Get('new_cache') for _ in range(cache.MAX_CACHE_TIMES + 10): cache.AddCacheTime(1, True) cache.AddCacheTime(1, False) self.assertEqual(cache.MAX_CACHE_TIMES, len(cache.cold_cache_times)) self.assertEqual(cache.MAX_CACHE_TIMES, len(cache.warm_cache_times))
def setUp(self): super(WfTryBotCacheTest, self).setUp() cache = WfTryBotCache.Get('popular_cache') cache.recent_bots = [ 'bot%d' % x for x in range(WfTryBotCache.MAX_RECENT_BOTS) ] cache.put()
def testNoDuplicates(self): cache = WfTryBotCache.Get('new_cache') self.assertFalse(cache.recent_bots) bot_id = 'fake_slave_123' cache.AddBot(bot_id) cache.AddBot(bot_id) cache.AddBot(bot_id) self.assertEqual(1, len(cache.recent_bots))
def testSelectWarmCacheNoOp(self, mock_fn): class MockTryJobBuildbot(object): is_swarmbucket_build = False try_job_buildbot = MockTryJobBuildbot() cache_name = 'some_other_cache_name' WfTryBotCache.Get(cache_name).recent_bots = ['slave1'] swarmbot_util.AssignWarmCacheHost(try_job_buildbot, cache_name, None) self.assertFalse(mock_fn.called)
def testAddFullBuildEvictionDetection(self, mockEvictionMetric): cache_name = 'full_build_existing_cache' bot_id = 'full_build_bot_2' dimensions = [{ 'key': 'caches', 'value': [cache_name, 'some_other_cache'], }, { 'key': 'os', 'value': ['Windows', 'Windows2008R2'], }] cache = WfTryBotCache.Get(cache_name) cache.AddFullBuild(bot_id, 1000, dimensions) cache.put() dimensions = [ { 'key': 'caches', 'value': [cache_name], # Removed 'some_other_cache'. }, { 'key': 'os', 'value': ['Windows', 'Windows2008R2'], } ] cache = WfTryBotCache.Get(cache_name) cache.AddFullBuild(bot_id, 1001, dimensions) cache.put() # Make sure the bot has correct caches in datastore. saved_bot = WfTryBot.Get(bot_id) self.assertNotIn('some_other_cache', saved_bot.caches) self.assertIn(cache_name, saved_bot.caches) # Make sure cache has bot, and built commit position. saved_cache = WfTryBotCache.Get(cache_name) self.assertIn(bot_id, saved_cache.full_build_commit_positions) self.assertEqual(1001, saved_cache.full_build_commit_positions[bot_id]) # Make sure metric incremented. self.assertTrue( mockEvictionMetric.increment.called_once_with( {'platform': 'windows'}))
def testAddFullBuild(self): cache_name = 'full_build_new_cache' bot_id = 'full_build_bot' dimensions = [{ 'key': 'caches', 'value': [cache_name, 'some_other_cache'], }, { 'key': 'os', 'value': ['Windows', 'Windows2008R2'], }] cache = WfTryBotCache.Get(cache_name) cache.AddFullBuild(bot_id, 1000, dimensions) cache.put() # Make sure the bot has both caches in datastore. saved_bot = WfTryBot.Get(bot_id) self.assertEqual(set([cache_name, 'some_other_cache']), set(saved_bot.caches)) # Make sure cache has bot, and built commit position. saved_cache = WfTryBotCache.Get(cache_name) self.assertIn(bot_id, saved_cache.full_build_commit_positions) self.assertEqual(1000, saved_cache.full_build_commit_positions[bot_id])
def _SortByDistanceToCommitPosition(bots, cache_name, commit_position, include_later): cache_stats = WfTryBotCache.Get(cache_name) def _distance(bot_id): # If the bot is new, the bot_id will not be present, but if it failed to get # the revision, the key will be present with a value of None. local_cp = cache_stats.checked_out_commit_positions.get(bot_id) or 0 return commit_position - local_cp if include_later: distance = lambda x: abs(_distance(x)) else: distance = _distance result = sorted([b for b in bots if distance(b['bot_id']) >= 0], key=lambda x: distance(x['bot_id'])) return result
def _RecordCacheStats(build, report): """Save the bot's state at the end of a successful. This function aims to save the following data in the data store: - The last revision that the bot synced to under the specific work directory (named cache) it used for its local checkout. - The latest revision fetched into the bot's local git cache, which is shared across all work directories. These are saved as commit positions rather than revision hashes for faster comparisons when selecting a bot for new tryjobs. """ bot = swarmbot_util.GetBot(build) cache_name = swarmbot_util.GetBuilderCacheName(build) if bot and cache_name: git_repo = CachedGitilesRepository( FinditHttpClient(), services_constants.CHROMIUM_GIT_REPOSITORY_URL) last_checked_out_revision = report.get('last_checked_out_revision') last_checked_out_cp = ( git_repo.GetChangeLog(last_checked_out_revision).commit_position if last_checked_out_revision else None) cached_revision = report.get('previously_cached_revision') cached_cp = git_repo.GetChangeLog( cached_revision).commit_position if cached_revision else None bad_revision = json.loads(build.response.get( 'parameters_json', '{}')).get('properties', {}).get('bad_revision') bad_cp = git_repo.GetChangeLog( bad_revision).commit_position if bad_revision else None # If the bad_revision is later than the previously cached revision, that # means that the bot had to sync with the remote repository, and the local # git cache was updated to that revision at least. latest_synced_cp = max(bad_cp, cached_cp) cache_stats = WfTryBotCache.Get(cache_name) cache_stats.AddBot(bot, last_checked_out_cp, latest_synced_cp) # TODO(robertocn): Record the time it took to complete the task # with a cold or warm cache. cache_stats.put()
def testSortByDistanceToCommitPosition(self): cache_name = 'cache_name' cache_stats = WfTryBotCache.Get(cache_name) cache_stats.AddBot('bot1', 80, 80) cache_stats.AddBot('bot2', 90, 90) cache_stats.AddBot('bot3', 110, 110) cache_stats.AddBot('bot4', 120, 120) cache_stats.put() bots = [{'bot_id': 'bot%d' % i} for i in range(1, 5)] closest = swarmbot_util._ClosestEarlier(bots, cache_name, 70) self.assertFalse(closest) closest = swarmbot_util._ClosestLater(bots, cache_name, 70) self.assertEqual({'bot_id': 'bot1'}, closest) sorted_bots = swarmbot_util._SortByDistanceToCommitPosition( bots, cache_name, 100, False) self.assertEqual({'bot_id': 'bot2'}, sorted_bots[0]) sorted_bots = swarmbot_util._SortByDistanceToCommitPosition( bots, cache_name, 121, False) self.assertEqual({'bot_id': 'bot4'}, sorted_bots[0])
def _RecordFullBuild(build, build_ahead): properties = json.loads(build.response.get('result_details_json', '{}')).get('properties', {}) built_cp_string = properties.get('got_revision_cp') bot_id = properties.get('bot_id') if built_cp_string and bot_id: built_cp = buildbot.GetCommitPosition(built_cp_string) if built_cp: cache = WfTryBotCache.Get(build_ahead.cache_name) cache.full_build_commit_positions[bot_id] = built_cp cache.put() return try: # Raise an exception and catch immediately so that logging.exception can # attach a stack trace to the entry and thus make error reporting detect it. raise ValueError('bot_id and got_revision_cp are both required') except ValueError: logging.exception( 'Buildahead with build id %s completed successfully, but does not have ' 'valid "got_revision_cp" and "bot_id" properties.', build.id)
def _GetSupportedCompileCaches(platform): """Gets config'd compile builders by platform & their cache name and stats.""" supported_masters = ( waterfall_config.GetStepsForMastersRules()['supported_masters'].keys()) builder_pairs = bot_db.GetBuilders(master_filter=supported_masters, bot_type_filter=['builder'], platform_filter=[platform]) result = [] waterfall_builders = swarmbucket.GetBuilders('luci.chromium.ci') for master_name, builder_name in builder_pairs: if builder_name not in waterfall_builders: logging.info( 'Skipping %s, exists in bot_db, but not in buildbucket', builder_name) continue builder = {'master': master_name, 'builder': builder_name} builder['cache_name'] = swarmbot_util.GetCacheName( master_name, builder_name) builder['cache_stats'] = WfTryBotCache.Get(builder['cache_name']) result.append(builder) return result
def testTruncateList(self): cache = WfTryBotCache.Get('popular_cache') self.assertEqual(WfTryBotCache.MAX_RECENT_BOTS, len(cache.recent_bots)) cache.AddBot('fake_slave_123') self.assertEqual(WfTryBotCache.MAX_RECENT_BOTS, len(cache.recent_bots)) self.assertEqual('fake_slave_123', cache.recent_bots[0])
def testMoveToFront(self): cache = WfTryBotCache.Get('new_cache') cache.recent_bots = ['bot1', 'bot2'] cache.AddBot('bot2') self.assertEqual(['bot2', 'bot1'], cache.recent_bots)
def testAddFirstBot(self): bot_id = 'fake_slave_123' cache = WfTryBotCache.Get('new_cache') self.assertFalse(cache.recent_bots) cache.AddBot(bot_id) self.assertIn(bot_id, cache.recent_bots)