[apt-proxy-devel] r638 - in trunk: . apt_proxy apt_proxy/test debian
Chris Halls
halls at alioth.debian.org
Wed Dec 20 15:53:28 CET 2006
Author: halls
Date: Wed Dec 20 15:53:27 2006
New Revision: 638
Modified:
trunk/apt_proxy/apt_proxy.py
trunk/apt_proxy/apt_proxy_conf.py
trunk/apt_proxy/cache.py
trunk/apt_proxy/clients.py
trunk/apt_proxy/fetchers.py
trunk/apt_proxy/test/test_apt_proxy.py
trunk/apt_proxy/test/test_requests.py
trunk/aptest
trunk/debian/changelog
Log:
* Fix username + password parsing in backend Urls
* Add switch for decompressors until code is stable
* Promote some debug error messages to error level
* Add test for username & passwords in backend urls
* Add new test for backend server hangs (not yet complete)
* Unify some test request code
* aptest: make /var/run/apt-proxy if non existent
* Update changelog
Modified: trunk/apt_proxy/apt_proxy.py
==============================================================================
--- trunk/apt_proxy/apt_proxy.py (original)
+++ trunk/apt_proxy/apt_proxy.py Wed Dec 20 15:53:27 2006
@@ -191,7 +191,7 @@
if '@' in netloc:
auth = netloc[:netloc.rindex('@')]
- netloc = netloc[netloc.rindex('@'):]
+ netloc = netloc[netloc.rindex('@')+1:]
self.username, self.password = auth.split(':')
else:
self.username = None
Modified: trunk/apt_proxy/apt_proxy_conf.py
==============================================================================
--- trunk/apt_proxy/apt_proxy_conf.py (original)
+++ trunk/apt_proxy/apt_proxy_conf.py Wed Dec 20 15:53:27 2006
@@ -100,7 +100,8 @@
['dynamic_backends', 'on', 'boolean'],
['http_proxy', None , 'proxyspec'],
['username', 'aptproxy', 'string'],
- ['bandwidth_limit', None, '*int']
+ ['bandwidth_limit', None, '*int'],
+ ['use_experimental_decompressors', False, 'boolean']
]
"""
Modified: trunk/apt_proxy/cache.py
==============================================================================
--- trunk/apt_proxy/cache.py (original)
+++ trunk/apt_proxy/cache.py Wed Dec 20 15:53:27 2006
@@ -30,6 +30,18 @@
import clients
+class InvalidCachePath(Exception):
+ """
+ Exception generated if client specifies an invalid path
+ """
+ def __init__(self, path, position, reason):
+ self.path = path
+ self.position = position
+ self.reason = reason
+ def __str__(self):
+ return "Invalid cache path (%s) at position %i: %s" % \
+ (self.path, self.position, self.reason)
+
class CacheEntry:
"""
This class manages operations on a file in the cache. Each physical
@@ -68,7 +80,7 @@
"""
Create a new cache entry
@param backend Backend where this entry belongs
- @param path Path to file within backend directory
+ @param path Path to file within backend directory (not escaped)
"""
self.backend = backend
self.factory = backend.factory
@@ -102,10 +114,12 @@
self.fetcher = None
- if self.filetype.decompressor is not None:
- # File needs to be decompressed
- self.filetype.decompressor(self)
-
+ # decompressors are currently disabled until debugged :)
+ if self.factory.config.use_experimental_decompressors:
+ if self.filetype.decompressor is not None:
+ # File needs to be decompressed
+ self.filetype.decompressor(self)
+
def add_request(self, request):
"""
A new request has been received for this file
Modified: trunk/apt_proxy/clients.py
==============================================================================
--- trunk/apt_proxy/clients.py (original)
+++ trunk/apt_proxy/clients.py Wed Dec 20 15:53:27 2006
@@ -24,7 +24,7 @@
CacheEntry objects will notify subscribed Clients of changes in state
"""
-import os, re, urlparse, gzip, bz2
+import os, re, urlparse, urllib, gzip, bz2
from StringIO import StringIO
from twisted.web import http
@@ -55,13 +55,18 @@
"""
self.uri = self.clean_path(self.uri)
+ if re.search(self.uri, '[^a-zA-Z0-9~,.+%:;@#?{}[]()$-]'):
+ log.err("Invalid characters found in filename")
+ self.finishCode(http.FORBIDDEN, "Invalid characters in filename")
+ return
+
if_modified_since = self.getHeader('if-modified-since')
if if_modified_since != None:
self.if_modified_since = http.stringToDatetime(
if_modified_since)
if self.uri[0] != '/':
- log.debug("Request must include at least one '/'")
+ log.err("Request must include at least one '/'")
self.finishCode(http.FORBIDDEN, "Request must include at least one '/'")
return
@@ -71,17 +76,18 @@
if self.method != 'GET':
#we currently only support GET
- log.debug("abort - method not implemented", 'HttpRequestClient')
+ log.err("abort - method not implemented", 'HttpRequestClient')
self.finishCode(http.NOT_IMPLEMENTED)
return
if re.search('/\.\./', self.uri):
- log.debug("/../ in simplified uri ("+self.uri+")", 'HttpRequestClient')
+ log.err("/../ in simplified uri ("+self.uri+")", 'HttpRequestClient')
self.finishCode(http.FORBIDDEN)
return
self.backend = self.factory.getBackend(backendName)
if self.backend is None:
+ log.err("backend %s not found" % (backendName), 'HttpRequestClient')
self.finishCode(http.NOT_FOUND, "NON-EXISTENT BACKEND")
return None
@@ -89,7 +95,7 @@
elements = self.uri.split('/', 2)
if len(elements) < 3:
- log.debug("abort - too few slashes in URI %s" % (self.uri), 'Request')
+ log.err("abort - too few slashes in URI %s" % (self.uri), 'Request')
self.finishCode(http.FORBIDDEN, 'too few slashes in URI %s' % (self.uri))
return
@@ -97,14 +103,14 @@
self.cacheEntry = self.backend.get_cache_entry(backend_path)
if not self.cacheEntry.filetype:
- log.debug("abort - unknown extension for file %s" % (backend_path), 'HttpRequestClient')
+ log.err("abort - unknown extension for file %s" % (backend_path), 'HttpRequestClient')
self.finishCode(http.FORBIDDEN, 'File not found - unknown extension')
return
self.setHeader('content-type', self.cacheEntry.filetype.contype)
if os.path.isdir(self.cacheEntry.file_path):
- log.debug("abort - Directory listing not allowed", 'HttpRequestClient')
+ log.err("abort - Directory listing not allowed", 'HttpRequestClient')
self.finishCode(http.FORBIDDEN, 'Directory listing not permitted')
return
@@ -113,7 +119,8 @@
def clean_path(self, uri):
# Clean up URL given
scheme, netloc, path, params, query, fragment = urlparse.urlparse(uri)
- return os.path.normpath(path)
+ unquoted_path = urllib.url2pathname(path)
+ return os.path.normpath(unquoted_path)
def not_modified(self):
"""
@@ -153,7 +160,10 @@
log.debug("finish. fileno:%s uri:%s" % (self.getFileno(), self.uri) , 'HttpRequestClient')
#import traceback
#traceback.print_stack()
- http.Request.finish(self)
+ try:
+ http.Request.finish(self)
+ except Exception, e:
+ log.debug("Unexpected error finishing http request: %s" % (e), 'HttpRequestClient')
if self.cacheEntry:
reactor.callLater(0, self.cacheEntry.remove_request, self)
Modified: trunk/apt_proxy/fetchers.py
==============================================================================
--- trunk/apt_proxy/fetchers.py (original)
+++ trunk/apt_proxy/fetchers.py Wed Dec 20 15:53:27 2006
@@ -21,7 +21,7 @@
network backends
"""
-import re, os, string, time, glob, signal, stat, base64
+import re, os, string, time, glob, signal, stat, base64, urllib
from twisted.web import static, http
from twisted.internet import protocol, reactor, defer, error, abstract
from twisted.python import failure
@@ -125,7 +125,7 @@
def download_failed(self, reason_code, reason_msg):
#self.cacheEntry.download_data_end()
- log.debug("download_failed: (%s) %s " %(reason_code, reason_msg), "Fetcher")
+ log.msg("download_failed: (%s) %s " %(reason_code, reason_msg), "Fetcher")
if self.fetcher is not None and not self.fetcher.pipelining:
self.connection_closed(self.fetcher)
self.cacheEntry.download_failure(reason_code, reason_msg)
@@ -306,6 +306,7 @@
self.fetcher = fetcher
self.uri = uri
self.finished = False
+ self.http_status = None
backendServer = self.parent.backendServer
if self.proxy is None:
serverpath = backendServer.path
@@ -315,8 +316,9 @@
serverpath = serverpath + ":" + str(backendServer.port)
serverpath = serverpath + "/" + backendServer.path
+ get_path = serverpath + "/" + urllib.quote(uri)
#self.sendCommand(self.request.method,
- self.sendCommand("GET", serverpath + "/" + uri)
+ self.sendCommand("GET", get_path)
self.sendHeader('host', backendServer.host)
if self.proxy is not None and self.proxy.user is not None:
@@ -473,6 +475,9 @@
else:
# Limit download rate
factory = policies.ThrottlingFactory(self, readLimit=self.read_limit)
+ self.timeout = self.backendServer.backend.config.timeout
+ if self.timeout:
+ factory = policies.TimeoutFactory(self, timeoutPeriod=self.timeout)
reactor.connectTCP(host, port, factory, self.backendServer.backend.config.timeout)
return self.connectCallback
@@ -501,7 +506,10 @@
%param uri: URI of file to be downloaded within backend
%param mtime: Modification time of current file in cache
"""
- self.connection.download(fetcher, uri, mtime)
+ if self.connection:
+ self.connection.download(fetcher, uri, mtime)
+ else:
+ fetcher.fetcher_internal_error("http_client self.connection == None")
def disconnect(self):
if self.isConnected:
@@ -609,11 +617,15 @@
def ftpMtimeFailed(self, msgs):
if msgs.check(ftp.CommandFailed):
code = msgs.getErrorMessage()[2:5]
- log.debug("ftp fetch of Mtime failed: %s code:%s" % (msgs.getErrorMessage(), code), 'ftp_client')
+ log.err("ftp fetch of Mtime failed: %s code:%s" % (msgs.getErrorMessage(), code), 'ftp_client')
if code == '550':
# Not found
self.parent.file_not_found()
return
+ elif msgs.check(ftp.ConnectionLost):
+ log.err("ftp connection lost: %s" % (msgs.getErrorMessage()), 'ftp_client')
+ self.parent.download_failed(http.SERVICE_UNAVAILABLE, "Connection lost to FTP server")
+ return
log.debug("ftp fetch of Mtime for %s unknown failure: %s" % (self.remote_file, msgs), 'ftp_client')
self.ftpFetchSize()
@@ -654,7 +666,7 @@
fetcher.ftpFetchFile()
def ftpListFailed(self, msgs):
- log.debug("ftp list failed: %s" % (msgs), 'ftp_client')
+ log.err("ftp list failed: %s" % (msgs), 'ftp_client')
self.parent.fetcher_internal_error("Could not list directory")
def ftpFetchFile(self):
@@ -833,7 +845,7 @@
self.file_path = fetcher.cacheEntry.file_path # Absolute path of file
self.cache_dir = fetcher.cacheEntry.filedir
self.remote_file = (self.backendServer.path + '/'
- + uri)
+ + urllib.quote(uri))
# Change /path/to/FILE -> /path/to/.FILE.* to match rsync tempfile
self.globpattern = re.sub(r'/([^/]*)$', r'/.\1.*', self.file_path)
@@ -954,10 +966,18 @@
log.debug("Status: %s" %(status_object.value.exitCode)
,'rsync_client')
exitcode = status_object.value.exitCode
- if exitcode == 10:
- # Host not found
- self.parent.connection_failed('rsync connection to %s failed'
- % (self.backendServer.host))
+ class rsyncError(Exception):
+ def __init__(self, host, code):
+ if code == 10: msg = "Host not found"
+ elif code == 12: msg = "error in protocol stream"
+ else: msg = "unhandled error"
+ self.error = "rsync://%s failed with code %i:%s" % (host, code, msg)
+ def __str__(self):
+ return "rsyncError: " + self.error
+
+ if exitcode in (10,12):
+ self.parent.connection_failed(
+ failure.Failure(rsyncError(self.backendServer.host, exitcode)))
elif exitcode == 23:
self.parent.file_not_found()
else:
@@ -1101,4 +1121,4 @@
def stop(self):
for q in self.queues.values():
- q.stop()
\ No newline at end of file
+ q.stop()
Modified: trunk/apt_proxy/test/test_apt_proxy.py
==============================================================================
--- trunk/apt_proxy/test/test_apt_proxy.py (original)
+++ trunk/apt_proxy/test/test_apt_proxy.py Wed Dec 20 15:53:27 2006
@@ -274,7 +274,8 @@
rsync://server3/path3
file://server4/path4
[test_usernames]
-backends=http://myUser:thePassword@server/path
+backends=http://myUser:thePassword@httpserver/httppath
+ ftp://myFtpUser:theFtpPassword@ftpserver/ftppath
"""
class BackendServerTest(FactoryTestHelper):
def setUp(self):
@@ -283,17 +284,26 @@
"""
FactoryTestHelper.setUp(self, backendServerConfig)
self.backend = self.factory.getBackend('test_servers')
+ self.backend2 = self.factory.getBackend('test_usernames')
def testServerHosts(self):
values = ['server1','server2','server3','server4']
for server in self.backend.uris:
value = values[self.backend.uris.index(server)]
self.assertEquals(server.host, value)
+ values = ['httpserver','ftpserver']
+ for server in self.backend2.uris:
+ value = values[self.backend2.uris.index(server)]
+ self.assertEquals(server.host, value)
def testServerPaths(self):
values = ['/path1','/path2','/path3','/path4']
for server in self.backend.uris:
value = values[self.backend.uris.index(server)]
self.assertEquals(server.path, value)
+ values = ['/httppath','/ftppath']
+ for server in self.backend2.uris:
+ value = values[self.backend2.uris.index(server)]
+ self.assertEquals(server.path, value)
def testServerProtocols(self):
values = ['http','ftp','rsync','file']
for server in self.backend.uris:
@@ -313,11 +323,12 @@
def testNoPassword(self):
self.assertEquals(self.backend.uris[0].password,None)
def testUser(self):
- backend = self.factory.getBackend('test_usernames')
- self.assertEquals(backend.uris[0].username,'myUser')
+ self.assertEquals(self.backend2.uris[0].username,'myUser')
+ self.assertEquals(self.backend2.uris[1].username,'myFtpUser')
def testPassword(self):
backend = self.factory.getBackend('test_usernames')
- self.assertEquals(backend.uris[0].password,'thePassword')
+ self.assertEquals(self.backend2.uris[0].password,'thePassword')
+ self.assertEquals(self.backend2.uris[1].password,'theFtpPassword')
class testRequests(unittest.TestCase):
def setUp(self):
Modified: trunk/apt_proxy/test/test_requests.py
==============================================================================
--- trunk/apt_proxy/test/test_requests.py (original)
+++ trunk/apt_proxy/test/test_requests.py Wed Dec 20 15:53:27 2006
@@ -16,7 +16,7 @@
"""This module tests the client protocol itself"""
-import os, time
+import os, time, urllib
from twisted.trial import unittest
from twisted.internet import protocol, reactor, defer
from twisted.python import failure
@@ -92,9 +92,10 @@
log.debug("connection made to test apt-proxy server", 'uriRequester')
for i in range(0,len(self.tests)):
test = self.tests[i]
- log.debug("requesting: %s" %(test.filename), 'uriRequester')
+ url = urllib.quote(test.filename)
+ log.debug("requesting: %s" %(url), 'uriRequester')
#self.sendCommand("GET", test.filename)
- self.transport.write('%s %s HTTP/1.1\r\n' % ("GET", test.filename))
+ self.transport.write('%s %s HTTP/1.1\r\n' % ("GET", url))
self.sendHeader('Host', self.host)
if len(self.tests)>1 and i != len(self.tests):
@@ -114,14 +115,16 @@
self.firstLine = 1
#self.length = None
self.__buffer = ''
+ log.debug("getNextTest")
if len(self.tests):
self.nextTest = self.tests[0]
self.tests = self.tests[1:]
log.debug("waiting for test results for: " + self.nextTest.filename, 'uriRequester')
else:
- log.debug('test passed', 'uriRequester')
+ log.debug('final test passed', 'uriRequester')
self.connection.disconnect()
+ log.debug("============ callback 127 [%s]" % (self.deferred))
self.deferred.callback(None)
def handleStatus(self, version, code, message):
@@ -144,6 +147,7 @@
else:
log.debug("aborting transfer", 'uriRequester')
self.disconnect()
+ log.debug("============ callback 150")
self.deferred.callback(None)
#self.passed() # Trigger disconnection of connection
@@ -186,6 +190,7 @@
def failed(self, data):
log.debug('test failed', 'uriRequester')
self.disconnect()
+ log.debug("============ errorback 193")
self.deferred.errback(data)
def disconnect(self):
reactor.callLater(0, self.connection.disconnect)
@@ -279,19 +284,31 @@
"""
Class to perform a series of requests against a test backend.
Derived classes should arrange for a local server to serve
- files from the test_daya directory.
+ files from the test_data directory.
"""
# Name of test backend
backendName = 'test_data'
packagesTestFile = '/packages/Packages'
- def setUp(self, backend_uri):
+ def setUp(self, debugName, protocol, serverFactory, uriSuffix=None):
"""
Make a configuration with a single backend
-
- @param backend_uri: backend server uri e.g. http://127.0.0.1:1234
- """
+
+ @param debugName Name of class to print in debug messages
+ @param protocol Protocol of fetcher to be tested (http, ftp, rysnc etc)
+ @param serverFactory Class to provide start() and stop() methods for backend server
+ @param uriSuffix This is added to uri requests if necessary
+ """
+ self.debugname = debugName
+ self.protocol = protocol
+ self.server = serverFactory()
+ self.uriSuffix = uriSuffix
+ self.port = self.server.start()
+
+ backend_uri = self.protocol + "://127.0.0.1:" + str(self.port)
+ if self.uriSuffix:
+ backend_uri += '/' + self.uriSuffix
config = ("dynamic_backends=off\n" +
"[test_data]\n" +
"backends=" + str(backend_uri))
@@ -299,11 +316,10 @@
self.testfilesdir = os.path.normpath(os.getcwd()+"/../test_data")
def tearDown(self):
log.debug("tearDown", self.debugname)
+ reactor.iterate(0.1)
+ self.server.stop()
+ reactor.iterate(0.1)
TestRequestHelper.tearDown(self)
- def testNotFound(self):
- return self.doRequest(uriData('/test_data/NotHere.gz', http.NOT_FOUND))
- testNotFound.timeout = 2
-
def downloadFile(self, file=packagesTestFile):
"""
Download a file to cache
@@ -318,7 +334,10 @@
Given a filename, generate real filename and request path
"""
filename = '/' + self.backendName + file
- sourcepath = self.testfilesdir+file
+ if hasattr(self, 'testfilesdir'):
+ sourcepath = self.testfilesdir+file
+ else:
+ sourcepath = None
destpath = self.cache_dir + filename
return filename, sourcepath, destpath
@@ -351,6 +370,13 @@
d.addCallback(checkPath)
return d
+class BackendProtocolTests(BackendTestBase):
+ """
+ Class which implements tests which should be run for all tested protocols
+ """
+ def testNotFound(self):
+ return self.doRequest(uriData('/test_data/NotHere.gz', http.NOT_FOUND))
+ testNotFound.timeout = 2
def testPackagesFile(self):
return self.downloadFile().addCallback(self.PackagesFile2)
def PackagesFile2(self, x):
@@ -368,10 +394,12 @@
filename = self.calcFilePaths(self.packagesTestFile)[0][1:] # Remove leading '/' from path
backend = self.factory.getBackend(self.backendName)
self.assertEquals(backend.get_packages_db().packages.get_files(), [filename])
+ testPackagesGzFile.todo = "Need to test this"
def testPackagesBz2File(self):
return self.downloadFile(self.packagesTestFile+'.bz2').addCallback(self.PackagesUncompressed)
testPackagesBz2File.timeout = 2
+ testPackagesBz2File.todo = "Need to test this code"
def testNotModifiedGreater(self):
"Check http not modified is sent for new file"
@@ -517,6 +545,16 @@
return self.downloadFiles('/packages/tilde~test.txt')
testTilde.timeout = 10
+ def testConnectionRefused(self):
+ self.server.stop()
+ reactor.iterate(0.1)
+ filename, sourcepath, destpath = self.getFilePaths('/packages/apt_0.0.1_test.deb')
+ d = self.doRequest(uriData(filename, http.SERVICE_UNAVAILABLE))
+ d.addBoth(lambda x: self.server.start())
+ return d
+ testConnectionRefused.timeout = 2
+
+
#def testTimeout(self):
#pass
#testTimeout.todo = True
@@ -535,23 +573,18 @@
# - file mtime is same as server mtime
# - correct file path is entered in databases after download
-class HttpBackendTest(TestRequestHelper, BackendTestBase):
+class HttpBackendTest(TestRequestHelper, BackendProtocolTests):
def setUp(self):
"""
Make a configuration with a single backend
[files]
backends=file:///<path to test packages directory>
"""
- self.debugname = 'HttpBackendTest'
- self.httpserver = WebServer()
- port = self.httpserver.start()
- uri = "http://127.0.0.1:" + str(port)
- BackendTestBase.setUp(self, uri)
+ BackendTestBase.setUp(self, 'HttpBackendTest', 'http', WebServer)
def tearDown(self):
- self.httpserver.stop()
BackendTestBase.tearDown(self)
-class FtpBackendTest(TestRequestHelper, BackendTestBase):
+class FtpBackendTest(TestRequestHelper, BackendProtocolTests):
def setUp(self):
"""
Make a configuration with a single backend
@@ -559,37 +592,26 @@
backends=file:///<path to test packages directory>
"""
import test_fetchers
- import twisted
- self.debugname = 'FtpBackendTest'
- self.ftpserver = test_fetchers.FtpServer()
- port = self.ftpserver.start()
- uri = "ftp://127.0.0.1:" + str(port)
- BackendTestBase.setUp(self, uri)
+ BackendTestBase.setUp(self, 'FtpBackendTest', 'ftp', test_fetchers.FtpServer)
def tearDown(self):
- self.ftpserver.stop()
BackendTestBase.tearDown(self)
-class RsyncBackendTest(TestRequestHelper, BackendTestBase):
+class RsyncBackendTest(TestRequestHelper, BackendProtocolTests):
def setUp(self):
"""
Make a configuration with a single backend
[files]
backends=file:///<path to test packages directory>
"""
- self.debugname = 'RsyncBackendTest'
- self.rsyncserver = RsyncServer()
- port = self.rsyncserver.start()
- uri = "rsync://127.0.0.1:" + str(port) + '/apt-proxy'
- BackendTestBase.setUp(self, uri)
+ BackendTestBase.setUp(self, 'RsyncBackendTest', 'rsync', RsyncServer, uriSuffix='apt-proxy')
def tearDown(self):
- self.rsyncserver.stop()
- reactor.iterate(0.1)
BackendTestBase.tearDown(self)
def testTempFile(self):
"rysnc Tempfile is detected"
b = self.factory.getBackend(self.backendName)
b.config.bandwidth_limit = 100000
- self.downloadFile(file='/packages/apt_0.0.1_test.deb')
+ filename, sourcepath, destpath = self.getFilePaths('/packages/apt_0.0.1_test.deb')
+ self.doRequest(uriData(filename, None))
reactor.callLater(0.5, self.TempFile2)
self.testResult = defer.Deferred()
return self.testResult
@@ -604,4 +626,82 @@
self.testResult.callback("Tempfile is %s" %(file))
else:
raise UnknownFailure()
- testTempFile.timeout=2
\ No newline at end of file
+ testTempFile.timeout=2
+
+
+# HangTest classes
+#
+# Define a protocol that allows a connection but does not respond
+class HangProtocol(protocol.Protocol):
+ pass
+class HangFactory(protocol.ServerFactory):
+ protocol = HangProtocol
+class HangServer:
+ def start(self):
+ self.port = reactor.listenTCP(0, HangFactory(), interface="127.0.0.1")
+ return self.port.getHost().port
+ def stop(self):
+ self.port.stopListening()
+class HangTestBase(BackendTestBase):
+ def setUp(self, protocol):
+ BackendTestBase.setUp(self,protocol + 'HangTest', protocol, HangServer)
+ def tearDown(self):
+ BackendTestBase.tearDown(self)
+ def testConnectionHang(self):
+ b = self.factory.getBackend(self.backendName)
+ b.config.timeout = 1
+ filename, sourcepath, destpath = self.getFilePaths('/packages/apt_0.0.1_test.deb')
+ d = self.doRequest(uriData(filename, http.SERVICE_UNAVAILABLE))
+ def printTrace(x):
+ import traceback
+ log.debug("-------test errback------")
+ print("test errback----")
+ traceback.print_stack()
+ def printOK(x):
+ log.debug("---trace OK ---")
+ d.addCallback(printOK)
+ d.addErrback(printTrace)
+ return d
+ testConnectionHang.timeout = 5
+
+class HttpHangTest(HangTestBase, TestRequestHelper):
+ def setUp(self):
+ HangTestBase.setUp(self, 'http')
+class FtpHangTest(HangTestBase, TestRequestHelper):
+ def setUp(self):
+ HangTestBase.setUp(self, 'ftp')
+class RsyncHangTest(HangTestBase, TestRequestHelper):
+ def setUp(self):
+ HangTestBase.setUp(self, 'rsync')
+
+# Attempt a connection to a server that is not responding
+dead_ip_address = '127.0.0.2:1'
+
+class NoConnectionBase(BackendTestBase):
+ def setUp(self, protocol):
+ self.debugname = protocol + 'HangTest'
+ backend_uri = protocol + "://"+ dead_ip_address
+
+ config = ("dynamic_backends=off\n" +
+ "[test_data]\n" +
+ "backends=" + backend_uri)
+ TestRequestHelper.setUp(self, config)
+ def tearDown(self):
+ TestRequestHelper.tearDown(self)
+ def testConnectionTimeout(self):
+ b = self.factory.getBackend(self.backendName)
+ b.config.timeout = 1
+ filename, sourcepath, destpath = self.getFilePaths('/packages/apt_0.0.1_test.deb')
+ d = self.doRequest(uriData(filename, http.SERVICE_UNAVAILABLE))
+ return d
+ testConnectionTimeout.timeout = 2
+
+class HttpNoConnectionTest(NoConnectionBase, TestRequestHelper):
+ def setUp(self):
+ NoConnectionBase.setUp(self, 'http')
+class FtpNoConnectionTest(NoConnectionBase, TestRequestHelper):
+ def setUp(self):
+ NoConnectionBase.setUp(self, 'http')
+class HttpNoConnectionTest(NoConnectionBase, TestRequestHelper):
+ def setUp(self):
+ NoConnectionBase.setUp(self, 'http')
Modified: trunk/aptest
==============================================================================
--- trunk/aptest (original)
+++ trunk/aptest Wed Dec 20 15:53:27 2006
@@ -2,6 +2,8 @@
profile=
+mkdir -p /var/run/apt-proxy || exit -1
+
# If you run 'aptest profile' you will get a dump of all functions to ap-profile.log
if [ "$1" = profile ]; then
profile="-p ap-profile.log"
Modified: trunk/debian/changelog
==============================================================================
--- trunk/debian/changelog (original)
+++ trunk/debian/changelog Wed Dec 20 15:53:27 2006
@@ -4,16 +4,24 @@
* Change the meaning of min_refresh_delay parameter, so the
delay is measured from the modification time of the file on the
backend instead of the time a client last requested this file.
+ Now apt-proxy will always query backends when a file is too
+ old (Closes: #266000)
+ * Set process name to apt-proxy
+ * Properly deal with escaped characters, including ~ in URLs on FTP
+ backends. Unescape URLs and check for invalid characters when parsing
+ a request. A big thanks to Ben Hutchings for the patch
+ (Closes: #393483, #366262)
+ * Fix username at password given in backend server URLs and add a test case.
+ Thanks Jason Thomas for the patch (Closes: #348985)
* Uncompress Packages.gz and Packages.bz2 on the fly, and
update databases from these files (Closes: #TODO)
- * Set process name to apt-proxy
[ Mark Sheppard ]
* Generate an error if a client attempts to retrieve
http://server:9999/ (Closes: #386546)
* When returning an error, generate an HTML page containing the error
- -- Chris Halls <halls at debian.org> Wed, 27 Sep 2006 18:29:15 +0100
+ -- Chris Halls <chris.halls at credativ.co.uk> Wed, 13 Dec 2006 22:33:24 +0100
apt-proxy (1.9.35) unstable; urgency=low
More information about the apt-proxy-devel
mailing list