44from urllib .error import URLError , HTTPError
55from urllib .request import urlopen
66from test import support
7+ import threading
8+ from http .server import BaseHTTPRequestHandler , HTTPServer
9+
710
811class RobotTestCase (unittest .TestCase ):
912 def __init__ (self , index = None , parser = None , url = None , good = None , agent = None ):
@@ -247,33 +250,51 @@ def RobotTest(index, robots_txt, good_urls, bad_urls,
247250RobotTest (16 , doc , good , bad )
248251
249252
250- class NetworkTestCase (unittest .TestCase ):
253+ class RobotHandler (BaseHTTPRequestHandler ):
254+
255+ def do_GET (self ):
256+ self .send_error (403 , "Forbidden access" )
257+
258+ def log_message (self , format , * args ):
259+ pass
260+
261+
262+ class PasswordProtectedSiteTestCase (unittest .TestCase ):
263+
264+ def setUp (self ):
265+ self .server = HTTPServer ((support .HOST , 0 ), RobotHandler )
266+
267+ self .t = threading .Thread (
268+ name = 'HTTPServer serving' ,
269+ target = self .server .serve_forever ,
270+ # Short poll interval to make the test finish quickly.
271+ # Time between requests is short enough that we won't wake
272+ # up spuriously too many times.
273+ kwargs = {'poll_interval' :0.01 })
274+ self .t .daemon = True # In case this function raises.
275+ self .t .start ()
276+
277+ def tearDown (self ):
278+ self .server .shutdown ()
279+ self .t .join ()
280+ self .server .server_close ()
281+
282+ def runTest (self ):
283+ self .testPasswordProtectedSite ()
251284
252285 def testPasswordProtectedSite (self ):
253- support .requires ('network' )
254- with support .transient_internet ('mueblesmoraleda.com' ):
255- url = 'http://mueblesmoraleda.com'
256- robots_url = url + "/robots.txt"
257- # First check the URL is usable for our purposes, since the
258- # test site is a bit flaky.
259- try :
260- urlopen (robots_url )
261- except HTTPError as e :
262- if e .code not in {401 , 403 }:
263- self .skipTest (
264- "%r should return a 401 or 403 HTTP error, not %r"
265- % (robots_url , e .code ))
266- else :
267- self .skipTest (
268- "%r should return a 401 or 403 HTTP error, not succeed"
269- % (robots_url ))
270- parser = urllib .robotparser .RobotFileParser ()
271- parser .set_url (url )
272- try :
273- parser .read ()
274- except URLError :
275- self .skipTest ('%s is unavailable' % url )
276- self .assertEqual (parser .can_fetch ("*" , robots_url ), False )
286+ addr = self .server .server_address
287+ url = 'http://' + support .HOST + ':' + str (addr [1 ])
288+ robots_url = url + "/robots.txt"
289+ parser = urllib .robotparser .RobotFileParser ()
290+ parser .set_url (url )
291+ parser .read ()
292+ self .assertFalse (parser .can_fetch ("*" , robots_url ))
293+
294+ def __str__ (self ):
295+ return '%s' % self .__class__ .__name__
296+
297+ class NetworkTestCase (unittest .TestCase ):
277298
278299 @unittest .skip ('does not handle the gzip encoding delivered by pydotorg' )
279300 def testPythonOrg (self ):
@@ -288,6 +309,7 @@ def testPythonOrg(self):
288309def load_tests (loader , suite , pattern ):
289310 suite = unittest .makeSuite (NetworkTestCase )
290311 suite .addTest (tests )
312+ suite .addTest (PasswordProtectedSiteTestCase ())
291313 return suite
292314
293315if __name__ == '__main__' :
0 commit comments