Skip to content

Commit

Permalink
Finally found and fixed the race condition causing tests to fail in T…
Browse files Browse the repository at this point in the history
…ravis CI. Cleaning up.

This was caused by PSDASH_URL_PREFIX being modified on the webapp Blueprint instance which is global and as such it leaked to other tests causing 404s as the blueprint from then on always expected an url prefix.
  • Loading branch information
Jahaja committed Aug 31, 2014
1 parent c27dea9 commit faa0c15
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 150 deletions.
142 changes: 0 additions & 142 deletions psdash/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
from gevent.monkey import patch_all
patch_all()

from werkzeug._compat import wsgi_decoding_dance, to_unicode, string_types
from werkzeug._internal import _get_environ, _encode_idna
from werkzeug.exceptions import NotFound, MethodNotAllowed
from werkzeug.urls import url_quote, url_join
from werkzeug.routing import Map, MapAdapter, RequestSlash, RequestRedirect, RequestAliasRedirect, _simple_rule_re
from gevent.pywsgi import WSGIServer
import locale
import argparse
Expand All @@ -24,142 +19,6 @@
logger = getLogger('psdash.run')


class DebugMapAdapter(MapAdapter):
def match(self, path_info=None, method=None, return_rule=False,
query_args=None):
self.map.update()
if path_info is None:
path_info = self.path_info
else:
path_info = to_unicode(path_info, self.map.charset)
if query_args is None:
query_args = self.query_args
method = (method or self.default_method).upper()

path = u'%s|/%s' % (self.map.host_matching and self.server_name or
self.subdomain, path_info.lstrip('/'))

have_match_for = set()
for rule in self.map._rules:
print "RULE", path, rule.rule
try:
rv = rule.match(path)
except RequestSlash:
raise RequestRedirect(self.make_redirect_url(
url_quote(path_info, self.map.charset,
safe='/:|+') + '/', query_args))
except RequestAliasRedirect as e:
raise RequestRedirect(self.make_alias_redirect_url(
path, rule.endpoint, e.matched_values, method, query_args))
if rv is None:
continue
if rule.methods is not None and method not in rule.methods:
have_match_for.update(rule.methods)
continue

if self.map.redirect_defaults:
redirect_url = self.get_default_redirect(rule, method, rv,
query_args)
if redirect_url is not None:
raise RequestRedirect(redirect_url)

if rule.redirect_to is not None:
if isinstance(rule.redirect_to, string_types):
def _handle_match(match):
value = rv[match.group(1)]
return rule._converters[match.group(1)].to_url(value)
redirect_url = _simple_rule_re.sub(_handle_match,
rule.redirect_to)
else:
redirect_url = rule.redirect_to(self, **rv)
raise RequestRedirect(str(url_join('%s://%s%s%s' % (
self.url_scheme,
self.subdomain and self.subdomain + '.' or '',
self.server_name,
self.script_name
), redirect_url)))

if return_rule:
return rule, rv
else:
return rule.endpoint, rv

if have_match_for:
raise MethodNotAllowed(valid_methods=list(have_match_for))

print "NOT FOUND, RAISING"

raise NotFound()


class DebugMap(Map):
def bind(self, server_name, script_name=None, subdomain=None,
url_scheme='http', default_method='GET', path_info=None,
query_args=None):
server_name = server_name.lower()
if self.host_matching:
if subdomain is not None:
raise RuntimeError('host matching enabled and a '
'subdomain was provided')
elif subdomain is None:
subdomain = self.default_subdomain
if script_name is None:
script_name = '/'
server_name = _encode_idna(server_name)
return DebugMapAdapter(self, server_name, script_name, subdomain,
url_scheme, path_info, default_method, query_args)

def bind_to_environ(self, environ, server_name=None, subdomain=None):
environ = _get_environ(environ)
if server_name is None:
if 'HTTP_HOST' in environ:
server_name = environ['HTTP_HOST']
print 'HTTP_HOST', server_name
else:
server_name = environ['SERVER_NAME']
if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \
in (('https', '443'), ('http', '80')):
server_name += ':' + environ['SERVER_PORT']
elif subdomain is None and not self.host_matching:
server_name = server_name.lower()
if 'HTTP_HOST' in environ:
wsgi_server_name = environ.get('HTTP_HOST')
else:
wsgi_server_name = environ.get('SERVER_NAME')
if (environ['wsgi.url_scheme'], environ['SERVER_PORT']) not \
in (('https', '443'), ('http', '80')):
wsgi_server_name += ':' + environ['SERVER_PORT']
wsgi_server_name = wsgi_server_name.lower()
cur_server_name = wsgi_server_name.split('.')
real_server_name = server_name.split('.')
offset = -len(real_server_name)
if cur_server_name[offset:] != real_server_name:
print "NOT MATCHING", cur_server_name[offset:] != real_server_name
# This can happen even with valid configs if the server was
# accesssed directly by IP address under some situations.
# Instead of raising an exception like in Werkzeug 0.7 or
# earlier we go by an invalid subdomain which will result
# in a 404 error on matching.
subdomain = '<invalid>'
else:
subdomain = '.'.join(filter(None, cur_server_name[:offset]))

def _get_wsgi_string(name):
val = environ.get(name)
if val is not None:
return wsgi_decoding_dance(val, self.charset)

print "SERVER NAME RES", server_name

script_name = _get_wsgi_string('SCRIPT_NAME')
path_info = _get_wsgi_string('PATH_INFO')
query_args = _get_wsgi_string('QUERY_STRING')
return DebugMap.bind(self, server_name, script_name,
subdomain, environ['wsgi.url_scheme'],
environ['REQUEST_METHOD'], path_info,
query_args=query_args)


class PsDashRunner(object):
DEFAULT_LOG_INTERVAL = 60
DEFAULT_NET_IO_COUNTER_INTERVAL = 3
Expand Down Expand Up @@ -283,7 +142,6 @@ def register_node(self, name, host, port):

def _create_app(self, config=None):
app = Flask(__name__)
app.url_map = DebugMap()
app.psdash = self
app.config.from_envvar('PSDASH_CONFIG', silent=True)

Expand Down
14 changes: 6 additions & 8 deletions tests/test_run.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
from psdash.run import PsDashRunner
from psdash.node import LocalNode
import gevent
Expand Down Expand Up @@ -96,10 +95,10 @@ def test_register_agent(self):
'PSDASH_REGISTER_TO': 'http://localhost:5000',
'PSDASH_REGISTER_AS': 'the_agent'
}
r = PsDashRunner({'DEBUG': True})
r = PsDashRunner()
agent = PsDashRunner(agent_options)
jobs.append(gevent.spawn(r.run))
gevent.sleep(0.5)
gevent.sleep(0.3)
jobs.append(gevent.spawn(agent.run))
gevent.sleep(0.3)

Expand All @@ -117,11 +116,11 @@ def test_register_agent_without_name_defaults_to_hostname(self):
'PSDASH_PORT': 5001,
'PSDASH_REGISTER_TO': 'http://localhost:5000'
}
r = PsDashRunner({'DEBUG': True})
r = PsDashRunner()
agent = PsDashRunner(agent_options)
jobs = []
jobs.append(gevent.spawn(r.run))
gevent.sleep(0.5)
gevent.sleep(0.3)
jobs.append(gevent.spawn(agent.run))
gevent.sleep(0.3)

Expand All @@ -136,8 +135,7 @@ def test_register_agent_without_name_defaults_to_hostname(self):
def test_register_agent_to_auth_protected_host(self):
r = PsDashRunner({
'PSDASH_AUTH_USERNAME': 'user',
'PSDASH_AUTH_PASSWORD': 'pass',
'DEBUG': True
'PSDASH_AUTH_PASSWORD': 'pass'
})
agent = PsDashRunner({
'PSDASH_AGENT': True,
Expand All @@ -148,7 +146,7 @@ def test_register_agent_to_auth_protected_host(self):
})
jobs = []
jobs.append(gevent.spawn(r.run))
gevent.sleep(0.5)
gevent.sleep(0.3)
jobs.append(gevent.spawn(agent.run))
gevent.sleep(0.3)

Expand Down

0 comments on commit faa0c15

Please sign in to comment.