1
# Copyright (C) 2007, 2008, 2009, 2011 Canonical Ltd.
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.
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.
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
10
from configobj import ConfigObj
12
from loggerhead.history import History
22
from bzrlib.tests import TestCaseWithTransport
24
from bzrlib.util.configobj.configobj import ConfigObj
26
from configobj import ConfigObj
27
from bzrlib import config
13
29
from loggerhead.apps.branch import BranchWSGIApp
30
from loggerhead.apps.http_head import HeadMiddleware
14
31
from paste.fixture import TestApp
17
def test_config_root():
18
from loggerhead.apps.config import Root
20
app = TestApp(Root(config))
22
res.mustcontain('loggerhead branches')
25
class BasicTests(object):
27
# setup_method and teardown_method are so i can run the tests with
28
# py.test and take advantage of the error reporting.
29
def setup_method(self, meth):
32
def teardown_method(self, meth):
32
from paste.httpexceptions import HTTPExceptionHandler, HTTPMovedPermanently
36
class BasicTests(TestCaseWithTransport):
36
logging.basicConfig(level=logging.DEBUG)
38
self.old_bzrhome = None
39
TestCaseWithTransport.setUp(self)
40
logging.basicConfig(level=logging.ERROR)
41
logging.getLogger('bzr').setLevel(logging.CRITICAL)
40
43
def createBranch(self):
41
self.old_bzrhome = bzrlib.osutils.set_or_unset_env('BZR_HOME', '')
42
self.bzrbranch = tempfile.mkdtemp()
43
self.branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
44
self.bzrbranch, force_new_tree=True)
45
self.tree = self.branch.bzrdir.open_workingtree()
50
branch_name = 'branch'
54
def makeHistory(self):
55
return History.from_folder(self.bzrbranch)
57
def setUpLoggerhead(self):
58
app = TestApp(BranchWSGIApp(self.bzrbranch).app)
62
if self.bzrbranch is not None:
63
shutil.rmtree(self.bzrbranch)
64
bzrlib.osutils.set_or_unset_env('BZR_HOME', self.old_bzrhome)
44
self.tree = self.make_branch_and_tree('.')
46
def setUpLoggerhead(self, **kw):
47
branch_app = BranchWSGIApp(self.tree.branch, '', **kw).app
48
return TestApp(HTTPExceptionHandler(branch_app))
67
51
class TestWithSimpleTree(BasicTests):
70
54
BasicTests.setUp(self)
71
55
self.createBranch()
73
f = open(os.path.join(self.bzrbranch, 'myfilename'), 'w')
74
57
self.filecontents = ('some\nmultiline\ndata\n'
75
58
'with<htmlspecialchars\n')
77
f.write(self.filecontents)
80
self.tree.add('myfilename')
59
filenames = ['myfilename', 'anotherfile<']
60
self.build_tree_contents(
61
(filename, self.filecontents) for filename in filenames)
62
for filename in filenames:
63
self.tree.add(filename, '%s-id' % filename)
81
64
self.fileid = self.tree.path2id('myfilename')
82
65
self.msg = 'a very exciting commit message <'
83
66
self.revid = self.tree.commit(message=self.msg)
86
68
def test_changes(self):
87
69
app = self.setUpLoggerhead()
88
70
res = app.get('/changes')
89
71
res.mustcontain(cgi.escape(self.msg))
73
def test_changes_for_file(self):
74
app = self.setUpLoggerhead()
75
res = app.get('/changes?filter_file_id=myfilename-id')
76
res.mustcontain(cgi.escape(self.msg))
78
def test_changes_branch_from(self):
79
app = self.setUpLoggerhead(served_url="lp:loggerhead")
80
res = app.get('/changes')
81
self.failUnless("To get this branch, use:" in res)
82
self.failUnless("lp:loggerhead" in res)
83
app = self.setUpLoggerhead(served_url=None)
84
res = app.get('/changes')
85
self.failIf("To get this branch, use:" in res)
91
87
def test_changes_search(self):
92
88
app = self.setUpLoggerhead()
93
89
res = app.get('/changes', params={'q': 'foo'})
96
92
def test_annotate(self):
97
93
app = self.setUpLoggerhead()
98
res = app.get('/annotate', params={'file_id':self.fileid})
94
res = app.get('/annotate', params={'file_id': self.fileid})
95
# If pygments is installed, it inserts <span class="pyg" content into
96
# the output, to trigger highlighting. And it specifically highlights
97
# the < that we are interested in seeing in the output.
98
# Without pygments we have a simple: 'with<htmlspecialchars'
100
# '<span class='pyg-n'>with</span><span class='pyg-o'><</span>'
101
# '<span class='pyg-n'>htmlspecialchars</span>
102
# So we pre-filter the body, to make sure remove spans of that type.
103
body_no_span = re.sub(r'<span class="pyg-.">', '', res.body)
104
body_no_span = body_no_span.replace('</span>', '')
99
105
for line in self.filecontents.splitlines():
100
res.mustcontain(cgi.escape(line))
106
escaped = cgi.escape(line)
107
self.assertTrue(escaped in body_no_span,
108
"did not find %r in %r" % (escaped, body_no_span))
102
110
def test_inventory(self):
103
111
app = self.setUpLoggerhead()
104
112
res = app.get('/files')
105
113
res.mustcontain('myfilename')
114
res = app.get('/files/')
115
res.mustcontain('myfilename')
116
res = app.get('/files/1')
117
res.mustcontain('myfilename')
118
res = app.get('/files/1/')
119
res.mustcontain('myfilename')
120
res = app.get('/files/1/?file_id=' + self.tree.path2id(''))
121
res.mustcontain('myfilename')
123
def test_inventory_bad_rev_404(self):
124
app = self.setUpLoggerhead()
125
res = app.get('/files/200', status=404)
126
res = app.get('/files/invalid-revid', status=404)
128
def test_inventory_bad_path_404(self):
129
app = self.setUpLoggerhead()
130
res = app.get('/files/1/hooha', status=404)
131
res = app.get('/files/1?file_id=dssadsada', status=404)
107
133
def test_revision(self):
108
134
app = self.setUpLoggerhead()
109
135
res = app.get('/revision/1')
136
res.mustcontain(no=['anotherfile<'])
137
res.mustcontain('anotherfile<')
110
138
res.mustcontain('myfilename')
113
141
class TestEmptyBranch(BasicTests):
142
"""Test that an empty branch doesn't break"""
116
145
BasicTests.setUp(self)
121
150
res = app.get('/changes')
122
151
res.mustcontain('No revisions!')
153
def test_inventory(self):
154
app = self.setUpLoggerhead()
155
res = app.get('/files')
156
res.mustcontain('No revisions!')
159
class TestHiddenBranch(BasicTests):
161
Test that hidden branches aren't shown
162
FIXME: not tested that it doesn't show up on listings
166
BasicTests.setUp(self)
168
locations = config.locations_config_filename()
169
config.ensure_config_dir_exists()
170
open(locations, 'wb').write('[%s]\nhttp_serve = False'
171
% (self.tree.branch.base,))
173
def test_no_access(self):
174
app = self.setUpLoggerhead()
175
res = app.get('/changes', status=404)
178
class TestControllerRedirects(BasicTests):
180
Test that a file under /files redirects to /view,
181
and a directory under /view redirects to /files.
185
BasicTests.setUp(self)
187
self.build_tree(('file', 'folder/', 'folder/file'))
188
self.tree.smart_add([])
191
def test_view_folder(self):
192
app = TestApp(BranchWSGIApp(self.tree.branch, '').app)
194
e = self.assertRaises(HTTPMovedPermanently, app.get, '/view/head:/folder')
195
self.assertEqual(e.location(), '/files/head:/folder')
197
def test_files_file(self):
198
app = TestApp(BranchWSGIApp(self.tree.branch, '').app)
200
e = self.assertRaises(HTTPMovedPermanently, app.get, '/files/head:/folder/file')
201
self.assertEqual(e.location(), '/view/head:/folder/file')
202
e = self.assertRaises(HTTPMovedPermanently, app.get, '/files/head:/file')
203
self.assertEqual(e.location(), '/view/head:/file')
206
class TestHeadMiddleware(BasicTests):
209
BasicTests.setUp(self)
211
self.msg = 'trivial commit message'
212
self.revid = self.tree.commit(message=self.msg)
214
def setUpLoggerhead(self, **kw):
215
branch_app = BranchWSGIApp(self.tree.branch, '', **kw).app
216
return TestApp(HTTPExceptionHandler(HeadMiddleware(branch_app)))
219
app = self.setUpLoggerhead()
220
res = app.get('/changes')
221
res.mustcontain(self.msg)
222
self.assertEqual('text/html', res.header('Content-Type'))
225
app = self.setUpLoggerhead()
226
res = app.get('/changes', extra_environ={'REQUEST_METHOD': 'HEAD'})
227
self.assertEqual('text/html', res.header('Content-Type'))
228
self.assertEqualDiff('', res.body)
231
#class TestGlobalConfig(BasicTests):
233
# Test that global config settings are respected
237
# BasicTests.setUp(self)
238
# self.createBranch()
239
# config.GlobalConfig().set_user_option('http_version', 'True')
241
# def test_setting_respected(self):
242
#FIXME: Figure out how to test this properly
243
# app = self.setUpLoggerhead()
244
# res = app.get('/changes', status=200)