Esempio n. 1
0
    def _testHook(self, methodName, callerName=None):
        """
        Verify that the named hook is run with the expected arguments as
        specified by the arguments used to create the L{Runner}, when the
        specified caller is invoked.

        @param methodName: The name of the hook to verify.
        @type methodName: L{str}

        @param callerName: The name of the method that is expected to cause the
            hook to be called.
            If C{None}, use the L{Runner} method with the same name as the
            hook.
        @type callerName: L{str}
        """
        if callerName is None:
            callerName = methodName

        arguments = dict(a=object(), b=object(), c=object())
        argumentsSeen = []

        def hook(**arguments):
            argumentsSeen.append(arguments)

        runnerArguments = {
            methodName: hook,
            "{}Arguments".format(methodName): arguments.copy(),
        }
        runner = Runner(reactor=MemoryReactor(), **runnerArguments)

        hookCaller = getattr(runner, callerName)
        hookCaller()

        self.assertEqual(len(argumentsSeen), 1)
        self.assertEqual(argumentsSeen[0], arguments)
Esempio n. 2
0
 def test_memoryReactorProvides(self):
     """
     L{MemoryReactor} provides all of the attributes described by the
     interfaces it advertises.
     """
     memoryReactor = MemoryReactor()
     verifyObject(IReactorTCP, memoryReactor)
     verifyObject(IReactorSSL, memoryReactor)
     verifyObject(IReactorUNIX, memoryReactor)
Esempio n. 3
0
    def test_startReactorWithReactor(self) -> None:
        """
        L{Runner.startReactor} with the C{reactor} argument runs the given
        reactor.
        """
        reactor = MemoryReactor()
        runner = Runner(reactor=reactor)
        runner.startReactor()

        self.assertTrue(reactor.hasRun)
Esempio n. 4
0
    def test_killNotRequested(self) -> None:
        """
        L{Runner.killIfRequested} when C{kill} is false doesn't exit and
        doesn't indiscriminately murder anyone.
        """
        runner = Runner(reactor=MemoryReactor())
        runner.killIfRequested()

        self.assertEqual(self.kill.calls, [])
        self.assertFalse(self.exit.exited)
Esempio n. 5
0
    def test_killRequestedWithPIDFileNotAnInt(self) -> None:
        """
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        containing a non-integer value exits with L{ExitStatus.EX_DATAERR}.
        """
        pidFile = PIDFile(self.filePath(b"** totally not a number, dude **"))
        runner = Runner(reactor=MemoryReactor(), kill=True, pidFile=pidFile)
        runner.killIfRequested()

        self.assertEqual(self.exit.status, ExitStatus.EX_DATAERR)
        self.assertEqual(self.exit.message, "Invalid PID file.")
Esempio n. 6
0
    def test_killRequestedWithPIDFileEmpty(self) -> None:
        """
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        containing no value exits with L{ExitStatus.EX_DATAERR}.
        """
        pidFile = PIDFile(self.filePath(b""))
        runner = Runner(reactor=MemoryReactor(), kill=True, pidFile=pidFile)
        runner.killIfRequested()

        self.assertEqual(self.exit.status, ExitStatus.EX_DATAERR)
        self.assertEqual(self.exit.message, "Invalid PID file.")
Esempio n. 7
0
    def _verify_error(self, config, expected):
        """
        Assert that when ``DaemonizeTheRealService`` is started using the given
        configuration it writes the given message to stderr and stops the
        reactor.

        :param bytes config: The contents of a ``tahoe.cfg`` file to give to
            the service.

        :param bytes expected: A string to assert appears in stderr after the
            service starts.
        """
        nodedir = FilePath(self.mktemp())
        nodedir.makedirs()
        nodedir.child("tahoe.cfg").setContent(config.encode("ascii"))
        nodedir.child("tahoe-client.tac").touch()

        options = parse_options(["run", nodedir.path])
        stdout = options.stdout = StringIO()
        stderr = options.stderr = StringIO()
        run_options = options.subOptions

        reactor = MemoryReactor()
        with AlternateReactor(reactor):
            service = DaemonizeTheRealService(
                "client",
                nodedir.path,
                run_options,
            )
            service.startService()

            # We happen to know that the service uses reactor.callWhenRunning
            # to schedule all its work (though I couldn't tell you *why*).
            # Make sure those scheduled calls happen.
            waiting = reactor.whenRunningHooks[:]
            del reactor.whenRunningHooks[:]
            for f, a, k in waiting:
                f(*a, **k)

        self.assertThat(
            reactor.hasStopped,
            Equals(True),
        )

        self.assertThat(
            stdout.getvalue(),
            Equals(""),
        )

        self.assertThat(
            stderr.getvalue(),
            Contains(expected),
        )
Esempio n. 8
0
    def test_killRequestedWithPIDFile(self) -> None:
        """
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        performs a targeted killing of the appropriate process.
        """
        pidFile = PIDFile(self.filePath(self.pidFileContent))
        runner = Runner(reactor=MemoryReactor(), kill=True, pidFile=pidFile)
        runner.killIfRequested()

        self.assertEqual(self.kill.calls, [(self.pid, SIGTERM)])
        self.assertEqual(self.exit.status, ExitStatus.EX_OK)
        self.assertIdentical(self.exit.message, None)
Esempio n. 9
0
    def test_killRequestedWithoutPIDFile(self) -> None:
        """
        L{Runner.killIfRequested} when C{kill} is true but C{pidFile} is
        L{nonePIDFile} exits with L{ExitStatus.EX_USAGE} and the expected
        message; and also doesn't indiscriminately murder anyone.
        """
        runner = Runner(reactor=MemoryReactor(), kill=True)
        runner.killIfRequested()

        self.assertEqual(self.kill.calls, [])
        self.assertEqual(self.exit.status, ExitStatus.EX_USAGE)
        self.assertEqual(self.exit.message, "No PID file specified.")
Esempio n. 10
0
 def test_listenDefaultHost(self):
     """
     L{MemoryReactor.listenTCP}, L{MemoryReactor.listenSSL} and
     L{MemoryReactor.listenUNIX} will return an L{IListeningPort} whose
     C{getHost} method returns an L{IAddress}; C{listenTCP} and C{listenSSL}
     will have a default host of C{'0.0.0.0'}, and a port that reflects the
     value passed, and C{listenUNIX} will have a name that reflects the path
     passed.
     """
     memoryReactor = MemoryReactor()
     for port in [memoryReactor.listenTCP(8242, Factory()),
                  memoryReactor.listenSSL(8242, Factory(), None)]:
         verifyObject(IListeningPort, port)
         address = port.getHost()
         verifyObject(IAddress, address)
         self.assertEqual(address.host, '0.0.0.0')
         self.assertEqual(address.port, 8242)
     port = memoryReactor.listenUNIX(b"/path/to/socket", Factory())
     verifyObject(IListeningPort, port)
     address = port.getHost()
     verifyObject(IAddress, address)
     self.assertEqual(address.name, b"/path/to/socket")
Esempio n. 11
0
    def test_runInOrder(self):
        """
        L{Runner.run} calls the expected methods in order.
        """
        runner = DummyRunner(reactor=MemoryReactor())
        runner.run()

        self.assertEqual(runner.calledMethods, [
            "killIfRequested",
            "startLogging",
            "startReactor",
            "reactorExited",
        ])
Esempio n. 12
0
 def test_connectDestination(self):
     """
     L{MemoryReactor.connectTCP}, L{MemoryReactor.connectSSL}, and
     L{MemoryReactor.connectUNIX} will return an L{IConnector} whose
     C{getDestination} method returns an L{IAddress} with attributes which
     reflect the values passed.
     """
     memoryReactor = MemoryReactor()
     for connector in [
         memoryReactor.connectTCP("test.example.com", 8321, ClientFactory()),
         memoryReactor.connectSSL("test.example.com", 8321, ClientFactory(), None),
     ]:
         verifyObject(IConnector, connector)
         address = connector.getDestination()
         verifyObject(IAddress, address)
         self.assertEqual(address.host, "test.example.com")
         self.assertEqual(address.port, 8321)
     connector = memoryReactor.connectUNIX(b"/fake/path", ClientFactory())
     verifyObject(IConnector, connector)
     address = connector.getDestination()
     verifyObject(IAddress, address)
     self.assertEqual(address.name, b"/fake/path")
Esempio n. 13
0
    def test_writers(self):
        """
        Adding, removing, and listing writers works.
        """
        writer = object()
        reactor = MemoryReactor()

        reactor.addWriter(writer)
        reactor.addWriter(writer)

        self.assertEqual(reactor.getWriters(), [writer])

        reactor.removeWriter(writer)

        self.assertEqual(reactor.getWriters(), [])
Esempio n. 14
0
    def test_readers(self):
        """
        Adding, removing, and listing readers works.
        """
        reader = object()
        reactor = MemoryReactor()

        reactor.addReader(reader)
        reactor.addReader(reader)

        self.assertEqual(reactor.getReaders(), [reader])

        reactor.removeReader(reader)

        self.assertEqual(reactor.getReaders(), [])
Esempio n. 15
0
    def test_runAlreadyRunning(self) -> None:
        """
        L{Runner.run} exits with L{ExitStatus.EX_USAGE} and the expected
        message if a process is already running that corresponds to the given
        PID file.
        """
        pidFile = PIDFile(self.filePath(self.pidFileContent))
        pidFile.isRunning = lambda: True  # type: ignore[assignment]

        runner = Runner(reactor=MemoryReactor(), pidFile=pidFile)
        runner.run()

        self.assertEqual(self.exit.status, ExitStatus.EX_CONFIG)
        self.assertEqual(self.exit.message, "Already running.")
Esempio n. 16
0
    def test_runUsesPIDFile(self) -> None:
        """
        L{Runner.run} uses the provided PID file.
        """
        pidFile = DummyPIDFile()

        runner = Runner(reactor=MemoryReactor(), pidFile=pidFile)

        self.assertFalse(pidFile.entered)
        self.assertFalse(pidFile.exited)

        runner.run()

        self.assertTrue(pidFile.entered)
        self.assertTrue(pidFile.exited)
Esempio n. 17
0
    def test_killRequestedWithPIDFileCantRead(self) -> None:
        """
        L{Runner.killIfRequested} when C{kill} is true and given a C{pidFile}
        that it can't read exits with L{ExitStatus.EX_IOERR}.
        """
        pidFile = PIDFile(self.filePath(None))

        def read() -> int:
            raise OSError(errno.EACCES, "Permission denied")

        pidFile.read = read  # type: ignore[assignment]

        runner = Runner(reactor=MemoryReactor(), kill=True, pidFile=pidFile)
        runner.killIfRequested()

        self.assertEqual(self.exit.status, ExitStatus.EX_IOERR)
        self.assertEqual(self.exit.message, "Unable to read PID file.")
Esempio n. 18
0
    def setUp(self):
        self.make_httpbin_site_returns = Site(Resource())

        self.serve_tcp_calls = []
        self.serve_tcp_returns = defer.Deferred()

        self.serve_tls_calls = []
        self.serve_tls_returns = defer.Deferred()

        self.output_process_description_calls = []
        self.output_process_description_returns = None

        self.reactor = MemoryReactor()

        self.forever_httpbin = functools.partial(
            child._forever_httpbin,
            _make_httpbin_site=self.make_httpbin_site,
            _serve_tcp=self.serve_tcp,
            _serve_tls=self.serve_tls,
            _output_process_description=self.output_process_description,
        )
Esempio n. 19
0
 def setUp(self):
     self.fake_threadpool_state = FakeThreadPoolState()
     self.fake_threadpool = FakeThreadPool(self.fake_threadpool_state)
     self.reactor = MemoryReactor()
Esempio n. 20
0
 def setUp(self):
     self.reactor = MemoryReactor()
     self.site = Site(Resource)
Esempio n. 21
0
    def test_startLogging(self) -> None:
        """
        L{Runner.startLogging} sets up a filtering observer with a log level
        predicate set to the given log level that contains a file observer of
        the given type which writes to the given file.
        """
        logFile = StringIO()

        # Patch the log beginner so that we don't try to start the already
        # running (started by trial) logging system.

        class LogBeginner:
            observers: List[ILogObserver] = []

            def beginLoggingTo(self,
                               observers: Iterable[ILogObserver]) -> None:
                LogBeginner.observers = list(observers)

        self.patch(_runner, "globalLogBeginner", LogBeginner())

        # Patch FilteringLogObserver so we can capture its arguments

        class MockFilteringLogObserver(FilteringLogObserver):
            observer: Optional[ILogObserver] = None
            predicates: List[LogLevelFilterPredicate] = []

            def __init__(
                self,
                observer: ILogObserver,
                predicates: Iterable[LogLevelFilterPredicate],
                negativeObserver: ILogObserver = cast(ILogObserver,
                                                      lambda event: None),
            ):
                MockFilteringLogObserver.observer = observer
                MockFilteringLogObserver.predicates = list(predicates)
                FilteringLogObserver.__init__(self, observer, predicates,
                                              negativeObserver)

        self.patch(_runner, "FilteringLogObserver", MockFilteringLogObserver)

        # Patch FileLogObserver so we can capture its arguments

        class MockFileLogObserver(FileLogObserver):
            outFile: Optional[TextIO] = None

            def __init__(self, outFile: TextIO) -> None:
                MockFileLogObserver.outFile = outFile
                FileLogObserver.__init__(self, outFile, str)

        # Start logging
        runner = Runner(
            reactor=MemoryReactor(),
            defaultLogLevel=LogLevel.critical,
            logFile=logFile,
            fileLogObserverFactory=MockFileLogObserver,
        )
        runner.startLogging()

        # Check for a filtering observer
        self.assertEqual(len(LogBeginner.observers), 1)
        self.assertIsInstance(LogBeginner.observers[0], FilteringLogObserver)

        # Check log level predicate with the correct default log level
        self.assertEqual(len(MockFilteringLogObserver.predicates), 1)
        self.assertIsInstance(MockFilteringLogObserver.predicates[0],
                              LogLevelFilterPredicate)
        self.assertIdentical(
            MockFilteringLogObserver.predicates[0].defaultLogLevel,
            LogLevel.critical)

        # Check for a file observer attached to the filtering observer
        observer = cast(MockFileLogObserver, MockFilteringLogObserver.observer)
        self.assertIsInstance(observer, MockFileLogObserver)

        # Check for the file we gave it
        self.assertIdentical(observer.outFile, logFile)
Esempio n. 22
0
 def __init__(self):
     MemoryReactor.__init__(self)
     self.spawnedProcesses = []