3 # test step.ShellCommand and the slave-side commands.ShellCommand
6 from twisted
.trial
import unittest
7 from twisted
.internet
import reactor
, defer
8 from twisted
.python
import util
9 from buildbot
.slave
.commands
import SlaveShellCommand
10 from buildbot
.test
.runutils
import SlaveCommandTestBase
12 class SlaveSide(SlaveCommandTestBase
, unittest
.TestCase
):
14 self
.setUpBuilder("test_shell.testOne")
15 emitcmd
= util
.sibpath(__file__
, "emit.py")
17 'command': [sys
.executable
, emitcmd
, "0"],
20 d
= self
.startCommand(SlaveShellCommand
, args
)
21 d
.addCallback(self
.collectUpdates
)
23 self
.failUnlessEqual(logs
['stdout'], "this is stdout\n")
24 self
.failUnlessEqual(logs
['stderr'], "this is stderr\n")
28 # TODO: move test_slavecommand.Shell and .ShellPTY over here
30 def _generateText(self
, filename
):
33 lines
.append("this is %s %d\n" % (filename
, i
))
36 def testLogFiles_0(self
):
37 return self
._testLogFiles
(0)
39 def testLogFiles_1(self
):
40 return self
._testLogFiles
(1)
42 def testLogFiles_2(self
):
43 return self
._testLogFiles
(2)
45 def testLogFiles_3(self
):
46 return self
._testLogFiles
(3)
48 def _testLogFiles(self
, mode
):
49 basedir
= "test_shell.testLogFiles"
50 self
.setUpBuilder(basedir
)
51 # emitlogs.py writes two lines to stdout and two logfiles, one second
52 # apart. Then it waits for us to write something to stdin, then it
53 # writes one more line.
56 # we write something to the log file first, to exercise the logic
57 # that distinguishes between the old file and the one as modified
58 # by the ShellCommand. We set the timestamp back 5 seconds so
59 # that timestamps can be used to distinguish old from new.
60 log2file
= os
.path
.join(basedir
, "log2.out")
61 f
= open(log2file
, "w")
62 f
.write("dummy text\n")
64 earlier
= time
.time() - 5
65 os
.utime(log2file
, (earlier
, earlier
))
68 # mode=3 doesn't create the old logfiles in the first place, but
69 # then behaves like mode=1 (where the command pauses before
73 # mode=1 will cause emitlogs.py to delete the old logfiles first, and
74 # then wait two seconds before creating the new files. mode=0 does
77 'command': [sys
.executable
,
78 util
.sibpath(__file__
, "emitlogs.py"),
81 'logfiles': {"log2": "log2.out",
83 'keep_stdin_open': True,
85 finishd
= self
.startCommand(SlaveShellCommand
, args
)
86 # The first batch of lines is written immediately. The second is
87 # written after a pause of one second. We poll once per second until
88 # we see both batches.
90 self
._check
_timeout
= 10
91 d
= self
._check
_and
_wait
()
92 def _wait_for_finish(res
, finishd
):
94 d
.addCallback(_wait_for_finish
, finishd
)
95 d
.addCallback(self
.collectUpdates
)
97 self
.failUnlessEqual(logs
['stdout'], self
._generateText
("stdout"))
99 self
.failIf(('log','log2') in logs
)
100 self
.failIf(('log','log3') in logs
)
102 self
.failUnlessEqual(logs
[('log','log2')],
103 self
._generateText
("log2"))
104 self
.failUnlessEqual(logs
[('log','log3')],
105 self
._generateText
("log3"))
106 d
.addCallback(_check
)
107 d
.addBoth(self
._maybePrintError
)
110 def _check_and_wait(self
, res
=None):
111 self
._check
_timeout
-= 1
112 if self
._check
_timeout
<= 0:
113 raise defer
.TimeoutError("gave up on command")
114 logs
= self
.collectUpdates()
115 if logs
.get('stdout') == "this is stdout 0\nthis is stdout 1\n":
116 # the emitlogs.py process is now waiting for something to arrive
118 self
.cmd
.command
.pp
.transport
.write("poke\n")
120 if not self
.cmd
.running
:
121 self
.fail("command finished too early")
122 spin
= defer
.Deferred()
123 spin
.addCallback(self
._check
_and
_wait
)
124 reactor
.callLater(1, spin
.callback
, None)
127 def _maybePrintError(self
, res
):
130 print "Command ended with rc=%s" % rc
135 # MAYBE TODO: a command which appends to an existing logfile should
136 # result in only the new text being sent up to the master. I need to
137 # think about this more first.