Example #1
0
def _getInstallFunction(platform):
    """
    Return a function to install the reactor most suited for the given platform.

    @param platform: The platform for which to select a reactor.
    @type platform: L{twisted.python.runtime.Platform}

    @return: A zero-argument callable which will install the selected
        reactor.
    """
    # Linux: epoll(7) is the default, since it scales well.
    #
    # macOS: poll(2) is not exposed by Python because it doesn't support all
    # file descriptors (in particular, lack of PTY support is a problem) --
    # see <http://bugs.python.org/issue5154>. kqueue has the same restrictions
    # as poll(2) as far PTY support goes.
    #
    # Windows: IOCP should eventually be default, but still has some serious
    # bugs, e.g. <http://twistedmatrix.com/trac/ticket/4667>.
    #
    # We therefore choose epoll(7) on Linux, poll(2) on other non-macOS POSIX
    # platforms, and select(2) everywhere else.
    try:
        if platform.isLinux():
            try:
                from twisted.internet.epollreactor import install
            except ImportError:
                from twisted.internet.pollreactor import install
        elif platform.getType() == 'posix' and not platform.isMacOSX():
            from twisted.internet.pollreactor import install
        else:
            from twisted.internet.selectreactor import install
    except ImportError:
        from twisted.internet.selectreactor import install
    return install
Example #2
0
    def getHandleErrorCode(self):
        """
        Return the argument L{OpenSSL.SSL.Error} will be constructed with for
        this case. This is basically just a random OpenSSL implementation
        detail. It would be better if this test worked in a way which did not
        require this.
        """
        # Windows 2000 SP 4 and Windows XP SP 2 give back WSAENOTSOCK for
        # SSL.Connection.write for some reason.  The twisted.protocols.tls
        # implementation of IReactorSSL doesn't suffer from this imprecation,
        # though, since it is isolated from the Windows I/O layer (I suppose?).

        # If test_properlyCloseFiles waited for the SSL handshake to complete
        # and performed an orderly shutdown, then this would probably be a
        # little less weird: writing to a shutdown SSL connection has a more
        # well-defined failure mode (or at least it should).

        # So figure out if twisted.protocols.tls is in use.  If it can be
        # imported, it should be.
        if requireModule('twisted.protocols.tls') is None:
            # It isn't available, so we expect WSAENOTSOCK if we're on Windows.
            if platform.getType() == 'win32':
                return errno.WSAENOTSOCK

        # Otherwise, we expect an error about how we tried to write to a
        # shutdown connection.  This is terribly implementation-specific.
        return [('SSL routines', 'SSL_write', 'protocol is shutdown')]
    def test_recursiveConfiguration(self):
        """
        Recursive DNS lookups, if enabled, should be a last-resort option.
        Any other lookup method (cache, local lookup, etc.) should take
        precedence over recursive lookups
        """
        options = Options()
        options.parseOptions(['--hosts-file', 'hosts.txt', '--recursive'])
        ca, cl = _buildResolvers(options)

        # Extra cleanup, necessary on POSIX because client.Resolver doesn't know
        # when to stop parsing resolv.conf.  See #NNN for improving this.
        for x in cl:
            if isinstance(x, ResolverChain):
                recurser = x.resolvers[-1]
                if isinstance(recurser, Resolver):
                    recurser._parseCall.cancel()

        # On Windows, we need to use a threaded resolver, which leaves trash
        # lying about that we can't easily clean up without reaching into the
        # reactor and cancelling them. We only cancel the cleanup functions, as
        # there should be no others (and it leaving a callLater lying about
        # should rightly cause the test to fail).
        if platform.getType() != 'posix':

            # We want the delayed calls on the reactor, which should be all of
            # ours from the threaded resolver cleanup
            from twisted.internet import reactor
            for x in reactor._newTimedCalls:
                self.assertEqual(x.func.__func__, ThreadedResolver._cleanup)
                x.cancel()

        self.assertIsInstance(cl[-1], ResolverChain)
Example #4
0
def createResolver(servers=None, resolvconf=None, hosts=None):
    if hosts is None:
        hosts = b'/etc/hosts' if platform.getType() == 'posix' else r'c:\windows\hosts'
    theResolver = Resolver(resolvconf, servers)
    hostResolver = hostsModule.Resolver(hosts)
    chain = [hostResolver, cache.CacheResolver(), theResolver]
    return resolve.ResolverChain(chain)
Example #5
0
    def __init__(self, name, uid=None, gid=None, authorizer=None):
        """Initialize me.

        Arguments:

          * name: a name

          * uid: (optional) a POSIX user-id.  Only used on POSIX systems.

          * gid: (optional) a POSIX group-id.  Only used on POSIX systems.

          * authorizer: a twisted.internet.passport.Authorizer.

        If uid and gid arguments are not provided, this application will
        default to having the uid and gid of the user and group who created it.
        """
        roots.Constrained.__init__(self)
        
        self.name = name
        # a list of (tcp, ssl, udp) Ports
        self.ports = []
        # a list of twisted.python.delay.Delayeds
        self.delayeds = []
        # a list of twisted.internet.passport.Services
        self.services = {}
        # a passport authorizer
        self.authorizer = authorizer or passport.DefaultAuthorizer()
        if platform.getType() == "posix":
            self.uid = uid or os.getuid()
            self.gid = gid or os.getgid()
        self.resolver = main.resolver
        self._addEntitiesAndLock()
Example #6
0
    def wrapper(self, *args, **kwargs):
        supported = platform.getType() == "posix"

        if supported:
            return f(self, *args, **kwargs)
        else:
            e = self.assertRaises(
                (NotImplementedError, SkipTest, self.failureException), f,
                self, *args, **kwargs)
            if isinstance(e, NotImplementedError):
                self.assertTrue(
                    str(e).startswith("isRunning is not implemented on "))
Example #7
0
 def getHandleErrorCode(self):
     """
     Return the argument L{SSL.Error} will be constructed with for this
     case.  This is basically just a random OpenSSL implementation detail.
     It would be better if this test worked in a way which did not require
     this.
     """
     # Windows 2000 SP 4 and Windows XP SP 2 give back WSAENOTSOCK for
     # SSL.Connection.write for some reason.
     if platform.getType() == 'win32':
         return errno.WSAENOTSOCK
     # This is terribly implementation-specific.
     return [('SSL routines', 'SSL_write', 'protocol is shutdown')]
Example #8
0
    def save(self, tag=None, filename=None, passphrase=None):
        """Save a pickle of this application to a file in the current directory.
        """
        if self.persistStyle == "xml":
            from twisted.persisted.marmalade import jellyToXML
            dumpFunc = jellyToXML
            ext = "tax"
        elif self.persistStyle == "aot":
            from twisted.persisted.aot import jellyToSource
            dumpFunc = jellyToSource
            ext = "tas"
        else:

            def dumpFunc(obj, file, _dump=pickle.dump):
                _dump(obj, file, 1)

            ext = "tap"
        if filename:
            finalname = filename
            filename = finalname + "-2"
        else:
            if passphrase:
                ext = 'e' + ext
            if tag:
                filename = "%s-%s-2.%s" % (self.name, tag, ext)
                finalname = "%s-%s.%s" % (self.name, tag, ext)
            else:
                filename = "%s-2.%s" % (self.name, ext)
                finalname = "%s.%s" % (self.name, ext)
        log.msg("Saving " + self.name + " application to " + finalname + "...")

        if passphrase is None:
            f = open(filename, 'wb')
            dumpFunc(self, f)
            f.flush()
            f.close()
        else:
            f = StringIO.StringIO()
            dumpFunc(self, f)
            s = encrypt(passphrase, f.getvalue())
            f = open(filename, 'wb')
            f.write(s)
            f.flush()
            f.close()

        if platform.getType() == "win32":
            if os.path.isfile(finalname):
                os.remove(finalname)
        os.rename(filename, finalname)
        log.msg("Saved.")
Example #9
0
    def __init__(self,
                 name,
                 uid=None,
                 gid=None,
                 authorizer=None,
                 authorizer_=None):
        """Initialize me.

        If uid and gid arguments are not provided, this application will
        default to having the uid and gid of the user and group who created it.

        @param name: a name

        @param uid: (optional) a POSIX user-id.  Only used on POSIX systems.

        @param gid: (optional) a POSIX group-id.  Only used on POSIX systems.
        """
        _AbstractServiceCollection.__init__(self)
        self.name = name
        # a list of (tcp, ssl, udp) Ports
        self.tcpPorts = []  # check
        self.udpPorts = []
        self.sslPorts = []
        self.unixPorts = []
        self.extraPorts = []
        self._listenerDict = {}
        self._extraListeners = {}
        # a list of (tcp, ssl, udp) Connectors
        self.tcpConnectors = []
        self.udpConnectors = []
        self.sslConnectors = []
        self.unixConnectors = []
        self.extraConnectors = []
        # a dict of ApplicationServices
        self.services = {}  # check
        # a cred authorizer
        a = authorizer or authorizer_
        if a:
            self._authorizer = a
            self._authorizer.setServiceCollection(self)
        if platform.getType() == "posix":
            if uid is None:
                uid = os.getuid()
            self.uid = uid
            if gid is None:
                gid = os.getgid()
            self.gid = gid
Example #10
0
def create_resolver(servers=None, resolvconf=None, hosts=None):
    if platform.getType() == 'posix':
        if resolvconf is None:
            resolvconf = b'/etc/resolv.conf'
        if hosts is None:
            hosts = b'/etc/hosts'
        the_resolver = client.Resolver(resolvconf, servers)
        host_resolver = Resolver(hosts)
    else:
        if hosts is None:
            hosts = r'c:\windows\hosts'
        from twisted.internet import reactor
        bootstrap = client._ThreadedResolverImpl(reactor)
        host_resolver = Resolver(hosts)
        the_resolver = root.bootstrap(bootstrap, resolverFactory=client.Resolver)

    return resolve.ResolverChain([host_resolver, cache.CacheResolver(), the_resolver])
Example #11
0
def createResolver(servers=None, resolvconf=None, hosts=None):
    from twisted.names import resolve, cache, root, hosts as hostsModule
    if platform.getType() == 'posix':
        if resolvconf is None:
            resolvconf = '/etc/resolv.conf'
        if hosts is None:
            hosts = '/etc/hosts'
        theResolver = HardcoreResolver(resolvconf, servers)
        hostResolver = hostsModule.Resolver(hosts)
    else:
        if hosts is None:
            hosts = r'c:\windows\hosts'
        from twisted.internet import reactor
        bootstrap = _ThreadedResolverImpl(reactor)
        hostResolver = hostsModule.Resolver(hosts)
        theResolver = root.bootstrap(bootstrap)

    L = [hostResolver, cache.CacheResolver(), theResolver]
    return resolve.ResolverChain(L)
Example #12
0
 def save(self, tag=None):
     """Save a pickle of this application to a file in the current directory.
     """
     from cPickle import dump
     if tag:
         filename = self.name+'-'+tag+'-2.tap'
         finalname = self.name+'-'+tag+'.tap'
     else:
         filename = self.name+"-2.tap"
         finalname = self.name+".tap"
     log.msg("Saving "+self.name+" application to "+finalname+"...")
     f = open(filename, 'wb')
     dump(self, f, 1)
     f.flush()
     f.close()
     if platform.getType() == "win32":
         if os.path.isfile(finalname):
             os.remove(finalname)
     os.rename(filename, finalname)
     log.msg("Saved.")
Example #13
0
    def getHandleErrorCode(self):
        """
        Return the argument L{SSL.Error} will be constructed with for this
        case.  This is basically just a random OpenSSL implementation detail.
        It would be better if this test worked in a way which did not require
        this.
        """
        # Windows 2000 SP 4 and Windows XP SP 2 give back WSAENOTSOCK for
        # SSL.Connection.write for some reason.  The twisted.protocols.tls
        # implementation of IReactorSSL doesn't suffer from this imprecation,
        # though, since it is isolated from the Windows I/O layer (I suppose?).

        # If test_properlyCloseFiles waited for the SSL handshake to complete
        # and performed an orderly shutdown, then this would probably be a
        # little less weird: writing to a shutdown SSL connection has a more
        # well-defined failure mode (or at least it should).
        name = fullyQualifiedName(getClass(reactor))
        if platform.getType() == 'win32' and name != self._iocp:
            return errno.WSAENOTSOCK
        # This is terribly implementation-specific.
        return [('SSL routines', 'SSL_write', 'protocol is shutdown')]
Example #14
0
def createResolver(servers=None, resolvconf=None, hosts=None):
    r"""
    Create and return a Resolver.

    @type servers: C{list} of C{(str, int)} or L{None}

    @param servers: If not L{None}, interpreted as a list of domain name servers
    to attempt to use. Each server is a tuple of address in C{str} dotted-quad
    form and C{int} port number.

    @type resolvconf: C{str} or L{None}
    @param resolvconf: If not L{None}, on posix systems will be interpreted as
    an alternate resolv.conf to use. Will do nothing on windows systems. If
    L{None}, /etc/resolv.conf will be used.

    @type hosts: C{str} or L{None}
    @param hosts: If not L{None}, an alternate hosts file to use. If L{None}
    on posix systems, /etc/hosts will be used. On windows, C:\windows\hosts
    will be used.

    @rtype: C{IResolver}
    """
    if platform.getType() == "posix":
        if resolvconf is None:
            resolvconf = b"/etc/resolv.conf"
        if hosts is None:
            hosts = b"/etc/hosts"
        theResolver = Resolver(resolvconf, servers)
        hostResolver = hostsModule.Resolver(hosts)
    else:
        if hosts is None:
            hosts = r"c:\windows\hosts"
        from twisted.internet import reactor

        bootstrap = _ThreadedResolverImpl(reactor)
        hostResolver = hostsModule.Resolver(hosts)
        theResolver = root.bootstrap(bootstrap, resolverFactory=Resolver)

    L = [hostResolver, cache.CacheResolver(), theResolver]
    return resolve.ResolverChain(L)
Example #15
0
def createResolver(servers=None, resolvconf=None, hosts=None):
    """
    Create and return a Resolver.

    @type servers: C{list} of C{(str, int)} or C{None}
    @param servers: If not C{None}, interpreted as a list of addresses of
    domain name servers to attempt to use.  Addresses should be in dotted-quad
    form.

    @type resolvconf: C{str} or C{None}
    @param resolvconf: If not C{None}, on posix systems will be interpreted as
    an alternate resolv.conf to use. Will do nothing on windows systems. If
    C{None}, /etc/resolv.conf will be used.

    @type hosts: C{str} or C{None}
    @param hosts: If not C{None}, an alternate hosts file to use. If C{None}
    on posix systems, /etc/hosts will be used. On windows, C:\windows\hosts
    will be used.

    @rtype: C{IResolver}
    """
    from twisted.names import resolve, cache, root, hosts as hostsModule
    if platform.getType() == 'posix':
        if resolvconf is None:
            resolvconf = '/etc/resolv.conf'
        if hosts is None:
            hosts = '/etc/hosts'
        theResolver = Resolver(resolvconf, servers)
        hostResolver = hostsModule.Resolver(hosts)
    else:
        if hosts is None:
            hosts = r'c:\windows\hosts'
        from twisted.internet import reactor
        bootstrap = _ThreadedResolverImpl(reactor)
        hostResolver = hostsModule.Resolver(hosts)
        theResolver = root.bootstrap(bootstrap)

    L = [hostResolver, cache.CacheResolver(), theResolver]
    return resolve.ResolverChain(L)
Example #16
0
def _get_reactor(platform):
    try:
        if platform.isLinux():
            try:
                from twisted.internet import epollreactor
                cls = epollreactor.EPollReactor
            except ImportError:
                from twisted.internet import pollreactor
                cls = pollreactor.PollReactor
        elif platform.isMacOSX():
            from twisted.internet import kqreactor
            cls = kqreactor.KQueueReactor
        elif platform.getType() == 'posix' and not platform.isMacOSX():
            from twisted.internet import pollreactor
            cls = pollreactor.PollReactor
        else:
            from twisted.internet import selectreactor
            cls = selectreactor.SelectReactor
    except ImportError:
        from twisted.internet import selectreactor
        cls = selectreactor.SelectReactor
    return cls()
Example #17
0
class Gtk3ReactorTests(TestCase):
    """
    Tests for L{gtk3reactor}.
    """

    def test_requiresDISPLAY(self):
        """
        On X11, L{gtk3reactor} is unimportable if the C{DISPLAY} environment
        variable is not set.
        """
        display = os.environ.get("DISPLAY", None)
        if display is not None:
            self.addCleanup(os.environ.__setitem__, "DISPLAY", display)
            del os.environ["DISPLAY"]
        with SetAsideModule("twisted.internet.gtk3reactor"):
            exc = self.assertRaises(ImportError,
                                    __import__, "twisted.internet.gtk3reactor")
            self.assertEqual(
                exc.args[0],
                "Gtk3 requires X11, and no DISPLAY environment variable is set")

    if platform.getType() != "posix" or platform.isMacOSX():
        test_requiresDISPLAY.skip = "This test is only relevant when using X11"
Example #18
0
class FilePathTestCase(unittest.TestCase):

    f1content = "file 1"
    f2content = "file 2"

    def _mkpath(self, *p):
        x = os.path.abspath(os.path.join(self.cmn, *p))
        self.all.append(x)
        return x

    def subdir(self, *dirname):
        os.mkdir(self._mkpath(*dirname))

    def subfile(self, *dirname):
        return open(self._mkpath(*dirname), "wb")

    def setUp(self):
        self.now = time.time()
        cmn = self.cmn = os.path.abspath(self.mktemp())
        self.all = [cmn]
        os.mkdir(cmn)
        self.subdir("sub1")
        f = self.subfile("file1")
        f.write(self.f1content)
        f = self.subfile("sub1", "file2")
        f.write(self.f2content)
        self.subdir('sub3')
        f = self.subfile("sub3", "file3.ext1")
        f = self.subfile("sub3", "file3.ext2")
        f = self.subfile("sub3", "file3.ext3")
        self.all.sort()

        self.path = filepath.FilePath(cmn)

    def testWalk(self):
        x = [foo.path for foo in self.path.walk()]
        x.sort()
        self.assertEquals(x, self.all)

    def testGetAndSet(self):
        content = 'newcontent'
        self.path.child('new').setContent(content)
        newcontent = self.path.child('new').getContent()
        self.failUnlessEqual(content, newcontent)
        content = 'content'
        self.path.child('new').setContent(content, '.tmp')
        newcontent = self.path.child('new').getContent()
        self.failUnlessEqual(content, newcontent)

    if platform.getType() == 'win32':
        testGetAndSet.todo = "os.rename in FilePath.setContent doesn't work too well on Windows"

    def testValidSubdir(self):
        sub1 = self.path.child('sub1')
        self.failUnless(sub1.exists(), "This directory does exist.")
        self.failUnless(sub1.isdir(), "It's a directory.")
        self.failUnless(not sub1.isfile(), "It's a directory.")
        self.failUnless(not sub1.islink(), "It's a directory.")
        self.failUnlessEqual(sub1.listdir(), ['file2'])

    def testMultiExt(self):
        f3 = self.path.child('sub3').child('file3')
        exts = '.foo', '.bar', 'ext1', 'ext2', 'ext3'
        self.failIf(f3.siblingExtensionSearch(*exts))
        f3e = f3.siblingExtension(".foo")
        f3e.touch()
        self.failIf(not f3.siblingExtensionSearch(*exts).exists())
        self.failIf(not f3.siblingExtensionSearch('*').exists())
        f3e.remove()
        self.failIf(f3.siblingExtensionSearch(*exts))

    def testInvalidSubdir(self):
        sub2 = self.path.child('sub2')
        self.failIf(sub2.exists(), "This directory does not exist.")

    def testValidFiles(self):
        f1 = self.path.child('file1')
        self.failUnlessEqual(f1.open().read(), self.f1content)
        f2 = self.path.child('sub1').child('file2')
        self.failUnlessEqual(f2.open().read(), self.f2content)

    def testPreauthChild(self):
        fp = filepath.FilePath('.')
        fp.preauthChild('foo/bar')
        self.assertRaises(filepath.InsecurePath, fp.child, '/foo')

    def testStatCache(self):
        p = self.path.child('stattest')
        p.touch()
        self.failUnlessEqual(p.getsize(), 0)
        self.failUnlessEqual(abs(p.getmtime() - time.time()) // 20, 0)
        self.failUnlessEqual(abs(p.getctime() - time.time()) // 20, 0)
        self.failUnlessEqual(abs(p.getatime() - time.time()) // 20, 0)
        self.failUnlessEqual(p.exists(), True)
        self.failUnlessEqual(p.exists(), True)
        # OOB removal: FilePath.remove() will automatically restat
        os.remove(p.path)
        # test caching
        self.failUnlessEqual(p.exists(), True)
        p.restat(reraise=False)
        self.failUnlessEqual(p.exists(), False)
        self.failUnlessEqual(p.islink(), False)
        self.failUnlessEqual(p.isdir(), False)
        self.failUnlessEqual(p.isfile(), False)

    def testPersist(self):
        newpath = pickle.loads(pickle.dumps(self.path))
        self.failUnlessEqual(self.path.__class__, newpath.__class__)
        self.failUnlessEqual(self.path.path, newpath.path)

    def testInsecureUNIX(self):
        self.assertRaises(filepath.InsecurePath, self.path.child, "..")
        self.assertRaises(filepath.InsecurePath, self.path.child, "/etc")
        self.assertRaises(filepath.InsecurePath, self.path.child, "../..")

    def testInsecureWin32(self):
        self.assertRaises(filepath.InsecurePath, self.path.child, r"..\..")
        self.assertRaises(filepath.InsecurePath, self.path.child,
                          r"C:randomfile")

    if platform.getType() != 'win32':
        testInsecureWin32.skip = "Consider yourself lucky."

    def testInsecureWin32Whacky(self):
        """Windows has 'special' filenames like NUL and CON and COM1 and LPR
        and PRN and ... god knows what else.  They can be located anywhere in
        the filesystem.  For obvious reasons, we do not wish to normally permit
        access to these.
        """
        self.assertRaises(filepath.InsecurePath, self.path.child, "CON")
        self.assertRaises(filepath.InsecurePath, self.path.child, "C:CON")
        self.assertRaises(filepath.InsecurePath, self.path.child, r"C:\CON")

    if platform.getType() != 'win32':
        testInsecureWin32Whacky.skip = "Consider yourself lucky."

    def testComparison(self):
        self.assertEquals(filepath.FilePath('a'), filepath.FilePath('a'))
        self.failUnless(filepath.FilePath('z') > filepath.FilePath('a'))
        self.failUnless(filepath.FilePath('z') >= filepath.FilePath('a'))
        self.failUnless(filepath.FilePath('a') >= filepath.FilePath('a'))
        self.failUnless(filepath.FilePath('a') <= filepath.FilePath('a'))
        self.failUnless(filepath.FilePath('a') < filepath.FilePath('z'))
        self.failUnless(filepath.FilePath('a') <= filepath.FilePath('z'))
        self.failUnless(filepath.FilePath('a') != filepath.FilePath('z'))
        self.failUnless(filepath.FilePath('z') != filepath.FilePath('a'))

        self.failIf(filepath.FilePath('z') != filepath.FilePath('z'))

    def testSibling(self):
        p = self.path.child('sibling_start')
        ts = p.sibling('sibling_test')
        self.assertEquals(ts.dirname(), p.dirname())
        self.assertEquals(ts.basename(), 'sibling_test')
        ts.createDirectory()
        self.assertIn(ts, self.path.children())

    def testTemporarySibling(self):
        ts = self.path.temporarySibling()
        self.assertEquals(ts.dirname(), self.path.dirname())
        self.assertNotIn(ts.basename(), self.path.listdir())
        ts.createDirectory()
        self.assertIn(ts, self.path.parent().children())

    def testRemove(self):
        self.path.remove()
        self.failIf(self.path.exists())

    def testCopyTo(self):
        self.assertRaises((OSError, IOError), self.path.copyTo,
                          self.path.child('file1'))
        oldPaths = list(self.path.walk())  # Record initial state
        fp = filepath.FilePath(self.mktemp())
        self.path.copyTo(fp)
        self.path.remove()
        fp.copyTo(self.path)
        newPaths = list(self.path.walk())  # Record double-copy state
        newPaths.sort()
        oldPaths.sort()
        self.assertEquals(newPaths, oldPaths)

    def testMoveTo(self):
        self.assertRaises((OSError, IOError), self.path.moveTo,
                          self.path.child('file1'))
        oldPaths = list(self.path.walk())  # Record initial state
        fp = filepath.FilePath(self.mktemp())
        self.path.moveTo(fp)
        fp.moveTo(self.path)
        newPaths = list(self.path.walk())  # Record double-move state
        newPaths.sort()
        oldPaths.sort()
        self.assertEquals(newPaths, oldPaths)

    def testCrossMountMoveTo(self):
        """
        """
        # Bit of a whitebox test - force os.rename, which moveTo tries
        # before falling back to a slower method, to fail, forcing moveTo to
        # use the slower behavior.
        invokedWith = []

        def faultyRename(src, dest):
            invokedWith.append((src, dest))
            if len(invokedWith) == 2:
                raise OSError(
                    errno.EXDEV,
                    'Test-induced failure simulating cross-device rename failure'
                )
            return originalRename(src, dest)

        originalRename = os.rename
        os.rename = faultyRename
        try:
            self.testMoveTo()
            # A bit of a sanity check for this whitebox test - if our rename
            # was never invoked, the test has probably fallen into
            # disrepair!
            self.failUnless(len(invokedWith) >= 2)
        finally:
            os.rename = originalRename

    def testOpen(self):
        # Opening a file for reading when it does not already exist is an error
        nonexistent = self.path.child('nonexistent')
        e = self.assertRaises(IOError, nonexistent.open)
        self.assertEquals(e.errno, errno.ENOENT)

        # Opening a file for writing when it does not exist is okay
        writer = self.path.child('writer')
        f = writer.open('w')
        f.write('abc\ndef')
        f.close()

        # Make sure those bytes ended up there - and test opening a file for
        # reading when it does exist at the same time
        f = writer.open()
        self.assertEquals(f.read(), 'abc\ndef')
        f.close()

        # Re-opening that file in write mode should erase whatever was there.
        f = writer.open('w')
        f.close()
        f = writer.open()
        self.assertEquals(f.read(), '')
        f.close()

        # Put some bytes in a file so we can test that appending does not
        # destroy them.
        appender = self.path.child('appender')
        f = appender.open('w')
        f.write('abc')
        f.close()

        f = appender.open('a')
        f.write('def')
        f.close()

        f = appender.open('r')
        self.assertEquals(f.read(), 'abcdef')
        f.close()

        # read/write should let us do both without erasing those bytes
        f = appender.open('r+')
        self.assertEquals(f.read(), 'abcdef')
        # ANSI C *requires* an fseek or an fgetpos between an fread and an
        # fwrite or an fwrite and a fread.  We can't reliable get Python to
        # invoke fgetpos, so we seek to a 0 byte offset from the current
        # position instead.  Also, Python sucks for making this seek
        # relative to 1 instead of a symbolic constant representing the
        # current file position.
        f.seek(0, 1)
        # Put in some new bytes for us to test for later.
        f.write('ghi')
        f.close()

        # Make sure those new bytes really showed up
        f = appender.open('r')
        self.assertEquals(f.read(), 'abcdefghi')
        f.close()

        # write/read should let us do both, but erase anything that's there
        # already.
        f = appender.open('w+')
        self.assertEquals(f.read(), '')
        f.seek(0, 1)  # Don't forget this!
        f.write('123')
        f.close()

        # super append mode should let us read and write and also position the
        # cursor at the end of the file, without erasing everything.
        f = appender.open('a+')

        # The order of these lines may seem surprising, but it is necessary.
        # The cursor is not at the end of the file until after the first write.
        f.write('456')
        f.seek(0, 1)  # Asinine.
        self.assertEquals(f.read(), '')

        f.seek(0, 0)
        self.assertEquals(f.read(), '123456')
        f.close()

        # Opening a file exclusively must fail if that file exists already.
        nonexistent.requireCreate(True)
        nonexistent.open('w').close()
        existent = nonexistent
        del nonexistent
        self.assertRaises((OSError, IOError), existent.open)
Example #19
0
    def testPersist(self):
        newpath = pickle.loads(pickle.dumps(self.path))
        self.failUnlessEqual(self.path.__class__, newpath.__class__)
        self.failUnlessEqual(self.path.path, newpath.path)

    def testInsecureUNIX(self):
        self.assertRaises(filepath.InsecurePath, self.path.child, "..")
        self.assertRaises(filepath.InsecurePath, self.path.child, "/etc")
        self.assertRaises(filepath.InsecurePath, self.path.child, "../..")

    def testInsecureWin32(self):
        self.assertRaises(filepath.InsecurePath, self.path.child, r"..\..")
        self.assertRaises(filepath.InsecurePath, self.path.child,
                          r"C:randomfile")

    if platform.getType() != 'win32':
        testInsecureWin32.skip = "Consider yourself lucky."

    def testInsecureWin32Whacky(self):
        """Windows has 'special' filenames like NUL and CON and COM1 and LPR
        and PRN and ... god knows what else.  They can be located anywhere in
        the filesystem.  For obvious reasons, we do not wish to normally permit
        access to these.
        """
        self.assertRaises(filepath.InsecurePath, self.path.child, "CON")
        self.assertRaises(filepath.InsecurePath, self.path.child, "C:CON")
        self.assertRaises(filepath.InsecurePath, self.path.child, r"C:\CON")

    if platform.getType() != 'win32':
        testInsecureWin32Whacky.skip = "Consider yourself lucky."
Example #20
0
class AsyncioSelectorReactorTests(ReactorBuilder, SynchronousTestCase):
    """
    L{AsyncioSelectorReactor} tests.
    """

    _defaultEventLoop = DefaultEventLoopPolicy().new_event_loop()
    _defaultEventLoopIsSelector = isinstance(_defaultEventLoop,
                                             SelectorEventLoop)

    def assertReactorWorksWithAsyncioFuture(self, reactor):
        """
        Ensure that C{reactor} has an event loop that works
        properly with L{asyncio.Future}.
        """
        future = Future()
        result = []

        def completed(future):
            result.append(future.result())
            reactor.stop()

        future.add_done_callback(completed)
        future.set_result(True)

        self.assertEqual(result, [])
        self.runReactor(reactor, timeout=1)
        self.assertEqual(result, [True])

    @skipIf(
        not _defaultEventLoopIsSelector,
        "default event loop: {}\nis not of type SelectorEventLoop "
        "on Python {}.{} ({})".format(
            type(_defaultEventLoop),
            sys.version_info.major,
            sys.version_info.minor,
            platform.getType(),
        ),
    )
    def test_defaultSelectorEventLoopFromGlobalPolicy(self):
        """
        L{AsyncioSelectorReactor} wraps the global policy's event loop
        by default.  This ensures that L{asyncio.Future}s and
        coroutines created by library code that uses
        L{asyncio.get_event_loop} are bound to the same loop.
        """
        reactor = AsyncioSelectorReactor()
        self.assertReactorWorksWithAsyncioFuture(reactor)

    @skipIf(
        not _defaultEventLoopIsSelector,
        "default event loop: {}\nis not of type SelectorEventLoop "
        "on Python {}.{} ({})".format(
            type(_defaultEventLoop),
            sys.version_info.major,
            sys.version_info.minor,
            platform.getType(),
        ),
    )
    def test_newSelectorEventLoopFromDefaultEventLoopPolicy(self):
        """
        If we use the L{asyncio.DefaultLoopPolicy} to create a new event loop,
        and then pass that event loop to a new L{AsyncioSelectorReactor},
        this reactor should work properly with L{asyncio.Future}.
        """
        event_loop = DefaultEventLoopPolicy().new_event_loop()
        reactor = AsyncioSelectorReactor(event_loop)
        set_event_loop(event_loop)
        self.assertReactorWorksWithAsyncioFuture(reactor)
        set_event_loop_policy(None)

    @skipIf(
        _defaultEventLoopIsSelector,
        "default event loop: {}\nis of type SelectorEventLoop "
        "on Python {}.{} ({})".format(
            type(_defaultEventLoop),
            sys.version_info.major,
            sys.version_info.minor,
            platform.getType(),
        ),
    )
    def test_defaultNotASelectorEventLoopFromGlobalPolicy(self):
        """
        On Windows Python 3.5 to 3.7, L{get_event_loop()} returns a
        L{WindowsSelectorEventLoop} by default.
        On Windows Python 3.8+, L{get_event_loop()} returns a
        L{WindowsProactorEventLoop} by default.
        L{AsyncioSelectorReactor} should raise a
        L{TypeError} if the default event loop is not a
        L{WindowsSelectorEventLoop}.
        """
        self.assertRaises(TypeError, AsyncioSelectorReactor)

    @skipIf(not hasWindowsProactorEventLoopPolicy,
            "WindowsProactorEventLoop not available")
    def test_WindowsProactorEventLoop(self):
        """
        L{AsyncioSelectorReactor} will raise a L{TypeError}
        if instantiated with a L{asyncio.WindowsProactorEventLoop}
        """
        event_loop = WindowsProactorEventLoopPolicy().new_event_loop()
        self.assertRaises(TypeError, AsyncioSelectorReactor, event_loop)

    @skipIf(
        not hasWindowsSelectorEventLoopPolicy,
        "WindowsSelectorEventLoop only on Windows",
    )
    def test_WindowsSelectorEventLoop(self):
        """
        L{WindowsSelectorEventLoop} works with L{AsyncioSelectorReactor}
        """
        event_loop = WindowsSelectorEventLoopPolicy().new_event_loop()
        reactor = AsyncioSelectorReactor(event_loop)
        set_event_loop(event_loop)
        self.assertReactorWorksWithAsyncioFuture(reactor)
        set_event_loop_policy(None)

    @skipIf(
        not hasWindowsProactorEventLoopPolicy,
        "WindowsProactorEventLoopPolicy only on Windows",
    )
    def test_WindowsProactorEventLoopPolicy(self):
        """
        L{AsyncioSelectorReactor} will raise a L{TypeError}
        if L{asyncio.WindowsProactorEventLoopPolicy} is default.
        """
        set_event_loop_policy(WindowsProactorEventLoopPolicy())
        with self.assertRaises(TypeError):
            AsyncioSelectorReactor()
        set_event_loop_policy(None)

    @skipIf(
        not hasWindowsSelectorEventLoopPolicy,
        "WindowsSelectorEventLoopPolicy only on Windows",
    )
    def test_WindowsSelectorEventLoopPolicy(self):
        """
        L{AsyncioSelectorReactor} will work if
        if L{asyncio.WindowsSelectorEventLoopPolicy} is default.
        """
        set_event_loop_policy(WindowsSelectorEventLoopPolicy())
        reactor = AsyncioSelectorReactor()
        self.assertReactorWorksWithAsyncioFuture(reactor)
        set_event_loop_policy(None)

    def test_seconds(self):
        """L{seconds} should return a plausible epoch time."""
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(WindowsSelectorEventLoopPolicy())
        reactor = AsyncioSelectorReactor()
        result = reactor.seconds()

        # greater than 2020-01-01
        self.assertGreater(result, 1577836800)

        # less than 2120-01-01
        self.assertLess(result, 4733510400)
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(None)

    def test_delayedCallResetToLater(self):
        """
        L{DelayedCall.reset()} properly reschedules timer to later time
        """
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(WindowsSelectorEventLoopPolicy())

        reactor = AsyncioSelectorReactor()

        timer_called_at = [None]

        def on_timer():
            timer_called_at[0] = reactor.seconds()

        start_time = reactor.seconds()
        dc = reactor.callLater(0, on_timer)
        dc.reset(0.5)
        reactor.callLater(1, reactor.stop)
        reactor.run()

        self.assertIsNotNone(timer_called_at[0])
        self.assertGreater(timer_called_at[0] - start_time, 0.4)
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(None)

    def test_delayedCallResetToEarlier(self):
        """
        L{DelayedCall.reset()} properly reschedules timer to earlier time
        """
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(WindowsSelectorEventLoopPolicy())
        reactor = AsyncioSelectorReactor()

        timer_called_at = [None]

        def on_timer():
            timer_called_at[0] = reactor.seconds()

        start_time = reactor.seconds()
        dc = reactor.callLater(0.5, on_timer)
        dc.reset(0)
        reactor.callLater(1, reactor.stop)

        import io
        from contextlib import redirect_stderr

        stderr = io.StringIO()
        with redirect_stderr(stderr):
            reactor.run()

        self.assertEqual(stderr.getvalue(), "")
        self.assertIsNotNone(timer_called_at[0])
        self.assertLess(timer_called_at[0] - start_time, 0.4)
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(None)

    def test_noCycleReferencesInCallLater(self):
        """
        L{AsyncioSelectorReactor.callLater()} doesn't leave cyclic references
        """
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(WindowsSelectorEventLoopPolicy())
        gc_was_enabled = gc.isenabled()
        gc.disable()
        try:
            objects_before = len(gc.get_objects())
            timer_count = 1000

            reactor = AsyncioSelectorReactor()
            for _ in range(timer_count):
                reactor.callLater(0, lambda: None)
            reactor.runUntilCurrent()

            objects_after = len(gc.get_objects())
            self.assertLess((objects_after - objects_before) / timer_count, 1)
        finally:
            if gc_was_enabled:
                gc.enable()
        if hasWindowsSelectorEventLoopPolicy:
            set_event_loop_policy(None)
Example #21
0
'''

import sys, os
# from twisted.internet import default
# default.install()
from twisted.python.runtime import platform

# print(os.name, '000000000000')                      # posix
if os.name != 'nt':
    try:
        if platform.isLinux():
            try:
                from twisted.internet.epollreactor import install
            except ImportError:
                from twisted.internet.pollreactor import install
        elif platform.getType() == 'posix' and not platform.isMacOSX():
            from twisted.internet.pollreactor import install
        else:
            from twisted.internet.selectreactor import install
    except ImportError:
        from twisted.internet.selectreactor import install
    install()

from twisted.internet import reactor
from twisted.python import log
from learn_twist.utils import services
from learn_twist.netconnect.protoc import LiberateFactory

reactor = reactor
service = services.CommandService("loginService",
                                  run_style=services.Service.PARALLEL_STYLE)
                    # Some unexpected error occurred.
                    raise
        else:
            self.fail(
                "Could provoke neither EMFILE nor ENOBUFS from platform.")

        # Non-blocking connect is supposed to fail, but this is not true
        # everywhere (e.g. freeBSD)
        self.assertIn(client.connect_ex(('127.0.0.1', serverPortNumber)),
                      (0, EINPROGRESS))

        # Make sure that the accept call fails in the way we expect.
        exc = self.assertRaises(socket.error, port.accept)
        self.assertIn(exc.args[0], (EMFILE, ENOBUFS))

    if platform.getType() == "win32":
        test_acceptOutOfFiles.skip = (
            "Windows requires an unacceptably large amount of resources to "
            "provoke this behavior in the naive manner.")


class SelectReactorTestCase(TestCase):
    """
    Tests for select-specific failure conditions.
    """
    def setUp(self):
        self.ports = []
        self.messages = []
        log.addObserver(self.messages.append)

    def tearDown(self):
Example #23
0
class SelectReactorTests(TestCase):
    """
    Tests for select-specific failure conditions.
    """

    def setUp(self):
        self.ports = []
        self.messages = []
        log.addObserver(self.messages.append)


    def tearDown(self):
        log.removeObserver(self.messages.append)
        return gatherResults([
            maybeDeferred(p.stopListening)
            for p in self.ports])


    def port(self, portNumber, factory, interface):
        """
        Create, start, and return a new L{Port}, also tracking it so it can
        be stopped in the test tear down.
        """
        p = Port(portNumber, factory, interface=interface)
        p.startListening()
        self.ports.append(p)
        return p


    def _acceptFailureTest(self, socketErrorNumber):
        """
        Test behavior in the face of an exception from C{accept(2)}.

        On any exception which indicates the platform is unable or unwilling
        to allocate further resources to us, the existing port should remain
        listening, a message should be logged, and the exception should not
        propagate outward from doRead.

        @param socketErrorNumber: The errno to simulate from accept.
        """
        class FakeSocket(object):
            """
            Pretend to be a socket in an overloaded system.
            """
            def accept(self):
                raise socket.error(
                    socketErrorNumber, os.strerror(socketErrorNumber))

        factory = ServerFactory()
        port = self.port(0, factory, interface='127.0.0.1')
        self.patch(port, "socket", FakeSocket())

        port.doRead()

        expectedFormat = "Could not accept new connection ({acceptError})"
        expectedErrorCode = errno.errorcode[socketErrorNumber]
        matchingMessages = [
            (msg.get('log_format') == expectedFormat
             and msg.get('acceptError') == expectedErrorCode)
            for msg in self.messages
        ]
        self.assertGreater(len(matchingMessages), 0,
                           "Log event for failed accept not found in "
                           "%r" % (self.messages,))


    def test_tooManyFilesFromAccept(self):
        """
        C{accept(2)} can fail with C{EMFILE} when there are too many open file
        descriptors in the process.  Test that this doesn't negatively impact
        any other existing connections.

        C{EMFILE} mainly occurs on Linux when the open file rlimit is
        encountered.
        """
        return self._acceptFailureTest(EMFILE)


    def test_noBufferSpaceFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENOBUFS}.

        This mainly occurs on Windows and FreeBSD, but may be possible on
        Linux and other platforms as well.
        """
        return self._acceptFailureTest(ENOBUFS)


    def test_connectionAbortedFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ECONNABORTED}.

        It is not clear whether this is actually possible for TCP
        connections on modern versions of Linux.
        """
        return self._acceptFailureTest(ECONNABORTED)


    @skipIf(platform.getType() == 'win32',
            "Windows accept(2) cannot generate ENFILE")
    def test_noFilesFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENFILE}.

        This can occur on Linux when the system has exhausted (!) its supply
        of inodes.
        """
        return self._acceptFailureTest(ENFILE)


    @skipIf(platform.getType() == 'win32',
            "Windows accept(2) cannot generate ENOMEM")
    def test_noMemoryFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENOMEM}.

        On Linux at least, this can sensibly occur, even in a Python program
        (which eats memory like no ones business), when memory has become
        fragmented or low memory has been filled (d_alloc calls
        kmem_cache_alloc calls kmalloc - kmalloc only allocates out of low
        memory).
        """
        return self._acceptFailureTest(ENOMEM)


    @skipIf(os.environ.get("INFRASTRUCTURE") == "AZUREPIPELINES",
            "Hangs on Azure Pipelines due to firewall")
    def test_acceptScaling(self):
        """
        L{tcp.Port.doRead} increases the number of consecutive
        C{accept} calls it performs if all of the previous C{accept}
        calls succeed; otherwise, it reduces the number to the amount
        of successful calls.
        """
        factory = ServerFactory()
        factory.protocol = Protocol
        port = self.port(0, factory, interface='127.0.0.1')
        self.addCleanup(port.stopListening)

        clients = []

        def closeAll():
            for client in clients:
                client.close()

        self.addCleanup(closeAll)

        def connect():
            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            client.connect(("127.0.0.1", port.getHost().port))
            return client

        clients.append(connect())
        port.numberAccepts = 1
        port.doRead()
        self.assertGreater(port.numberAccepts, 1)

        clients.append(connect())
        port.doRead()
        # There was only one outstanding client connection, so only
        # one accept(2) was possible.
        self.assertEqual(port.numberAccepts, 1)

        port.doRead()
        # There were no outstanding client connections, so only one
        # accept should be tried next.
        self.assertEqual(port.numberAccepts, 1)


    @skipIf(platform.getType() == 'win32',
            "Windows accept(2) cannot generate EPERM")
    def test_permissionFailure(self):
        """
        C{accept(2)} returning C{EPERM} is treated as a transient
        failure and the call retried no more than the maximum number
        of consecutive C{accept(2)} calls.
        """
        maximumNumberOfAccepts = 123
        acceptCalls = [0]

        class FakeSocketWithAcceptLimit(object):
            """
            Pretend to be a socket in an overloaded system whose
            C{accept} method can only be called
            C{maximumNumberOfAccepts} times.
            """
            def accept(oself):
                acceptCalls[0] += 1
                if acceptCalls[0] > maximumNumberOfAccepts:
                    self.fail("Maximum number of accept calls exceeded.")
                raise socket.error(EPERM, os.strerror(EPERM))

        # Verify that FakeSocketWithAcceptLimit.accept() fails the
        # test if the number of accept calls exceeds the maximum.
        for _ in range(maximumNumberOfAccepts):
            self.assertRaises(socket.error,
                              FakeSocketWithAcceptLimit().accept)

        self.assertRaises(self.failureException,
                          FakeSocketWithAcceptLimit().accept)

        acceptCalls = [0]

        factory = ServerFactory()
        port = self.port(0, factory, interface='127.0.0.1')
        port.numberAccepts = 123
        self.patch(port, "socket", FakeSocketWithAcceptLimit())

        # This should not loop infinitely.
        port.doRead()

        # This is scaled down to 1 because no accept(2)s returned
        # successfully.
        self.assertEquals(port.numberAccepts, 1)


    def test_unknownSocketErrorRaise(self):
        """
        A C{socket.error} raised by C{accept(2)} whose C{errno} is
        unknown to the recovery logic is logged.
        """
        knownErrors = list(_ACCEPT_ERRORS)
        knownErrors.extend([EAGAIN, EPERM, EWOULDBLOCK])
        # Windows has object()s stubs for some errnos.
        unknownAcceptError = max(
            error for error in knownErrors
            if isinstance(error, (int, compat.long))
        ) + 1

        class FakeSocketWithUnknownAcceptError(object):
            """
            Pretend to be a socket in an overloaded system whose
            C{accept} method can only be called
            C{maximumNumberOfAccepts} times.
            """
            def accept(oself):
                raise socket.error(unknownAcceptError,
                                   "unknown socket error message")

        factory = ServerFactory()
        port = self.port(0, factory, interface='127.0.0.1')
        self.patch(port, "socket", FakeSocketWithUnknownAcceptError())

        port.doRead()

        failures = self.flushLoggedErrors(socket.error)
        self.assertEqual(1, len(failures))
        self.assertEqual(failures[0].value.args[0], unknownAcceptError)
Example #24
0
 def getHandleErrorCode(self):
     # Windows 2000 SP 4 and Windows XP SP 2 give back WSAENOTSOCK for
     # SSL.Connection.write for some reason.
     if platform.getType() == 'win32':
         return errno.WSAENOTSOCK
     return ProperlyCloseFilesMixin.getHandleErrorCode(self)
class SelectReactorTestCase(TestCase):
    """
    Tests for select-specific failure conditions.
    """
    def setUp(self):
        self.ports = []
        self.messages = []
        log.addObserver(self.messages.append)

    def tearDown(self):
        log.removeObserver(self.messages.append)
        return gatherResults(
            [maybeDeferred(p.stopListening) for p in self.ports])

    def port(self, portNumber, factory, interface):
        """
        Create, start, and return a new L{Port}, also tracking it so it can
        be stopped in the test tear down.
        """
        p = Port(portNumber, factory, interface=interface)
        p.startListening()
        self.ports.append(p)
        return p

    def _acceptFailureTest(self, socketErrorNumber):
        """
        Test behavior in the face of an exception from C{accept(2)}.

        On any exception which indicates the platform is unable or unwilling
        to allocate further resources to us, the existing port should remain
        listening, a message should be logged, and the exception should not
        propagate outward from doRead.

        @param socketErrorNumber: The errno to simulate from accept.
        """
        class FakeSocket(object):
            """
            Pretend to be a socket in an overloaded system.
            """
            def accept(self):
                raise socket.error(socketErrorNumber,
                                   os.strerror(socketErrorNumber))

        factory = ServerFactory()
        port = self.port(0, factory, interface='127.0.0.1')
        originalSocket = port.socket
        try:
            port.socket = FakeSocket()

            port.doRead()

            expectedFormat = "Could not accept new connection (%s)"
            expectedErrorCode = errno.errorcode[socketErrorNumber]
            expectedMessage = expectedFormat % (expectedErrorCode, )
            for msg in self.messages:
                if msg.get('message') == (expectedMessage, ):
                    break
            else:
                self.fail("Log event for failed accept not found in "
                          "%r" % (self.messages, ))
        finally:
            port.socket = originalSocket

    def test_tooManyFilesFromAccept(self):
        """
        C{accept(2)} can fail with C{EMFILE} when there are too many open file
        descriptors in the process.  Test that this doesn't negatively impact
        any other existing connections.

        C{EMFILE} mainly occurs on Linux when the open file rlimit is
        encountered.
        """
        return self._acceptFailureTest(EMFILE)

    def test_noBufferSpaceFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENOBUFS}.

        This mainly occurs on Windows and FreeBSD, but may be possible on
        Linux and other platforms as well.
        """
        return self._acceptFailureTest(ENOBUFS)

    def test_connectionAbortedFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ECONNABORTED}.

        It is not clear whether this is actually possible for TCP
        connections on modern versions of Linux.
        """
        return self._acceptFailureTest(ECONNABORTED)

    def test_noFilesFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENFILE}.

        This can occur on Linux when the system has exhausted (!) its supply
        of inodes.
        """
        return self._acceptFailureTest(ENFILE)

    if platform.getType() == 'win32':
        test_noFilesFromAccept.skip = "Windows accept(2) cannot generate ENFILE"

    def test_noMemoryFromAccept(self):
        """
        Similar to L{test_tooManyFilesFromAccept}, but test the case where
        C{accept(2)} fails with C{ENOMEM}.

        On Linux at least, this can sensibly occur, even in a Python program
        (which eats memory like no ones business), when memory has become
        fragmented or low memory has been filled (d_alloc calls
        kmem_cache_alloc calls kmalloc - kmalloc only allocates out of low
        memory).
        """
        return self._acceptFailureTest(ENOMEM)

    if platform.getType() == 'win32':
        test_noMemoryFromAccept.skip = "Windows accept(2) cannot generate ENOMEM"
Example #26
0
def run():
    """Run input/output and dispatched/delayed code.

    This call never returns.  It is the main loop which runs
    delayed timers (see twisted.python.delay and addDelayed),
    and the I/O monitor (doSelect).
    """
    global running
    running = 1
    threadable.registerAsIOThread()
    signal.signal(signal.SIGINT, shutDown)
    signal.signal(signal.SIGTERM, shutDown)

    # Catch Ctrl-Break in windows (only available in 2.2b1 onwards)
    if hasattr(signal, "SIGBREAK"):
        signal.signal(signal.SIGBREAK, shutDown)

    if platform.getType() == 'posix':
        signal.signal(signal.SIGCHLD, process.reapProcess)

    try:
        try:
            while running:
                # Advance simulation time in delayed event
                # processors.
                timeout = None
                for delayed in delayeds:
                    delayed.runUntilCurrent()
                    newTimeout = delayed.timeout()
                    if ((newTimeout is not None)
                            and ((timeout is None) or (newTimeout < timeout))):
                        timeout = newTimeout
                doSelect(timeout)
        except select.error:
            log.msg('shutting down after select() loop interruption')
            if running:
                log.msg('Warning!  Shutdown not called properly!')
                traceback.print_exc(file=log.logfile)
                shutDown()
            if platform.getType() == 'win32':
                log.msg("(Logging traceback for WinXX exception info)")
                traceback.print_exc(file=log.logfile)
        except:
            log.msg("Unexpected error in Selector.run.")
            traceback.print_exc(file=log.logfile)
            shutDown()
            raise
        else:
            log.msg('Select loop terminated.')

    finally:
        for reader in reads.keys():
            if reads.has_key(reader):
                del reads[reader]
            if writes.has_key(reader):
                del writes[reader]
            log.logOwner.own(reader)
            try:
                reader.connectionLost()
            except:
                traceback.print_exc(file=log.logfile)
            log.logOwner.disown(reader)
        # TODO: implement shutdown callbacks for gtk & tk
        for callback in shutdowns:
            try:
                callback()
            except:
                traceback.print_exc(file=log.logfile)
Example #27
0
class ErrorFormatingTestCase(TestCase):
    """
    Tests for C{_ErrorFormatter.formatError}.
    """
    probeErrorCode = ECONNABORTED
    probeMessage = "correct message value"

    def test_strerrorFormatting(self):
        """
        L{_ErrorFormatter.formatError} should use L{os.strerror} to format
        error messages if it is constructed without any better mechanism.
        """
        formatter = _ErrorFormatter(None, None, None)
        message = formatter.formatError(self.probeErrorCode)
        self.assertEqual(message, os.strerror(self.probeErrorCode))

    def test_emptyErrorTab(self):
        """
        L{_ErrorFormatter.formatError} should use L{os.strerror} to format
        error messages if it is constructed with only an error tab which does
        not contain the error code it is called with.
        """
        error = 1
        # Sanity check
        self.assertNotEqual(self.probeErrorCode, error)
        formatter = _ErrorFormatter(None, None, {error: 'wrong message'})
        message = formatter.formatError(self.probeErrorCode)
        self.assertEqual(message, os.strerror(self.probeErrorCode))

    def test_errorTab(self):
        """
        L{_ErrorFormatter.formatError} should use C{errorTab} if it is supplied
        and contains the requested error code.
        """
        formatter = _ErrorFormatter(None, None,
                                    {self.probeErrorCode: self.probeMessage})
        message = formatter.formatError(self.probeErrorCode)
        self.assertEqual(message, self.probeMessage)

    def test_formatMessage(self):
        """
        L{_ErrorFormatter.formatError} should return the return value of
        C{formatMessage} if it is supplied.
        """
        formatCalls = []

        def formatMessage(errorCode):
            formatCalls.append(errorCode)
            return self.probeMessage

        formatter = _ErrorFormatter(None, formatMessage,
                                    {self.probeErrorCode: 'wrong message'})
        message = formatter.formatError(self.probeErrorCode)
        self.assertEqual(message, self.probeMessage)
        self.assertEqual(formatCalls, [self.probeErrorCode])

    def test_winError(self):
        """
        L{_ErrorFormatter.formatError} should return the message argument from
        the exception L{winError} returns, if L{winError} is supplied.
        """
        winCalls = []

        def winError(errorCode):
            winCalls.append(errorCode)
            return _MyWindowsException(errorCode, self.probeMessage)

        formatter = _ErrorFormatter(
            winError, lambda error: 'formatMessage: wrong message',
            {self.probeErrorCode: 'errorTab: wrong message'})
        message = formatter.formatError(self.probeErrorCode)
        self.assertEqual(message, self.probeMessage)

    def test_fromEnvironment(self):
        """
        L{_ErrorFormatter.fromEnvironment} should create an L{_ErrorFormatter}
        instance with attributes populated from available modules.
        """
        formatter = _ErrorFormatter.fromEnvironment()

        if formatter.winError is not None:
            from ctypes import WinError
            self.assertEqual(formatter.formatError(self.probeErrorCode),
                             WinError(self.probeErrorCode).strerror)
            formatter.winError = None

        if formatter.formatMessage is not None:
            from win32api import FormatMessage
            self.assertEqual(formatter.formatError(self.probeErrorCode),
                             FormatMessage(self.probeErrorCode))
            formatter.formatMessage = None

        if formatter.errorTab is not None:
            from socket import errorTab
            self.assertEqual(formatter.formatError(self.probeErrorCode),
                             errorTab[self.probeErrorCode])

    if platform.getType() != "win32":
        test_fromEnvironment.skip = "Test will run only on Windows."

    def test_correctLookups(self):
        """
        Given an known-good errno, make sure that formatMessage gives results
        matching either C{socket.errorTab}, C{ctypes.WinError}, or
        C{win32api.FormatMessage}.
        """
        acceptable = [socket.errorTab[ECONNABORTED]]
        try:
            from ctypes import WinError
            acceptable.append(WinError(ECONNABORTED).strerror)
        except ImportError:
            pass
        try:
            from win32api import FormatMessage
            acceptable.append(FormatMessage(ECONNABORTED))
        except ImportError:
            pass

        self.assertIn(formatError(ECONNABORTED), acceptable)

    if platform.getType() != "win32":
        test_correctLookups.skip = "Test will run only on Windows."
Example #28
0
def initThreads():
    """Perform initialization required for threading.
    """
    if platform.getType() != 'java':
        installWaker()
Example #29
0
class PlatformAssumptionsTests(TestCase):
    """
    Test assumptions about platform behaviors.
    """

    socketLimit = 8192

    def setUp(self):
        self.openSockets = []
        if resource is not None:
            # On some buggy platforms we might leak FDs, and the test will
            # fail creating the initial two sockets we *do* want to
            # succeed. So, we make the soft limit the current number of fds
            # plus two more (for the two sockets we want to succeed). If we've
            # leaked too many fds for that to work, there's nothing we can
            # do.
            from twisted.internet.process import _listOpenFDs
            newLimit = len(_listOpenFDs()) + 2
            self.originalFileLimit = resource.getrlimit(resource.RLIMIT_NOFILE)
            resource.setrlimit(resource.RLIMIT_NOFILE, (newLimit, self.originalFileLimit[1]))
            self.socketLimit = newLimit + 100


    def tearDown(self):
        while self.openSockets:
            self.openSockets.pop().close()
        if resource is not None:
            # `macOS` implicitly lowers the hard limit in the setrlimit call
            # above.  Retrieve the new hard limit to pass in to this
            # setrlimit call, so that it doesn't give us a permission denied
            # error.
            currentHardLimit = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
            newSoftLimit = min(self.originalFileLimit[0], currentHardLimit)
            resource.setrlimit(resource.RLIMIT_NOFILE, (newSoftLimit, currentHardLimit))


    def socket(self):
        """
        Create and return a new socket object, also tracking it so it can be
        closed in the test tear down.
        """
        s = socket.socket()
        self.openSockets.append(s)
        return s


    @skipIf(platform.getType() == "win32",
            "Windows requires an unacceptably large amount of resources to "
            "provoke this behavior in the naive manner.")
    def test_acceptOutOfFiles(self):
        """
        Test that the platform accept(2) call fails with either L{EMFILE} or
        L{ENOBUFS} when there are too many file descriptors open.
        """
        # Make a server to which to connect
        port = self.socket()
        port.bind(('127.0.0.1', 0))
        serverPortNumber = port.getsockname()[1]
        port.listen(5)

        # Make a client to use to connect to the server
        client = self.socket()
        client.setblocking(False)

        # Use up all the rest of the file descriptors.
        for i in range(self.socketLimit):
            try:
                self.socket()
            except socket.error as e:
                if e.args[0] in (EMFILE, ENOBUFS):
                    # The desired state has been achieved.
                    break
                else:
                    # Some unexpected error occurred.
                    raise
        else:
            self.fail("Could provoke neither EMFILE nor ENOBUFS from platform.")

        # Non-blocking connect is supposed to fail, but this is not true
        # everywhere (e.g. freeBSD)
        self.assertIn(client.connect_ex(('127.0.0.1', serverPortNumber)),
                      (0, EINPROGRESS))

        # Make sure that the accept call fails in the way we expect.
        exc = self.assertRaises(socket.error, port.accept)
        self.assertIn(exc.args[0], (EMFILE, ENOBUFS))
Example #30
0
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# System Imports
import os

# Twisted Import
from twisted.python.runtime import platform

if platform.getType() != 'java':
    import select, signal
    from errno import EINTR

import traceback
import sys
import socket
CONNECTION_LOST = -1
CONNECTION_DONE = -2

theApplication = None

# Twisted Imports

from twisted.python import threadable, log, delay
from twisted.persisted import styles