~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/tests/test_simple.py

  • Committer: Martin Albisetti
  • Date: 2008-10-25 19:02:04 UTC
  • mto: This revision was merged to the branch mainline in revision 233.
  • Revision ID: martin.albisetti@canonical.com-20081025190204-3fmvke4wlkv90o6o
Updated NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2008, 2009, 2011 Canonical Ltd.
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
#
17
 
 
18
1
import cgi
 
2
import os
 
3
import tempfile
 
4
import shutil
19
5
import logging
20
 
import re
21
 
import simplejson
22
 
from cStringIO import StringIO
23
6
 
24
 
from bzrlib.tests import TestCaseWithTransport
25
 
try:
26
 
    from bzrlib.util.configobj.configobj import ConfigObj
27
 
except ImportError:
28
 
    from configobj import ConfigObj
29
 
from bzrlib import config
 
7
import bzrlib.bzrdir
 
8
import bzrlib.osutils
 
9
from configobj import ConfigObj
30
10
 
31
11
from loggerhead.apps.branch import BranchWSGIApp
32
 
from loggerhead.apps.http_head import HeadMiddleware
33
12
from paste.fixture import TestApp
34
 
from paste.httpexceptions import HTTPExceptionHandler, HTTPMovedPermanently
35
 
 
36
 
 
37
 
 
38
 
class BasicTests(TestCaseWithTransport):
 
13
 
 
14
 
 
15
def test_config_root():
 
16
    from loggerhead.apps.config import Root
 
17
    config = ConfigObj()
 
18
    app = TestApp(Root(config))
 
19
    res = app.get('/')
 
20
    res.mustcontain('loggerhead branches')
 
21
 
 
22
 
 
23
class BasicTests(object):
 
24
 
 
25
    # setup_method and teardown_method are so i can run the tests with
 
26
    # py.test and take advantage of the error reporting.
 
27
    def setup_method(self, meth):
 
28
        self.setUp()
 
29
 
 
30
    def teardown_method(self, meth):
 
31
        self.tearDown()
39
32
 
40
33
    def setUp(self):
41
 
        TestCaseWithTransport.setUp(self)
42
 
        logging.basicConfig(level=logging.ERROR)
43
 
        logging.getLogger('bzr').setLevel(logging.CRITICAL)
 
34
        logging.basicConfig(level=logging.DEBUG)
 
35
        self.bzrbranch = None
 
36
        self.old_bzrhome = None
44
37
 
45
38
    def createBranch(self):
46
 
        self.tree = self.make_branch_and_tree('.')
47
 
 
48
 
    def setUpLoggerhead(self, **kw):
49
 
        branch_app = BranchWSGIApp(self.tree.branch, '', export_tarballs=True, **kw).app
50
 
        return TestApp(HTTPExceptionHandler(branch_app))
51
 
 
52
 
    def assertOkJsonResponse(self, app, env):
53
 
        start, content = consume_app(app, env)
54
 
        self.assertEqual('200 OK', start[0])
55
 
        self.assertEqual('application/json', dict(start[1])['Content-Type'])
56
 
        self.assertEqual(None, start[2])
57
 
        simplejson.loads(content)
58
 
 
59
 
    def make_branch_app(self, branch, **kw):
60
 
        branch_app = BranchWSGIApp(branch, friendly_name='friendly-name', **kw)
61
 
        branch_app._environ = {
62
 
            'wsgi.url_scheme':'',
63
 
            'SERVER_NAME':'',
64
 
            'SERVER_PORT':'80',
65
 
            }
66
 
        branch_app._url_base = ''
67
 
        return branch_app
 
39
        self.old_bzrhome = bzrlib.osutils.set_or_unset_env('BZR_HOME', '')
 
40
        self.bzrbranch = tempfile.mkdtemp()
 
41
        self.branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
 
42
            self.bzrbranch, force_new_tree=True)
 
43
        self.tree = self.branch.bzrdir.open_workingtree()
 
44
 
 
45
    config_template = """
 
46
    [project]
 
47
        [[branch]]
 
48
            branch_name = 'branch'
 
49
            folder = '%(branch)s'
 
50
    """
 
51
 
 
52
    def setUpLoggerhead(self):
 
53
        app = TestApp(BranchWSGIApp(self.branch, '').app)
 
54
        return app
 
55
 
 
56
    def tearDown(self):
 
57
        if self.bzrbranch is not None:
 
58
            shutil.rmtree(self.bzrbranch)
 
59
        bzrlib.osutils.set_or_unset_env('BZR_HOME', self.old_bzrhome)
68
60
 
69
61
 
70
62
class TestWithSimpleTree(BasicTests):
73
65
        BasicTests.setUp(self)
74
66
        self.createBranch()
75
67
 
 
68
        f = open(os.path.join(self.bzrbranch, 'myfilename'), 'w')
76
69
        self.filecontents = ('some\nmultiline\ndata\n'
77
70
                             'with<htmlspecialchars\n')
78
 
        filenames = ['myfilename', 'anotherfile<']
79
 
        self.build_tree_contents(
80
 
            (filename, self.filecontents) for filename in filenames)
81
 
        for filename in filenames:
82
 
            self.tree.add(filename, '%s-id' % filename)
 
71
        try:
 
72
            f.write(self.filecontents)
 
73
        finally:
 
74
            f.close()
 
75
        self.tree.add('myfilename')
83
76
        self.fileid = self.tree.path2id('myfilename')
84
77
        self.msg = 'a very exciting commit message <'
85
78
        self.revid = self.tree.commit(message=self.msg)
86
79
 
87
 
    def test_public_private(self):
88
 
        app = self.make_branch_app(self.tree.branch, private=True)
89
 
        self.assertEqual(app.public_private_css(), 'private')
90
 
        app = self.make_branch_app(self.tree.branch)
91
 
        self.assertEqual(app.public_private_css(), 'public')
92
80
 
93
81
    def test_changes(self):
94
82
        app = self.setUpLoggerhead()
95
83
        res = app.get('/changes')
96
84
        res.mustcontain(cgi.escape(self.msg))
97
85
 
98
 
    def test_changes_for_file(self):
99
 
        app = self.setUpLoggerhead()
100
 
        res = app.get('/changes?filter_file_id=myfilename-id')
101
 
        res.mustcontain(cgi.escape(self.msg))
102
 
 
103
 
    def test_changes_branch_from(self):
104
 
        app = self.setUpLoggerhead(served_url="lp:loggerhead")
105
 
        res = app.get('/changes')
106
 
        self.failUnless("To get this branch, use:" in res)
107
 
        self.failUnless("lp:loggerhead" in res)
108
 
        app = self.setUpLoggerhead(served_url=None)
109
 
        res = app.get('/changes')
110
 
        self.failIf("To get this branch, use:" in res)
111
 
 
112
86
    def test_changes_search(self):
113
87
        app = self.setUpLoggerhead()
114
88
        res = app.get('/changes', params={'q': 'foo'})
116
90
 
117
91
    def test_annotate(self):
118
92
        app = self.setUpLoggerhead()
119
 
        res = app.get('/annotate', params={'file_id': self.fileid})
120
 
        # If pygments is installed, it inserts <span class="pyg" content into
121
 
        # the output, to trigger highlighting. And it specifically highlights
122
 
        # the &lt; that we are interested in seeing in the output.
123
 
        # Without pygments we have a simple: 'with&lt;htmlspecialchars'
124
 
        # With it, we have
125
 
        # '<span class='pyg-n'>with</span><span class='pyg-o'>&lt;</span>'
126
 
        # '<span class='pyg-n'>htmlspecialchars</span>
127
 
        # So we pre-filter the body, to make sure remove spans of that type.
128
 
        body_no_span = re.sub(r'<span class="pyg-.">', '', res.body)
129
 
        body_no_span = body_no_span.replace('</span>', '')
 
93
        res = app.get('/annotate', params={'file_id':self.fileid})
130
94
        for line in self.filecontents.splitlines():
131
 
            escaped = cgi.escape(line)
132
 
            self.assertTrue(escaped in body_no_span,
133
 
                            "did not find %r in %r" % (escaped, body_no_span))
 
95
            res.mustcontain(cgi.escape(line))
134
96
 
135
97
    def test_inventory(self):
136
98
        app = self.setUpLoggerhead()
137
99
        res = app.get('/files')
138
100
        res.mustcontain('myfilename')
139
 
        res = app.get('/files/')
140
 
        res.mustcontain('myfilename')
141
 
        res = app.get('/files/1')
142
 
        res.mustcontain('myfilename')
143
 
        res = app.get('/files/1/')
144
 
        res.mustcontain('myfilename')
145
 
        res = app.get('/files/1/?file_id=' + self.tree.path2id(''))
146
 
        res.mustcontain('myfilename')
147
 
 
148
 
    def test_inventory_bad_rev_404(self):
149
 
        app = self.setUpLoggerhead()
150
 
        res = app.get('/files/200', status=404)
151
 
        res = app.get('/files/invalid-revid', status=404)
152
 
 
153
 
    def test_inventory_bad_path_404(self):
154
 
        app = self.setUpLoggerhead()
155
 
        res = app.get('/files/1/hooha', status=404)
156
 
        res = app.get('/files/1?file_id=dssadsada', status=404)
157
101
 
158
102
    def test_revision(self):
159
103
        app = self.setUpLoggerhead()
160
104
        res = app.get('/revision/1')
161
 
        res.mustcontain(no=['anotherfile<'])
162
 
        res.mustcontain('anotherfile&lt;')
163
105
        res.mustcontain('myfilename')
164
106
 
165
107
 
166
108
class TestEmptyBranch(BasicTests):
167
 
    """Test that an empty branch doesn't break"""
168
109
 
169
110
    def setUp(self):
170
111
        BasicTests.setUp(self)
175
116
        res = app.get('/changes')
176
117
        res.mustcontain('No revisions!')
177
118
 
178
 
    def test_inventory(self):
179
 
        app = self.setUpLoggerhead()
180
 
        res = app.get('/files')
181
 
        res.mustcontain('No revisions!')
182
 
 
183
 
 
184
 
class TestHiddenBranch(BasicTests):
185
 
    """
186
 
    Test that hidden branches aren't shown
187
 
    FIXME: not tested that it doesn't show up on listings
188
 
    """
189
 
 
190
 
    def setUp(self):
191
 
        BasicTests.setUp(self)
192
 
        self.createBranch()
193
 
        locations = config.locations_config_filename()
194
 
        config.ensure_config_dir_exists()
195
 
        open(locations, 'wb').write('[%s]\nhttp_serve = False'
196
 
                                    % (self.tree.branch.base,))
197
 
 
198
 
    def test_no_access(self):
199
 
        app = self.setUpLoggerhead()
200
 
        res = app.get('/changes', status=404)
201
 
 
202
 
 
203
 
class TestControllerRedirects(BasicTests):
204
 
    """
205
 
    Test that a file under /files redirects to /view,
206
 
    and a directory under /view redirects to /files.
207
 
    """
208
 
 
209
 
    def setUp(self):
210
 
        BasicTests.setUp(self)
211
 
        self.createBranch()
212
 
        self.build_tree(('file', 'folder/', 'folder/file'))
213
 
        self.tree.smart_add([])
214
 
        self.tree.commit('')
215
 
 
216
 
    def test_view_folder(self):
217
 
        app = TestApp(BranchWSGIApp(self.tree.branch, '').app)
218
 
 
219
 
        e = self.assertRaises(HTTPMovedPermanently, app.get, '/view/head:/folder')
220
 
        self.assertEqual(e.location(), '/files/head:/folder')
221
 
 
222
 
    def test_files_file(self):
223
 
        app = TestApp(BranchWSGIApp(self.tree.branch, '').app)
224
 
 
225
 
        e = self.assertRaises(HTTPMovedPermanently, app.get, '/files/head:/folder/file')
226
 
        self.assertEqual(e.location(), '/view/head:/folder/file')
227
 
        e = self.assertRaises(HTTPMovedPermanently, app.get, '/files/head:/file')
228
 
        self.assertEqual(e.location(), '/view/head:/file')
229
 
 
230
 
 
231
 
class TestHeadMiddleware(BasicTests):
232
 
 
233
 
    def setUp(self):
234
 
        BasicTests.setUp(self)
235
 
        self.createBranch()
236
 
        self.msg = 'trivial commit message'
237
 
        self.revid = self.tree.commit(message=self.msg)
238
 
 
239
 
    def setUpLoggerhead(self, **kw):
240
 
        branch_app = BranchWSGIApp(self.tree.branch, '', **kw).app
241
 
        return TestApp(HTTPExceptionHandler(HeadMiddleware(branch_app)))
242
 
 
243
 
    def test_get(self):
244
 
        app = self.setUpLoggerhead()
245
 
        res = app.get('/changes')
246
 
        res.mustcontain(self.msg)
247
 
        self.assertEqual('text/html', res.header('Content-Type'))
248
 
 
249
 
    def test_head(self):
250
 
        app = self.setUpLoggerhead()
251
 
        res = app.get('/changes', extra_environ={'REQUEST_METHOD': 'HEAD'})
252
 
        self.assertEqual('text/html', res.header('Content-Type'))
253
 
        self.assertEqualDiff('', res.body)
254
 
 
255
 
 
256
 
def consume_app(app, env):
257
 
    body = StringIO()
258
 
    start = []
259
 
    def start_response(status, headers, exc_info=None):
260
 
        start.append((status, headers, exc_info))
261
 
        return body.write
262
 
    extra_content = list(app(env, start_response))
263
 
    body.writelines(extra_content)
264
 
    return start[0], body.getvalue()
265
 
 
266
 
 
267
 
 
268
 
#class TestGlobalConfig(BasicTests):
269
 
#    """
270
 
#    Test that global config settings are respected
271
 
#    """
272
 
 
273
 
#    def setUp(self):
274
 
#        BasicTests.setUp(self)
275
 
#        self.createBranch()
276
 
#        config.GlobalConfig().set_user_option('http_version', 'True')
277
 
 
278
 
#    def test_setting_respected(self):
279
 
        #FIXME: Figure out how to test this properly
280
 
#        app = self.setUpLoggerhead()
281
 
#        res = app.get('/changes', status=200)