Beispiel #1
0
    def __init__(self, server_key, config):
        self._subtype = config["subtype"].lower()
        self._server_key = server_key
        self._config = config

        #setup logging
        self.logdata = []
        self.lastlogtime = time.time()
        self.loggingport = 0

        self._dediids = {'tf': 232250, 'dod': 232290, 'css': 232330}

        #setup rcon
        self.rcon = SourceRcon.SourceRcon(self._config["ip"], int(self._config["port"]), self._config["rcon_password"])

        if self._subtype == "":
            self._subtype = None

        log.debug("server_key:", server_key, "self._subtype:", self._subtype)
        if self._subtype is None:
            if platform.isWindows():
                self._server = SRCDSServerProcessWin32(server_key, config)
            else:
                self._server = SRCDSServerBase(server_key, config)

        elif self._subtype == "svc":
            if platform.isWindows():
                self._server = SRCDSServerServiceWin32(server_key, config)
            else:
                self._server = SRCDSServerBase(server_key, config)

        elif self._subtype == "gs":
            self._server = SRCDSServerGS(server_key, config)
Beispiel #2
0
 def setUp(self):
     """
     Clear the SIGCHLD handler, if there is one, to ensure an environment
     like the one which exists prior to a call to L{reactor.run}.
     """
     if not platform.isWindows():
         self.originalHandler = signal.signal(signal.SIGCHLD, signal.SIG_DFL)
Beispiel #3
0
    def test_parseOptionsHelp(self):
        """
        L{Start.parseOptions} writes usage information to stdout if C{"--help"}
        is in the argument list it is passed and L{twistd.run} is not called.
        """
        start = axiomatic.Start()
        start.run = None
        original = sys.stdout
        sys.stdout = stdout = StringIO.StringIO()
        try:
            self.assertRaises(SystemExit, start.parseOptions, ["--help"])
        finally:
            sys.stdout = original

        # Some random options that should be present.  This is a bad test
        # because we don't control what C{opt_help} actually does and we don't
        # even really care as long as it's the same as what I{twistd --help}
        # does.  We could try running them both and comparing, but then we'd
        # still want to do some sanity check against one of them in case we end
        # up getting the twistd version incorrectly somehow... -exarkun
        self.assertIn("--reactor", stdout.getvalue())
        if not platform.isWindows():
            # This isn't an option on Windows, so it shouldn't be there.
            self.assertIn("--uid", stdout.getvalue())

        # Also, we don't want to see twistd plugins here.
        self.assertNotIn("axiomatic-start", stdout.getvalue())
Beispiel #4
0
 def _sendSignal(self, signal):
     if platform.isWindows():
         raise usage.UsageError("You can't send signals on Windows (XXX TODO)")
     dbdir = self.parent.getStoreDirectory()
     serverpid = int(file(os.path.join(dbdir, 'run', 'axiomatic.pid')).read())
     os.kill(serverpid, signal)
     return serverpid
Beispiel #5
0
    def getArguments(self, store, args):
        run = store.dbdir.child("run")
        logs = run.child("logs")
        handleLogfile = True
        handlePidfile = True

        for arg in args:
            if arg.startswith("--logfile=") or arg in (
                "-l", "--logfile", "-n", "--nodaemon"
            ):
                handleLogfile = False
            elif arg.startswith("--pidfile=") or arg == "--pidfile":
                handlePidfile = False

        if handleLogfile:
            if not logs.exists():
                logs.makedirs()
            args.extend(["--logfile", logs.child("axiomatic.log").path])

        if not platform.isWindows() and handlePidfile:
            args.extend(["--pidfile", run.child("axiomatic.pid").path])
        args.extend(["axiomatic-start", "--dbdir", store.dbdir.path])
        if store.journalMode is not None:
            args.extend(['--journal-mode', store.journalMode.encode('ascii')])
        return args
    def _parseWorker(reactor, name, executable=None):
        """
        Constructs a process endpoint for a spreadflow worker process.

        Args:
            reactor: The reactor passed to ``clientFromString``.
            name (str): The partition name this worker should operate on.
            executable (Optional[str]). Path to the spreadflow-twistd command.

        Returns:
            A client process endpoint
        """
        if executable is None:
            executable = sys.argv[0]

        logger = 'spreadflow_core.scripts.spreadflow_twistd.StderrLogger'
        args = [executable, '-n', '--logger', logger, '--multiprocess',
                '--partition', name]

        if not platform.isWindows():
            args.extend(['--pidfile', ''])

        fds = {0: "w", 1: "r", 2: 2}

        return ProcessEndpoint(reactor, executable, args=args,
                               env=os.environ.copy(), childFDs=fds)
Beispiel #7
0
 def checkProtocol(stdioOb):
     from twisted.python.runtime import platform
     if platform.isWindows():
         self.assertIsInstance(stdioOb.proto, basic.LineReceiver)
     else:
         self.assertIsInstance(stdioOb.protocol, basic.LineReceiver)
     stdioOb.loseConnection()
    def test_disconnectWhileProducing(self):
        """
        If C{loseConnection} is called while a producer is registered with the
        transport, the connection is closed after the producer is unregistered.
        """
        reactor = self.buildReactor()

        # For some reason, pyobject/pygtk will not deliver the close
        # notification that should happen after the unregisterProducer call in
        # this test.  The selectable is in the write notification set, but no
        # notification ever arrives.  Probably for the same reason #5233 led
        # win32eventreactor to be broken.
        skippedReactors = ["Glib2Reactor", "Gtk2Reactor"]
        reactorClassName = reactor.__class__.__name__
        if reactorClassName in skippedReactors and platform.isWindows():
            raise SkipTest("A pygobject/pygtk bug disables this functionality " "on Windows.")

        class Producer:
            def resumeProducing(self):
                log.msg("Producer.resumeProducing")

        self.listen(reactor, ServerFactory.forProtocol(Protocol))

        finished = Deferred()
        finished.addErrback(log.err)
        finished.addCallback(lambda ign: reactor.stop())

        class ClientProtocol(Protocol):
            """
            Protocol to connect, register a producer, try to lose the
            connection, unregister the producer, and wait for the connection to
            actually be lost.
            """

            def connectionMade(self):
                log.msg("ClientProtocol.connectionMade")
                self.transport.registerProducer(Producer(), False)
                self.transport.loseConnection()
                # Let the reactor tick over, in case synchronously calling
                # loseConnection and then unregisterProducer is the same as
                # synchronously calling unregisterProducer and then
                # loseConnection (as it is in several reactors).
                reactor.callLater(0, reactor.callLater, 0, self.unregister)

            def unregister(self):
                log.msg("ClientProtocol unregister")
                self.transport.unregisterProducer()
                # This should all be pretty quick.  Fail the test
                # if we don't get a connectionLost event really
                # soon.
                reactor.callLater(1.0, finished.errback, Failure(Exception("Connection was not lost")))

            def connectionLost(self, reason):
                log.msg("ClientProtocol.connectionLost")
                finished.callback(None)

        clientFactory = ClientFactory()
        clientFactory.protocol = ClientProtocol
        self.connect(reactor, clientFactory)
        self.runReactor(reactor)
Beispiel #9
0
    def child(self, path):
        """
        Create and return a new L{FilePath} representing a path contained by
        C{self}.

        @param path: The base name of the new L{FilePath}.  If this contains
            directory separators or parent references it will be rejected.
        @type path: L{bytes}

        @raise InsecurePath: If the result of combining this path with C{path}
            would result in a path which is not a direct child of this path.

        @return: The child path.
        @rtype: L{FilePath}
        """
        if platform.isWindows() and path.count(b":"):
            # Catch paths like C:blah that don't have a slash
            raise InsecurePath("%r contains a colon." % (path,))
        norm = normpath(path)
        if self.sep in norm:
            raise InsecurePath("%r contains one or more directory separators" % (path,))
        newpath = abspath(joinpath(self.path, norm))
        if not newpath.startswith(self.path):
            raise InsecurePath("%r is not a child of %s" % (newpath, self.path))
        return self.clonePath(newpath)
 def stopped(ignored):
     # Should still be possible to recv on portSocket.  If
     # it was shutdown, the exception would be EINVAL instead.
     exc = self.assertRaises(socket.error, portSocket.recvfrom, 1)
     if platform.isWindows() and _PY3:
         self.assertEqual(exc.args[0], errno.WSAEWOULDBLOCK)
     else:
         self.assertEqual(exc.args[0], errno.EAGAIN)
 def setContent(self, content, ext=".new"):
     sib = self.siblingExtension(ext)
     f = sib.open("w")
     f.write(content)
     f.close()
     if platform.isWindows() and exists(self.path):
         os.unlink(self.path)
     os.rename(sib.path, self.path)
Beispiel #12
0
    def setContent(self, content, ext='.new'):
        """
        Replace the file at this path with a new file that contains the given
        bytes, trying to avoid data-loss in the meanwhile.

        On UNIX-like platforms, this method does its best to ensure that by the
        time this method returns, either the old contents I{or} the new contents
        of the file will be present at this path for subsequent readers
        regardless of premature device removal, program crash, or power loss,
        making the following assumptions:

            - your filesystem is journaled (i.e. your filesystem will not
              I{itself} lose data due to power loss)

            - your filesystem's C{rename()} is atomic

            - your filesystem will not discard new data while preserving new
              metadata (see U{http://mjg59.livejournal.com/108257.html} for more
              detail)

        On most versions of Windows there is no atomic C{rename()} (see
        U{http://bit.ly/win32-overwrite} for more information), so this method
        is slightly less helpful.  There is a small window where the file at
        this path may be deleted before the new file is moved to replace it:
        however, the new file will be fully written and flushed beforehand so in
        the unlikely event that there is a crash at that point, it should be
        possible for the user to manually recover the new version of their data.
        In the future, Twisted will support atomic file moves on those versions
        of Windows which I{do} support them: see U{Twisted ticket
        3004<http://twistedmatrix.com/trac/ticket/3004>}.

        This method should be safe for use by multiple concurrent processes, but
        note that it is not easy to predict which process's contents will
        ultimately end up on disk if they invoke this method at close to the
        same time.

        @param content: The desired contents of the file at this path.

        @type content: L{str}

        @param ext: An extension to append to the temporary filename used to
            store the bytes while they are being written.  This can be used to
            make sure that temporary files can be identified by their suffix,
            for cleanup in case of crashes.

        @type ext: C{str}
        """
        sib = self.temporarySibling(ext)
        f = sib.open('w')
        try:
            f.write(content)
        finally:
            f.close()
        if platform.isWindows() and exists(self.path):
            os.unlink(self.path)
        os.rename(sib.path, self.path)
Beispiel #13
0
 def child(self, path):
     if platform.isWindows() and path.count(":"):
         raise InsecurePath("%r contains a colon." % (path,))
     norm = normpath(path)
     if slash in norm:
         raise InsecurePath("%r contains one or more directory separators" % (path,))
     newpath = abspath(joinpath(self.path, norm))
     if not newpath.startswith(self.path):
         raise InsecurePath("%r is not a child of %s" % (newpath, self.path))
     return self.clonePath(newpath)
Beispiel #14
0
 def getArguments(self, store, args):
     run = store.dbdir.child("run")
     logs = run.child("logs")
     if "--logfile" not in args and "-l" not in args and "--nodaemon" not in args and "-n" not in args:
         if not logs.exists():
             logs.makedirs()
         args.extend(["--logfile", logs.child("axiomatic.log").path])
     if not platform.isWindows() and "--pidfile" not in args:
         args.extend(["--pidfile", run.child("axiomatic.pid").path])
     args.extend(["axiomatic-start", "--dbdir", store.dbdir.path])
     return args
Beispiel #15
0
 def test_getProgramsMenuPath(self):
     """
     L{getProgramsMenuPath} guesses the programs menu path on non-win32
     platforms. On non-win32 it will try to figure out the path by
     examining the registry.
     """
     if not platform.isWindows():
         self.assertEqual(win32.getProgramsMenuPath(),
             "C:\\Windows\\Start Menu\\Programs")
     else:
         self.assertIsInstance(win32.getProgramsMenuPath(), str)
Beispiel #16
0
        def get(self):
            yield ('start', None, Start, 'Launch the given Axiom database')
            if not platform.isWindows():
                yield ('stop', None, Stop, 'Stop the server running from the given Axiom database')
                yield ('status', None, Status, 'Report whether a server is running from the given Axiom database')

            from axiom import plugins
            for plg in getPlugins(IAxiomaticCommand, plugins):
                try:
                    yield (plg.name, None, plg, plg.description)
                except AttributeError:
                    raise RuntimeError("Maldefined plugin: %r" % (plg,))
Beispiel #17
0
    def test_gid(self):
        """
        Should be the current user by default
        """
        if platform.isWindows():
            raise SkipTest('Windows-only test')

        r = _spawnDefaultArgs('exec')
        self.assertEqual(r['gid'], os.getegid())
        
        r = _spawnDefaultArgs('exec', gid='foo')
        self.assertEqual(r['gid'], 'foo')
Beispiel #18
0
    def __init__(self, controller, id, who, keeplog=None):
        """
        Ctor.

        :param controller: The node controller this worker was created by.
        :type controller: instance of NodeController
        :param id: The ID of the worker.
        :type id: str
        :param who: Who triggered creation of this worker.
        :type who: str
        :param keeplog: If not `None`, buffer log message received to be later
                        retrieved via getlog(). If `0`, keep infinite log internally.
                        If `> 0`, keep at most such many log entries in buffer.
        :type keeplog: int or None
        """
        self._logger = make_logger()

        self._controller = controller

        self.id = id
        self.who = who
        self.pid = None
        self.status = u'starting'

        self.created = datetime.utcnow()
        self.connected = None
        self.started = None

        self.proto = None
        self.pinfo = None

        self._log_entries = deque(maxlen=10)

        if platform.isWindows():
            self._log_fds = [2]
        else:
            self._log_fds = [1, 2]
        self._log_lineno = 0
        self._log_topic = u'crossbar.worker.{}.on_log'.format(self.id)

        self._log_rich = None  # Does not support rich logs

        # track stats for worker->controller traffic
        self._stats = {}
        self._stats_printer = None

        # A deferred that resolves when the worker is ready.
        self.ready = Deferred()

        # A deferred that resolves when the worker has exited.
        self.exit = Deferred()
        self.exit.addBoth(self._dump_remaining_log)
Beispiel #19
0
def getServerObjType(server):
    obj_type = SrcdsServerProcessTwisted
    if platform.isWindows():
        if "subtype" in server and server["subtype"] == "svc":
            from srcds_win32 import SrcdsServerServiceWin32

            obj_type = SrcdsServerServiceWin32
        else:
            from srcds_win32 import SrcdsServerProcessWin32

            obj_type = SrcdsServerProcessWin32

    return obj_type
Beispiel #20
0
class PTYProcessTestsBuilder(ProcessTestsBuilderBase):
    """
    Builder defining tests relating to L{IReactorProcess} for child processes
    which have a PTY.
    """
    usePTY = True

    if platform.isWindows():
        skip = "PTYs are not supported on Windows."
    elif platform.isMacOSX():
        skippedReactors = {
            "twisted.internet.pollreactor.PollReactor":
                "OS X's poll() does not support PTYs"}
Beispiel #21
0
class ProcessIsUnimportableOnUnsupportedPlatormsTests(TestCase):
    """
    Tests to ensure that L{twisted.internet.process} is unimportable on
    platforms where it does not work (namely Windows).
    """
    @skipIf(not platform.isWindows(), "Only relevant on Windows.")
    def test_unimportableOnWindows(self):
        """
        L{twisted.internet.process} is unimportable on Windows.
        """
        with self.assertRaises(ImportError):
            import twisted.internet.process
            twisted.internet.process  # shh pyflakes
Beispiel #22
0
 def child(self, path):
     if platform.isWindows() and path.count(":"):
         # Catch paths like C:blah that don't have a slash
         raise InsecurePath("%r contains a colon." % (path, ))
     norm = normpath(path)
     if slash in norm:
         raise InsecurePath("%r contains one or more directory separators" %
                            (path, ))
     newpath = abspath(joinpath(self.path, norm))
     if not newpath.startswith(self.path):
         raise InsecurePath("%r is not a child of %s" %
                            (newpath, self.path))
     return self.clonePath(newpath)
Beispiel #23
0
    def test_normalFileStandardOut(self):
        """
        If L{StandardIO} is created with a file descriptor which refers to a
        normal file (ie, a file from the filesystem), L{StandardIO.write}
        writes bytes to that file.  In particular, it does not immediately
        consider the file closed or call its protocol's C{connectionLost}
        method.
        """
        onConnLost = defer.Deferred()
        proto = ConnectionLostNotifyingProtocol(onConnLost)
        path = filepath.FilePath(self.mktemp())
        self.normal = normal = path.open('w')
        self.addCleanup(normal.close)

        kwargs = dict(stdout=normal.fileno())
        if not platform.isWindows():
            # Make a fake stdin so that StandardIO doesn't mess with the *real*
            # stdin.
            r, w = os.pipe()
            self.addCleanup(os.close, r)
            self.addCleanup(os.close, w)
            kwargs['stdin'] = r
        connection = stdio.StandardIO(proto, **kwargs)

        # The reactor needs to spin a bit before it might have incorrectly
        # decided stdout is closed.  Use this counter to keep track of how
        # much we've let it spin.  If it closes before we expected, this
        # counter will have a value that's too small and we'll know.
        howMany = 5
        count = itertools.count()

        def spin():
            for value in count:
                if value == howMany:
                    connection.loseConnection()
                    return
                connection.write(str(value))
                break
            reactor.callLater(0, spin)

        reactor.callLater(0, spin)

        # Once the connection is lost, make sure the counter is at the
        # appropriate value.
        def cbLost(reason):
            self.assertEquals(count.next(), howMany + 1)
            self.assertEquals(path.getContent(),
                              ''.join(map(str, range(howMany))))

        onConnLost.addCallback(cbLost)
        return onConnLost
Beispiel #24
0
    def _large_request_test(self, request_body_size):
        """
        Assert that when a request with a body of of the given size is received
        its content is written to the directory the ``TahoeLAFSSite`` is
        configured with.
        """
        tempdir = FilePath(self.mktemp())
        tempdir.makedirs()
        request = self._create_request(tempdir)

        # So.  Bad news.  The temporary file for the uploaded content is
        # unnamed (and this isn't even necessarily a bad thing since it is how
        # you get automatic on-process-exit cleanup behavior on POSIX).  It's
        # not visible by inspecting the filesystem.  It has no name we can
        # discover.  Then how do we verify it is written to the right place?
        # The question itself is meaningless if we try to be too precise.  It
        # *has* no filesystem location.  However, it is still stored *on* some
        # filesystem.  We still want to make sure it is on the filesystem we
        # specified because otherwise it might be on a filesystem that's too
        # small or undesirable in some other way.
        #
        # I don't know of any way to ask a file descriptor which filesystem
        # it's on, either, though.  It might be the case that the [f]statvfs()
        # result could be compared somehow to infer the filesystem but
        # ... it's not clear what the failure modes might be there, across
        # different filesystems and runtime environments.
        #
        # Another approach is to make the temp directory unwriteable and
        # observe the failure when an attempt is made to create a file there.
        # This is hardly a lovely solution but at least it's kind of simple.
        #
        # It would be nice if it worked consistently cross-platform but on
        # Windows os.chmod is more or less broken.
        if platform.isWindows():
            request.gotLength(request_body_size)
            self.assertThat(
                tempdir.children(),
                HasLength(1),
            )
        else:
            tempdir.chmod(0o550)
            with self.assertRaises(OSError) as ctx:
                request.gotLength(request_body_size)
                raise Exception(
                    "OSError not raised, instead tempdir.children() = {}".
                    format(tempdir.children(), ), )

            self.assertThat(
                ctx.exception.errno,
                Equals(EACCES),
            )
Beispiel #25
0
    def __init__(self, controller, id, who, keeplog=None):
        """
        Ctor.

        :param controller: The node controller this worker was created by.
        :type controller: instance of NodeControllerSession
        :param id: The ID of the worker.
        :type id: str
        :param who: Who triggered creation of this worker.
        :type who: str
        :param keeplog: If not `None`, buffer log message received to be later
                        retrieved via getlog(). If `0`, keep infinite log internally.
                        If `> 0`, keep at most such many log entries in buffer.
        :type keeplog: int or None
        """
        self._logger = make_logger()

        self._controller = controller

        self.id = id
        self.who = who
        self.pid = None
        self.status = "starting"

        self.created = datetime.utcnow()
        self.connected = None
        self.started = None

        self._log_entries = deque(maxlen=10)

        if platform.isWindows():
            self._log_fds = [2]
        else:
            self._log_fds = [1, 2]
        self._log_lineno = 0
        self._log_topic = 'crossbar.node.{}.worker.{}.on_log'.format(
            self._controller._node_id, self.id)

        self._log_rich = None  # Does not support rich logs

        # track stats for worker->controller traffic
        self._stats = {}
        self._stats_printer = None

        # A deferred that resolves when the worker is ready.
        self.ready = Deferred()

        # A deferred that resolves when the worker has exited.
        self.exit = Deferred()
        self.exit.addBoth(self._dump_remaining_log)
Beispiel #26
0
class TLSMixin:
    requiredInterfaces = [
        IReactorSSL
    ]  # type: Optional[Sequence[Type[Interface]]]  # noqa

    if platform.isWindows():
        msg = (
            "For some reason, these reactors don't deal with SSL "
            "disconnection correctly on Windows.  See #3371."
        )
        skippedReactors = {
            "twisted.internet.glib2reactor.Glib2Reactor": msg,
            "twisted.internet.gtk2reactor.Gtk2Reactor": msg,
        }
    def test_normalFileStandardOut(self):
        """
        If L{StandardIO} is created with a file descriptor which refers to a
        normal file (ie, a file from the filesystem), L{StandardIO.write}
        writes bytes to that file.  In particular, it does not immediately
        consider the file closed or call its protocol's C{connectionLost}
        method.
        """
        onConnLost = defer.Deferred()
        proto = ConnectionLostNotifyingProtocol(onConnLost)
        path = filepath.FilePath(self.mktemp())
        self.normal = normal = path.open('w')
        self.addCleanup(normal.close)

        kwargs = dict(stdout=normal.fileno())
        if not platform.isWindows():
            # Make a fake stdin so that StandardIO doesn't mess with the *real*
            # stdin.
            r, w = os.pipe()
            self.addCleanup(os.close, r)
            self.addCleanup(os.close, w)
            kwargs['stdin'] = r
        connection = stdio.StandardIO(proto, **kwargs)

        # The reactor needs to spin a bit before it might have incorrectly
        # decided stdout is closed.  Use this counter to keep track of how
        # much we've let it spin.  If it closes before we expected, this
        # counter will have a value that's too small and we'll know.
        howMany = 5
        count = itertools.count()

        def spin():
            for value in count:
                if value == howMany:
                    connection.loseConnection()
                    return
                connection.write(str(value))
                break
            reactor.callLater(0, spin)
        reactor.callLater(0, spin)

        # Once the connection is lost, make sure the counter is at the
        # appropriate value.
        def cbLost(reason):
            self.assertEquals(count.next(), howMany + 1)
            self.assertEquals(
                path.getContent(),
                ''.join(map(str, range(howMany))))
        onConnLost.addCallback(cbLost)
        return onConnLost
Beispiel #28
0
    def test_stopStartReading(self):
        """
        This test verifies transport socket read state after multiple
        pause/resumeProducing calls.
        """
        sf = ServerFactory()
        reactor = sf.reactor = self.buildReactor()

        skippedReactors = ["Glib2Reactor", "Gtk2Reactor"]
        reactorClassName = reactor.__class__.__name__
        if reactorClassName in skippedReactors and platform.isWindows():
            raise SkipTest("This test is broken on gtk/glib under Windows.")

        sf.protocol = StopStartReadingProtocol
        sf.ready = Deferred()
        sf.stop = Deferred()
        p = reactor.listenTCP(0, sf)
        port = p.getHost().port

        def proceed(protos, port):
            """
            Send several IOCPReactor's buffers' worth of data.
            """
            self.assertTrue(protos[0])
            self.assertTrue(protos[1])
            protos = protos[0][1], protos[1][1]
            protos[0].transport.write('x' * (2 * 4096) + 'y' * (2 * 4096))
            return (sf.stop.addCallback(
                cleanup, protos, port).addCallback(lambda ign: reactor.stop()))

        def cleanup(data, protos, port):
            """
            Make sure IOCPReactor didn't start several WSARecv operations
            that clobbered each other's results.
            """
            self.assertEquals(data, 'x' * (2 * 4096) + 'y' * (2 * 4096),
                              'did not get the right data')
            return DeferredList([
                maybeDeferred(protos[0].transport.loseConnection),
                maybeDeferred(protos[1].transport.loseConnection),
                maybeDeferred(port.stopListening)
            ])

        cc = TCP4ClientEndpoint(reactor, '127.0.0.1', port)
        cf = ClientFactory()
        cf.protocol = Protocol
        d = DeferredList([cc.connect(cf), sf.ready]).addCallback(proceed, p)
        self.runReactor(reactor)
        return d
Beispiel #29
0
 def stop_and_wait(self):
     if platform.isWindows():
         # On Windows there is no PID file and no "tahoe stop".
         if self.process is not None:
             while True:
                 try:
                     self.process.signalProcess("TERM")
                 except ProcessExitedAlready:
                     break
                 else:
                     yield deferLater(self.reactor, 0.1, lambda: None)
     else:
         protocol, ended = wait_for_exit()
         self.stop(protocol)
         yield ended
Beispiel #30
0
def getProgramsMenuPath():
    """
    Get the path to the Programs menu.

    Probably will break on non-US Windows.

    @return: the filesystem location of the common Start Menu->Programs.
    @rtype: L{str}
    """
    if not platform.isWindows():
        return "C:\\Windows\\Start Menu\\Programs"
    keyname = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders'
    hShellFolders = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE,
                                          keyname, 0, win32con.KEY_READ)
    return win32api.RegQueryValueEx(hShellFolders, 'Common Programs')[0]
Beispiel #31
0
    def test_env_POSIX(self):
        """
        default on POSIX is {} unless it's None, then it's os.environ.
        """
        if platform.isWindows():
            raise SkipTest('POSIX-only test')

        r = _spawnDefaultArgs('exec')
        self.assertEqual(r['env'], {})
        
        r = _spawnDefaultArgs('exec', env=None)
        self.assertEqual(r['env'], os.environ)

        r = _spawnDefaultArgs('exec', env={'foo': 'bar'})
        self.assertEqual(r['env'], {'foo': 'bar'})
Beispiel #32
0
    def test_stopStartReading(self):
        """
        This test verifies transport socket read state after multiple
        pause/resumeProducing calls.
        """
        sf = ServerFactory()
        reactor = sf.reactor = self.buildReactor()

        skippedReactors = ["Glib2Reactor", "Gtk2Reactor"]
        reactorClassName = reactor.__class__.__name__
        if reactorClassName in skippedReactors and platform.isWindows():
            raise SkipTest(
                "This test is broken on gtk/glib under Windows.")

        sf.protocol = StopStartReadingProtocol
        sf.ready = Deferred()
        sf.stop = Deferred()
        p = reactor.listenTCP(0, sf)
        port = p.getHost().port
        def proceed(protos, port):
            """
            Send several IOCPReactor's buffers' worth of data.
            """
            self.assertTrue(protos[0])
            self.assertTrue(protos[1])
            protos = protos[0][1], protos[1][1]
            protos[0].transport.write('x' * (2 * 4096) + 'y' * (2 * 4096))
            return (sf.stop.addCallback(cleanup, protos, port)
                           .addCallback(lambda ign: reactor.stop()))
        
        def cleanup(data, protos, port):
            """
            Make sure IOCPReactor didn't start several WSARecv operations
            that clobbered each other's results.
            """
            self.assertEqual(data, 'x'*(2*4096) + 'y'*(2*4096),
                                 'did not get the right data')
            return DeferredList([
                    maybeDeferred(protos[0].transport.loseConnection),
                    maybeDeferred(protos[1].transport.loseConnection),
                    maybeDeferred(port.stopListening)])

        cc = TCP4ClientEndpoint(reactor, '127.0.0.1', port)
        cf = ClientFactory()
        cf.protocol = Protocol
        d = DeferredList([cc.connect(cf), sf.ready]).addCallback(proceed, p)
        self.runReactor(reactor)
        return d
Beispiel #33
0
    def test_getArguments(self):
        """
        L{Start.getArguments} adds a I{--pidfile} argument if one is not
        present and a I{--logfile} argument if one is not present and
        daemonization is enabled and adds a I{--dbdir} argument pointing at the
        store it is passed. It also adds I{--journal-mode} if this is passed.
        """
        dbdir = FilePath(self.mktemp())
        store = Store(dbdir, journalMode=u'WAL')
        run = self._getRunDir(dbdir)
        logs = self._getLogDir(dbdir)
        start = axiomatic.Start()

        logfileArg = ["--logfile", logs.child("axiomatic.log").path]

        # twistd on Windows doesn't support PID files, so on Windows,
        # getArguments should *not* add --pidfile.
        if platform.isWindows():
            pidfileArg = []
        else:
            pidfileArg = ["--pidfile", run.child("axiomatic.pid").path]
        restArg = [
            "axiomatic-start", "--dbdir", dbdir.path, "--journal-mode", "WAL"]

        self.assertEqual(
            start.getArguments(store, []),
            logfileArg + pidfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["--logfile=foo"]),
            ["--logfile=foo"] + pidfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["--logfile", "foo"]),
            ["--logfile", "foo"] + pidfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["-l", "foo"]),
            ["-l", "foo"] + pidfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["--nodaemon"]),
            ["--nodaemon"] + pidfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["-n"]),
            ["-n"] + pidfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["--pidfile=foo"]),
            ["--pidfile=foo"] + logfileArg + restArg)
        self.assertEqual(
            start.getArguments(store, ["--pidfile", "foo"]),
            ["--pidfile", "foo"] + logfileArg + restArg)
Beispiel #34
0
        def get(self):
            yield ('start', None, Start, 'Launch the given Axiom database')
            if not platform.isWindows():
                yield ('stop', None, Stop,
                       'Stop the server running from the given Axiom database')
                yield (
                    'status', None, Status,
                    'Report whether a server is running from the given Axiom database'
                )

            from axiom import plugins
            for plg in getPlugins(IAxiomaticCommand, plugins):
                try:
                    yield (plg.name, None, plg, plg.description)
                except AttributeError:
                    raise RuntimeError("Maldefined plugin: %r" % (plg, ))
Beispiel #35
0
 def processEnded(self, reason):
     """
     Check that the process exited in the way expected and that the required
     text has been found in its output and fire the result L{Deferred} with
     either a value or a failure.
     """
     self._complete, result = None, self._complete
     if self._success:
         if platform.isWindows() or (
                 # Windows can't tell that we SIGTERM'd it, so sorry.
                 reason.check(ProcessTerminated)
                 and reason.value.signal == signal.SIGTERM):
             result.callback(None)
             return
     # Something went wrong.
     result.errback(reason)
Beispiel #36
0
 def processEnded(self, reason):
     """
     Check that the process exited in the way expected and that the required
     text has been found in its output and fire the result L{Deferred} with
     either a value or a failure.
     """
     self._complete, result = None, self._complete
     if self._success:
         if platform.isWindows() or (
             # Windows can't tell that we SIGTERM'd it, so sorry.
             reason.check(ProcessTerminated) and
             reason.value.signal == signal.SIGTERM):
             result.callback(None)
             return
     # Something went wrong.
     result.errback(reason)
Beispiel #37
0
    def setUp(self):
        # A memory-only terminal emulator, into which the server will
        # write things and make other state changes.  What ends up
        # here is basically what a user would have seen on their
        # screen.
        testTerminal = NotifyingExpectableBuffer()

        # An insults client protocol which will translate bytes
        # received from the child process into keystroke commands for
        # an ITerminalProtocol.
        insultsClient = insults.ClientProtocol(lambda: testTerminal)

        # A process protocol which will translate stdout and stderr
        # received from the child process to dataReceived calls and
        # error reporting on an insults client protocol.
        processClient = stdio.TerminalProcessProtocol(insultsClient)

        # Run twisted/conch/stdio.py with the name of a class
        # implementing ITerminalProtocol.  This class will be used to
        # handle bytes we send to the child process.
        exe = sys.executable
        module = stdio.__file__
        if module.endswith('.pyc') or module.endswith('.pyo'):
            module = module[:-1]
        args = [exe, module, reflect.qual(self.serverProtocol)]
        if not platform.isWindows():
            args = [arg.encode(sys.getfilesystemencoding()) for arg in args]

        from twisted.internet import reactor
        clientTransport = reactor.spawnProcess(processClient,
                                               exe,
                                               args,
                                               env=properEnv,
                                               usePTY=True)

        self.recvlineClient = self.testTerminal = testTerminal
        self.processClient = processClient
        self.clientTransport = clientTransport

        # Wait for the process protocol and test terminal to become
        # connected before proceeding.  The former should always
        # happen first, but it doesn't hurt to be safe.
        return defer.gatherResults(
            filter(None,
                   [processClient.onConnection,
                    testTerminal.expect(b">>> ")]))
Beispiel #38
0
 def cbExited((failure,)):
     # Trapping implicitly verifies that it's a Failure (rather than
     # an exception) and explicitly makes sure it's the right type.
     failure.trap(ProcessTerminated)
     err = failure.value
     if platform.isWindows():
         # Windows can't really /have/ signals, so it certainly can't
         # report them as the reason for termination.  Maybe there's
         # something better we could be doing here, anyway?  Hard to
         # say.  Anyway, this inconsistency between different platforms
         # is extremely unfortunate and I would remove it if I
         # could. -exarkun
         self.assertIdentical(err.signal, None)
         self.assertEqual(err.exitCode, 1)
     else:
         self.assertEqual(err.signal, sigNum)
         self.assertIdentical(err.exitCode, None)
Beispiel #39
0
 def tearDown(self):
     try:
         super().tearDown()
     finally:
         warnings = self.flushWarnings()
         if os.environ.get("CI",
                           "").lower() == "true" and platform.isWindows():
             # FIXME:
             # https://twistedmatrix.com/trac/ticket/10332
             # For now don't raise errors on Windows as the existing tests are dirty and we don't have the dev resources to fix this.
             # If you care about Twisted on Windows, enable this check and hunt for the test that is generating the warnings.
             # Note that even with this check disabled, you can still see flaky tests on Windows, as due to stray delayed calls
             # the warnings can be generated while another test is running.
             return
         self.assertEqual(
             len(warnings), 0,
             f"Warnings found at the end of the test:\n{warnings}")
Beispiel #40
0
 def cbExited((failure,)):
     # Trapping implicitly verifies that it's a Failure (rather than
     # an exception) and explicitly makes sure it's the right type.
     failure.trap(ProcessTerminated)
     err = failure.value
     if platform.isWindows():
         # Windows can't really /have/ signals, so it certainly can't
         # report them as the reason for termination.  Maybe there's
         # something better we could be doing here, anyway?  Hard to
         # say.  Anyway, this inconsistency between different platforms
         # is extremely unfortunate and I would remove it if I
         # could. -exarkun
         self.assertIdentical(err.signal, None)
         self.assertEqual(err.exitCode, 1)
     else:
         self.assertEqual(err.signal, sigNum)
         self.assertIdentical(err.exitCode, None)
Beispiel #41
0
 def test_env_Windows(self):
     """
     default on windows is os.environ updated with whatever
     """
     if not platform.isWindows():
         raise SkipTest('Windows-only test')
     
     r = _spawnDefaultArgs('exec')
     self.assertEqual(r['env'], os.environ)
     
     r = _spawnDefaultArgs('exec', env=None)
     self.assertEqual(r['env'], os.environ)
     
     r = _spawnDefaultArgs('exec', env={'foo': 'bar'})
     e = os.environ.copy()
     e.update({'foo': 'bar'})
     self.assertEqual(r['env'], e)
Beispiel #42
0
        def f():
            try:
                if platform.isWindows():
                    exe = pyExe.decode('mbcs')
                else:
                    exe = pyExe.decode('ascii')

                subprocess.Popen([exe, "-c", "import time; time.sleep(0.1)"])
                f2 = subprocess.Popen([exe, "-c",
                                       ("import time; time.sleep(0.5);"
                                        "print(\'Foo\')")],
                                      stdout=subprocess.PIPE)
                # The read call below will blow up with an EINTR from the
                # SIGCHLD from the first process exiting if we install a
                # SIGCHLD handler without SA_RESTART.  (which we used to do)
                result.append(f2.stdout.read())
            finally:
                reactor.stop()
Beispiel #43
0
    def test_invalidDescriptor(self):
        """
        An implementation of L{IReactorSocket.adoptStreamPort} raises
        L{socket.error} if passed an integer which is not associated with a
        socket.
        """
        reactor = self.buildReactor()

        probe = socket.socket()
        fileno = probe.fileno()
        probe.close()

        exc = self.assertRaises(socket.error, reactor.adoptStreamPort, fileno,
                                socket.AF_INET, ServerFactory())
        if platform.isWindows() and _PY3:
            self.assertEqual(exc.args[0], errno.WSAENOTSOCK)
        else:
            self.assertEqual(exc.args[0], errno.EBADF)
    def getGroupID(self):
        """
        Returns the group ID of the file.

        @raise: NotImplementedError if the platform is Windows, since the GID
                is always 0 on windows
        @return: the group ID of the file
        @rtype: C{int}
        @since: 11.0
        """
        if platform.isWindows():
            raise NotImplementedError

        st = self.statinfo
        if not st:
            self.restat()
            st = self.statinfo
        return int(st.st_gid)
    def getUserID(self):
        """
        Returns the user ID of the file's owner.

        @raise: NotImplementedError if the platform is Windows, since the UID
                is always 0 on Windows
        @return: the user ID of the file's owner
        @rtype: C{int}
        @since: 11.0
        """
        if platform.isWindows():
            raise NotImplementedError

        st = self.statinfo
        if not st:
            self.restat()
            st = self.statinfo
        return int(st.st_uid)
class BytesEnvironTests(TestCase):
    """
    Tests for L{BytesEnviron}.
    """
    @skipIf(platform.isWindows(),
            "Environment vars are always str on Windows.")
    def test_alwaysBytes(self):
        """
        The output of L{BytesEnviron} should always be a L{dict} with L{bytes}
        values and L{bytes} keys.
        """
        result = bytesEnviron()
        types = set()

        for key, val in result.items():
            types.add(type(key))
            types.add(type(val))

        self.assertEqual(list(types), [bytes])
    def getInodeNumber(self):
        """
        Retrieve the file serial number, also called inode number, which 
        distinguishes this file from all other files on the same device.

        @raise: NotImplementedError if the platform is Windows, since the
                inode number would be a dummy value for all files in Windows
        @return: a number representing the file serial number
        @rtype: C{long}
        @since: 11.0
        """
        if platform.isWindows():
            raise NotImplementedError

        st = self.statinfo
        if not st:
            self.restat()
            st = self.statinfo
        return long(st.st_ino)
Beispiel #48
0
    def getDevice(self):
        """
        Retrieves the device containing the file.  The inode number and device
        number together uniquely identify the file, but the device number is
        not necessarily consistent across reboots or system crashes.

        @raise NotImplementedError: if the platform is Windows, since the device
            number would be 0 for all partitions on a Windows platform
        @return: a number representing the device
        @rtype: L{int}
        @since: 11.0
        """
        if platform.isWindows():
            raise NotImplementedError

        st = self.statinfo
        if not st:
            self.restat()
            st = self.statinfo
        return st.st_dev
Beispiel #49
0
        def f():
            try:
                if platform.isWindows():
                    exe = pyExe.decode('mbcs')
                else:
                    exe = pyExe.decode('ascii')

                subprocess.Popen([exe, "-c", "import time; time.sleep(0.1)"])
                f2 = subprocess.Popen([
                    exe, "-c",
                    ("import time; time.sleep(0.5);"
                     "print(\'Foo\')")
                ],
                                      stdout=subprocess.PIPE)
                # The read call below will blow up with an EINTR from the
                # SIGCHLD from the first process exiting if we install a
                # SIGCHLD handler without SA_RESTART.  (which we used to do)
                result.append(f2.stdout.read())
            finally:
                reactor.stop()
Beispiel #50
0
def write_config(tahoe_cfg, config):
    """
    Write a configuration to a file.

    :param FilePath tahoe_cfg: The path to which to write the config.

    :param ConfigParser config: The configuration to write.

    :return: ``None``
    """
    tmp = tahoe_cfg.temporarySibling()
    # FilePath.open can only open files in binary mode which does not work
    # with ConfigParser.write.
    with open(tmp.path, "wt") as fp:
        config.write(fp)
    # Windows doesn't have atomic overwrite semantics for moveTo.  Thus we end
    # up slightly less than atomic.
    if platform.isWindows():
        tahoe_cfg.remove()
    tmp.moveTo(tahoe_cfg)
Beispiel #51
0
class GlibTimeTestsBuilder(ReactorBuilder):
    """
    Builder for defining tests relating to L{IReactorTime} for reactors based
    off glib.
    """

    requiredInterfaces = (IReactorTime, )

    if platform.isWindows():
        _reactors = ["twisted.internet.gtk2reactor.PortableGtkReactor"]
    else:
        _reactors = [
            "twisted.internet.glib2reactor.Glib2Reactor",
            "twisted.internet.gtk2reactor.Gtk2Reactor",
        ]

    def test_timeout_add(self):
        """
        A
        L{reactor.callLater<twisted.internet.interfaces.IReactorTime.callLater>}
        call scheduled from a C{gobject.timeout_add}
        call is run on time.
        """
        import gobject  # type: ignore[import]

        reactor = self.buildReactor()

        result = []

        def gschedule():
            reactor.callLater(0, callback)
            return 0

        def callback():
            result.append(True)
            reactor.stop()

        reactor.callWhenRunning(gobject.timeout_add, 10, gschedule)
        self.runReactor(reactor, 5)
        self.assertEqual(result, [True])
    def child(self, path):
        """
        Create and return a new L{FilePath} representing a path contained by
        C{self}.

        @param path: The base name of the new L{FilePath}.  If this contains
            directory separators or parent references it will be rejected.
        @type path: C{str}

        @raise InsecurePath: If the result of combining this path with C{path}
            would result in a path which is not a direct child of this path.
        """
        if platform.isWindows() and path.count(":"):
            # Catch paths like C:blah that don't have a slash
            raise InsecurePath("%r contains a colon." % (path,))
        norm = normpath(path)
        if self.sep in norm:
            raise InsecurePath("%r contains one or more directory separators" % (path,))
        newpath = abspath(joinpath(self.path, norm))
        if not newpath.startswith(self.path):
            raise InsecurePath("%r is not a child of %s" % (newpath, self.path))
        return self.clonePath(newpath)
Beispiel #53
0
    def getArguments(self, store, args):
        run = store.dbdir.child("run")
        logs = run.child("logs")
        handleLogfile = True
        handlePidfile = True

        for arg in args:
            if arg.startswith("--logfile=") or arg in ("-l", "--logfile", "-n",
                                                       "--nodaemon"):
                handleLogfile = False
            elif arg.startswith("--pidfile=") or arg == "--pidfile":
                handlePidfile = False

        if handleLogfile:
            if not logs.exists():
                logs.makedirs()
            args.extend(["--logfile", logs.child("axiomatic.log").path])

        if not platform.isWindows() and handlePidfile:
            args.extend(["--pidfile", run.child("axiomatic.pid").path])
        args.extend(["axiomatic-start", "--dbdir", store.dbdir.path])
        return args
    def getNumberOfHardLinks(self):
        """
        Retrieves the number of hard links to the file.  This count keeps
        track of how many directories have entries for this file.  If the
        count is ever decremented to zero then the file itself is discarded
        as soon as no process still holds it open.  Symbolic links are not
        counted in the total.

        @raise: NotImplementedError if the platform is Windows, since Windows
                doesn't maintain a link count for directories, and os.stat
                does not set st_nlink on Windows anyway.
        @return: the number of hard links to the file
        @rtype: C{int}
        @since: 11.0
        """
        if platform.isWindows():
            raise NotImplementedError

        st = self.statinfo
        if not st:
            self.restat()
            st = self.statinfo
        return int(st.st_nlink)
Beispiel #55
0
    def setUp(self):
        """
        Create a file that will have known line numbers when emitting warnings.
        """
        self.package = FilePath(
            self.mktemp().encode("utf-8")).child(b'twisted_private_helper')
        self.package.makedirs()
        self.package.child(b'__init__.Dockerfile.vv').setContent(b'')
        self.package.child(b'module.Dockerfile.vv').setContent(b'''
"A module string"

from twisted.python import deprecate

def testFunction():
    "A doc string"
    a = 1 + 2
    return a

def callTestFunction():
    b = testFunction()
    if b == 3:
        deprecate.warnAboutFunction(testFunction, "A Warning String")
''')
        # Python 3 doesn't accept bytes in sys.path:
        packagePath = self.package.parent().path.decode("utf-8")
        sys.path.insert(0, packagePath)
        self.addCleanup(sys.path.remove, packagePath)

        modules = sys.modules.copy()
        self.addCleanup(lambda:
                        (sys.modules.clear(), sys.modules.update(modules)))

        # On Windows on Python 3, most FilePath interactions produce
        # DeprecationWarnings, so flush them here so that they don't interfere
        # with the tests.
        if platform.isWindows() and _PY3:
            self.flushWarnings()
Beispiel #56
0
    def _cbLostConns(self, results):
        (sSuccess, sResult), (cSuccess, cResult) = results

        self.assertFalse(sSuccess)
        self.assertFalse(cSuccess)

        acceptableErrors = [SSL.Error]

        # Rather than getting a verification failure on Windows, we are getting
        # a connection failure.  Without something like sslverify proxying
        # in-between we can't fix up the platform's errors, so let's just
        # specifically say it is only OK in this one case to keep the tests
        # passing.  Normally we'd like to be as strict as possible here, so
        # we're not going to allow this to report errors incorrectly on any
        # other platforms.

        if platform.isWindows():
            from twisted.internet.error import ConnectionLost
            acceptableErrors.append(ConnectionLost)

        sResult.trap(*acceptableErrors)
        cResult.trap(*acceptableErrors)

        return self.serverPort.stopListening()