Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: third_party/buildbot_7_12/buildbot/test/test_slavecommand.py

Issue 12207158: Bye bye buildbot 0.7.12. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: buildbot.test.test_slavecommand -*-
2
3 from twisted.trial import unittest
4 from twisted.internet import reactor, interfaces
5 from twisted.python import runtime, failure, util
6
7 import os, sys
8
9 from buildbot.slave import commands
10 SlaveShellCommand = commands.SlaveShellCommand
11
12 from buildbot.test.runutils import SignalMixin, FakeSlaveBuilder
13
14 # test slavecommand.py by running the various commands with a fake
15 # SlaveBuilder object that logs the calls to sendUpdate()
16
17 class Utilities(unittest.TestCase):
18 def mkdir(self, basedir, path, mode=None):
19 fn = os.path.join(basedir, path)
20 os.makedirs(fn)
21 if mode is not None:
22 os.chmod(fn, mode)
23
24 def touch(self, basedir, path, mode=None):
25 fn = os.path.join(basedir, path)
26 f = open(fn, "w")
27 f.write("touch\n")
28 f.close()
29 if mode is not None:
30 os.chmod(fn, mode)
31
32 def test_rmdirRecursive(self):
33 basedir = "slavecommand/Utilities/test_rmdirRecursive"
34 os.makedirs(basedir)
35 d = os.path.join(basedir, "doomed")
36 self.mkdir(d, "a/b")
37 self.touch(d, "a/b/1.txt")
38 self.touch(d, "a/b/2.txt", 0444)
39 self.touch(d, "a/b/3.txt", 0)
40 self.mkdir(d, "a/c")
41 self.touch(d, "a/c/1.txt")
42 self.touch(d, "a/c/2.txt", 0444)
43 self.touch(d, "a/c/3.txt", 0)
44 os.chmod(os.path.join(d, "a/c"), 0444)
45 self.mkdir(d, "a/d")
46 self.touch(d, "a/d/1.txt")
47 self.touch(d, "a/d/2.txt", 0444)
48 self.touch(d, "a/d/3.txt", 0)
49 os.chmod(os.path.join(d, "a/d"), 0)
50
51 commands.rmdirRecursive(d)
52 self.failIf(os.path.exists(d))
53
54
55 class ShellBase(SignalMixin):
56
57 def setUp(self):
58 self.setUpSignalHandler()
59 self.basedir = "test_slavecommand"
60 if not os.path.isdir(self.basedir):
61 os.mkdir(self.basedir)
62 self.subdir = os.path.join(self.basedir, "subdir")
63 if not os.path.isdir(self.subdir):
64 os.mkdir(self.subdir)
65 self.builder = FakeSlaveBuilder(self.usePTY, self.basedir)
66 self.emitcmd = util.sibpath(__file__, "emit.py")
67 self.subemitcmd = os.path.join(util.sibpath(__file__, "subdir"),
68 "emit.py")
69 self.sleepcmd = util.sibpath(__file__, "sleep.py")
70
71 def tearDown(self):
72 self.tearDownSignalHandler()
73
74 def failUnlessIn(self, substring, string):
75 self.failUnless(string.find(substring) != -1,
76 "'%s' not in '%s'" % (substring, string))
77
78 def getfile(self, which):
79 got = ""
80 for r in self.builder.updates:
81 if r.has_key(which):
82 got += r[which]
83 return got
84
85 def checkOutput(self, expected):
86 """
87 @type expected: list of (streamname, contents) tuples
88 @param expected: the expected output
89 """
90 expected_linesep = os.linesep
91 if self.usePTY:
92 # PTYs change the line ending. I'm not sure why.
93 expected_linesep = "\r\n"
94 expected = [(stream, contents.replace("\n", expected_linesep, 1000))
95 for (stream, contents) in expected]
96 if self.usePTY:
97 # PTYs merge stdout+stderr into a single stream
98 expected = [('stdout', contents)
99 for (stream, contents) in expected]
100 # now merge everything into one string per stream
101 streams = {}
102 for (stream, contents) in expected:
103 streams[stream] = streams.get(stream, "") + contents
104 for (stream, contents) in streams.items():
105 got = self.getfile(stream)
106 self.assertEquals(got, contents)
107
108 def getrc(self):
109 # updates[-2] is the rc, unless the step was interrupted
110 # updates[-1] is the elapsed-time header
111 u = self.builder.updates[-1]
112 if "rc" not in u:
113 self.failUnless(len(self.builder.updates) >= 2)
114 u = self.builder.updates[-2]
115 self.failUnless("rc" in u)
116 return u['rc']
117 def checkrc(self, expected):
118 got = self.getrc()
119 self.assertEquals(got, expected)
120
121 def testShell1(self):
122 targetfile = os.path.join(self.basedir, "log1.out")
123 if os.path.exists(targetfile):
124 os.unlink(targetfile)
125 cmd = "%s %s 0" % (sys.executable, self.emitcmd)
126 args = {'command': cmd, 'workdir': '.', 'timeout': 60}
127 c = SlaveShellCommand(self.builder, None, args)
128 d = c.start()
129 expected = [('stdout', "this is stdout\n"),
130 ('stderr', "this is stderr\n")]
131 d.addCallback(self._checkPass, expected, 0)
132 def _check_targetfile(res):
133 self.failUnless(os.path.exists(targetfile))
134 d.addCallback(_check_targetfile)
135 return d
136
137 def _checkPass(self, res, expected, rc):
138 self.checkOutput(expected)
139 self.checkrc(rc)
140
141 def testShell2(self):
142 cmd = [sys.executable, self.emitcmd, "0"]
143 args = {'command': cmd, 'workdir': '.', 'timeout': 60}
144 c = SlaveShellCommand(self.builder, None, args)
145 d = c.start()
146 expected = [('stdout', "this is stdout\n"),
147 ('stderr', "this is stderr\n")]
148 d.addCallback(self._checkPass, expected, 0)
149 return d
150
151 def testShellRC(self):
152 cmd = [sys.executable, self.emitcmd, "1"]
153 args = {'command': cmd, 'workdir': '.', 'timeout': 60}
154 c = SlaveShellCommand(self.builder, None, args)
155 d = c.start()
156 expected = [('stdout', "this is stdout\n"),
157 ('stderr', "this is stderr\n")]
158 d.addCallback(self._checkPass, expected, 1)
159 return d
160
161 def testShellEnv(self):
162 cmd = "%s %s 0" % (sys.executable, self.emitcmd)
163 args = {'command': cmd, 'workdir': '.',
164 'env': {'EMIT_TEST': "envtest"}, 'timeout': 60}
165 c = SlaveShellCommand(self.builder, None, args)
166 d = c.start()
167 expected = [('stdout', "this is stdout\n"),
168 ('stderr', "this is stderr\n"),
169 ('stdout', "EMIT_TEST: envtest\n"),
170 ]
171 d.addCallback(self._checkPass, expected, 0)
172 return d
173
174 def testShellSubdir(self):
175 targetfile = os.path.join(self.basedir, "subdir", "log1.out")
176 if os.path.exists(targetfile):
177 os.unlink(targetfile)
178 cmd = "%s %s 0" % (sys.executable, self.subemitcmd)
179 args = {'command': cmd, 'workdir': "subdir", 'timeout': 60}
180 c = SlaveShellCommand(self.builder, None, args)
181 d = c.start()
182 expected = [('stdout', "this is stdout in subdir\n"),
183 ('stderr', "this is stderr\n")]
184 d.addCallback(self._checkPass, expected, 0)
185 def _check_targetfile(res):
186 self.failUnless(os.path.exists(targetfile))
187 d.addCallback(_check_targetfile)
188 return d
189
190 def testShellMissingCommand(self):
191 args = {'command': "/bin/EndWorldHungerAndMakePigsFly",
192 'workdir': '.', 'timeout': 10,
193 'env': {"LC_ALL": "C"},
194 }
195 c = SlaveShellCommand(self.builder, None, args)
196 d = c.start()
197 d.addCallback(self._testShellMissingCommand_1)
198 return d
199 def _testShellMissingCommand_1(self, res):
200 self.failIfEqual(self.getrc(), 0)
201 # we used to check the error message to make sure it said something
202 # about a missing command, but there are a variety of shells out
203 # there, and they emit message sin a variety of languages, so we
204 # stopped trying.
205
206 def testTimeout(self):
207 args = {'command': [sys.executable, self.sleepcmd, "10"],
208 'workdir': '.', 'timeout': 2}
209 c = SlaveShellCommand(self.builder, None, args)
210 d = c.start()
211 d.addCallback(self._testTimeout_1)
212 return d
213 def _testTimeout_1(self, res):
214 self.failIfEqual(self.getrc(), 0)
215 got = self.getfile('header')
216 self.failUnlessIn("command timed out: 2 seconds without output", got)
217 if runtime.platformType == "posix":
218 # the "killing pid" message is not present in windows
219 self.failUnlessIn("killing pid", got)
220 # but the process *ought* to be killed somehow
221 self.failUnlessIn("process killed by signal", got)
222 #print got
223 if runtime.platformType != 'posix':
224 testTimeout.todo = "timeout doesn't appear to work under windows"
225
226 def testInterrupt1(self):
227 args = {'command': [sys.executable, self.sleepcmd, "10"],
228 'workdir': '.', 'timeout': 20}
229 c = SlaveShellCommand(self.builder, None, args)
230 d = c.start()
231 reactor.callLater(1, c.interrupt)
232 d.addCallback(self._testInterrupt1_1)
233 return d
234 def _testInterrupt1_1(self, res):
235 self.failIfEqual(self.getrc(), 0)
236 got = self.getfile('header')
237 self.failUnlessIn("command interrupted", got)
238 if runtime.platformType == "posix":
239 self.failUnlessIn("process killed by signal", got)
240 if runtime.platformType != 'posix':
241 testInterrupt1.todo = "interrupt doesn't appear to work under windows"
242
243
244 # todo: twisted-specific command tests
245
246 class Shell(ShellBase, unittest.TestCase):
247 usePTY = False
248
249 def testInterrupt2(self):
250 # test the backup timeout. This doesn't work under a PTY, because the
251 # transport.loseConnection we do in the timeout handler actually
252 # *does* kill the process.
253 args = {'command': [sys.executable, self.sleepcmd, "5"],
254 'workdir': '.', 'timeout': 20}
255 c = SlaveShellCommand(self.builder, None, args)
256 d = c.start()
257 c.command.BACKUP_TIMEOUT = 1
258 # make it unable to kill the child, by changing the signal it uses
259 # from SIGKILL to the do-nothing signal 0.
260 c.command.KILL = None
261 reactor.callLater(1, c.interrupt)
262 d.addBoth(self._testInterrupt2_1)
263 return d
264 def _testInterrupt2_1(self, res):
265 # the slave should raise a TimeoutError exception. In a normal build
266 # process (i.e. one that uses step.RemoteShellCommand), this
267 # exception will be handed to the Step, which will acquire an ERROR
268 # status. In our test environment, it isn't such a big deal.
269 self.failUnless(isinstance(res, failure.Failure),
270 "res is not a Failure: %s" % (res,))
271 self.failUnless(res.check(commands.TimeoutError))
272 self.checkrc(-1)
273 return
274 # the command is still actually running. Start another command, to
275 # make sure that a) the old command's output doesn't interfere with
276 # the new one, and b) the old command's actual termination doesn't
277 # break anything
278 args = {'command': [sys.executable, self.sleepcmd, "5"],
279 'workdir': '.', 'timeout': 20}
280 c = SlaveShellCommand(self.builder, None, args)
281 d = c.start()
282 d.addCallback(self._testInterrupt2_2)
283 return d
284 def _testInterrupt2_2(self, res):
285 self.checkrc(0)
286 # N.B.: under windows, the trial process hangs out for another few
287 # seconds. I assume that the win32eventreactor is waiting for one of
288 # the lingering child processes to really finish.
289
290 haveProcess = interfaces.IReactorProcess(reactor, None)
291 if runtime.platformType == 'posix':
292 # test with PTYs also
293 class ShellPTY(ShellBase, unittest.TestCase):
294 usePTY = True
295 if not haveProcess:
296 ShellPTY.skip = "this reactor doesn't support IReactorProcess"
297 if not haveProcess:
298 Shell.skip = "this reactor doesn't support IReactorProcess"
OLDNEW
« no previous file with comments | « third_party/buildbot_7_12/buildbot/test/test_shell.py ('k') | third_party/buildbot_7_12/buildbot/test/test_slaves.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698