def test_metaDescriptorInheritance(self): """ If a L{TwistdSlaveProcess} specifies a meta-file-descriptor to be inherited, it should be inherited by the subprocess, and a configuration argument should be passed that indicates to the subprocess. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) # Most arguments here will be ignored, so these are bogus values. slave = TwistdSlaveProcess( twistd="bleh", tapname="caldav", configFile="/does/not/exist", id=10, interfaces="127.0.0.1", metaSocket=FakeDispatcher().addSocket(), ) dspm.addProcessObject(slave, {}) dspm.startService() oneProcessTransport = imps.waitForOneProcess() self.assertIn("MetaFD=4", oneProcessTransport.args) self.assertEquals( oneProcessTransport.args[oneProcessTransport.args.index("MetaFD=4") - 1], "-o", "MetaFD argument was not passed as an option", ) self.assertEquals(oneProcessTransport.childFDs, {0: "w", 1: "r", 2: "r", 4: 4})
def test_acceptDescriptorInheritance(self): """ If a L{TwistdSlaveProcess} specifies some file descriptors to be inherited, they should be inherited by the subprocess. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) # Most arguments here will be ignored, so these are bogus values. slave = TwistdSlaveProcess( twistd="bleh", tapname="caldav", configFile="/does/not/exist", id=10, interfaces="127.0.0.1", inheritFDs=[3, 7], inheritSSLFDs=[19, 25], ) dspm.addProcessObject(slave, {}) dspm.startService() # We can easily stub out spawnProcess, because caldav calls it, but a # bunch of callLater calls are buried in procmon itself, so we need to # use the real clock. oneProcessTransport = imps.waitForOneProcess() self.assertEquals(oneProcessTransport.childFDs, {0: "w", 1: "r", 2: "r", 3: 3, 7: 7, 19: 19, 25: 25})
def test_lineAfterLongLine(self): """ A "long" line of output from a monitored process (longer than L{LineReceiver.MAX_LENGTH}) should be logged in chunks rather than all at once, to avoid resource exhaustion. """ dspm = DelayedStartupProcessMonitor() dspm.addProcessObject( ScriptProcessObject( 'longlines.py', str(DelayedStartupLineLogger.MAX_LENGTH) ), os.environ ) dspm.startService() self.addCleanup(dspm.stopService) logged = [] def tempObserver(event): # Probably won't be a problem, but let's not have any intermittent # test issues that stem from multi-threaded log messages randomly # going off... if not isInIOThread(): callFromThread(tempObserver, event) return if event.get('isError'): d.errback() m = event.get('message')[0] if m.startswith('[Dummy] '): logged.append(event) if m == '[Dummy] z': d.callback("done") logging.addObserver(tempObserver) self.addCleanup(logging.removeObserver, tempObserver) d = Deferred() def assertions(result): self.assertEquals(["[Dummy] x", "[Dummy] y", "[Dummy] y", # final segment "[Dummy] z"], [''.join(evt['message'])[:len('[Dummy]') + 2] for evt in logged]) self.assertEquals([" (truncated, continued)", " (truncated, continued)", "[Dummy] y", "[Dummy] z"], [''.join(evt['message'])[-len(" (truncated, continued)"):] for evt in logged]) d.addCallback(assertions) return d
def test_changedArgumentEachSpawn(self): """ If the result of C{getCommandLine} changes on subsequent calls, subsequent calls should result in different arguments being passed to C{spawnProcess} each time. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) slave = DummyProcessObject("scriptname", "first") dspm.addProcessObject(slave, {}) dspm.startService() oneProcessTransport = imps.waitForOneProcess() self.assertEquals(oneProcessTransport.args, ["scriptname", "first"]) slave.args = ["second"] oneProcessTransport.processProtocol.processEnded(None) twoProcessTransport = imps.waitForOneProcess() self.assertEquals(twoProcessTransport.args, ["scriptname", "second"])
def test_startServiceDelay(self): """ Starting a L{DelayedStartupProcessMonitor} should result in the process objects that have been added to it being started once per delayInterval. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) dspm.delayInterval = 3.0 sampleCounter = range(0, 5) for counter in sampleCounter: slave = TwistdSlaveProcess(twistd="bleh", tapname="caldav", configFile="/does/not/exist", id=counter * 10, interfaces='127.0.0.1', metaSocket=FakeDispatcher().addSocket()) dspm.addProcessObject(slave, {"SAMPLE_ENV_COUNTER": str(counter)}) dspm.startService() # Advance the clock a bunch of times, allowing us to time things with a # comprehensible resolution. imps.pump([0] + [dspm.delayInterval / 2.0] * len(sampleCounter) * 3) expectedValues = [dspm.delayInterval * n for n in sampleCounter] self.assertEquals([x.startedAt for x in imps.processTransports], expectedValues)
def test_startServiceDelay(self): """ Starting a L{DelayedStartupProcessMonitor} should result in the process objects that have been added to it being started once per delayInterval. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) dspm.delayInterval = 3.0 sampleCounter = range(0, 5) for counter in sampleCounter: slave = TwistdSlaveProcess( twistd="bleh", tapname="caldav", configFile="/does/not/exist", id=counter * 10, interfaces="127.0.0.1", metaSocket=FakeDispatcher().addSocket(), ) dspm.addProcessObject(slave, {"SAMPLE_ENV_COUNTER": str(counter)}) dspm.startService() # Advance the clock a bunch of times, allowing us to time things with a # comprehensible resolution. imps.pump([0] + [dspm.delayInterval / 2.0] * len(sampleCounter) * 3) expectedValues = [dspm.delayInterval * n for n in sampleCounter] self.assertEquals([x.startedAt for x in imps.processTransports], expectedValues)
def test_metaDescriptorInheritance(self): """ If a L{TwistdSlaveProcess} specifies a meta-file-descriptor to be inherited, it should be inherited by the subprocess, and a configuration argument should be passed that indicates to the subprocess. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) # Most arguments here will be ignored, so these are bogus values. slave = TwistdSlaveProcess(twistd="bleh", tapname="caldav", configFile="/does/not/exist", id=10, interfaces='127.0.0.1', metaSocket=FakeDispatcher().addSocket()) dspm.addProcessObject(slave, {}) dspm.startService() oneProcessTransport = imps.waitForOneProcess() self.assertIn("MetaFD=4", oneProcessTransport.args) self.assertEquals( oneProcessTransport.args[oneProcessTransport.args.index("MetaFD=4") - 1], '-o', "MetaFD argument was not passed as an option") self.assertEquals(oneProcessTransport.childFDs, { 0: 'w', 1: 'r', 2: 'r', 4: 4 })
def test_acceptDescriptorInheritance(self): """ If a L{TwistdSlaveProcess} specifies some file descriptors to be inherited, they should be inherited by the subprocess. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) # Most arguments here will be ignored, so these are bogus values. slave = TwistdSlaveProcess( twistd="bleh", tapname="caldav", configFile="/does/not/exist", id=10, interfaces='127.0.0.1', inheritFDs=[3, 7], inheritSSLFDs=[19, 25], ) dspm.addProcessObject(slave, {}) dspm.startService() # We can easily stub out spawnProcess, because caldav calls it, but a # bunch of callLater calls are buried in procmon itself, so we need to # use the real clock. oneProcessTransport = imps.waitForOneProcess() self.assertEquals(oneProcessTransport.childFDs, { 0: 'w', 1: 'r', 2: 'r', 3: 3, 7: 7, 19: 19, 25: 25 })
def test_lineAfterLongLine(self): """ A "long" line of output from a monitored process (longer than L{LineReceiver.MAX_LENGTH}) should be logged in chunks rather than all at once, to avoid resource exhaustion. """ dspm = DelayedStartupProcessMonitor() dspm.addProcessObject( ScriptProcessObject('longlines.py', str(DelayedStartupLineLogger.MAX_LENGTH)), os.environ) dspm.startService() self.addCleanup(dspm.stopService) logged = [] def tempObserver(event): # Probably won't be a problem, but let's not have any intermittent # test issues that stem from multi-threaded log messages randomly # going off... if not isInIOThread(): callFromThread(tempObserver, event) return if event.get('isError'): d.errback() m = event.get('message')[0] if m.startswith('[Dummy] '): logged.append(event) if m == '[Dummy] z': d.callback("done") logging.addObserver(tempObserver) self.addCleanup(logging.removeObserver, tempObserver) d = Deferred() def assertions(result): self.assertEquals( [ "[Dummy] x", "[Dummy] y", "[Dummy] y", # final segment "[Dummy] z" ], [ ''.join(evt['message'])[:len('[Dummy]') + 2] for evt in logged ]) self.assertEquals([ " (truncated, continued)", " (truncated, continued)", "[Dummy] y", "[Dummy] z" ], [ ''.join(evt['message'])[-len(" (truncated, continued)"):] for evt in logged ]) d.addCallback(assertions) return d
def test_changedArgumentEachSpawn(self): """ If the result of C{getCommandLine} changes on subsequent calls, subsequent calls should result in different arguments being passed to C{spawnProcess} each time. """ imps = InMemoryProcessSpawner() dspm = DelayedStartupProcessMonitor(imps) slave = DummyProcessObject('scriptname', 'first') dspm.addProcessObject(slave, {}) dspm.startService() oneProcessTransport = imps.waitForOneProcess() self.assertEquals(oneProcessTransport.args, ['scriptname', 'first']) slave.args = ['second'] oneProcessTransport.processProtocol.processEnded(None) twoProcessTransport = imps.waitForOneProcess() self.assertEquals(twoProcessTransport.args, ['scriptname', 'second'])
def test_metaDescriptorInheritance(self): """ If a L{TwistdSlaveProcess} specifies a meta-file-descriptor to be inherited, it should be inherited by the subprocess, and a configuration argument should be passed that indicates to the subprocess. """ dspm = DelayedStartupProcessMonitor() dspm.reactor = InMemoryProcessSpawner() class FakeFD: def __init__(self, n): self.fd = n def fileno(self): return self.fd class FakeDispatcher: n = 3 def addSocket(self): self.n += 1 return FakeFD(self.n) # Most arguments here will be ignored, so these are bogus values. slave = TwistdSlaveProcess( twistd = "bleh", tapname = "caldav", configFile = "/does/not/exist", id = 10, interfaces = '127.0.0.1', metaSocket = FakeDispatcher().addSocket() ) dspm.addProcessObject(slave, {}) dspm.startService() self.addCleanup(dspm.consistency.cancel) oneProcessTransport = yield dspm.reactor.waitForOneProcess() self.assertIn("MetaFD=4", oneProcessTransport.args) self.assertEquals( oneProcessTransport.args[oneProcessTransport.args.index("MetaFD=4")-1], '-o', "MetaFD argument was not passed as an option" ) self.assertEquals(oneProcessTransport.childFDs, {0: 'w', 1: 'r', 2: 'r', 4: 4})