Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy McKay committed Nov 14, 2012
0 parents commit 87af084
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 0 deletions.
5 changes: 5 additions & 0 deletions LICENSE.rst
@@ -0,0 +1,5 @@
BSD and MPL

Portions of this are from commonware:

https://github.com/jsocol/commonware/blob/master/LICENSE
20 changes: 20 additions & 0 deletions README.rst
@@ -0,0 +1,20 @@
An experimental nose plugin to block access to external services that you
really should not be accessing in your unit tests.

To use::

pip install nose-blockage

Then add the following to your tests::

--with-blockage

By default it whitelists `localhost` and `127.0.0.1`. To change the whitelist::

--http-whitelist=some.site,some.other.site

If the code hits a http connection then instead of completing it will raise a
MockHTTPCall exception. Please go an mock your tests appropriately.

To come, maybe more libs.

1 change: 1 addition & 0 deletions blockage/__init__.py
@@ -0,0 +1 @@
from blockage.plugins import NoseBlockage
55 changes: 55 additions & 0 deletions blockage/plugin.py
@@ -0,0 +1,55 @@
import httplib
import logging
import os
import urlparse

NOSE = False
try:
from nose.plugins.base import Plugin
NOSE = True
except ImportError:
class Plugin:
pass

log = logging.getLogger(__name__)


class MockHTTPCall(Exception):
# If you don't mock out http calls in your tests, we'll raise an error
# for you so you'll remember to do it next time.
pass



class NoseBlockage(Plugin):
name = 'blockage'

def options(self, parse, env=os.environ):
import pdb; pdb.set_trace()
print parse
super(NoseBlockage, self).options(parse, env=env)

def configure(self, options, conf):
import pdb; pdb.set_trace()
print options, conf
super(NoseBlockage, self).configure(options, conf)

def begin(self):

# These are the ES hosts.
HTTP_DOMAINS = ['http://127.0.0.1:9200']
HTTP_DOMAINS = [urlparse.urlparse(d).netloc for d in HTTP_DOMAINS]

old = httplib.HTTPConnection
def whitelisted(self, host, *args, **kwargs):
if host not in HTTP_DOMAINS:
print '-', host
raise MockHTTPCall(host)
print '+', host
return old(self, host, *args, **kwargs)

whitelisted.patched = True

if not getattr(httplib.HTTPConnection.__init__, 'patched', None):
httplib.HTTPConnection.__init__ = whitelisted

55 changes: 55 additions & 0 deletions blockage/plugins.py
@@ -0,0 +1,55 @@
import httplib
import logging
import os

NOSE = False
try:
from nose.plugins.base import Plugin
NOSE = True
except ImportError:
class Plugin:
pass

log = logging.getLogger(__name__)


class MockHTTPCall(Exception):
# If you don't mock out http calls in your tests, we'll raise an error
# for you so you'll remember to do it next time.
pass



class NoseBlockage(Plugin):
name = 'blockage'
default_http_whitelist = '127.0.0.1,localhost'

def options(self, parser, env=os.environ):
super(NoseBlockage, self).options(parser, env=env)
parser.add_option('--http-whitelist', action='store',
default=env.get('HTTP_WHITELIST',
self.default_http_whitelist),
dest='http_whitelist')

def configure(self, options, conf):
self.options = options
super(NoseBlockage, self).configure(options, conf)
self.http_whitelist = [s.strip() for s in
self.options.http_whitelist.split(',')]

def begin(self):
http_whitelist = self.http_whitelist

def whitelisted(self, host, *args, **kwargs):
if isinstance(host, basestring) and host not in http_whitelist:
log.warning('Denied HTTP connection to: %s' % host)
raise MockHTTPCall(host)
log.debug('Allowed HTTP connection to: %s' % host)
return self.old(host, *args, **kwargs)

whitelisted.blockage = True

if not getattr(httplib.HTTPConnection, 'blockage', False):
log.debug('Monkey patching httplib')
httplib.HTTPConnection.old = httplib.HTTPConnection.__init__
httplib.HTTPConnection.__init__ = whitelisted
28 changes: 28 additions & 0 deletions setup.py
@@ -0,0 +1,28 @@
from setuptools import setup


setup(
name='nose-blockage',
version='0.1',
description='Raise errors when communicating outside of tests',
long_description=open('README.rst').read(),
author='Andy McKay',
author_email='andym@mozilla.com',
license='BSD',
install_requires=['nose'],
packages=['blockage'],
url='https://github.com/andymckay/nose-blockage',
entry_points={
'nose.plugins.0.10': [
'blockage = blockage:NoseBlockage'
]
},
include_package_data=True,
zip_safe=False,
classifiers=[
'Intended Audience :: Developers',
'Natural Language :: English',
'Operating System :: OS Independent',
'Framework :: Django'
]
)

0 comments on commit 87af084

Please sign in to comment.