1 # -*- coding: utf-8 -*-
10 from openerp import tools
14 __all__ = ['load_tests', 'CrawlSuite']
16 class RedirectHandler(urllib2.HTTPRedirectHandler):
18 HTTPRedirectHandler is predicated upon HTTPErrorProcessor being used and
19 works by intercepting 3xy "errors".
21 Inherit from it to handle 3xy non-error responses instead, as we're not
22 using the error processor
25 def http_response(self, request, response):
26 code, msg, hdrs = response.code, response.msg, response.info()
29 return self.parent.error(
30 'http', request, response, code, msg, hdrs)
34 https_response = http_response
36 class CrawlSuite(unittest2.TestSuite):
37 """ Test suite crawling an openerp CMS instance and checking that all
38 internal links lead to a 200 response.
40 If a username and a password are provided, authenticates the user before
44 def __init__(self, user=None, password=None):
45 super(CrawlSuite, self).__init__()
47 registry = openerp.registry(tools.config['db_name'])
49 # switch registry to test mode, so that requests can be made
50 registry.enter_test_mode()
52 self.opener = urllib2.OpenerDirector()
53 self.opener.add_handler(urllib2.UnknownHandler())
54 self.opener.add_handler(urllib2.HTTPHandler())
55 self.opener.add_handler(urllib2.HTTPSHandler())
56 self.opener.add_handler(urllib2.HTTPCookieProcessor())
57 self.opener.add_handler(RedirectHandler())
59 self._authenticate(user, password)
63 registry.leave_test_mode()
65 def _request(self, path):
66 return self.opener.open(urlparse.urlunsplit([
67 'http', 'localhost:%s' % tools.config['xmlrpc_port'],
71 def _authenticate(self, user, password):
72 # force tools.config['db_name'] in user session so opening `/` doesn't
73 # blow up in multidb situations
74 self.opener.open('http://localhost:{port}/web/?db={db}'.format(
75 port=tools.config['xmlrpc_port'],
76 db=werkzeug.urls.url_quote_plus(tools.config['db_name']),
79 url = 'http://localhost:{port}/login?{query}'.format(
80 port=tools.config['xmlrpc_port'],
81 query=werkzeug.urls.url_encode({
82 'db': tools.config['db_name'],
87 auth = self.opener.open(url)
88 assert auth.getcode() < 400, "Auth failure %d" % auth.getcode()
90 def _wrapped_run(self, result, debug=False):
91 registry = openerp.registry(tools.config['db_name'])
93 # switch registry to test mode, so that requests can be made
94 registry.enter_test_mode()
96 paths = [URL('/'), URL('/sitemap')]
101 r = self._request(url.url)
102 url.to_case(self.user, r).run(result)
104 if r.info().gettype() != 'text/html':
107 doc = lxml.html.fromstring(r.read())
108 for link in doc.xpath('//a[@href]'):
109 href = link.get('href')
111 # avoid repeats, even for links we won't crawl no need to
112 # bother splitting them if we've already ignored them
114 if href in seen: continue
117 parts = urlparse.urlsplit(href)
120 not parts.path.startswith('/') or \
121 parts.path == '/web' or\
122 parts.path.startswith('/web/') or \
123 (parts.scheme and parts.scheme not in ('http', 'https')):
126 paths.append(URL(href, url.url))
129 registry.leave_test_mode()
132 def __init__(self, url, source=None):
136 def to_case(self, user, result):
137 return cases.URLCase(user, self.url, self.source, result)
139 def load_tests(loader, base, _):
140 base.addTest(CrawlSuite())
141 base.addTest(CrawlSuite('admin', 'admin'))
142 base.addTest(CrawlSuite('demo', 'demo'))