1# -*- mode: python; coding: utf-8 -*-
2# :Progetto: vcpx -- svn specific tests
3# :Creato:   gio 11 nov 2004 19:09:06 CET
4# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
5# :Licenza:  GNU General Public License
6#
7
8from builtins import next
9from builtins import object
10from unittest import TestCase
11from datetime import datetime
12from vcpx.repository.svn import changesets_from_svnlog
13from vcpx.tzinfo import UTC
14
15
16class FakeLogger(object):
17    def warning(self, *args):
18        pass
19
20
21class FakeRepository(object):
22    def __init__(self, repo, module):
23        self.repository = repo
24        self.module = module
25        self.log = FakeLogger()
26FR = FakeRepository
27
28
29class SvnLogParser(TestCase):
30    """Ensure the svn log parser does its job"""
31
32    def getSvnLog(self, testname):
33        from os.path import join, split
34
35        logname = join(split(__file__)[0], 'data', testname)+'.log'
36        return file(logname)
37
38    def testRenameBehaviour(self):
39        """Verify svn log parser behaves correctly on renames"""
40
41        log = self.getSvnLog('svn-simple_rename_test')
42        csets = changesets_from_svnlog(log, FR('file:///tmp/t/repo', '/trunk'))
43
44        cset = next(csets)
45        self.assertEqual(cset.author, 'lele')
46        self.assertEqual(cset.date, datetime(2004,11,12,15,0o5,37,134366,UTC))
47        self.assertEqual(cset.log, 'create tree')
48        self.assertEqual(len(cset.entries), 2)
49
50        entry = cset.entries[0]
51        self.assertEqual(entry.name, 'dir')
52        self.assertEqual(entry.action_kind, entry.ADDED)
53
54        entry = cset.entries[1]
55        self.assertEqual(entry.name, 'dir/a.txt')
56        self.assertEqual(entry.action_kind, entry.ADDED)
57
58        cset = next(csets)
59        self.assertEqual(cset.author, 'lele')
60        self.assertEqual(cset.date, datetime(2004,11,12,15,0o6,0o4,193650,UTC))
61        self.assertEqual(cset.log, 'rename dir')
62        self.assertEqual(len(cset.entries), 1)
63
64        entry = cset.entries[0]
65        self.assertEqual(entry.name, 'new')
66        self.assertEqual(entry.action_kind, entry.RENAMED)
67        self.assertEqual(entry.old_name, 'dir')
68
69        self.assertRaises(StopIteration, csets.__next__)
70
71    def testRenameOutBehaviour(self):
72        """Verify svn log parser behaves correctly on renames out of scope"""
73
74        log = self.getSvnLog('svn-rename_out_test')
75        csets = changesets_from_svnlog(log,
76                                       FR('http://srv/svn/Shtoom', '/trunk'))
77
78        cset = next(csets)
79        self.assertEqual(cset.author, 'anthony')
80        self.assertEqual(cset.date, datetime(2004,11,9,6,54,20,709243,UTC))
81        self.assertEqual(cset.log, 'Moving to a /sandbox\n')
82        self.assertEqual(len(cset.entries), 1)
83
84        entry = cset.entries[0]
85        self.assertEqual(entry.name, 'shtoom/tmp')
86        self.assertEqual(entry.action_kind, entry.DELETED)
87
88        self.assertRaises(StopIteration, csets.__next__)
89
90    def testCopyAndRename(self):
91        """Verify svn log parser behaves correctly on copies"""
92
93        log = self.getSvnLog('svn-copy_and_rename_test')
94        csets = list(changesets_from_svnlog(log,
95                                            FR('file:///tmp/rep', '/test')))
96        self.assertEqual(len(csets), 4)
97
98        cset = csets[1]
99        self.assertEqual(cset.author, 'lele')
100        self.assertEqual(cset.date, datetime(2005,1,8, 17,36,55,174757,UTC))
101        self.assertEqual(cset.log, 'Copy')
102        self.assertEqual(len(cset.entries), 1)
103
104        entry = cset.entries[0]
105        self.assertEqual(entry.name, 'file2.txt')
106        self.assertEqual(entry.action_kind, entry.ADDED)
107        self.assertEqual(entry.old_name, 'file1.txt')
108
109        cset = csets[2]
110        self.assertEqual(cset.date, datetime(2005,1,8, 17,42,41,347315,UTC))
111        self.assertEqual(cset.log, 'Remove')
112        self.assertEqual(len(cset.entries), 1)
113
114        entry = cset.entries[0]
115        self.assertEqual(entry.name, 'file1.txt')
116        self.assertEqual(entry.action_kind, entry.DELETED)
117
118        cset = csets[3]
119        self.assertEqual(cset.date, datetime(2005,1,8, 17,43,9,909127,UTC))
120        self.assertEqual(cset.log, 'Move')
121        self.assertEqual(len(cset.entries), 1)
122
123        entry = cset.entries[0]
124        self.assertEqual(entry.name, 'file1.txt')
125        self.assertEqual(entry.action_kind, entry.RENAMED)
126        self.assertEqual(entry.old_name, 'file2.txt')
127
128    def testREvent(self):
129        """Verify how tailor handle svn "R" event"""
130
131        log = self.getSvnLog('svn-svn_r_event_test')
132        csets = changesets_from_svnlog(log, FR('file:///tmp/rep', '/trunk'))
133
134        cset = next(csets)
135
136        cset = next(csets)
137        self.assertEqual(cset.author, 'cmlenz')
138        self.assertEqual(cset.date, datetime(2005,3,21, 8,34, 2,522947,UTC))
139        self.assertEqual(len(cset.entries), 7)
140
141        entry = cset.entries[0]
142        self.assertEqual(entry.name, 'setup.py')
143        self.assertEqual(entry.action_kind, entry.UPDATED)
144
145        entry = cset.entries[1]
146        self.assertEqual(entry.name, 'trac/scripts')
147        self.assertEqual(entry.action_kind, entry.ADDED)
148
149        entry = cset.entries[2]
150        self.assertEqual(entry.name, 'trac/scripts/__init__.py')
151        self.assertEqual(entry.action_kind, entry.ADDED)
152
153        entry = cset.entries[3]
154        self.assertEqual(entry.name, 'trac/scripts/admin.py')
155        self.assertEqual(entry.action_kind, entry.RENAMED)
156        self.assertEqual(entry.old_name, 'scripts/trac-admin')
157
158        entry = cset.entries[4]
159        self.assertEqual(entry.name, 'trac/tests/environment.py')
160        self.assertEqual(entry.action_kind, entry.UPDATED)
161
162        entry = cset.entries[6]
163        self.assertEqual(entry.name, 'scripts/trac-admin')
164        self.assertEqual(entry.action_kind, entry.ADDED)
165
166        self.assertRaises(StopIteration, csets.__next__)
167
168    def testTrackingRoot(self):
169        """Verify we are able to track the root of the repository"""
170
171        log = self.getSvnLog('svn-svn_repos_root_test')
172        csets = list(changesets_from_svnlog(log,
173                                            FR('svn+ssh://caia/tmp/svn', '/')))
174        self.assertEqual(len(csets), 4)
175
176        cset = csets[1]
177        self.assertEqual(len(cset.entries), 3)
178
179        entry = cset.entries[0]
180        self.assertEqual(entry.name, 'branches/branch-a')
181        self.assertEqual(entry.action_kind, entry.ADDED)
182
183        entry = cset.entries[1]
184        self.assertEqual(entry.name, 'branches/branch-a/a.txt')
185        self.assertEqual(entry.action_kind, entry.ADDED)
186
187        entry = cset.entries[2]
188        self.assertEqual(entry.name, 'branches/branch-a/b.txt')
189        self.assertEqual(entry.action_kind, entry.ADDED)
190
191    def testPydistStrangeCase(self):
192        """Verify we are able to groke with svn 'R' strangeness"""
193
194        log = self.getSvnLog('svn-pydist_strange_case')
195        csets = changesets_from_svnlog(log, FR('http://srv/svn', '/py/dist'))
196
197        cset = next(csets)
198        self.assertEqual(len(cset.entries), 3)
199
200        entry = cset.entries[0]
201        self.assertEqual(entry.name, 'py/documentation/example')
202        self.assertEqual(entry.action_kind, entry.RENAMED)
203        self.assertEqual(entry.old_name, 'example')
204
205        entry = cset.entries[1]
206        self.assertEqual(entry.name, 'py/documentation/test.txt')
207        self.assertEqual(entry.action_kind, entry.UPDATED)
208
209        entry = cset.entries[2]
210        self.assertEqual(entry.name, 'py/documentation/example/test')
211        self.assertEqual(entry.action_kind, entry.ADDED)
212
213        self.assertRaises(StopIteration, csets.__next__)
214
215    def testUnicode(self):
216        """Verify svn parser returns unicode strings"""
217
218        log = self.getSvnLog('svn-encoding_test')
219        csets = changesets_from_svnlog(log, FR('http://srv/plone/CMFPlone',
220                                               '/branches/2.1'))
221
222        log = csets.next().log
223        self.assertEqual(type(log), type(u'€'))
224        self.assertEqual(len(log), 91)
225        self.assertRaises(UnicodeEncodeError, log.encode, 'iso-8859-1')
226        self.assertEqual(len(log.encode('ascii', 'ignore')), 90)
227
228        self.assertRaises(StopIteration, csets.__next__)
229
230    def testCopyAndReplace(self):
231        """Verify the svn parser handle copy+replace"""
232
233        log = self.getSvnLog('svn-copy_and_replace_test')
234        csets = changesets_from_svnlog(log,
235                                       FR('http://srv/repos/trac', '/trunk'))
236
237        cset = next(csets)
238        self.assertEqual(len(cset.entries), 7)
239
240        entry = cset.entries[0]
241        self.assertEqual(entry.name, 'setup.py')
242        self.assertEqual(entry.action_kind, entry.UPDATED)
243
244        entry = cset.entries[1]
245        self.assertEqual(entry.name, 'trac/scripts')
246        self.assertEqual(entry.action_kind, entry.ADDED)
247
248        entry = cset.entries[2]
249        self.assertEqual(entry.name, 'trac/scripts/__init__.py')
250        self.assertEqual(entry.action_kind, entry.ADDED)
251
252        entry = cset.entries[3]
253        self.assertEqual(entry.name, 'trac/scripts/admin.py')
254        self.assertEqual(entry.action_kind, entry.RENAMED)
255        self.assertEqual(entry.old_name, 'scripts/trac-admin')
256
257        entry = cset.entries[4]
258        self.assertEqual(entry.name, 'trac/tests/environment.py')
259        self.assertEqual(entry.action_kind, entry.UPDATED)
260
261        entry = cset.entries[5]
262        self.assertEqual(entry.name, 'trac/tests/tracadmin.py')
263        self.assertEqual(entry.action_kind, entry.UPDATED)
264
265        entry = cset.entries[6]
266        self.assertEqual(entry.name, 'scripts/trac-admin')
267        self.assertEqual(entry.action_kind, entry.ADDED)
268
269    def testCopyFromAndRemove(self):
270        """Verify the svn parser handle copyfrom+remove"""
271
272        log = self.getSvnLog('svn-copyfrom_and_remove_test')
273        csets = changesets_from_svnlog(log, FR('http://srv/samba',
274                                               '/branches/SAMBA_4_0'))
275
276        cset = next(csets)
277        self.assertEqual(len(cset.entries), 4)
278
279        entry = cset.entries[0]
280        self.assertEqual(entry.name, 'source/nsswitch')
281        self.assertEqual(entry.action_kind, entry.ADDED)
282
283        entry = cset.entries[1]
284        self.assertEqual(entry.name, 'source/nsswitch/config.m4')
285        self.assertEqual(entry.action_kind, entry.ADDED)
286
287        entry = cset.entries[2]
288        self.assertEqual(entry.name, 'source/nsswitch/wb_common.c')
289        self.assertEqual(entry.action_kind, entry.ADDED)
290
291        entry = cset.entries[3]
292        self.assertEqual(entry.name, 'source/nsswitch/wins.c')
293        self.assertEqual(entry.action_kind, entry.DELETED)
294
295    def testIncrementalParser(self):
296        """Verify that the svn log parser is effectively incremental"""
297
298        log = self.getSvnLog('svn-svn_repos_root_test')
299        csets = list(changesets_from_svnlog(log,
300                                            FR('svn+ssh://caia/tmp/svn', '/'),
301                                            chunksize=100))
302        self.assertEqual(len(csets), 4)
303
304    def testExternalCopies(self):
305        """Verify that external copies+deletions are handled ok"""
306
307        log = self.getSvnLog('svn-external_copies_test')
308        csets = changesets_from_svnlog(log,
309                                       FR('svn+ssh://caia/tmp/svn', '/trunk'))
310
311        cset = next(csets)
312        cset = next(csets)
313        self.assertEqual(len(cset.entries), 5)
314
315        entry = cset.removedEntries()[0]
316        self.assertEqual(entry.name, 'README_LOGIN')
317
318        cset = next(csets)
319        self.assertEqual(len(cset.entries), 5)
320
321    def testCollidingNames(self):
322        """Verify svn log parser behaves correctly with colliding names"""
323
324        # Sorry, couldn't find a better name
325
326        log = self.getSvnLog('svn-colliding_names_test')
327        csets = changesets_from_svnlog(log,
328                                       FR('svn://ixion.tartarus.org/main', '/putty'))
329
330        cset = next(csets)
331        self.assertEqual(len(cset.entries), 1)
332