17.12
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Unit tests for L{twisted.python}.
|
||||
"""
|
||||
@@ -0,0 +1,55 @@
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
"""
|
||||
Facilities for helping test code which interacts with Python's module system
|
||||
to load code.
|
||||
"""
|
||||
|
||||
from __future__ import division, absolute_import
|
||||
|
||||
import sys
|
||||
|
||||
from twisted.python.filepath import FilePath
|
||||
|
||||
|
||||
class TwistedModulesMixin(object):
|
||||
"""
|
||||
A mixin for C{twisted.trial.unittest.SynchronousTestCase} providing useful
|
||||
methods for manipulating Python's module system.
|
||||
"""
|
||||
|
||||
def replaceSysPath(self, sysPath):
|
||||
"""
|
||||
Replace sys.path, for the duration of the test, with the given value.
|
||||
"""
|
||||
originalSysPath = sys.path[:]
|
||||
def cleanUpSysPath():
|
||||
sys.path[:] = originalSysPath
|
||||
self.addCleanup(cleanUpSysPath)
|
||||
sys.path[:] = sysPath
|
||||
|
||||
|
||||
def replaceSysModules(self, sysModules):
|
||||
"""
|
||||
Replace sys.modules, for the duration of the test, with the given value.
|
||||
"""
|
||||
originalSysModules = sys.modules.copy()
|
||||
def cleanUpSysModules():
|
||||
sys.modules.clear()
|
||||
sys.modules.update(originalSysModules)
|
||||
self.addCleanup(cleanUpSysModules)
|
||||
sys.modules.clear()
|
||||
sys.modules.update(sysModules)
|
||||
|
||||
|
||||
def pathEntryWithOnePackage(self, pkgname="test_package"):
|
||||
"""
|
||||
Generate a L{FilePath} with one package, named C{pkgname}, on it, and
|
||||
return the L{FilePath} of the path entry.
|
||||
"""
|
||||
entry = FilePath(self.mktemp())
|
||||
pkg = entry.child("test_package")
|
||||
pkg.makedirs()
|
||||
pkg.child("__init__.py").setContent(b"")
|
||||
return entry
|
||||
@@ -0,0 +1,39 @@
|
||||
# -*- test-case-name: twisted.python.test.test_sendmsg -*-
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import socket
|
||||
from struct import unpack
|
||||
|
||||
from twisted.python.sendmsg import recvmsg
|
||||
|
||||
|
||||
def recvfd(socketfd):
|
||||
"""
|
||||
Receive a file descriptor from a L{sendmsg} message on the given C{AF_UNIX}
|
||||
socket.
|
||||
|
||||
@param socketfd: An C{AF_UNIX} socket, attached to another process waiting
|
||||
to send sockets via the ancillary data mechanism in L{send1msg}.
|
||||
|
||||
@param fd: C{int}
|
||||
|
||||
@return: a 2-tuple of (new file descriptor, description).
|
||||
@rtype: 2-tuple of (C{int}, C{bytes})
|
||||
"""
|
||||
ourSocket = socket.fromfd(socketfd, socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
data, ancillary, flags = recvmsg(ourSocket)
|
||||
[(cmsgLevel, cmsgType, packedFD)] = ancillary
|
||||
# cmsgLevel and cmsgType really need to be SOL_SOCKET / SCM_RIGHTS, but
|
||||
# since those are the *only* standard values, there's not much point in
|
||||
# checking.
|
||||
[unpackedFD] = unpack("i", packedFD)
|
||||
return (unpackedFD, data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
fd, description = recvfd(int(sys.argv[1]))
|
||||
os.write(fd, b"Test fixture data: " + description + b".\n")
|
||||
os.close(fd)
|
||||
@@ -0,0 +1,290 @@
|
||||
# -*- test-case-name: twisted.python.test.test_urlpath -*-
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
"""
|
||||
Tests for L{twisted.python.urlpath}.
|
||||
"""
|
||||
|
||||
from twisted.trial import unittest
|
||||
from twisted.python import urlpath
|
||||
from twisted.python.compat import _PY3
|
||||
|
||||
|
||||
class _BaseURLPathTests(object):
|
||||
"""
|
||||
Tests for instantiated L{urlpath.URLPath}s.
|
||||
"""
|
||||
def test_partsAreBytes(self):
|
||||
"""
|
||||
All of the attributes of L{urlpath.URLPath} should be L{bytes}.
|
||||
"""
|
||||
self.assertIsInstance(self.path.scheme, bytes)
|
||||
self.assertIsInstance(self.path.netloc, bytes)
|
||||
self.assertIsInstance(self.path.path, bytes)
|
||||
self.assertIsInstance(self.path.query, bytes)
|
||||
self.assertIsInstance(self.path.fragment, bytes)
|
||||
|
||||
|
||||
def test_strReturnsStr(self):
|
||||
"""
|
||||
Calling C{str()} with a L{URLPath} will always return a L{str}.
|
||||
"""
|
||||
self.assertEqual(type(self.path.__str__()), str)
|
||||
|
||||
|
||||
def test_mutabilityWithText(self, stringType=type(u"")):
|
||||
"""
|
||||
Setting attributes on L{urlpath.URLPath} should change the value
|
||||
returned by L{str}.
|
||||
|
||||
@param stringType: a callable to parameterize this test for different
|
||||
text types.
|
||||
@type stringType: 1-argument callable taking L{unicode} and returning
|
||||
L{str} or L{bytes}.
|
||||
"""
|
||||
self.path.scheme = stringType(u"https")
|
||||
self.assertEqual(
|
||||
str(self.path),
|
||||
"https://example.com/foo/bar?yes=no&no=yes#footer")
|
||||
self.path.netloc = stringType(u"another.example.invalid")
|
||||
self.assertEqual(
|
||||
str(self.path),
|
||||
"https://another.example.invalid/foo/bar?yes=no&no=yes#footer")
|
||||
self.path.path = stringType(u"/hello")
|
||||
self.assertEqual(
|
||||
str(self.path),
|
||||
"https://another.example.invalid/hello?yes=no&no=yes#footer")
|
||||
self.path.query = stringType(u"alpha=omega&opposites=same")
|
||||
self.assertEqual(
|
||||
str(self.path),
|
||||
"https://another.example.invalid/hello?alpha=omega&opposites=same"
|
||||
"#footer")
|
||||
self.path.fragment = stringType(u"header")
|
||||
self.assertEqual(
|
||||
str(self.path),
|
||||
"https://another.example.invalid/hello?alpha=omega&opposites=same"
|
||||
"#header")
|
||||
|
||||
|
||||
def test_mutabilityWithBytes(self):
|
||||
"""
|
||||
Same as L{test_mutabilityWithText} but for bytes.
|
||||
"""
|
||||
self.test_mutabilityWithText(lambda x: x.encode("ascii"))
|
||||
|
||||
|
||||
def test_allAttributesAreBytes(self):
|
||||
"""
|
||||
A created L{URLPath} has bytes attributes.
|
||||
"""
|
||||
self.assertIsInstance(self.path.scheme, bytes)
|
||||
self.assertIsInstance(self.path.netloc, bytes)
|
||||
self.assertIsInstance(self.path.path, bytes)
|
||||
self.assertIsInstance(self.path.query, bytes)
|
||||
self.assertIsInstance(self.path.fragment, bytes)
|
||||
|
||||
|
||||
def test_stringConversion(self):
|
||||
"""
|
||||
Calling C{str()} with a L{URLPath} will return the same URL that it was
|
||||
constructed with.
|
||||
"""
|
||||
self.assertEqual(str(self.path),
|
||||
"http://example.com/foo/bar?yes=no&no=yes#footer")
|
||||
|
||||
|
||||
def test_childString(self):
|
||||
"""
|
||||
Calling C{str()} with a C{URLPath.child()} will return a URL which is
|
||||
the child of the URL it was instantiated with.
|
||||
"""
|
||||
self.assertEqual(str(self.path.child(b'hello')),
|
||||
"http://example.com/foo/bar/hello")
|
||||
self.assertEqual(str(self.path.child(b'hello').child(b'')),
|
||||
"http://example.com/foo/bar/hello/")
|
||||
self.assertEqual(str(self.path.child(b'hello', keepQuery=True)),
|
||||
"http://example.com/foo/bar/hello?yes=no&no=yes")
|
||||
|
||||
|
||||
def test_siblingString(self):
|
||||
"""
|
||||
Calling C{str()} with a C{URLPath.sibling()} will return a URL which is
|
||||
the sibling of the URL it was instantiated with.
|
||||
"""
|
||||
self.assertEqual(str(self.path.sibling(b'baz')),
|
||||
'http://example.com/foo/baz')
|
||||
self.assertEqual(str(self.path.sibling(b'baz', keepQuery=True)),
|
||||
"http://example.com/foo/baz?yes=no&no=yes")
|
||||
|
||||
# The sibling of http://example.com/foo/bar/
|
||||
# is http://example.comf/foo/bar/baz
|
||||
# because really we are constructing a sibling of
|
||||
# http://example.com/foo/bar/index.html
|
||||
self.assertEqual(str(self.path.child(b'').sibling(b'baz')),
|
||||
'http://example.com/foo/bar/baz')
|
||||
|
||||
|
||||
def test_parentString(self):
|
||||
"""
|
||||
Calling C{str()} with a C{URLPath.parent()} will return a URL which is
|
||||
the parent of the URL it was instantiated with.
|
||||
"""
|
||||
# .parent() should be equivalent to '..'
|
||||
# 'foo' is the current directory, '/' is the parent directory
|
||||
self.assertEqual(str(self.path.parent()),
|
||||
'http://example.com/')
|
||||
self.assertEqual(str(self.path.parent(keepQuery=True)),
|
||||
'http://example.com/?yes=no&no=yes')
|
||||
self.assertEqual(str(self.path.child(b'').parent()),
|
||||
'http://example.com/foo/')
|
||||
self.assertEqual(str(self.path.child(b'baz').parent()),
|
||||
'http://example.com/foo/')
|
||||
self.assertEqual(
|
||||
str(self.path.parent().parent().parent().parent().parent()),
|
||||
'http://example.com/')
|
||||
|
||||
|
||||
def test_hereString(self):
|
||||
"""
|
||||
Calling C{str()} with a C{URLPath.here()} will return a URL which is
|
||||
the URL that it was instantiated with, without any file, query, or
|
||||
fragment.
|
||||
"""
|
||||
# .here() should be equivalent to '.'
|
||||
self.assertEqual(str(self.path.here()), 'http://example.com/foo/')
|
||||
self.assertEqual(str(self.path.here(keepQuery=True)),
|
||||
'http://example.com/foo/?yes=no&no=yes')
|
||||
self.assertEqual(str(self.path.child(b'').here()),
|
||||
'http://example.com/foo/bar/')
|
||||
|
||||
|
||||
def test_doubleSlash(self):
|
||||
"""
|
||||
Calling L{urlpath.URLPath.click} on a L{urlpath.URLPath} with a
|
||||
trailing slash with a relative URL containing a leading slash will
|
||||
result in a URL with a single slash at the start of the path portion.
|
||||
"""
|
||||
self.assertEqual(
|
||||
str(self.path.click(b"/hello/world")).encode("ascii"),
|
||||
b"http://example.com/hello/world"
|
||||
)
|
||||
|
||||
|
||||
def test_pathList(self):
|
||||
"""
|
||||
L{urlpath.URLPath.pathList} returns a L{list} of L{bytes}.
|
||||
"""
|
||||
self.assertEqual(
|
||||
self.path.child(b"%00%01%02").pathList(),
|
||||
[b"", b"foo", b"bar", b"%00%01%02"]
|
||||
)
|
||||
|
||||
# Just testing that the 'copy' argument exists for compatibility; it
|
||||
# was originally provided for performance reasons, and its behavioral
|
||||
# contract is kind of nonsense (where is the state shared? who with?)
|
||||
# so it doesn't actually *do* anything any more.
|
||||
self.assertEqual(
|
||||
self.path.child(b"%00%01%02").pathList(copy=False),
|
||||
[b"", b"foo", b"bar", b"%00%01%02"]
|
||||
)
|
||||
self.assertEqual(
|
||||
self.path.child(b"%00%01%02").pathList(unquote=True),
|
||||
[b"", b"foo", b"bar", b"\x00\x01\x02"]
|
||||
)
|
||||
|
||||
|
||||
|
||||
class BytesURLPathTests(_BaseURLPathTests, unittest.TestCase):
|
||||
"""
|
||||
Tests for interacting with a L{URLPath} created with C{fromBytes}.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.path = urlpath.URLPath.fromBytes(
|
||||
b"http://example.com/foo/bar?yes=no&no=yes#footer")
|
||||
|
||||
|
||||
def test_mustBeBytes(self):
|
||||
"""
|
||||
L{URLPath.fromBytes} must take a L{bytes} argument.
|
||||
"""
|
||||
with self.assertRaises(ValueError):
|
||||
urlpath.URLPath.fromBytes(None)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
urlpath.URLPath.fromBytes(u"someurl")
|
||||
|
||||
|
||||
def test_withoutArguments(self):
|
||||
"""
|
||||
An instantiation with no arguments creates a usable L{URLPath} with
|
||||
default arguments.
|
||||
"""
|
||||
url = urlpath.URLPath()
|
||||
self.assertEqual(str(url), "http://localhost/")
|
||||
|
||||
|
||||
def test_partialArguments(self):
|
||||
"""
|
||||
Leaving some optional arguments unfilled makes a L{URLPath} with those
|
||||
optional arguments filled with defaults.
|
||||
"""
|
||||
# Not a "full" URL given to fromBytes, no /
|
||||
# / is filled in
|
||||
url = urlpath.URLPath.fromBytes(b"http://google.com")
|
||||
self.assertEqual(url.scheme, b"http")
|
||||
self.assertEqual(url.netloc, b"google.com")
|
||||
self.assertEqual(url.path, b"/")
|
||||
self.assertEqual(url.fragment, b"")
|
||||
self.assertEqual(url.query, b"")
|
||||
self.assertEqual(str(url), "http://google.com/")
|
||||
|
||||
|
||||
def test_nonASCIIBytes(self):
|
||||
"""
|
||||
L{URLPath.fromBytes} can interpret non-ASCII bytes as percent-encoded
|
||||
"""
|
||||
url = urlpath.URLPath.fromBytes(b"http://example.com/\xff\x00")
|
||||
self.assertEqual(str(url), "http://example.com/%FF%00")
|
||||
|
||||
|
||||
|
||||
class StringURLPathTests(_BaseURLPathTests, unittest.TestCase):
|
||||
"""
|
||||
Tests for interacting with a L{URLPath} created with C{fromString} and a
|
||||
L{str} argument.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.path = urlpath.URLPath.fromString(
|
||||
"http://example.com/foo/bar?yes=no&no=yes#footer")
|
||||
|
||||
|
||||
def test_mustBeStr(self):
|
||||
"""
|
||||
C{URLPath.fromString} must take a L{str} or L{unicode} argument.
|
||||
"""
|
||||
with self.assertRaises(ValueError):
|
||||
urlpath.URLPath.fromString(None)
|
||||
|
||||
if _PY3:
|
||||
with self.assertRaises(ValueError):
|
||||
urlpath.URLPath.fromString(b"someurl")
|
||||
|
||||
|
||||
|
||||
class UnicodeURLPathTests(_BaseURLPathTests, unittest.TestCase):
|
||||
"""
|
||||
Tests for interacting with a L{URLPath} created with C{fromString} and a
|
||||
L{unicode} argument.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.path = urlpath.URLPath.fromString(
|
||||
u"http://example.com/foo/bar?yes=no&no=yes#footer")
|
||||
|
||||
|
||||
def test_nonASCIICharacters(self):
|
||||
"""
|
||||
L{URLPath.fromString} can load non-ASCII characters.
|
||||
"""
|
||||
url = urlpath.URLPath.fromString(u"http://example.com/\xff\x00")
|
||||
self.assertEqual(str(url), "http://example.com/%C3%BF%00")
|
||||
@@ -0,0 +1,101 @@
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
"""
|
||||
Test cases covering L{twisted.python.zippath}.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, division
|
||||
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
from twisted.test.test_paths import AbstractFilePathTests
|
||||
from twisted.python.zippath import ZipArchive
|
||||
from twisted.python.filepath import _coerceToFilesystemEncoding
|
||||
|
||||
|
||||
def zipit(dirname, zfname):
|
||||
"""
|
||||
Create a zipfile on zfname, containing the contents of dirname'
|
||||
"""
|
||||
dirname = _coerceToFilesystemEncoding('', dirname)
|
||||
zfname = _coerceToFilesystemEncoding('', zfname)
|
||||
|
||||
with zipfile.ZipFile(zfname, "w") as zf:
|
||||
for root, ignored, files, in os.walk(dirname):
|
||||
for fname in files:
|
||||
fspath = os.path.join(root, fname)
|
||||
arcpath = os.path.join(root, fname)[len(dirname)+1:]
|
||||
zf.write(fspath, arcpath)
|
||||
|
||||
|
||||
|
||||
class ZipFilePathTests(AbstractFilePathTests):
|
||||
"""
|
||||
Test various L{ZipPath} path manipulations as well as reprs for L{ZipPath}
|
||||
and L{ZipArchive}.
|
||||
"""
|
||||
def setUp(self):
|
||||
AbstractFilePathTests.setUp(self)
|
||||
zipit(self.cmn, self.cmn + b'.zip')
|
||||
self.nativecmn = _coerceToFilesystemEncoding('', self.cmn)
|
||||
self.path = ZipArchive(self.cmn + b'.zip')
|
||||
self.root = self.path
|
||||
self.all = [x.replace(self.cmn, self.cmn + b'.zip')
|
||||
for x in self.all]
|
||||
|
||||
|
||||
def test_zipPathRepr(self):
|
||||
"""
|
||||
Make sure that invoking ZipPath's repr prints the correct class name
|
||||
and an absolute path to the zip file.
|
||||
"""
|
||||
child = self.path.child("foo")
|
||||
pathRepr = "ZipPath(%r)" % (
|
||||
os.path.abspath(self.nativecmn + ".zip" + os.sep + 'foo'),)
|
||||
|
||||
# Check for an absolute path
|
||||
self.assertEqual(repr(child), pathRepr)
|
||||
|
||||
# Create a path to the file rooted in the current working directory
|
||||
relativeCommon = self.nativecmn.replace(os.getcwd() + os.sep,
|
||||
"", 1) + ".zip"
|
||||
relpath = ZipArchive(relativeCommon)
|
||||
child = relpath.child("foo")
|
||||
|
||||
# Check using a path without the cwd prepended
|
||||
self.assertEqual(repr(child), pathRepr)
|
||||
|
||||
|
||||
def test_zipPathReprParentDirSegment(self):
|
||||
"""
|
||||
The repr of a ZipPath with C{".."} in the internal part of its path
|
||||
includes the C{".."} rather than applying the usual parent directory
|
||||
meaning.
|
||||
"""
|
||||
child = self.path.child("foo").child("..").child("bar")
|
||||
pathRepr = "ZipPath(%r)" % (
|
||||
self.nativecmn + ".zip" + os.sep.join(["", "foo", "..", "bar"]))
|
||||
self.assertEqual(repr(child), pathRepr)
|
||||
|
||||
|
||||
def test_zipArchiveRepr(self):
|
||||
"""
|
||||
Make sure that invoking ZipArchive's repr prints the correct class
|
||||
name and an absolute path to the zip file.
|
||||
"""
|
||||
path = ZipArchive(self.nativecmn + '.zip')
|
||||
pathRepr = 'ZipArchive(%r)' % (os.path.abspath(
|
||||
self.nativecmn + '.zip'),)
|
||||
|
||||
# Check for an absolute path
|
||||
self.assertEqual(repr(path), pathRepr)
|
||||
|
||||
# Create a path to the file rooted in the current working directory
|
||||
relativeCommon = self.nativecmn.replace(os.getcwd() + os.sep,
|
||||
"", 1) + ".zip"
|
||||
relpath = ZipArchive(relativeCommon)
|
||||
|
||||
# Check using a path without the cwd prepended
|
||||
self.assertEqual(repr(relpath), pathRepr)
|
||||
Reference in New Issue
Block a user