PageRenderTime 446ms CodeModel.GetById 101ms app.highlight 227ms RepoModel.GetById 87ms app.codeStats 0ms

/tests/unit/test_disabledapps.py

https://bitbucket.org/ianb/silverlining/
Python | 169 lines | 121 code | 33 blank | 15 comment | 7 complexity | c8fea707146df63e0885bfaa01aaf4f4 MD5 | raw file
  1"""Tests for the functionality around disabled applications"""
  2import os
  3import os.path
  4import tempfile
  5from contextlib import contextmanager, nested
  6import sys
  7import shutil
  8
  9from webtest import TestApp
 10
 11from silversupport import disabledapps
 12from silversupport.appconfig import AppConfig
 13from silversupport import appdata
 14
 15ROOT = os.path.join(os.path.dirname(__file__),  '../..')
 16
 17
 18@contextmanager
 19def monkeypatch(module, global_, replacement):
 20    """Replace module.global_ with replacement"""
 21    if isinstance(module, str):
 22        __import__(module)
 23        module = sys.modules[module]
 24    old = getattr(module, global_)
 25    setattr(module, global_, replacement)
 26    try:
 27        yield
 28    finally:
 29        setattr(module, global_, old)
 30
 31
 32@contextmanager
 33def temporary_directory():
 34    """Make and then remove a temporary directory"""
 35    dirname = tempfile.mkdtemp()
 36    try:
 37        yield dirname
 38    finally:
 39        shutil.rmtree(dirname)
 40
 41
 42@contextmanager
 43def patch_disabled_apps_path(dirname):
 44    """Changes the location of the disabled apps list to be within dirname
 45
 46    Returns the new path of the file
 47    """
 48    with monkeypatch(disabledapps, 'DISABLED_APPS_FILE',
 49                     os.path.join(dirname, 'disabledapps.txt')):
 50        try:
 51            yield disabledapps.DISABLED_APPS_FILE
 52        finally:
 53            if os.path.exists(disabledapps.DISABLED_APPS_FILE):
 54                os.remove(disabledapps.DISABLED_APPS_FILE)
 55
 56
 57def test_addition():
 58    """Adding an application should correctly write the file"""
 59    with temporary_directory() as tempdir:
 60        with patch_disabled_apps_path(tempdir) as path:
 61            disabledapps.disable_application('testapp')
 62            with open(path) as file_:
 63                lines = [line.strip() for line in file_]
 64                assert lines == ['testapp'], lines
 65
 66
 67def test_is_disabled():
 68    """We should be able to identify disabled apps"""
 69    with temporary_directory() as tempdir:
 70        with patch_disabled_apps_path(tempdir):
 71            assert not disabledapps.is_disabled('testapp')
 72            disabledapps.disable_application('testapp')
 73            assert disabledapps.is_disabled('testapp')
 74
 75
 76def test_removal():
 77    """Removing applications should work correctly"""
 78    with temporary_directory() as tempdir:
 79        with patch_disabled_apps_path(tempdir) as path:
 80            disabledapps.disable_application('testapp-a')
 81            disabledapps.disable_application('testapp-b')
 82            disabledapps.disable_application('testapp-c')
 83            disabledapps.enable_application('testapp-b')
 84            with open(path) as file_:
 85                lines = [line.strip() for line in file_]
 86                assert lines == ['testapp-a', 'testapp-c'], lines
 87
 88
 89## Utilities to help set up a disabled site
 90def patch_deployment_location(dirname):
 91    """Replace /var/www with dirname, and set is_production to True"""
 92    return nested(
 93        patch_disabled_apps_path(dirname),
 94        monkeypatch(appdata, 'APPDATA_MAP',
 95                    os.path.join(dirname, 'appdata.map')),
 96        monkeypatch('silversupport.appconfig', 'DEPLOYMENT_LOCATION', dirname),
 97        monkeypatch('silversupport.appconfig', 'is_production', lambda: True))
 98
 99
100def install_default_disabled(dirname):
101    """Copy default-disabled into dirname"""
102    default_disabled = os.path.join(
103        ROOT, 'silverlining/server-root/var/www/default-disabled')
104    shutil.copytree(default_disabled,
105                    os.path.join(dirname, 'default-disabled'))
106    with open(os.path.join(dirname, 'appdata.map'), 'w') as file_:
107        file_.write(
108            "disabled / default-disabled|general_debug|/dev/null|python|\n")
109
110
111def install_sample_app(dirname):
112    """copy sample app into dirname"""
113    path = os.path.join(dirname, 'sampleapp.0')
114    os.mkdir(path)
115    with open(os.path.join(path, 'app.ini'), 'w') as file_:
116        file_.write('[production]\n')
117        file_.write('app_name = sampleapp\n')
118        file_.write('runner = app.py#application\n')
119    with open(os.path.join(path, 'app.py'), 'w') as file_:
120        file_.write(
121            'from wsgiref.simple_server import demo_app as application\n')
122    appdata.add_appdata('sampleapp.0', ['www.example.com'])
123
124
125@contextmanager
126def disabled_site():
127    with temporary_directory() as tempdir:
128        with patch_deployment_location(tempdir):
129
130            install_default_disabled(tempdir)
131            install_sample_app(tempdir)
132            disabledapps.disable_application('sampleapp')
133
134            app_config = AppConfig.from_location('www.example.com')
135            app = app_config.get_app_from_runner()
136            yield app
137
138
139def test_loading_disabled_site():
140    """Loading a site should return a DisabledSite when the site is disabled"""
141    with disabled_site() as app:
142        assert isinstance(app, disabledapps.DisabledSite), app
143
144
145def test_disabled_site_is_disabled():
146    with disabled_site() as app:
147        test_app = TestApp(app)
148        response = test_app.get(
149            '/', headers={'X-Forwarded-For':'123.123.123.123, localhost'},
150            status=503)
151
152
153def test_disabled_site_commandline_internal_access():
154    with disabled_site() as app:
155        test_app = TestApp(app)
156        response = test_app.get(
157            '/', headers={'X-Forwarded-For':'123.123.123.123, localhost'},
158            extra_environ={'silverlining.update': True},
159            status=200)
160        assert response.body.startswith('Hello world!'), str(response)
161
162
163def test_disabled_site_local_access():
164    with disabled_site() as app:
165        test_app = TestApp(app)
166        response = test_app.get(
167            '/', headers={'X-Forwarded-For':'localhost, localhost'})
168        assert response.status.startswith('200')
169        assert response.body.startswith('Hello world!')