def testSendBuffered(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) s._addToBuffers('stdout', 'hello ') s._addToBuffers('stdout', 'world') s._sendBuffers() self.assertEqual(b.updates, [{'stdout': 'hello world'}], b.show())
def testStderr(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stderrCommand("hello"), self.basedir) yield s.start() self.failIf({'stderr': nl('hello\n')} not in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testStart(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) yield s.start() self.assertTrue({'stdout': nl('hello\n')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testStringCommand(self): b = FakeWorkerForBuilder(self.basedir) # careful! This command must execute the same on windows and UNIX s = runprocess.RunProcess(b, 'echo hello', self.basedir) yield s.start() self.assertTrue({'stdout': nl('hello\n')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testInitialStdinUnicode(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess( b, catCommand(), self.basedir, initialStdin=u'hello') yield s.start() self.assertTrue({'stdout': nl('hello')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testKeepStderr(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess( b, stderrCommand("hello"), self.basedir, keepStderr=True) yield s.start() self.assertTrue({'stderr': nl('hello\n')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show()) self.assertEqual(s.stderr, nl('hello\n'))
def test_stdin_closed(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, scriptCommand('assert_stdin_closed'), self.basedir, # if usePTY=True, stdin is never closed usePTY=False, logEnviron=False) yield s.start() self.assertTrue({'rc': 0} in b.updates, b.show())
def testPipeString(self): b = FakeWorkerForBuilder(self.basedir) # this is highly contrived, but it proves the point. cmd = sys.executable + \ ' -c "import sys; sys.stdout.write(\'b\\na\\n\')" | sort' s = runprocess.RunProcess(b, cmd, self.basedir) yield s.start() self.assertTrue({'stdout': nl('a\nb\n')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testMultiWordStringCommand(self): b = FakeWorkerForBuilder(self.basedir) # careful! This command must execute the same on windows and UNIX s = runprocess.RunProcess(b, 'echo Happy Days and Jubilation', self.basedir) # no quoting occurs exp = nl('Happy Days and Jubilation\n') yield s.start() self.assertTrue({'stdout': exp} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testCommandMaxTime(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, sleepCommand(10), self.basedir, maxTime=5) clock = task.Clock() s._reactor = clock d = s.start() clock.advance(6) # should knock out maxTime yield d self.assertTrue( {'stdout': nl('hello\n')} not in b.updates, b.show()) self.assertTrue({'rc': FATAL_RC} in b.updates, b.show())
def test_startCommand_exception(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, ['whatever'], self.basedir) # set up to cause an exception in _startCommand def _startCommand(*args, **kwargs): raise RuntimeError('error message') s._startCommand = _startCommand try: yield s.start() except AbandonChain: pass stderr = [] # Here we're checking that the exception starting up the command # actually gets propagated back to the master in stderr. for u in b.updates: if 'stderr' in u: stderr.append(u['stderr']) stderr = ''.join(stderr) self.assertTrue( stderr.startswith( 'error in RunProcess._startCommand (error message)')) yield self.flushLoggedErrors()
def testEnvironInt(self): b = FakeWorkerForBuilder(self.basedir) with self.assertRaises(RuntimeError): runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"BUILD_NUMBER": 13})
def testMultiWordStringCommandQuotes(self): b = FakeWorkerForBuilder(self.basedir) # careful! This command must execute the same on windows and UNIX s = runprocess.RunProcess(b, 'echo "Happy Days and Jubilation"', self.basedir) if runtime.platformType == "win32": # echo doesn't parse out the quotes, so they come through in the # output exp = nl('"Happy Days and Jubilation"\n') else: exp = nl('Happy Days and Jubilation\n') yield s.start() self.assertTrue({'stdout': exp} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testObfuscatedCommand(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, [('obfuscated', 'abcd', 'ABCD')], self.basedir) self.assertEqual(s.command, [b'abcd']) self.assertEqual(s.fake_command, [b'ABCD'])
def _test_spawnAsBatch(self, cmd, comspec): def spawnProcess(processProtocol, executable, args=(), env=None, path=None, uid=None, gid=None, usePTY=False, childFDs=None): self.assertTrue(args[0].lower().endswith("cmd.exe"), "{0} is not cmd.exe".format(args[0])) self.patch(runprocess.reactor, "spawnProcess", spawnProcess) tempEnviron = os.environ.copy() if 'COMSPEC' not in tempEnviron: tempEnviron['COMSPEC'] = comspec self.patch(os, "environ", tempEnviron) b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, cmd, self.basedir) s.pp = runprocess.RunProcessPP(s) s.deferred = defer.Deferred() d = s._spawnAsBatch(s.pp, s.command, "args", tempEnviron, "path", False) return d
def testEnvironExpandVar(self): b = FakeWorkerForBuilder(self.basedir) environ = { "EXPND": "-${PATH}-", "DOESNT_EXPAND": "-${---}-", "DOESNT_FIND": "-${DOESNT_EXISTS}-" } s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ=environ) d = s.start() def check(ign): headers = "".join([ list(update.values())[0] for update in b.updates if list(update) == ["header"] ]) self.assertTrue("EXPND=-$" not in headers, "got:\n" + headers) self.assertTrue("DOESNT_FIND=--" in headers, "got:\n" + headers) self.assertTrue("DOESNT_EXPAND=-${---}-" in headers, "got:\n" + headers) d.addCallback(check) return d
def test_incrementalDecoder(self): b = FakeWorkerForBuilder(self.basedir) b.unicode_encoding = "utf-8" s = runprocess.RunProcess( b, stderrCommand("hello"), self.basedir, sendStderr=True) pp = runprocess.RunProcessPP(s) # u"\N{SNOWMAN} when encoded to utf-8 bytes is b"\xe2\x98\x83" pp.outReceived(b"\xe2") pp.outReceived(b"\x98\x83") pp.errReceived(b"\xe2") pp.errReceived(b"\x98\x83") yield s.start() self.assertTrue({'stderr': u"\N{SNOWMAN}"} in b.updates) self.assertTrue({'stdout': u"\N{SNOWMAN}"} in b.updates) self.assertTrue({'rc': 0} in b.updates, b.show())
def test_startCommand_exception(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, ['whatever'], self.basedir) # set up to cause an exception in _startCommand def _startCommand(*args, **kwargs): raise RuntimeError() s._startCommand = _startCommand d = s.start() def check(err): err.trap(AbandonChain) stderr = [] # Here we're checking that the exception starting up the command # actually gets propagated back to the master in stderr. for u in b.updates: if 'stderr' in u: stderr.append(u['stderr']) stderr = "".join(stderr) self.assertTrue("RuntimeError" in stderr, stderr) d.addBoth(check) d.addBoth(lambda _: self.flushLoggedErrors()) return d
def testCommandEncodingObfuscated(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, [bsutil.Obfuscated(u'abcd', u'ABCD')], self.basedir) self.assertIsInstance(s.command[0], bytes) self.assertIsInstance(s.fake_command[0], bytes)
def test_simple(self, interruptSignal=None): # test a simple process that just sleeps waiting to die pidfile = self.newPidfile() self.pid = None b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, scriptCommand( 'write_pidfile_and_sleep', pidfile), self.basedir) if interruptSignal is not None: s.interruptSignal = interruptSignal runproc_d = s.start() pidfile_d = self.waitForPidfile(pidfile) def check_alive(pid): self.pid = pid # for use in check_dead # test that the process is still alive self.assertAlive(pid) # and tell the RunProcess object to kill it s.kill("diaf") pidfile_d.addCallback(check_alive) def check_dead(_): self.assertDead(self.pid) runproc_d.addCallback(check_dead) return defer.gatherResults([pidfile_d, runproc_d])
def testSendChunked(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) data = "x" * int(runprocess.RunProcess.CHUNK_LIMIT * 3 / 2) s._addToBuffers('stdout', data) s._sendBuffers() self.assertEqual(len(b.updates), 2)
def testInvalidUTF8(self): b = FakeWorkerForBuilder(self.basedir) b.unicode_encoding = "utf-8" s = runprocess.RunProcess(b, stderrCommand("hello"), self.basedir, sendStderr=True) pp = runprocess.RunProcessPP(s) INVALID_UTF8 = b"\xff" with self.assertRaises(UnicodeDecodeError): INVALID_UTF8.decode('utf-8') pp.outReceived(INVALID_UTF8) yield s.start() stdout = [up['stdout'] for up in b.updates if 'stdout' in up][0] # On Python < 2.7 bytes is used, on Python >= 2.7 unicode self.assertIn(stdout, (b'\xef\xbf\xbd', u'\ufffd')) self.assertTrue({'rc': 0} in b.updates, b.show())
def testSendLog(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) s._addToBuffers(('log', 'stdout'), 'hello ') s._sendBuffers() self.assertEqual(b.updates, [ {'log': ('stdout', 'hello ')}, ])
def testTrickyArguments(self): # make sure non-trivial arguments are passed verbatim b = FakeWorkerForBuilder(self.basedir) args = [ 'Happy Days and Jubilation', # spaces r'''!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~''', # special characters '%PATH%', # Windows variable expansions # Expansions get an argument of their own, because the Windows # shell doesn't treat % as special unless it surrounds a # variable name. ] s = runprocess.RunProcess(b, printArgsCommand() + args, self.basedir) yield s.start() self.assertTrue({'stdout': nl(repr(args))} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show())
def testNoLogEnviron(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"FOO": "BAR"}, logEnviron=False) yield s.start() headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.assertTrue("FOO=BAR" not in headers, "got:\n" + headers)
def testStderr(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess(b, stderrCommand("hello"), self.basedir) d = s.start() def check(ign): self.failIf({'stderr': nl('hello\n')} not in b.updates, b.show()) self.failUnless({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testEnvironArray(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"FOO": ['a', 'b']}) yield s.start() headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.assertFalse(re.match('\bFOO=a{0}b\b'.format(os.pathsep), headers), "got:\n" + headers)
def testEnvironPythonPath(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"PYTHONPATH": 'a'}) yield s.start() headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.assertFalse(re.match('\bPYTHONPATH=a{0}'.format(os.pathsep), headers), "got:\n" + headers)
def testUnsetEnvironVar(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"PATH": None}) yield s.start() headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.assertFalse( re.match('\bPATH=', headers), "got:\n" + headers)
def testStart(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) d = s.start() def check(ign): self.assertTrue({'stdout': nl('hello\n')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testNoStdout(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess( b, stdoutCommand('hello'), self.basedir, sendStdout=False) d = s.start() def check(ign): self.failIf({'stdout': nl('hello\n')} in b.updates, b.show()) self.failUnless({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testStringCommand(self): b = FakeWorkerForBuilder(False, self.basedir) # careful! This command must execute the same on windows and UNIX s = runprocess.RunProcess(b, 'echo hello', self.basedir) d = s.start() def check(ign): self.failUnless({'stdout': nl('hello\n')} in b.updates, b.show()) self.failUnless({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testSendBufferedInterleaved(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) s._addToBuffers('stdout', 'hello ') s._addToBuffers('stderr', 'DIEEEEEEE') s._addToBuffers('stdout', 'world') s._sendBuffers() self.assertEqual(b.updates, [ {'stdout': 'hello '}, {'stderr': 'DIEEEEEEE'}, {'stdout': 'world'}, ])
def testInitialStdinUnicode(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess( b, catCommand(), self.basedir, initialStdin=u'hello') d = s.start() def check(ign): self.failUnless({'stdout': nl('hello')} in b.updates, b.show()) self.failUnless({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testKeepStderr(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess( b, stderrCommand("hello"), self.basedir, keepStderr=True) d = s.start() def check(ign): self.assertTrue({'stderr': nl('hello\n')} in b.updates, b.show()) self.assertTrue({'rc': 0} in b.updates, b.show()) self.assertEqual(s.stderr, nl('hello\n')) d.addCallback(check) return d
def testNoLogEnviron(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"FOO": "BAR"}, logEnviron=False) d = s.start() def check(ign): headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.failUnless("FOO=BAR" not in headers, "got:\n" + headers) d.addCallback(check) return d
def test_stdin_closed(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess(b, scriptCommand('assert_stdin_closed'), self.basedir, # if usePTY=True, stdin is never closed usePTY=False, logEnviron=False) d = s.start() def check(ign): self.failUnless({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testUnsetEnvironVar(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"PATH": None}) d = s.start() def check(ign): headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.failUnless( not re.match('\bPATH=', headers), "got:\n" + headers) d.addCallback(check) return d
def testPipeString(self): b = FakeWorkerForBuilder(False, self.basedir) # this is highly contrived, but it proves the point. cmd = sys.executable + ' -c "import sys; sys.stdout.write(\'b\\na\\n\')" | sort' s = runprocess.RunProcess(b, cmd, self.basedir) d = s.start() def check(ign): self.failUnless({'stdout': nl('a\nb\n')} in b.updates, b.show()) self.failUnless({'rc': 0} in b.updates, b.show()) d.addCallback(check) return d
def testEnvironArray(self): b = FakeWorkerForBuilder(False, self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir, environ={"FOO": ['a', 'b']}) d = s.start() def check(ign): headers = "".join([list(update.values())[0] for update in b.updates if list(update) == ["header"]]) self.failUnless(not re.match('\bFOO=a%sb\b' % (os.pathsep), headers), "got:\n" + headers) d.addCallback(check) return d
def testSendStatus(self): b = FakeWorkerForBuilder(self.basedir) s = runprocess.RunProcess(b, stdoutCommand('hello'), self.basedir) s.sendStatus({'stdout': nl('hello\n')}) self.assertEqual(b.updates, [{'stdout': nl('hello\n')}], b.show())