add max_builds= to BuildSlave, thanks to Dustin Mitchell. Closes #48.
[buildbot.git] / buildbot / test / test_runner.py
blob1f2c60ebb98caaebd4a5ca50b92e5c27f9c606ef
2 # this file tests the 'buildbot' command, with its various sub-commands
4 from twisted.trial import unittest
5 from twisted.python import usage
6 import os, shutil, shlex
8 from buildbot.scripts import runner, tryclient
10 class Options(unittest.TestCase):
11 optionsFile = "SDFsfsFSdfsfsFSD"
13 def make(self, d, key):
14 # we use a wacky filename here in case the test code discovers the
15 # user's real ~/.buildbot/ directory
16 os.makedirs(os.sep.join(d + [".buildbot"]))
17 f = open(os.sep.join(d + [".buildbot", self.optionsFile]), "w")
18 f.write("key = '%s'\n" % key)
19 f.close()
21 def check(self, d, key):
22 basedir = os.sep.join(d)
23 options = runner.loadOptions(self.optionsFile, here=basedir,
24 home=self.home)
25 if key is None:
26 self.failIf(options.has_key('key'))
27 else:
28 self.failUnlessEqual(options['key'], key)
30 def testFindOptions(self):
31 self.make(["home", "dir1", "dir2", "dir3"], "one")
32 self.make(["home", "dir1", "dir2"], "two")
33 self.make(["home"], "home")
34 self.home = os.path.abspath("home")
36 self.check(["home", "dir1", "dir2", "dir3"], "one")
37 self.check(["home", "dir1", "dir2"], "two")
38 self.check(["home", "dir1"], "home")
40 self.home = os.path.abspath("nothome")
41 os.makedirs(os.sep.join(["nothome", "dir1"]))
42 self.check(["nothome", "dir1"], None)
44 def doForce(self, args, expected):
45 o = runner.ForceOptions()
46 o.parseOptions(args)
47 self.failUnlessEqual(o.keys(), expected.keys())
48 for k in o.keys():
49 self.failUnlessEqual(o[k], expected[k],
50 "[%s] got %s instead of %s" % (k, o[k],
51 expected[k]))
53 def testForceOptions(self):
54 if not hasattr(shlex, "split"):
55 raise unittest.SkipTest("need python>=2.3 for shlex.split")
57 exp = {"builder": "b1", "reason": "reason",
58 "branch": None, "revision": None}
59 self.doForce(shlex.split("b1 reason"), exp)
60 self.doForce(shlex.split("b1 'reason'"), exp)
61 self.failUnlessRaises(usage.UsageError, self.doForce,
62 shlex.split("--builder b1 'reason'"), exp)
63 self.doForce(shlex.split("--builder b1 --reason reason"), exp)
64 self.doForce(shlex.split("--builder b1 --reason 'reason'"), exp)
65 self.doForce(shlex.split("--builder b1 --reason \"reason\""), exp)
67 exp['reason'] = "longer reason"
68 self.doForce(shlex.split("b1 'longer reason'"), exp)
69 self.doForce(shlex.split("b1 longer reason"), exp)
70 self.doForce(shlex.split("--reason 'longer reason' b1"), exp)
73 class Create(unittest.TestCase):
74 def failUnlessIn(self, substring, string, msg=None):
75 # trial provides a version of this that requires python-2.3 to test
76 # strings.
77 self.failUnless(string.find(substring) != -1, msg)
78 def failUnlessExists(self, filename):
79 self.failUnless(os.path.exists(filename), "%s should exist" % filename)
80 def failIfExists(self, filename):
81 self.failIf(os.path.exists(filename), "%s should not exist" % filename)
83 def testMaster(self):
84 basedir = "test_runner.master"
85 options = runner.MasterOptions()
86 options.parseOptions(["-q", basedir])
87 cwd = os.getcwd()
88 runner.createMaster(options)
89 os.chdir(cwd)
91 tac = os.path.join(basedir, "buildbot.tac")
92 self.failUnless(os.path.exists(tac))
93 tacfile = open(tac,"rt").read()
94 self.failUnlessIn("basedir", tacfile)
95 self.failUnlessIn("configfile = r'master.cfg'", tacfile)
96 self.failUnlessIn("BuildMaster(basedir, configfile)", tacfile)
98 cfg = os.path.join(basedir, "master.cfg")
99 self.failIfExists(cfg)
100 samplecfg = os.path.join(basedir, "master.cfg.sample")
101 self.failUnlessExists(samplecfg)
102 cfgfile = open(samplecfg,"rt").read()
103 self.failUnlessIn("This is a sample buildmaster config file", cfgfile)
105 makefile = os.path.join(basedir, "Makefile.sample")
106 self.failUnlessExists(makefile)
108 # now verify that running it a second time (with the same options)
109 # does the right thing: nothing changes
110 runner.createMaster(options)
111 os.chdir(cwd)
113 self.failIfExists(os.path.join(basedir, "buildbot.tac.new"))
114 self.failUnlessExists(os.path.join(basedir, "master.cfg.sample"))
116 oldtac = open(os.path.join(basedir, "buildbot.tac"), "rt").read()
118 # mutate Makefile.sample, since it should be rewritten
119 f = open(os.path.join(basedir, "Makefile.sample"), "rt")
120 oldmake = f.read()
121 f = open(os.path.join(basedir, "Makefile.sample"), "wt")
122 f.write(oldmake)
123 f.write("# additional line added\n")
124 f.close()
126 # also mutate master.cfg.sample
127 f = open(os.path.join(basedir, "master.cfg.sample"), "rt")
128 oldsamplecfg = f.read()
129 f = open(os.path.join(basedir, "master.cfg.sample"), "wt")
130 f.write(oldsamplecfg)
131 f.write("# additional line added\n")
132 f.close()
134 # now run it again (with different options)
135 options = runner.MasterOptions()
136 options.parseOptions(["-q", "--config", "other.cfg", basedir])
137 runner.createMaster(options)
138 os.chdir(cwd)
140 tac = open(os.path.join(basedir, "buildbot.tac"), "rt").read()
141 self.failUnlessEqual(tac, oldtac, "shouldn't change existing .tac")
142 self.failUnlessExists(os.path.join(basedir, "buildbot.tac.new"))
144 make = open(os.path.join(basedir, "Makefile.sample"), "rt").read()
145 self.failUnlessEqual(make, oldmake, "*should* rewrite Makefile.sample")
147 samplecfg = open(os.path.join(basedir, "master.cfg.sample"),
148 "rt").read()
149 self.failUnlessEqual(samplecfg, oldsamplecfg,
150 "*should* rewrite master.cfg.sample")
153 def testSlave(self):
154 basedir = "test_runner.slave"
155 options = runner.SlaveOptions()
156 options.parseOptions(["-q", basedir, "buildmaster:1234",
157 "botname", "passwd"])
158 cwd = os.getcwd()
159 runner.createSlave(options)
160 os.chdir(cwd)
162 tac = os.path.join(basedir, "buildbot.tac")
163 self.failUnless(os.path.exists(tac))
164 tacfile = open(tac,"rt").read()
165 self.failUnlessIn("basedir", tacfile)
166 self.failUnlessIn("buildmaster_host = 'buildmaster'", tacfile)
167 self.failUnlessIn("port = 1234", tacfile)
168 self.failUnlessIn("slavename = 'botname'", tacfile)
169 self.failUnlessIn("passwd = 'passwd'", tacfile)
170 self.failUnlessIn("keepalive = 600", tacfile)
171 self.failUnlessIn("BuildSlave(buildmaster_host, port, slavename",
172 tacfile)
174 makefile = os.path.join(basedir, "Makefile.sample")
175 self.failUnlessExists(makefile)
177 self.failUnlessExists(os.path.join(basedir, "info", "admin"))
178 self.failUnlessExists(os.path.join(basedir, "info", "host"))
179 # edit one to make sure the later install doesn't change it
180 f = open(os.path.join(basedir, "info", "admin"), "wt")
181 f.write("updated@buildbot.example.org\n")
182 f.close()
184 # now verify that running it a second time (with the same options)
185 # does the right thing: nothing changes
186 runner.createSlave(options)
187 os.chdir(cwd)
189 self.failIfExists(os.path.join(basedir, "buildbot.tac.new"))
190 admin = open(os.path.join(basedir, "info", "admin"), "rt").read()
191 self.failUnlessEqual(admin, "updated@buildbot.example.org\n")
194 # mutate Makefile.sample, since it should be rewritten
195 oldmake = open(os.path.join(basedir, "Makefile.sample"), "rt").read()
196 f = open(os.path.join(basedir, "Makefile.sample"), "wt")
197 f.write(oldmake)
198 f.write("# additional line added\n")
199 f.close()
200 oldtac = open(os.path.join(basedir, "buildbot.tac"), "rt").read()
202 # now run it again (with different options)
203 options = runner.SlaveOptions()
204 options.parseOptions(["-q", "--keepalive", "30",
205 basedir, "buildmaster:9999",
206 "newbotname", "passwd"])
207 runner.createSlave(options)
208 os.chdir(cwd)
210 tac = open(os.path.join(basedir, "buildbot.tac"), "rt").read()
211 self.failUnlessEqual(tac, oldtac, "shouldn't change existing .tac")
212 self.failUnlessExists(os.path.join(basedir, "buildbot.tac.new"))
213 tacfile = open(os.path.join(basedir, "buildbot.tac.new"),"rt").read()
214 self.failUnlessIn("basedir", tacfile)
215 self.failUnlessIn("buildmaster_host = 'buildmaster'", tacfile)
216 self.failUnlessIn("port = 9999", tacfile)
217 self.failUnlessIn("slavename = 'newbotname'", tacfile)
218 self.failUnlessIn("passwd = 'passwd'", tacfile)
219 self.failUnlessIn("keepalive = 30", tacfile)
220 self.failUnlessIn("BuildSlave(buildmaster_host, port, slavename",
221 tacfile)
223 make = open(os.path.join(basedir, "Makefile.sample"), "rt").read()
224 self.failUnlessEqual(make, oldmake, "*should* rewrite Makefile.sample")
226 class Try(unittest.TestCase):
227 # test some aspects of the 'buildbot try' command
228 def makeOptions(self, contents):
229 if os.path.exists(".buildbot"):
230 shutil.rmtree(".buildbot")
231 os.mkdir(".buildbot")
232 open(os.path.join(".buildbot", "options"), "w").write(contents)
234 def testGetopt1(self):
235 opts = "try_connect = 'ssh'\n" + "try_builders = ['a']\n"
236 self.makeOptions(opts)
237 config = runner.TryOptions()
238 config.parseOptions([])
239 t = tryclient.Try(config)
240 self.failUnlessEqual(t.connect, "ssh")
241 self.failUnlessEqual(t.builderNames, ['a'])
243 def testGetopt2(self):
244 opts = ""
245 self.makeOptions(opts)
246 config = runner.TryOptions()
247 config.parseOptions(['--connect=ssh', '--builder', 'a'])
248 t = tryclient.Try(config)
249 self.failUnlessEqual(t.connect, "ssh")
250 self.failUnlessEqual(t.builderNames, ['a'])
252 def testGetopt3(self):
253 opts = ""
254 self.makeOptions(opts)
255 config = runner.TryOptions()
256 config.parseOptions(['--connect=ssh',
257 '--builder', 'a', '--builder=b'])
258 t = tryclient.Try(config)
259 self.failUnlessEqual(t.connect, "ssh")
260 self.failUnlessEqual(t.builderNames, ['a', 'b'])
262 def testGetopt4(self):
263 opts = "try_connect = 'ssh'\n" + "try_builders = ['a']\n"
264 self.makeOptions(opts)
265 config = runner.TryOptions()
266 config.parseOptions(['--builder=b'])
267 t = tryclient.Try(config)
268 self.failUnlessEqual(t.connect, "ssh")
269 self.failUnlessEqual(t.builderNames, ['b'])
271 def testGetTopdir(self):
272 os.mkdir("gettopdir")
273 os.mkdir(os.path.join("gettopdir", "foo"))
274 os.mkdir(os.path.join("gettopdir", "foo", "bar"))
275 open(os.path.join("gettopdir", "1"),"w").write("1")
276 open(os.path.join("gettopdir", "foo", "2"),"w").write("2")
277 open(os.path.join("gettopdir", "foo", "bar", "3"),"w").write("3")
279 target = os.path.abspath("gettopdir")
280 t = tryclient.getTopdir("1", "gettopdir")
281 self.failUnlessEqual(os.path.abspath(t), target)
282 t = tryclient.getTopdir("1", os.path.join("gettopdir", "foo"))
283 self.failUnlessEqual(os.path.abspath(t), target)
284 t = tryclient.getTopdir("1", os.path.join("gettopdir", "foo", "bar"))
285 self.failUnlessEqual(os.path.abspath(t), target)
287 target = os.path.abspath(os.path.join("gettopdir", "foo"))
288 t = tryclient.getTopdir("2", os.path.join("gettopdir", "foo"))
289 self.failUnlessEqual(os.path.abspath(t), target)
290 t = tryclient.getTopdir("2", os.path.join("gettopdir", "foo", "bar"))
291 self.failUnlessEqual(os.path.abspath(t), target)
293 target = os.path.abspath(os.path.join("gettopdir", "foo", "bar"))
294 t = tryclient.getTopdir("3", os.path.join("gettopdir", "foo", "bar"))
295 self.failUnlessEqual(os.path.abspath(t), target)
297 nonexistent = "nonexistent\n29fis3kq\tBAR"
298 # hopefully there won't be a real file with that name between here
299 # and the filesystem root.
300 self.failUnlessRaises(ValueError, tryclient.getTopdir, nonexistent)