Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/buildbot/buildbot/test/test_properties.py
diff options
context:
space:
mode:
Diffstat (limited to 'buildbot/buildbot/test/test_properties.py')
-rw-r--r--buildbot/buildbot/test/test_properties.py274
1 files changed, 274 insertions, 0 deletions
diff --git a/buildbot/buildbot/test/test_properties.py b/buildbot/buildbot/test/test_properties.py
new file mode 100644
index 0000000..a8973dd
--- /dev/null
+++ b/buildbot/buildbot/test/test_properties.py
@@ -0,0 +1,274 @@
+# -*- test-case-name: buildbot.test.test_properties -*-
+
+import os
+
+from twisted.trial import unittest
+
+from buildbot.sourcestamp import SourceStamp
+from buildbot.process import base
+from buildbot.process.properties import WithProperties, Properties
+from buildbot.status import builder
+from buildbot.slave.commands import rmdirRecursive
+from buildbot.test.runutils import RunMixin
+
+
+class FakeBuild:
+ pass
+class FakeBuildMaster:
+ properties = Properties(masterprop="master")
+class FakeBotMaster:
+ parent = FakeBuildMaster()
+class FakeBuilder:
+ statusbag = None
+ name = "fakebuilder"
+ botmaster = FakeBotMaster()
+class FakeSlave:
+ slavename = "bot12"
+ properties = Properties(slavename="bot12")
+class FakeSlaveBuilder:
+ slave = FakeSlave()
+ def getSlaveCommandVersion(self, command, oldversion=None):
+ return "1.10"
+class FakeScheduler:
+ name = "fakescheduler"
+
+class TestProperties(unittest.TestCase):
+ def setUp(self):
+ self.props = Properties()
+
+ def testDictBehavior(self):
+ self.props.setProperty("do-tests", 1, "scheduler")
+ self.props.setProperty("do-install", 2, "scheduler")
+
+ self.assert_(self.props.has_key('do-tests'))
+ self.failUnlessEqual(self.props['do-tests'], 1)
+ self.failUnlessEqual(self.props['do-install'], 2)
+ self.assertRaises(KeyError, lambda : self.props['do-nothing'])
+ self.failUnlessEqual(self.props.getProperty('do-install'), 2)
+
+ def testUpdate(self):
+ self.props.setProperty("x", 24, "old")
+ newprops = { 'a' : 1, 'b' : 2 }
+ self.props.update(newprops, "new")
+
+ self.failUnlessEqual(self.props.getProperty('x'), 24)
+ self.failUnlessEqual(self.props.getPropertySource('x'), 'old')
+ self.failUnlessEqual(self.props.getProperty('a'), 1)
+ self.failUnlessEqual(self.props.getPropertySource('a'), 'new')
+
+ def testUpdateFromProperties(self):
+ self.props.setProperty("x", 24, "old")
+ newprops = Properties()
+ newprops.setProperty('a', 1, "new")
+ newprops.setProperty('b', 2, "new")
+ self.props.updateFromProperties(newprops)
+
+ self.failUnlessEqual(self.props.getProperty('x'), 24)
+ self.failUnlessEqual(self.props.getPropertySource('x'), 'old')
+ self.failUnlessEqual(self.props.getProperty('a'), 1)
+ self.failUnlessEqual(self.props.getPropertySource('a'), 'new')
+
+ # render() is pretty well tested by TestWithProperties
+
+class TestWithProperties(unittest.TestCase):
+ def setUp(self):
+ self.props = Properties()
+
+ def testBasic(self):
+ # test basic substitution with WithProperties
+ self.props.setProperty("revision", "47", "test")
+ command = WithProperties("build-%s.tar.gz", "revision")
+ self.failUnlessEqual(self.props.render(command),
+ "build-47.tar.gz")
+
+ def testDict(self):
+ # test dict-style substitution with WithProperties
+ self.props.setProperty("other", "foo", "test")
+ command = WithProperties("build-%(other)s.tar.gz")
+ self.failUnlessEqual(self.props.render(command),
+ "build-foo.tar.gz")
+
+ def testDictColonMinus(self):
+ # test dict-style substitution with WithProperties
+ self.props.setProperty("prop1", "foo", "test")
+ command = WithProperties("build-%(prop1:-empty)s-%(prop2:-empty)s.tar.gz")
+ self.failUnlessEqual(self.props.render(command),
+ "build-foo-empty.tar.gz")
+
+ def testDictColonPlus(self):
+ # test dict-style substitution with WithProperties
+ self.props.setProperty("prop1", "foo", "test")
+ command = WithProperties("build-%(prop1:+exists)s-%(prop2:+exists)s.tar.gz")
+ self.failUnlessEqual(self.props.render(command),
+ "build-exists-.tar.gz")
+
+ def testEmpty(self):
+ # None should render as ''
+ self.props.setProperty("empty", None, "test")
+ command = WithProperties("build-%(empty)s.tar.gz")
+ self.failUnlessEqual(self.props.render(command),
+ "build-.tar.gz")
+
+ def testRecursiveList(self):
+ self.props.setProperty("x", 10, "test")
+ self.props.setProperty("y", 20, "test")
+ command = [ WithProperties("%(x)s %(y)s"), "and",
+ WithProperties("%(y)s %(x)s") ]
+ self.failUnlessEqual(self.props.render(command),
+ ["10 20", "and", "20 10"])
+
+ def testRecursiveTuple(self):
+ self.props.setProperty("x", 10, "test")
+ self.props.setProperty("y", 20, "test")
+ command = ( WithProperties("%(x)s %(y)s"), "and",
+ WithProperties("%(y)s %(x)s") )
+ self.failUnlessEqual(self.props.render(command),
+ ("10 20", "and", "20 10"))
+
+ def testRecursiveDict(self):
+ self.props.setProperty("x", 10, "test")
+ self.props.setProperty("y", 20, "test")
+ command = { WithProperties("%(x)s %(y)s") :
+ WithProperties("%(y)s %(x)s") }
+ self.failUnlessEqual(self.props.render(command),
+ {"10 20" : "20 10"})
+
+class BuildProperties(unittest.TestCase):
+ """Test the properties that a build should have."""
+ def setUp(self):
+ self.builder = FakeBuilder()
+ self.builder_status = builder.BuilderStatus("fakebuilder")
+ self.builder_status.basedir = "test_properties"
+ self.builder_status.nextBuildNumber = 5
+ rmdirRecursive(self.builder_status.basedir)
+ os.mkdir(self.builder_status.basedir)
+ self.build_status = self.builder_status.newBuild()
+ req = base.BuildRequest("reason",
+ SourceStamp(branch="branch2", revision="1234"),
+ 'test_builder',
+ properties=Properties(scheduler="fakescheduler"))
+ self.build = base.Build([req])
+ self.build.build_status = self.build_status
+ self.build.setBuilder(self.builder)
+ self.build.setupProperties()
+ self.build.setupSlaveBuilder(FakeSlaveBuilder())
+
+ def testProperties(self):
+ self.failUnlessEqual(self.build.getProperty("scheduler"), "fakescheduler")
+ self.failUnlessEqual(self.build.getProperty("branch"), "branch2")
+ self.failUnlessEqual(self.build.getProperty("revision"), "1234")
+ self.failUnlessEqual(self.build.getProperty("slavename"), "bot12")
+ self.failUnlessEqual(self.build.getProperty("buildnumber"), 5)
+ self.failUnlessEqual(self.build.getProperty("buildername"), "fakebuilder")
+ self.failUnlessEqual(self.build.getProperty("masterprop"), "master")
+
+run_config = """
+from buildbot.process import factory
+from buildbot.steps.shell import ShellCommand, WithProperties
+from buildbot.buildslave import BuildSlave
+s = factory.s
+
+BuildmasterConfig = c = {}
+c['slaves'] = [BuildSlave('bot1', 'sekrit', properties={'slprop':'slprop'})]
+c['schedulers'] = []
+c['slavePortnum'] = 0
+c['properties'] = { 'global' : 'global' }
+
+# Note: when run against twisted-1.3.0, this locks up about 5% of the time. I
+# suspect that a command with no output that finishes quickly triggers a race
+# condition in 1.3.0's process-reaping code. The 'touch' process becomes a
+# zombie and the step never completes. To keep this from messing up the unit
+# tests too badly, this step runs with a reduced timeout.
+
+f1 = factory.BuildFactory([s(ShellCommand,
+ flunkOnFailure=True,
+ command=['touch',
+ WithProperties('%s-%s-%s',
+ 'slavename', 'global', 'slprop'),
+ ],
+ workdir='.',
+ timeout=10,
+ )])
+
+b1 = {'name': 'full1', 'slavename': 'bot1', 'builddir': 'bd1', 'factory': f1}
+c['builders'] = [b1]
+
+"""
+
+class Run(RunMixin, unittest.TestCase):
+ def testInterpolate(self):
+ # run an actual build with a step that interpolates a build property
+ d = self.master.loadConfig(run_config)
+ d.addCallback(lambda res: self.master.startService())
+ d.addCallback(lambda res: self.connectOneSlave("bot1"))
+ d.addCallback(lambda res: self.requestBuild("full1"))
+ d.addCallback(self.failUnlessBuildSucceeded)
+ def _check_touch(res):
+ f = os.path.join("slavebase-bot1", "bd1", "bot1-global-slprop")
+ self.failUnless(os.path.exists(f))
+ return res
+ d.addCallback(_check_touch)
+ return d
+
+ SetProperty_base_config = """
+from buildbot.process import factory
+from buildbot.steps.shell import ShellCommand, SetProperty, WithProperties
+from buildbot.buildslave import BuildSlave
+s = factory.s
+
+BuildmasterConfig = c = {}
+c['slaves'] = [BuildSlave('bot1', 'sekrit')]
+c['schedulers'] = []
+c['slavePortnum'] = 0
+
+f1 = factory.BuildFactory([
+##STEPS##
+])
+
+b1 = {'name': 'full1', 'slavename': 'bot1', 'builddir': 'bd1', 'factory': f1}
+c['builders'] = [b1]
+"""
+
+ SetPropertySimple_config = SetProperty_base_config.replace("##STEPS##", """
+ SetProperty(property='foo', command="echo foo"),
+ SetProperty(property=WithProperties('wp'), command="echo wp"),
+ SetProperty(property='bar', command="echo bar", strip=False),
+ """)
+
+ def testSetPropertySimple(self):
+ d = self.master.loadConfig(self.SetPropertySimple_config)
+ d.addCallback(lambda res: self.master.startService())
+ d.addCallback(lambda res: self.connectOneSlave("bot1"))
+ d.addCallback(lambda res: self.requestBuild("full1"))
+ d.addCallback(self.failUnlessBuildSucceeded)
+ def _check_props(bs):
+ self.failUnlessEqual(bs.getProperty("foo"), "foo")
+ self.failUnlessEqual(bs.getProperty("wp"), "wp")
+ # (will this fail on some platforms, due to newline differences?)
+ self.failUnlessEqual(bs.getProperty("bar"), "bar\n")
+ return bs
+ d.addCallback(_check_props)
+ return d
+
+ SetPropertyExtractFn_config = SetProperty_base_config.replace("##STEPS##", """
+ SetProperty(
+ extract_fn=lambda rc,stdout,stderr : {
+ 'foo' : stdout.strip(),
+ 'bar' : stderr.strip() },
+ command="echo foo; echo bar >&2"),
+ """)
+
+ def testSetPropertyExtractFn(self):
+ d = self.master.loadConfig(self.SetPropertyExtractFn_config)
+ d.addCallback(lambda res: self.master.startService())
+ d.addCallback(lambda res: self.connectOneSlave("bot1"))
+ d.addCallback(lambda res: self.requestBuild("full1"))
+ d.addCallback(self.failUnlessBuildSucceeded)
+ def _check_props(bs):
+ self.failUnlessEqual(bs.getProperty("foo"), "foo")
+ self.failUnlessEqual(bs.getProperty("bar"), "bar")
+ return bs
+ d.addCallback(_check_props)
+ return d
+
+# we test got_revision in test_vc