Skip to content

Commit

Permalink
Merge pull request #1677 from sa2ajj/port-from-0.8.12-part2
Browse files Browse the repository at this point in the history
Port from 0.8.12 part2
  • Loading branch information
Mikhail Sobolev committed May 19, 2015
2 parents 62fc7a1 + 126a196 commit c82c5ed
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 48 deletions.
8 changes: 6 additions & 2 deletions master/buildbot/process/buildstep.py
Expand Up @@ -1127,8 +1127,12 @@ def makeRemoteShellCommand(self, collectStdout=False, collectStderr=False,
kwargs['env'].update(self.env)
kwargs['stdioLogName'] = stdioLogName

if not kwargs.get('workdir'):
kwargs['workdir'] = self.workdir
# default the workdir appropriately
if not kwargs.get('workdir') and not self.workdir:
if callable(self.build.workdir):
kwargs['workdir'] = self.build.workdir(self.build.sources)
else:
kwargs['workdir'] = self.build.workdir

# the rest of the args go to RemoteShellCommand
cmd = remotecommand.RemoteShellCommand(
Expand Down
14 changes: 5 additions & 9 deletions master/buildbot/process/logobserver.py
Expand Up @@ -155,16 +155,12 @@ def errReceived(self, data):
self.stderr.append(data)

def _get(self, chunks):
if chunks is None:
return [u'']
if len(chunks) > 1:
chunks = [''.join(chunks)]
elif not chunks:
chunks = [u'']
return chunks
if chunks is None or not chunks:
return u''
return u''.join(chunks)

def getStdout(self):
return self._get(self.stdout)[0]
return self._get(self.stdout)

def getStderr(self):
return self._get(self.stderr)[0]
return self._get(self.stderr)
12 changes: 8 additions & 4 deletions master/buildbot/process/slavebuilder.py
Expand Up @@ -70,6 +70,14 @@ def isBusy(self):

def buildStarted(self):
self.state = BUILDING
# AbstractBuildSlave doesn't always have a buildStarted method
# so only call it if it is available.
try:
slave_buildStarted = self.slave.buildStarted
except AttributeError:
pass
else:
slave_buildStarted(self)

def buildFinished(self):
self.state = IDLE
Expand Down Expand Up @@ -269,10 +277,6 @@ def detached(self):
AbstractSlaveBuilder.detached(self)
self.state = LATENT

def buildStarted(self):
AbstractSlaveBuilder.buildStarted(self)
self.slave.buildStarted(self)

def _attachFailure(self, why, where):
self.state = LATENT
return AbstractSlaveBuilder._attachFailure(self, why, where)
Expand Down
22 changes: 11 additions & 11 deletions master/buildbot/schedulers/forcesched.py
Expand Up @@ -613,26 +613,26 @@ def __init__(self, name, builderNames,
name)

if not self.checkIfListOfType(builderNames, str):
config.error("ForceScheduler builderNames must be a list of strings: %r" %
builderNames)
config.error("ForceScheduler '%s': builderNames must be a list of strings: %r" %
(name, builderNames))

if self.checkIfType(reason, BaseParameter):
self.reason = reason
else:
config.error("ForceScheduler reason must be a StringParameter: %r" %
reason)
config.error("ForceScheduler '%s': reason must be a StringParameter: %r" %
(name, reason))

if properties is None:
properties = []
if not self.checkIfListOfType(properties, BaseParameter):
config.error("ForceScheduler properties must be a list of BaseParameters: %r" %
properties)
config.error("ForceScheduler '%s': properties must be a list of BaseParameters: %r" %
(name, properties))

if self.checkIfType(username, BaseParameter):
self.username = username
else:
config.error("ForceScheduler username must be a StringParameter: %r" %
username)
config.error("ForceScheduler '%s': username must be a StringParameter: %r" %
(name, username))

self.forcedProperties = []
self.label = name if label is None else label
Expand All @@ -641,16 +641,16 @@ def __init__(self, name, builderNames,
if codebases is None:
codebases = [CodebaseParameter(codebase='')]
elif not codebases:
config.error("ForceScheduler: 'codebases' cannot be empty; use [CodebaseParameter(codebase='', hide=True)] if needed: %r " % (codebases,))
config.error("ForceScheduler '%s': 'codebases' cannot be empty; use [CodebaseParameter(codebase='', hide=True)] if needed: %r " % (name, codebases))
elif not isinstance(codebases, list):
config.error("ForceScheduler: 'codebases' should be a list of strings or CodebaseParameter, not %s" % type(codebases))
config.error("ForceScheduler '%s': 'codebases' should be a list of strings or CodebaseParameter, not %s" % (name, type(codebases)))

codebase_dict = {}
for codebase in codebases:
if isinstance(codebase, basestring):
codebase = CodebaseParameter(codebase=codebase)
elif not isinstance(codebase, CodebaseParameter):
config.error("ForceScheduler: 'codebases' must be a list of strings or CodebaseParameter objects: %r" % (codebases,))
config.error("ForceScheduler '%s': 'codebases' must be a list of strings or CodebaseParameter objects: %r" % (name, codebases))

self.forcedProperties.append(codebase)
codebase_dict[codebase.codebase] = dict(branch='', repository='', revision='')
Expand Down
3 changes: 2 additions & 1 deletion master/buildbot/status/builder.py
Expand Up @@ -335,7 +335,8 @@ def setTags(self, tags):
self.tags = tags

def matchesAnyTag(self, tags):
return self.tags and any(tag for tag in self.tags if tag in tags)
# Need to guard against None with the "or []".
return bool(set(self.tags or []) & set(tags))

def getBuildByRevision(self, rev):
number = self.nextBuildNumber - 1
Expand Down
65 changes: 65 additions & 0 deletions master/buildbot/test/unit/test_process_slavebuilder.py
@@ -0,0 +1,65 @@
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members


from buildbot.buildslave.base import AbstractBuildSlave
from twisted.trial.unittest import TestCase

from buildbot.process.slavebuilder import AbstractSlaveBuilder


class TestAbstractSlaveBuilder(TestCase):
"""
Tests for ``AbstractSlaveBuilder``.
"""

def test_buildStarted_called(self):
"""
If the slave associated to slave builder has a ``buildStarted`` method,
calling ``buildStarted`` on the slave builder calls the method on the
slave with the slavebuilder as an argument.
"""
class ConcreteBuildSlave(AbstractBuildSlave):
_buildStartedCalls = []

def buildStarted(self, slavebuilder):
self._buildStartedCalls.append(slavebuilder)

slave = ConcreteBuildSlave("slave", "pass")
slavebuilder = AbstractSlaveBuilder()
# FIXME: This should call attached, instead of setting the attribute
# directly
slavebuilder.slave = slave
slavebuilder.buildStarted()

self.assertEqual(ConcreteBuildSlave._buildStartedCalls, [slavebuilder])

def test_buildStarted_missing(self):
"""
If the slave associated to slave builder doesn not have a
``buildStarted`` method, calling ``buildStarted`` on the slave builder
doesn't raise an exception.
"""
class ConcreteBuildSlave(AbstractBuildSlave):
pass

slave = ConcreteBuildSlave("slave", "pass")
slavebuilder = AbstractSlaveBuilder()
# FIXME: This should call attached, instead of setting the attribute
# directly
slavebuilder.slave = slave

# The following shouldn't raise an exception.
slavebuilder.buildStarted()
24 changes: 12 additions & 12 deletions master/buildbot/test/unit/test_schedulers_forcesched.py
Expand Up @@ -242,21 +242,21 @@ def test_force_someBuilders(self):
def test_bad_codebases(self):

# codebases must be a list of either string or BaseParameter types
self.assertRaisesConfigError("ForceScheduler: 'codebases' must be a list of strings or CodebaseParameter objects:",
self.assertRaisesConfigError("ForceScheduler 'foo': 'codebases' must be a list of strings or CodebaseParameter objects:",
lambda: ForceScheduler(name='foo', builderNames=['bar'],
codebases=[123],))
self.assertRaisesConfigError("ForceScheduler: 'codebases' must be a list of strings or CodebaseParameter objects:",
self.assertRaisesConfigError("ForceScheduler 'foo': 'codebases' must be a list of strings or CodebaseParameter objects:",
lambda: ForceScheduler(name='foo', builderNames=['bar'],
codebases=[IntParameter('foo')],))

# codebases cannot be empty
self.assertRaisesConfigError("ForceScheduler: 'codebases' cannot be empty; use [CodebaseParameter(codebase='', hide=True)] if needed:",
self.assertRaisesConfigError("ForceScheduler 'foo': 'codebases' cannot be empty; use [CodebaseParameter(codebase='', hide=True)] if needed:",
lambda: ForceScheduler(name='foo',
builderNames=['bar'],
codebases=[]))

# codebases cannot be a dictionnary
self.assertRaisesConfigError("ForceScheduler: 'codebases' should be a list of strings or CodebaseParameter, not <type 'dict'>",
self.assertRaisesConfigError("ForceScheduler 'foo': 'codebases' should be a list of strings or CodebaseParameter, not <type 'dict'>",
lambda: ForceScheduler(name='foo',
builderNames=['bar'],
codebases={'cb': {'branch': 'trunk'}}))
Expand Down Expand Up @@ -532,12 +532,12 @@ def test_NestedParameter_nullname(self):
klass=NestedParameter, fields=fields, name='')

def test_bad_reason(self):
self.assertRaisesConfigError("ForceScheduler reason must be a StringParameter",
self.assertRaisesConfigError("ForceScheduler 'testsched': reason must be a StringParameter",
lambda: ForceScheduler(name='testsched', builderNames=[],
codebases=['bar'], reason="foo"))

def test_bad_username(self):
self.assertRaisesConfigError("ForceScheduler username must be a StringParameter",
self.assertRaisesConfigError("ForceScheduler 'testsched': username must be a StringParameter",
lambda: ForceScheduler(name='testsched', builderNames=[],
codebases=['bar'], username="foo"))

Expand All @@ -552,35 +552,35 @@ def test_emptystring_name(self):
codebases=['bar'], username="foo"))

def test_integer_builderNames(self):
self.assertRaisesConfigError("ForceScheduler builderNames must be a list of strings:",
self.assertRaisesConfigError("ForceScheduler 'testsched': builderNames must be a list of strings:",
lambda: ForceScheduler(name='testsched', builderNames=1234,
codebases=['bar'], username="foo"))

def test_listofints_builderNames(self):
self.assertRaisesConfigError("ForceScheduler builderNames must be a list of strings:",
self.assertRaisesConfigError("ForceScheduler 'testsched': builderNames must be a list of strings:",
lambda: ForceScheduler(name='testsched', builderNames=[1234],
codebases=['bar'], username="foo"))

def test_listofmixed_builderNames(self):
self.assertRaisesConfigError("ForceScheduler builderNames must be a list of strings:",
self.assertRaisesConfigError("ForceScheduler 'testsched': builderNames must be a list of strings:",
lambda: ForceScheduler(name='testsched',
builderNames=['test', 1234],
codebases=['bar'], username="foo"))

def test_integer_properties(self):
self.assertRaisesConfigError("ForceScheduler properties must be a list of BaseParameters:",
self.assertRaisesConfigError("ForceScheduler 'testsched': properties must be a list of BaseParameters:",
lambda: ForceScheduler(name='testsched', builderNames=[],
codebases=['bar'], username="foo",
properties=1234))

def test_listofints_properties(self):
self.assertRaisesConfigError("ForceScheduler properties must be a list of BaseParameters:",
self.assertRaisesConfigError("ForceScheduler 'testsched': properties must be a list of BaseParameters:",
lambda: ForceScheduler(name='testsched', builderNames=[],
codebases=['bar'], username="foo",
properties=[1234, 2345]))

def test_listofmixed_properties(self):
self.assertRaisesConfigError("ForceScheduler properties must be a list of BaseParameters:",
self.assertRaisesConfigError("ForceScheduler 'testsched': properties must be a list of BaseParameters:",
lambda: ForceScheduler(name='testsched', builderNames=[],
codebases=['bar'], username="foo",
properties=[BaseParameter(name="test",),
Expand Down
67 changes: 67 additions & 0 deletions master/buildbot/test/unit/test_status_builder.py
@@ -0,0 +1,67 @@
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members
"""
Tests for buildbot.status.builder module.
"""
from buildbot.status import builder
from buildbot.test.fake import fakemaster
from twisted.trial import unittest


class TestBuilderStatus(unittest.TestCase):
"""
Unit tests for BuilderStatus.
"""

def makeBuilderStatus(self):
"""
Return a new BuilderStatus.
"""

return builder.BuilderStatus(
buildername='testing-builder',
tags=None,
master=fakemaster.make_master(),
description=None)

def test_matchesAnyTag_no_tags(self):
"""
Return False when builder has no tags.
"""
sut = self.makeBuilderStatus()

self.assertFalse(sut.matchesAnyTag(set()))
self.assertFalse(sut.matchesAnyTag(set(('any-tag', 'tag'))))

def test_matchesAnyTag_no_match(self):
"""
Return False when requested tags don't match.
"""
sut = self.makeBuilderStatus()
sut.tags = set('one')

self.assertFalse(sut.matchesAnyTag(set()))
self.assertFalse(sut.matchesAnyTag(set(('no-such-tag',))))
self.assertFalse(sut.matchesAnyTag(set(('other-tag', 'tag'))))

def test_matchesAnyTag_with_match(self):
"""
Return True when at least one of the requested tags match.
"""
sut = self.makeBuilderStatus()
sut.tags = set(('one', 'two'))

self.assertTrue(sut.matchesAnyTag(set(('two',))))
self.assertTrue(sut.matchesAnyTag(set(('two', 'one'))))
31 changes: 31 additions & 0 deletions master/buildbot/test/unit/test_steps_source_git.py
Expand Up @@ -1754,6 +1754,37 @@ def test_mode_full_logEnviron(self):
self.expectProperty('got_revision', 'f6ad368298bd941e934a41f3babc827b2aa95a1d', 'Git')
return self.runStep()

def test_wkdir_doesnt_exist(self):
self.setupStep(
git.Git(repourl='http://github.com/buildbot/buildbot.git',
mode='full'))
self.expectCommands(
ExpectShell(workdir='wkdir',
command=['git', '--version'])
+ ExpectShell.log('stdio',
stdout='git version 1.7.5')
+ 0,
Expect('stat', dict(file='wkdir/.buildbot-patched',
logEnviron=True))
+ 1,
Expect('listdir', {'dir': 'wkdir', 'logEnviron': True,
'timeout': 1200})
+ 1,
ExpectShell(workdir='wkdir',
command=['git', 'clone',
'http://github.com/buildbot/buildbot.git',
'.'])
+ 0,
ExpectShell(workdir='wkdir',
command=['git', 'rev-parse', 'HEAD'])
+ ExpectShell.log('stdio',
stdout='f6ad368298bd941e934a41f3babc827b2aa95a1d')
+ 0,
)
self.expectOutcome(result=SUCCESS)
self.expectProperty('got_revision', 'f6ad368298bd941e934a41f3babc827b2aa95a1d', 'Git')
return self.runStep()

def test_getDescription(self):
# clone of: test_mode_incremental
# only difference is to set the getDescription property
Expand Down
2 changes: 1 addition & 1 deletion master/buildbot/www/change_hook.py
Expand Up @@ -127,7 +127,7 @@ def getChanges(self, request):
else:
dialect = 'base'

if dialect in self.dialects.keys():
if dialect in self.dialects:
log.msg("Attempting to load module buildbot.www.hooks." + dialect)
tempModule = namedModule('buildbot.www.hooks.' + dialect)
changes, src = tempModule.getChanges(request, self.dialects[dialect])
Expand Down

0 comments on commit c82c5ed

Please sign in to comment.