1
# Copyright (C) 2005 Canonical Ltd
2
# Authors: Robert Collins <robert.collins@canonical.com>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""These tests are tests about the source code of bzrlib itself.
20
They are useful for testing code quality, checking coverage metric etc.
23
# import system imports here
28
#import bzrlib specific imports here
33
from bzrlib.tests import TestCase, TestSkipped
36
class TestSourceHelper(TestCase):
38
def source_file_name(self, package):
39
"""Return the path of the .py file for package."""
40
path = package.__file__
47
class TestApiUsage(TestSourceHelper):
49
def find_occurences(self, rule, filename):
50
"""Find the number of occurences of rule in a file."""
52
source = file(filename, 'r')
54
if line.find(rule) > -1:
58
def test_branch_working_tree(self):
59
"""Test that the number of uses of working_tree in branch is stable."""
60
occurences = self.find_occurences('self.working_tree()',
61
self.source_file_name(bzrlib.branch))
62
# do not even think of increasing this number. If you think you need to
63
# increase it, then you almost certainly are doing something wrong as
64
# the relationship from working_tree to branch is one way.
65
# Note that this is an exact equality so that when the number drops,
66
#it is not given a buffer but rather has this test updated immediately.
67
self.assertEqual(0, occurences)
69
def test_branch_WorkingTree(self):
70
"""Test that the number of uses of working_tree in branch is stable."""
71
occurences = self.find_occurences('WorkingTree',
72
self.source_file_name(bzrlib.branch))
73
# do not even think of increasing this number. If you think you need to
74
# increase it, then you almost certainly are doing something wrong as
75
# the relationship from working_tree to branch is one way.
76
# This number should be 4 (import NoWorkingTree and WorkingTree,
77
# raise NoWorkingTree from working_tree(), and construct a working tree
78
# there) but a merge that regressed this was done before this test was
79
# written. Note that this is an exact equality so that when the number
80
# drops, it is not given a buffer but rather this test updated
82
self.assertEqual(2, occurences)
85
class TestSource(TestSourceHelper):
87
def get_bzrlib_dir(self):
88
"""Get the path to the root of bzrlib"""
89
source = self.source_file_name(bzrlib)
90
source_dir = os.path.dirname(source)
92
# Avoid the case when bzrlib is packaged in a zip file
93
if not os.path.isdir(source_dir):
94
raise TestSkipped('Cannot find bzrlib source directory. Expected %s'
98
def get_source_files(self):
99
"""yield all source files for bzr and bzrlib"""
100
bzrlib_dir = self.get_bzrlib_dir()
102
# This is the front-end 'bzr' script
103
bzr_path = self.get_bzr_path()
106
for root, dirs, files in os.walk(bzrlib_dir):
108
if not f.endswith('.py'):
110
yield osutils.pathjoin(root, f)
112
def get_source_file_contents(self):
113
for fname in self.get_source_files():
114
f = open(fname, 'rb')
121
def is_exception(self, fname):
122
"""Certain files are allowed to be different"""
123
if '/util/' in fname:
124
# We don't require external utilities to be (C) Canonical Ltd
127
exceptions = ['bzrlib/lsprof.py',
128
'bzrlib/conflicts.py',
129
'bzrlib/iterablefile.py',
131
'bzrlib/tests/test_patches.py',
133
for exc in exceptions:
134
if fname.endswith(exc):
139
def test_copyright(self):
140
"""Test that all .py files have a valid copyright statement"""
141
# These are files which contain a different copyright statement
145
copyright_re = re.compile('#\\s*copyright.*\n', re.I)
146
copyright_canonical_re = re.compile(
147
r'# Copyright \(C\) ' # Opening "# Copyright (C)"
148
r'(\d+)(, \d+)*' # Followed by a series of dates
149
r'.*Canonical Ltd' # And containing 'Canonical Ltd'
152
for fname, text in self.get_source_file_contents():
153
if self.is_exception(fname):
155
match = copyright_canonical_re.search(text)
157
match = copyright_re.search(text)
159
incorrect.append((fname, 'found: %s' % (match.group(),)))
161
incorrect.append((fname, 'no copyright line found\n'))
163
if 'by Canonical' in match.group():
164
incorrect.append((fname,
165
'should not have: "by Canonical": %s'
169
help_text = ["Some files have missing or incorrect copyright"
171
"Please add '# Copyright (C) 2006 Canonical Ltd'"
175
for fname, comment in incorrect:
176
help_text.append(fname)
177
help_text.append((' '*4) + comment)
179
self.fail('\n'.join(help_text))
182
"""Test that all .py files have a GPL disclaimer"""
186
# This program is free software; you can redistribute it and/or modify
187
# it under the terms of the GNU General Public License as published by
188
# the Free Software Foundation; either version 2 of the License, or
189
# (at your option) any later version.
191
# This program is distributed in the hope that it will be useful,
192
# but WITHOUT ANY WARRANTY; without even the implied warranty of
193
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
194
# GNU General Public License for more details.
196
# You should have received a copy of the GNU General Public License
197
# along with this program; if not, write to the Free Software
198
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
200
gpl_re = re.compile(re.escape(gpl_txt), re.MULTILINE)
202
for fname, text in self.get_source_file_contents():
203
if self.is_exception(fname):
205
if not gpl_re.search(text):
206
incorrect.append(fname)
209
help_text = ['Some files have missing or incomplete GPL statement',
210
'Please fix the following files to have text:',
213
for fname in incorrect:
214
help_text.append((' '*4) + fname)
216
self.fail('\n'.join(help_text))