Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Bug 787449 - Stop running builds on pushes which only include changes…

… to b2g or mobile or browser directories. r=nthomas,bhearsum
  • Loading branch information...
commit d7d6933b13403bea903a01724e6a05569943ebe8 1 parent e0cf077
@catlee catlee authored
View
150 changes/hgpoller.py
@@ -86,10 +86,8 @@
"""
import time
-from calendar import timegm
-import operator
-from twisted.python import log, failure
+from twisted.python import log
from twisted.internet import defer, reactor
from twisted.internet.task import LoopingCall
from twisted.web.client import getPage
@@ -97,28 +95,13 @@
from buildbot.changes import base, changes
from buildbot.util import json
-def _parse_changes(data):
- pushes = json.loads(data)
- changes = []
- for push_id, push_data in pushes.iteritems():
- push_time = push_data['date']
- push_user = push_data['user']
- for cset in push_data['changesets']:
- change = {}
- change['updated'] = push_time
- change['author'] = push_user
- change['changeset'] = cset['node']
- change['files'] = cset['files']
- change['branch'] = cset['branch']
- change['comments'] = cset['desc']
- changes.append(change)
+def _parse_changes(data):
+ pushes = json.loads(data).values()
# Sort by push date
- # Changes in the same push have their order preserved because python list
- # sorts are stable. The leaf of each push is sorted at the end of the list
- # of changes for that push.
- changes.sort(key=lambda c:c['updated'])
- return changes
+ pushes.sort(key=lambda p: p['date'])
+ return pushes
+
class Pluggable(object):
'''The Pluggable class implements a forward for Deferred's that
@@ -191,7 +174,6 @@ def pollDone(self, res):
pass
-
class BaseHgPoller(BasePoller):
"""Common base of HgPoller, HgLocalePoller, and HgAllLocalesPoller.
@@ -200,7 +182,8 @@ class BaseHgPoller(BasePoller):
timeout = 30
def __init__(self, hgURL, branch, pushlogUrlOverride=None,
- tipsOnly=False, tree=None, repo_branch=None, maxChanges=100):
+ tipsOnly=False, tree=None, repo_branch=None, maxChanges=100,
+ mergePushChanges=True):
self.super_class = BasePoller
self.super_class.__init__(self)
self.hgURL = hgURL
@@ -219,6 +202,10 @@ def __init__(self, hgURL, branch, pushlogUrlOverride=None,
self.loadTime = None
self.repo_branch = repo_branch
self.maxChanges = maxChanges
+ # With mergePushChanges=True we get one buildbot change per push to hg.
+ # The files from all changes in the push will be accumulated in the buildbot change
+ # and the comments of tipmost change of the push will be used
+ self.mergePushChanges = mergePushChanges
self.emptyRepo = False
@@ -226,7 +213,7 @@ def getData(self):
url = self._make_url()
if self.verbose:
log.msg("Polling Hg server at %s" % url)
- return getPage(url, timeout = self.timeout)
+ return getPage(url, timeout=self.timeout)
def _make_url(self):
url = None
@@ -263,8 +250,8 @@ def dataFailed(self, res):
return self.super_class.dataFailed(self, res)
def processData(self, query):
- all_changes = _parse_changes(query)
- if len(all_changes) == 0:
+ pushes = _parse_changes(query)
+ if len(pushes) == 0:
if self.lastChangeset is None:
# We don't have a lastChangeset, and there are no changes. Assume
# the repository is empty.
@@ -274,18 +261,80 @@ def processData(self, query):
# Nothing else to do
return
- # We want to add at most self.maxChanges changes.
- # Go through the list of changes backwards, since we want to keep the
+ # We want to add at most self.maxChanges changes per push. If
+ # mergePushChanges is True, then we'll get up to maxChanges pushes,
+ # each with up to maxChanges changes.
+ # Go through the list of pushes backwards, since we want to keep the
# latest ones and possibly discard earlier ones.
change_list = []
- for change in reversed(all_changes):
- if self.maxChanges is not None and len(change_list) >= self.maxChanges:
- break
-
- # Ignore changes not on the specified in-repo branch.
- if self.repo_branch is not None and self.repo_branch != change['branch']:
- continue
- change_list.append(change)
+ too_many = False
+ for push in reversed(pushes):
+ # Used for merging push changes
+ c = dict(
+ user=push['user'],
+ date=push['date'],
+ files=[],
+ desc="",
+ node=None,
+ )
+
+ i = 0
+ for change in reversed(push['changesets']):
+ if self.maxChanges is not None and (len(change_list) >= self.maxChanges or
+ i >= self.maxChanges):
+ too_many = True
+ log.msg("%s: got too many changes" % self.baseURL)
+ break
+
+ # Ignore changes not on the specified in-repo branch.
+ if self.repo_branch is not None and self.repo_branch != change['branch']:
+ continue
+
+ i += 1
+
+ if self.mergePushChanges:
+ # Collect all the files for this push
+ c['files'].extend(change['files'])
+ # Keep the comments and revision of the last change of this push.
+ # We're going through the changes in reverse order, so we
+ # should use the comments and revision of the first change
+ # in this loop
+ if c['node'] is None:
+ c['desc'] = change['desc']
+ c['node'] = change['node']
+ else:
+ c = dict(
+ user=push['user'],
+ date=push['date'],
+ files=change['files'],
+ desc=change['desc'],
+ node=change['node'],
+ branch=change['branch'],
+ )
+ change_list.append(c)
+
+ if too_many and self.mergePushChanges:
+ # Add a dummy change to indicate we had too many changes
+ c['files'].extend(['overflow'])
+
+ if self.mergePushChanges and c['node'] is not None:
+ change_list.append(c)
+
+ if too_many and not self.mergePushChanges:
+ # We add this at the end, and the list gets reversed below. That
+ # means this dummy change ends up being the 'first' change of the
+ # set, and buildbot chooses the last change as the one to
+ # build, so this dummy change doesn't impact which revision
+ # gets built.
+ c = dict(
+ user='buildbot',
+ files=['overflow'],
+ node=None,
+ desc='more than maxChanges(%i) received; ignoring the rest' % self.maxChanges,
+ date=time.time(),
+ )
+ change_list.append(c)
+
# Un-reverse the list of changes so they get added in the right order
change_list.reverse()
@@ -300,14 +349,14 @@ def processData(self, query):
# the latest changeset in the repository
if self.lastChangeset is not None or self.emptyRepo:
for change in change_list:
- link = "%s/rev/%s" % (self.baseURL, change["changeset"])
- c = changes.Change(who = change["author"],
- files = change["files"],
- revision = change["changeset"],
- comments = change["comments"],
- revlink = link,
- when = change["updated"],
- branch = self.branch)
+ link = "%s/rev/%s" % (self.baseURL, change["node"])
+ c = changes.Change(who=change["user"],
+ files=change["files"],
+ revision=change["node"],
+ comments=change["desc"],
+ revlink=link,
+ when=change["date"],
+ branch=self.branch)
self.changeHook(c)
self.parent.addChange(c)
@@ -316,7 +365,7 @@ def processData(self, query):
# Use the last change found by the poller, regardless of if it's on our
# branch or not. This is so we don't have to constantly ignore it in
# future polls.
- self.lastChangeset = all_changes[-1]["changeset"]
+ self.lastChangeset = pushes[-1]["changesets"][-1]["node"]
if self.verbose:
log.msg("last changeset %s on %s" %
(self.lastChangeset, self.baseURL))
@@ -324,6 +373,7 @@ def processData(self, query):
def changeHook(self, change):
pass
+
class HgPoller(base.ChangeSource, BaseHgPoller):
"""This source will poll a Mercurial server over HTTP using
the built-in RSS feed for changes and submit them to the
@@ -331,14 +381,14 @@ class HgPoller(base.ChangeSource, BaseHgPoller):
compare_attrs = ['hgURL', 'branch', 'pollInterval',
'pushlogUrlOverride', 'tipsOnly', 'storeRev',
- 'repo_branch']
+ 'repo_branch', 'maxChanges']
parent = None
loop = None
volatile = ['loop']
def __init__(self, hgURL, branch, pushlogUrlOverride=None,
tipsOnly=False, pollInterval=30, storeRev=None,
- repo_branch="default"):
+ repo_branch="default", maxChanges=100):
"""
@type hgURL: string
@param hgURL: The base URL of the Hg repo
@@ -362,7 +412,7 @@ def __init__(self, hgURL, branch, pushlogUrlOverride=None,
"""
BaseHgPoller.__init__(self, hgURL, branch, pushlogUrlOverride,
- tipsOnly, repo_branch=repo_branch)
+ tipsOnly, repo_branch=repo_branch, maxChanges=maxChanges)
self.pollInterval = pollInterval
self.storeRev = storeRev
View
98 misc.py
@@ -1,7 +1,7 @@
from urlparse import urljoin
try:
import json
- assert json # pyflakes
+ assert json # pyflakes
except:
import simplejson as json
import collections
@@ -9,8 +9,6 @@
import re
import sys, os, time
-from copy import deepcopy
-
from twisted.python import log
from buildbot.scheduler import Nightly, Scheduler, Triggerable
@@ -112,16 +110,65 @@ def get_locales_from_json(jsonFile, l10nRepoPath, relbranch):
# dep/nightlies and release builds. Because they build the same "branch" this
# allows us to have the release builder ignore HgPoller triggered changse
# and the dep builders only obey HgPoller/Force Build triggered ones.
-
def isHgPollerTriggered(change, hgUrl):
if (change.revlink and hgUrl in change.revlink) or \
- change.comments.find(hgUrl) > -1:
+ change.comments.find(hgUrl) > -1:
return True
+
def shouldBuild(change):
"""check for commit message disabling build for this change"""
return "DONTBUILD" not in change.comments
+
+_product_excludes = {
+ 'firefox': [
+ re.compile('^mobile/'),
+ re.compile('^b2g/'),
+ ],
+ 'mobile': [
+ re.compile('^browser/'),
+ re.compile('^b2g/'),
+ re.compile('^xulrunner/'),
+ ],
+ 'b2g': [
+ re.compile('^browser/'),
+ re.compile('^mobile/'),
+ re.compile('^xulrunner/'),
+ ],
+ 'thunderbird': [re.compile("^suite/")],
+}
+def isImportantForProduct(change, product):
+ """Handles product specific handling of important files"""
+ # For each file, check each product's exclude list
+ # If a file is not excluded, then the change is important
+ # If all files are excluded, then the change is not important
+ # As long as hgpoller's 'overflow' marker isn't excluded, it will cause all
+ # products to build
+ excludes = _product_excludes.get(product, [])
+ for f in change.files:
+ excluded = any(e.search(f) for e in excludes)
+ if not excluded:
+ log.msg("%s important for %s because of %s" % (change.revision, product, f))
+ return True
+
+ # Everything was excluded
+ log.msg("%s not important for %s because all files were excluded" % (change.revision, product))
+ return False
+
+
+def makeImportantFunc(hgurl, product):
+ def isImportant(c):
+ if not isHgPollerTriggered(c, hgurl):
+ return False
+ if not shouldBuild(c):
+ return False
+ # No product is specified, so all changes are important
+ if product is None:
+ return True
+ return isImportantForProduct(c, product)
+ return isImportant
+
def isImportantL10nFile(change, l10nModules):
for f in change.files:
for basepath in l10nModules:
@@ -579,12 +626,11 @@ def generateBranchObjects(config, name, secrets=None):
if secrets is None:
secrets = {}
builders = []
- unittestBuilders = []
+ buildersByProduct = {}
triggeredUnittestBuilders = []
nightlyBuilders = []
xulrunnerNightlyBuilders = []
periodicPgoBuilders = [] # Only used for the 'periodic' strategy. rename to perodicPgoBuilders?
- debugBuilders = []
weeklyBuilders = []
coverageBuilders = []
# prettyNames is a mapping to pass to the try_parser for validation
@@ -624,11 +670,13 @@ def generateBranchObjects(config, name, secrets=None):
if 'mozharness_config' in pf:
buildername = '%s_dep' % pf['base_name']
builders.append(buildername)
+ buildersByProduct.setdefault(pf['stage_product'], []).append(buildername)
prettyNames[platform] = buildername
continue
if platform.endswith("-debug"):
- debugBuilders.append(pretty_name)
+ builders.append(pretty_name)
+ buildersByProduct.setdefault(pf['stage_product'], []).append(pretty_name)
prettyNames[platform] = pretty_name
# Debug unittests
if pf.get('enable_unittests'):
@@ -647,6 +695,7 @@ def generateBranchObjects(config, name, secrets=None):
continue
elif pf.get('enable_dep', True):
builders.append(pretty_name)
+ buildersByProduct.setdefault(pf['stage_product'], []).append(pretty_name)
prettyNames[platform] = pretty_name
# Fill the l10n dep dict
@@ -672,6 +721,7 @@ def generateBranchObjects(config, name, secrets=None):
periodicPgoBuilders.append('%s pgo-build' % pf['base_name'])
elif config['pgo_strategy'] in ('try',) and platform in config['pgo_platforms']:
builders.append('%s pgo-build' % pf['base_name'])
+ buildersByProduct.setdefault(pf['stage_product'], []).append('%s pgo-build' % pf['base_name'])
if do_nightly:
builder = '%s nightly' % base_name
@@ -764,10 +814,12 @@ def generateBranchObjects(config, name, secrets=None):
if config.get('enable_try', False):
tipsOnly = True
+ maxChanges = 100
# Pay attention to all branches for pushes to try
repo_branch = None
else:
- tipsOnly = True
+ tipsOnly = False
+ maxChanges = 100
# Other branches should only pay attention to the default branch
repo_branch = "default"
@@ -775,6 +827,7 @@ def generateBranchObjects(config, name, secrets=None):
hgURL=config['hgurl'],
branch=config['repo_path'],
tipsOnly=tipsOnly,
+ maxChanges=maxChanges,
repo_branch=repo_branch,
pollInterval=pollInterval,
))
@@ -802,7 +855,7 @@ def generateBranchObjects(config, name, secrets=None):
scheduler_class = makePropertiesScheduler(Scheduler, [buildIDSchedFunc, buildUIDSchedFunc])
if not config.get('enable_merging', True):
- nomergeBuilders.extend(builders + unittestBuilders + debugBuilders)
+ nomergeBuilders.extend(builders)
nomergeBuilders.extend(periodicPgoBuilders) # these should never, ever merge
extra_args['treeStableTimer'] = None
@@ -811,13 +864,24 @@ def generateBranchObjects(config, name, secrets=None):
else:
scheduler_name_prefix = name
- branchObjects['schedulers'].append(scheduler_class(
- name=scheduler_name_prefix,
- branch=config['repo_path'],
- builderNames=builders + unittestBuilders + debugBuilders,
- fileIsImportant=lambda c: isHgPollerTriggered(c, config['hgurl']) and shouldBuild(c),
- **extra_args
- ))
+ for product, product_builders in buildersByProduct.items():
+ if config.get('enable_try'):
+ fileIsImportant = lambda c: isHgPollerTriggered(c, config['hgurl'])
+ else:
+ # The per-produt build behaviour is tweakable per branch. If it's
+ # not enabled, pass None as the product, which disables the
+ # per-product build behaviour.
+ if not config.get('enable_perproduct_builds'):
+ product = None
+ fileIsImportant = makeImportantFunc(config['hgurl'], product)
+
+ branchObjects['schedulers'].append(scheduler_class(
+ name=scheduler_name_prefix + "-" + product,
+ branch=config['repo_path'],
+ builderNames=product_builders,
+ fileIsImportant=fileIsImportant,
+ **extra_args
+ ))
if config['enable_l10n']:
l10n_builders = []
View
120 test/test_hgpoller.py
@@ -1,4 +1,3 @@
-from twisted.internet import defer, reactor
from twisted.trial import unittest
import threading
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
@@ -42,6 +41,7 @@ class OurHandler(VerySimpleHTTPRequestHandler):
server_thread.start()
return (server, port)
+
class UrlCreation(unittest.TestCase):
def testSimpleUrl(self):
correctUrl = 'http://hg.mozilla.org/mozilla-central/json-pushes?full=1'
@@ -66,8 +66,8 @@ def testTipsOnlyUrl(self):
def testTipsOnlyWithLastChangeset(self):
# there's two possible correct URLs in this case
correctUrls = [
- 'http://hg.mozilla.org/releases/mozilla-1.9.1/json-pushes?full=1&fromchange=123456&tipsonly=1',
- 'http://hg.mozilla.org/releases/mozilla-1.9.1/json-pushes?full=1&tipsonly=1&fromchange=123456'
+ 'http://hg.mozilla.org/releases/mozilla-1.9.1/json-pushes?full=1&fromchange=123456&tipsonly=1',
+ 'http://hg.mozilla.org/releases/mozilla-1.9.1/json-pushes?full=1&tipsonly=1&fromchange=123456'
]
poller = BaseHgPoller(hgURL='http://hg.mozilla.org',
branch='releases/mozilla-1.9.1', tipsOnly=True)
@@ -78,7 +78,7 @@ def testTipsOnlyWithLastChangeset(self):
def testOverrideUrl(self):
correctUrl = 'http://hg.mozilla.org/other_repo/json-pushes?full=1&fromchange=123456'
poller = BaseHgPoller(hgURL='http://hg.mozilla.org', branch='mozilla-central',
- pushlogUrlOverride='http://hg.mozilla.org/other_repo/json-pushes?full=1')
+ pushlogUrlOverride='http://hg.mozilla.org/other_repo/json-pushes?full=1')
poller.lastChangeset = '123456'
url = poller._make_url()
self.failUnlessEqual(url, correctUrl)
@@ -99,6 +99,7 @@ def testUrlWithUnicodeLastChangeset(self):
/l10n-central/kk/
/l10n-central/zh-TW/"""
+
class FakeHgAllLocalesPoller(HgAllLocalesPoller):
def __init__(self):
HgAllLocalesPoller.__init__(self, hgURL='fake', repositoryIndex='fake', branch='fake')
@@ -106,6 +107,7 @@ def __init__(self):
def pollNextLocale(self):
pass
+
class RepositoryIndexParsing(unittest.TestCase):
def testRepositoryIndexParsing(self):
correctLocales = [('af', 'l10n-central'), ('be', 'l10n-central'),
@@ -244,26 +246,27 @@ def testHgAllLocalesPoller(self):
class PushlogParsing(unittest.TestCase):
def testValidPushlog(self):
- changes = _parse_changes(validPushlog)
- self.failUnlessEqual(len(changes), 3)
-
- self.failUnlessEqual(changes[0]['changeset'], '4c23e51a484f077ea27af3ea4a4ee13da5aeb5e6')
- self.failUnlessEqual(changes[0]['updated'], 1282358416)
- self.failUnlessEqual(len(changes[0]['files']), 4)
- self.failUnlessEqual(changes[0]['branch'], 'GECKO20b5pre_20100820_RELBRANCH')
- self.failUnlessEqual(changes[0]['author'], 'dougt@mozilla.com')
-
- self.failUnlessEqual(changes[1]['changeset'], 'ee6fb954cbc3de0f76e84cad6bdff452116e1b03')
- self.failUnlessEqual(changes[1]['updated'], 1282362551)
- self.failUnlessEqual(len(changes[1]['files']), 7)
- self.failUnlessEqual(changes[1]['branch'], 'default')
- self.failUnlessEqual(changes[1]['author'], 'bobbyholley@stanford.edu')
-
- self.failUnlessEqual(changes[2]['changeset'], '33be08836cb164f9e546231fc59e9e4cf98ed991')
- self.failUnlessEqual(changes[2]['updated'], 1282362551)
- self.failUnlessEqual(len(changes[2]['files']), 1)
- self.failUnlessEqual(changes[2]['branch'], 'default')
- self.failUnlessEqual(changes[2]['author'], 'bobbyholley@stanford.edu')
+ pushes = _parse_changes(validPushlog)
+ self.failUnlessEqual(len(pushes), 2)
+
+ self.failUnlessEqual(pushes[0]['changesets'][0]['node'], '4c23e51a484f077ea27af3ea4a4ee13da5aeb5e6')
+ self.failUnlessEqual(pushes[0]['date'], 1282358416)
+ self.failUnlessEqual(len(pushes[0]['changesets'][0]['files']), 4)
+ self.failUnlessEqual(pushes[0]['changesets'][0]['branch'], 'GECKO20b5pre_20100820_RELBRANCH')
+ self.failUnlessEqual(pushes[0]['changesets'][0]['author'], 'Jim Chen <jchen@mozilla.com>')
+ self.failUnlessEqual(pushes[0]['user'], 'dougt@mozilla.com')
+
+ self.failUnlessEqual(pushes[1]['changesets'][0]['node'], 'ee6fb954cbc3de0f76e84cad6bdff452116e1b03')
+ self.failUnlessEqual(pushes[1]['date'], 1282362551)
+ self.failUnlessEqual(len(pushes[1]['changesets'][0]['files']), 7)
+ self.failUnlessEqual(pushes[1]['changesets'][0]['branch'], 'default')
+ self.failUnlessEqual(pushes[1]['user'], 'bobbyholley@stanford.edu')
+ self.failUnlessEqual(pushes[1]['changesets'][0]['author'], 'Bobby Holley <bobbyholley@gmail.com>')
+
+ self.failUnlessEqual(pushes[1]['changesets'][1]['node'], '33be08836cb164f9e546231fc59e9e4cf98ed991')
+ self.failUnlessEqual(len(pushes[1]['changesets'][1]['files']), 1)
+ self.failUnlessEqual(pushes[1]['changesets'][1]['branch'], 'default')
+ self.failUnlessEqual(pushes[1]['changesets'][1]['author'], 'Bobby Holley <bobbyholley@gmail.com>')
def testMalformedPushlog(self):
self.failUnlessRaises(JSONDecodeError, _parse_changes, malformedPushlog)
@@ -294,12 +297,15 @@ def addChange(self, change):
def testNoRepoBranch(self):
self.doTest(None)
- self.assertEquals(len(self.changes), 3)
+ self.assertEquals(len(self.changes), 2)
def testDefaultRepoBranch(self):
self.doTest('default')
- self.assertEquals(len(self.changes), 2)
+ # mergePushChanges is on by default, so we end up with a single change
+ # here
+ self.assertEquals(len(self.changes), 1)
+ self.assertEquals(self.changes[0].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
def testRelbranch(self):
self.doTest('GECKO20b5pre_20100820_RELBRANCH')
@@ -307,16 +313,17 @@ def testRelbranch(self):
self.assertEquals(len(self.changes), 1)
self.assertEquals(self.changes[0].revision, '4c23e51a484f077ea27af3ea4a4ee13da5aeb5e6')
+
class MaxChangesHandling(unittest.TestCase):
def setUp(self):
self.changes = []
- def doTest(self, repo_branch, maxChanges):
+ def doTest(self, repo_branch, maxChanges, mergePushChanges):
changes = self.changes
class TestPoller(BaseHgPoller):
def __init__(self):
BaseHgPoller.__init__(self, 'http://localhost', 'whatever',
- repo_branch=repo_branch, maxChanges=maxChanges)
+ repo_branch=repo_branch, maxChanges=maxChanges, mergePushChanges=mergePushChanges)
self.emptyRepo = True
class parent:
@@ -329,7 +336,7 @@ def addChange(self, change):
def testNoRepoBigMax(self):
# Test that we get all of the changes when maxChanges is large enough
- self.doTest(None, 10)
+ self.doTest(None, 10, False)
self.assertEquals(len(self.changes), 3)
# Check that we got the right changes
@@ -337,9 +344,18 @@ def testNoRepoBigMax(self):
self.assertEquals(self.changes[1].revision, 'ee6fb954cbc3de0f76e84cad6bdff452116e1b03')
self.assertEquals(self.changes[2].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
+ def testMergingNoRepoBigMax(self):
+ # Test that we get all of the changes when maxChanges is large enough
+ self.doTest(None, 10, True)
+
+ self.assertEquals(len(self.changes), 2)
+ # Check that we got the right changes
+ self.assertEquals(self.changes[0].revision, '4c23e51a484f077ea27af3ea4a4ee13da5aeb5e6')
+ self.assertEquals(self.changes[1].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
+
def testNoRepoUnlimited(self):
# Test that we get all of the changes when maxChanges is large enough
- self.doTest(None, None)
+ self.doTest(None, None, False)
self.assertEquals(len(self.changes), 3)
# Check that we got the right changes
@@ -347,17 +363,39 @@ def testNoRepoUnlimited(self):
self.assertEquals(self.changes[1].revision, 'ee6fb954cbc3de0f76e84cad6bdff452116e1b03')
self.assertEquals(self.changes[2].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
- def testNoRepoSmallMax(self):
- # Test that we get only 2 changes if maxChanges is set to 2
- self.doTest(None, 2)
+ def testMergingNoRepoUnlimited(self):
+ # Test that we get all of the changes when maxChanges is large enough
+ self.doTest(None, None, True)
self.assertEquals(len(self.changes), 2)
# Check that we got the right changes
- self.assertEquals(self.changes[0].revision, 'ee6fb954cbc3de0f76e84cad6bdff452116e1b03')
+ self.assertEquals(self.changes[0].revision, '4c23e51a484f077ea27af3ea4a4ee13da5aeb5e6')
self.assertEquals(self.changes[1].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
+ def testNoRepoSmallMax(self):
+ # Test that we get only 2 changes if maxChanges is set to 2
+ self.doTest(None, 2, False)
+
+ # The extra change is the overflow indicator
+ self.assertEquals(len(self.changes), 3)
+ # Check that we got the right changes
+ self.assertEquals(self.changes[0].revision, None)
+ self.assertEquals(self.changes[0].files, ['overflow'])
+ self.assertEquals(self.changes[1].revision, 'ee6fb954cbc3de0f76e84cad6bdff452116e1b03')
+ self.assertEquals(self.changes[2].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
+
+ def testMergingNoRepoSmallMax(self):
+ # Test that we get only 1 change if maxChanges is set to 1
+ self.doTest(None, 1, True)
+
+ self.assertEquals(len(self.changes), 1)
+ # Check that we got the right changes
+ self.assertEquals(self.changes[0].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
+ self.assert_('overflow' in self.changes[0].files, self.changes[0].files)
+ self.assert_('widget/src/android/nsWindow.h' not in self.changes[0].files, self.changes[0].files)
+
def testDefaultRepoBigMax(self):
- self.doTest('default', 10)
+ self.doTest('default', 10, False)
self.assertEquals(len(self.changes), 2)
# Check that we got the right changes
@@ -365,13 +403,15 @@ def testDefaultRepoBigMax(self):
self.assertEquals(self.changes[1].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
def testDefaultRepoSmallMax(self):
- self.doTest('default', 1)
+ self.doTest('default', 1, False)
- self.assertEquals(len(self.changes), 1)
+ self.assertEquals(len(self.changes), 2)
# Check that we got the right changes
- self.assertEquals(self.changes[0].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
+ self.assertEquals(self.changes[0].revision, None)
+ self.assertEquals(self.changes[0].files, ['overflow'])
+ self.assertEquals(self.changes[1].revision, '33be08836cb164f9e546231fc59e9e4cf98ed991')
def testRelbranchSmallMax(self):
- self.doTest('GECKO20b5pre_20100820_RELBRANCH', 0)
+ self.doTest('GECKO20b5pre_20100820_RELBRANCH', 1, False)
- self.assertEquals(len(self.changes), 0)
+ self.assertEquals(len(self.changes), 1)
View
47 test/test_misc_important.py
@@ -0,0 +1,47 @@
+from twisted.trial import unittest
+
+from buildbotcustom.misc import makeImportantFunc
+
+
+class Change(object):
+ files = []
+ revlink = None
+ comments = ""
+ revision = None
+
+ def __init__(self, files=None, revlink=None, comments=None, revision=None):
+ if files:
+ self.files = files
+ if revlink:
+ self.revlink = revlink
+ if comments:
+ self.comments = comments
+ if revision:
+ self.revision = revision
+
+
+class TestProductImportance(unittest.TestCase):
+ def testImportant(self):
+ f = makeImportantFunc('http://hg.mozilla.org/mozilla-central', 'firefox')
+ c = Change(revlink="http://hg.mozilla.org/mozilla-central/rev/1234", files=['browser/foo', 'mobile/bar'])
+ self.assertTrue(f(c))
+
+ def testUnImportant(self):
+ f = makeImportantFunc('http://hg.mozilla.org/mozilla-central', 'firefox')
+ c = Change(revlink="http://hg.mozilla.org/mozilla-central/rev/1234", files=['b2g/foo', 'mobile/bar'])
+ self.assertFalse(f(c))
+
+ def testDontBuild(self):
+ f = makeImportantFunc('http://hg.mozilla.org/mozilla-central', 'firefox')
+ c = Change(revlink="http://hg.mozilla.org/mozilla-central/rev/1234", files=['browser/foo', 'mobile/bar'], comments="DONTBUILD me")
+ self.assertFalse(f(c))
+
+ def testNonpollerChange(self):
+ f = makeImportantFunc('http://hg.mozilla.org/mozilla-central', 'firefox')
+ c = Change(revlink="", files=['browser/foo', 'mobile/bar'])
+ self.assertFalse(f(c))
+
+ def testImportantNoProduct(self):
+ f = makeImportantFunc('http://hg.mozilla.org/mozilla-central', None)
+ c = Change(revlink="http://hg.mozilla.org/mozilla-central/rev/1234", files=['browser/foo', 'mobile/bar'])
+ self.assertTrue(f(c))
Please sign in to comment.
Something went wrong with that request. Please try again.