source: mergebot/trunk/utils/test.py @ 62

Last change on this file since 62 was 62, checked in by retracile, 15 years ago

Mergebot: handle property merge conflicts, and add tests for it

File size: 26.6 KB
RevLine 
[16]1#!/usr/bin/python
2"""Automated tests for MergeBot
[41]3
4Run from a Trac source tree with mergebot installed system-wide.  (This needs
5to be reworked to be less cumbersome.)
[16]6"""
7
8import os
9import unittest
10import time
11import shutil
12
13from subprocess import call, Popen #, PIPE, STDOUT
14from twill.errors import TwillAssertionError
15
16
[40]17from trac.tests.functional import FunctionalTestSuite, FunctionalTester, FunctionalTwillTestCaseSetup, tc, b, logfile
18from trac.tests.functional.svntestenv import SvnFunctionalTestEnvironment
[54]19from trac.tests.contentgen import random_page, random_sentence #, random_word
[16]20
21
[17]22#class MergeBotTestEnvironment(FunctionalTestEnvironment):
23#    """Slight change to FunctionalTestEnvironment to keep the PYTHONPATH from
24#    our environment.
25#    """
26#    def start(self):
27#        """Starts the webserver"""
28#        server = Popen(["python", "./trac/web/standalone.py",
29#                        "--port=%s" % self.port, "-s",
30#                        "--basic-auth=trac,%s," % self.htpasswd,
31#                        self.tracdir],
32#                       #env={'PYTHONPATH':'.'},
33#                       stdout=logfile, stderr=logfile,
34#                      )
35#        self.pid = server.pid
36#        time.sleep(1) # Give the server time to come up
37#
38#    def _tracadmin(self, *args):
39#        """Internal utility method for calling trac-admin"""
40#        if call(["python", "./trac/admin/console.py", self.tracdir] +
41#                list(args),
42#                #env={'PYTHONPATH':'.'},
43#                stdout=logfile, stderr=logfile):
44#            raise Exception('Failed running trac-admin with %r' % (args, ))
45#
46#
47#FunctionalTestEnvironment = MergeBotTestEnvironment
[16]48
49
50class MergeBotFunctionalTester(FunctionalTester):
51    """Adds some MergeBot functionality to the functional tester."""
52    # FIXME: the tc.find( <various actions> ) checks are bogus: any ticket can
53    # satisfy them, not just the one we're working on.
[44]54    def __init__(self, trac_url, repo_url):
55        FunctionalTester.__init__(self, trac_url)
56        self.repo_url = repo_url
[16]57        self.mergeboturl = self.url + '/mergebot'
58
59    def wait_until_find(self, search, timeout=5):
60        start = time.time()
61        while time.time() - start < timeout:
62            try:
[45]63                #tc.reload() # This appears to re-POST
64                tc.go(b.get_url())
[16]65                tc.find(search)
66                return
67            except TwillAssertionError:
68                pass
69        raise TwillAssertionError("Unable to find %r within %s seconds" % (search, timeout))
70
71    def wait_until_notfind(self, search, timeout=5):
72        start = time.time()
73        while time.time() - start < timeout:
74            try:
[45]75                #tc.reload() # This appears to re-POST
76                tc.go(b.get_url())
[16]77                tc.notfind(search)
78                return
79            except TwillAssertionError:
80                pass
81        raise TwillAssertionError("Unable to notfind %r within %s seconds" % (search, timeout))
82
83    def go_to_mergebot(self):
84        tc.go(self.mergeboturl)
85        tc.url(self.mergeboturl)
86        tc.notfind('No handler matched request to /mergebot')
87
88    def branch(self, ticket_id, component, timeout=1):
89        """timeout is in seconds."""
90        self.go_to_mergebot()
91        tc.formvalue('ops-%s' % ticket_id, 'ticket', ticket_id) # Essentially a noop to select the right form
92        tc.submit('Branch')
[44]93        self.wait_until_find('Nothing in the queue', timeout)
[16]94        tc.find('Rebranch')
95        tc.find('Merge')
96        tc.find('CheckMerge')
97        self.go_to_ticket(ticket_id)
98        tc.find('Created branch from .* for .*')
99        retval = call(['svn', 'ls', self.repo_url + '/' + component + '/branches/ticket-%s' % ticket_id],
100                    stdout=logfile, stderr=logfile)
101        if retval:
102            raise Exception('svn ls failed with exit code %s' % retval)
103
[57]104    def _rebranch(self, ticket_id, component, search, timeout=15):
[16]105        """timeout is in seconds."""
106        self.go_to_mergebot()
107        tc.formvalue('ops-%s' % ticket_id, 'ticket', ticket_id) # Essentially a noop to select the right form
108        tc.submit('Rebranch')
[44]109        self.wait_until_find('Nothing in the queue', timeout)
[16]110        tc.find('Rebranch')
111        tc.find('Merge')
112        tc.find('CheckMerge')
113        self.go_to_ticket(ticket_id)
[57]114        tc.find(search)
[16]115        retval = call(['svn', 'ls', self.repo_url + '/' + component + '/branches/ticket-%s' % ticket_id],
116                    stdout=logfile, stderr=logfile)
117        if retval:
118            raise Exception('svn ls failed with exit code %s' % retval)
119
[57]120    def rebranch(self, ticket_id, component, timeout=15):
121        self._rebranch(ticket_id, component, 'Rebranched from .* for .*', timeout)
122
123    def rebranch_conflict(self, ticket_id, component, timeout=15):
124        self._rebranch(ticket_id, component, 'There were conflicts on rebranching', timeout)
125
[16]126    def merge(self, ticket_id, component, timeout=5):
[59]127        self._merge(ticket_id, component, 'Merged .* to .* for', timeout)
128
129    def merge_conflict(self, ticket_id, component, timeout=5):
130        self._merge(ticket_id, component, 'Found [0-9]+ conflicts? in attempt to merge ', timeout)
131
132    def _merge(self, ticket_id, component, search, timeout=5):
[16]133        """timeout is in seconds."""
134        self.go_to_mergebot()
135        tc.formvalue('ops-%s' % ticket_id, 'ticket', ticket_id) # Essentially a noop to select the right form
136        tc.submit('Merge')
[44]137        self.wait_until_find('Nothing in the queue', timeout)
[16]138        tc.find('Branch')
139        self.go_to_ticket(ticket_id)
[59]140        tc.find(search)
[16]141        # TODO: We may want to change this to remove the "dead" branch
142        retval = call(['svn', 'ls', self.repo_url + '/' + component + '/branches/ticket-%s' % ticket_id],
143                    stdout=logfile, stderr=logfile)
144        if retval:
145            raise Exception('svn ls failed with exit code %s' % retval)
146
147    def checkmerge(self, ticket_id, component, timeout=5):
148        """timeout is in seconds."""
149        self.go_to_mergebot()
150        tc.formvalue('ops-%s' % ticket_id, 'ticket', ticket_id) # Essentially a noop to select the right form
151        tc.submit('CheckMerge')
[44]152        self.wait_until_find('Nothing in the queue', timeout)
[16]153        tc.find('Rebranch')
154        tc.find('Merge')
155        tc.find('CheckMerge')
156        self.go_to_ticket(ticket_id)
157        tc.find('while checking merge of')
158        retval = call(['svn', 'ls', self.repo_url + '/' + component + '/branches/ticket-%s' % ticket_id],
159                    stdout=logfile, stderr=logfile)
160        if retval:
161            raise Exception('svn ls failed with exit code %s' % retval)
162
163
164class MergeBotTestSuite(FunctionalTestSuite):
165    def setUp(self):
166        port = 8889
167        baseurl = "http://localhost:%s" % port
[40]168        self._testenv = SvnFunctionalTestEnvironment("testenv%s" % port, port, baseurl)
[16]169
170        # Configure mergebot
171        env = self._testenv.get_trac_environment()
172        env.config.set('components', 'mergebot.web_ui.mergebotmodule', 'enabled')
[40]173        env.config.save()
[44]174        os.mkdir(os.path.join("testenv%s" % port, 'trac', 'mergebot'))
[40]175        self._testenv._tracadmin('upgrade') # sets up the bulk of the mergebot config
176        env.config.parse_if_needed()
[16]177        env.config.set('mergebot', 'repository_url', self._testenv.repo_url())
178        env.config.set('logging', 'log_type', 'file')
179        env.config.save()
180        env.config.parse_if_needed()
181
182        self._testenv.start()
[44]183        self._tester = MergeBotFunctionalTester(baseurl, self._testenv.repo_url())
[47]184        os.system('mergebotdaemon -f "%s" > %s/mergebotdaemon.log 2>&1 &' % (self._testenv.tracdir, self._testenv.tracdir))
[40]185        self.fixture = (self._testenv, self._tester)
[16]186
187        # Setup some common component stuff for MergeBot's use:
188        svnurl = self._testenv.repo_url()
189        for component in ['stuff', 'flagship', 'submarine']:
190            self._tester.create_component(component)
191            if call(['svn', '-m', 'Create tree for "%s".' % component, 'mkdir',
192                     svnurl + '/' + component,
193                     svnurl + '/' + component + '/trunk',
194                     svnurl + '/' + component + '/tags',
195                     svnurl + '/' + component + '/branches'],
196                    stdout=logfile, stderr=logfile):
197                raise Exception("svn mkdir failed")
198
199        self._tester.create_version('trunk')
200
201
[51]202class FunctionalSvnTestCaseSetup(FunctionalTwillTestCaseSetup):
203    def get_workdir(self):
204        return os.path.join(self._testenv.dirname, self.__class__.__name__)
205
206    def checkout(self, ticket_id=None):
207        """checkout a working copy of the branch for the given ticket, or trunk if none given"""
208        if ticket_id is None:
209            svnurl = self._testenv.repo_url() + '/stuff/trunk'
210        else:
211            svnurl = self._testenv.repo_url() + '/stuff/branches/ticket-%s' % ticket_id
212        retval = call(['svn', 'checkout', svnurl, self.get_workdir()],
213            stdout=logfile, stderr=logfile)
214        self.assertEqual(retval, 0, "svn checkout failed with error %s" % (retval))
215
216    def switch(self, ticket_id=None):
217        if ticket_id is None:
218            svnurl = self._testenv.repo_url() + '/stuff/trunk'
219        else:
220            svnurl = self._testenv.repo_url() + '/stuff/branches/ticket-%s' % ticket_id
221        retval = call(['svn', 'switch', svnurl, self.get_workdir()],
222            stdout=logfile, stderr=logfile)
223        self.assertEqual(retval, 0, "svn checkout failed with error %s" % (retval))
224
225    def add_new_file(self, filename=None):
226        workdir = self.get_workdir()
227        if filename is None:
228            newfile = os.path.join(workdir, self.__class__.__name__)
229        else:
230            newfile = os.path.join(workdir, filename)
231        open(newfile, 'w').write(random_page())
232        retval = call(['svn', 'add', newfile],
233            cwd=workdir,
234            stdout=logfile, stderr=logfile)
235        self.assertEqual(retval, 0, "svn add failed with error %s" % (retval))
236
237    def commit(self, message, files=None):
238        if files is None:
239            files = ['.']
[54]240        commit_message = self.__class__.__name__ + ": " + message
241        retval = call(['svn', 'commit', '-m', commit_message] + list(files),
[51]242            cwd=self.get_workdir(),
243            stdout=logfile, stderr=logfile)
244        self.assertEqual(retval, 0, "svn commit failed with error %s" % (retval))
245
[57]246    def mv(self, oldname, newname):
247        retval = call(['svn', 'mv', oldname, newname],
248            cwd=self.get_workdir(),
249            stdout=logfile, stderr=logfile)
250        self.assertEqual(retval, 0, "svn mv failed with error %s" % (retval))
[51]251
[62]252    def propset(self, propname, propvalue, filename):
253        retval = call(['svn', 'propset', propname, propvalue, filename],
254            cwd=self.get_workdir(),
255            stdout=logfile, stderr=logfile)
256        self.assertEqual(retval, 0, "svn prposet failed with error %s" % (retval))
257       
[57]258
[62]259
[17]260class MergeBotTestEnabled(FunctionalTwillTestCaseSetup):
[16]261    def runTest(self):
262        self._tester.logout()
263        tc.go(self._tester.url)
264        self._tester.login('admin')
265        tc.follow('MergeBot')
266        mergeboturl = self._tester.url + '/mergebot'
267        tc.url(mergeboturl)
268        tc.notfind('No handler matched request to /mergebot')
269
270
[17]271class MergeBotTestNoVersion(FunctionalTwillTestCaseSetup):
[16]272    """Verify that if a ticket does not have the version field set, it will not
273    appear in the MergeBot list.
274    """
275    def runTest(self):
276        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
277            info={'component':'stuff', 'version':''})
278        tc.follow('MergeBot')
279        tc.notfind(self.__class__.__name__)
280
281
[17]282class MergeBotTestBranch(FunctionalTwillTestCaseSetup):
[16]283    def runTest(self):
284        """Verify that the 'branch' button works"""
285        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
286            info={'component':'stuff', 'version':'trunk'})
287        self._tester.branch(ticket_id, 'stuff')
288
289
[17]290class MergeBotTestRebranch(FunctionalTwillTestCaseSetup):
[16]291    def runTest(self):
292        """Verify that the 'rebranch' button works"""
293        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
294            info={'component':'stuff', 'version':'trunk'})
295        self._tester.branch(ticket_id, 'stuff')
296        self._tester.rebranch(ticket_id, 'stuff')
297
298
[17]299class MergeBotTestMerge(FunctionalTwillTestCaseSetup):
[16]300    def runTest(self):
301        """Verify that the 'merge' button works"""
302        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
303            info={'component':'stuff', 'version':'trunk'})
304        self._tester.branch(ticket_id, 'stuff')
305        self._tester.merge(ticket_id, 'stuff')
306
307
[59]308class MergeBotTestMergeWithChange(FunctionalSvnTestCaseSetup):
309    def runTest(self):
310        """Verify that the 'merge' button works with changes on the branch"""
311        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
312            info={'component':'stuff', 'version':'trunk'})
313        self._tester.branch(ticket_id, 'stuff')
314
315        # checkout a working copy & make a change
316        self.checkout(ticket_id)
317        # Create & add a new file
318        self.add_new_file()
319        self.commit('Add a new file')
320
321        self._tester.merge(ticket_id, 'stuff')
322
323
324class MergeBotTestMergeWithChangeAndTrunkChange(FunctionalSvnTestCaseSetup):
325    def runTest(self):
326        """Verify that the 'merge' button works with changes on the branch and trunk"""
327        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
328            info={'component':'stuff', 'version':'trunk'})
329        self._tester.branch(ticket_id, 'stuff')
330
331        # checkout a working copy & make a change
332        self.checkout(ticket_id)
333        # Create & add a new file
334        basename = self.__class__.__name__
335        self.add_new_file(basename + '-ticket')
336        self.commit('Add a new file on ticket')
337        self.switch()
338        self.add_new_file(basename + '-trunk')
339        self.commit('Add a new file on trunk')
340
341        self._tester.merge(ticket_id, 'stuff')
342
343
344class MergeBotTestMergeWithConflict(FunctionalSvnTestCaseSetup):
345    def runTest(self):
346        """Verify that the 'merge' button detects conflicts between the branch and trunk"""
347        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
348            info={'component':'stuff', 'version':'trunk'})
349        basename = self.__class__.__name__
350
351        # create a file in which to have conflicts
352        self.checkout()
353        self.add_new_file(basename)
354        self.commit('Add a new file on trunk')
355
356        # create the branch
357        self._tester.branch(ticket_id, 'stuff')
358
359        # modify the file on trunk
360        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
361        self.commit('Modify the file on trunk')
362
363        # modify the file on the branch
364        self.switch(ticket_id)
365        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
366        self.commit('Modify the file on branch')
367
368        # merge, make sure it shows a conflict
369        self._tester.merge_conflict(ticket_id, 'stuff')
370
371
[62]372class MergeBotTestMergeWithPropertyConflict(FunctionalSvnTestCaseSetup):
373    def runTest(self):
374        """Verify that the 'merge' button detects property conflicts between the branch and trunk"""
375        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
376            info={'component':'stuff', 'version':'trunk'})
377        basename = self.__class__.__name__
378
379        self.checkout()
380        self.propset('svn:ignore', basename, '.')
381        self.commit('set property on trunk')
382
383        # create the branch
384        self._tester.branch(ticket_id, 'stuff')
385
386        # modify the property on trunk
387        self.propset('svn:ignore', basename + '\ntrunk', '.')
388        self.commit('Modify the property on trunk')
389
390        # modify the property on the branch
391        self.switch(ticket_id)
392        self.propset('svn:ignore', basename + '\nbranch', '.')
393        self.commit('Modify the property on branch')
394
395        # merge, make sure it shows a conflict
396        self._tester.merge_conflict(ticket_id, 'stuff')
397
398
[59]399class MergeBotTestMergeWithBranchRenameConflict(FunctionalSvnTestCaseSetup):
400    def runTest(self):
401        """Verify that the 'merge' button detects a conflict when a file renamed on the branch was modified on trunk"""
402        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
403            info={'component':'stuff', 'version':'trunk'})
404        basename = self.__class__.__name__
405
406        # create a file in which to have conflicts
407        self.checkout()
408        self.add_new_file(basename)
409        self.commit('Add a new file on trunk')
410
411        # create the branch
412        self._tester.branch(ticket_id, 'stuff')
413
414        # modify the file on trunk
415        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
416        self.commit('Modify the file on trunk')
417
418        # rename the file on the branch
419        self.switch(ticket_id)
420        self.mv(basename, basename + '-renamed')
421        self.commit('Rename the file on the branch')
422
423        self._tester.merge_conflict(ticket_id, 'stuff')
424
425
426class MergeBotTestMergeWithTrunkRenameConflict(FunctionalSvnTestCaseSetup):
427    def runTest(self):
428        """Verify that the 'merge' button detects conflicts when a file renamed on trunk was modified on the branch"""
429        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
430            info={'component':'stuff', 'version':'trunk'})
431        basename = self.__class__.__name__
432
433        # create a file in which to have conflicts
434        self.checkout()
435        self.add_new_file(basename)
436        self.commit('Add a new file on trunk')
437
438        # create the branch
439        self._tester.branch(ticket_id, 'stuff')
440
441        # rename the file on trunk
442        self.mv(basename, basename + '-renamed')
443        self.commit('Rename the file on trunk')
444
445        # rename the file on the branch
446        self.switch(ticket_id)
447        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
448        self.commit('Modify the file on the branch')
449
450        # make sure it finds the conflict
451        self._tester.merge_conflict(ticket_id, 'stuff')
452
453
[17]454class MergeBotTestCheckMerge(FunctionalTwillTestCaseSetup):
[16]455    def runTest(self):
456        """Verify that the 'checkmerge' button works"""
457        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
458            info={'component':'stuff', 'version':'trunk'})
459        self._tester.branch(ticket_id, 'stuff')
460        self._tester.checkmerge(ticket_id, 'stuff')
461
462
[51]463class MergeBotTestRebranchWithChange(FunctionalSvnTestCaseSetup):
[46]464    def runTest(self):
465        """Verify that the 'rebranch' button works with changes on the branch"""
466        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
467            info={'component':'stuff', 'version':'trunk'})
468        self._tester.branch(ticket_id, 'stuff')
469
470        # checkout a working copy & make a change
[51]471        self.checkout(ticket_id)
[46]472        # Create & add a new file
[51]473        self.add_new_file()
474        self.commit('Add a new file')
[46]475
476        self._tester.rebranch(ticket_id, 'stuff')
477
478
[51]479class MergeBotTestRebranchWithChangeAndTrunkChange(FunctionalSvnTestCaseSetup):
480    def runTest(self):
[52]481        """Verify that the 'rebranch' button works with changes on the branch and trunk"""
[51]482        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
483            info={'component':'stuff', 'version':'trunk'})
484        self._tester.branch(ticket_id, 'stuff')
485
486        # checkout a working copy & make a change
487        self.checkout(ticket_id)
488        # Create & add a new file
489        basename = self.__class__.__name__
490        self.add_new_file(basename + '-ticket')
491        self.commit('Add a new file on ticket')
492        self.switch()
493        self.add_new_file(basename + '-trunk')
494        self.commit('Add a new file on trunk')
495
496        self._tester.rebranch(ticket_id, 'stuff')
497
498
[54]499class MergeBotTestRebranchWithConflict(FunctionalSvnTestCaseSetup):
500    def runTest(self):
[59]501        """Verify that the 'rebranch' button detects conflicts between the branch and trunk"""
[54]502        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
503            info={'component':'stuff', 'version':'trunk'})
504        basename = self.__class__.__name__
505
506        # create a file in which to have conflicts
507        self.checkout()
508        self.add_new_file(basename)
509        self.commit('Add a new file on trunk')
510
511        # create the branch
512        self._tester.branch(ticket_id, 'stuff')
513
514        # modify the file on trunk
515        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
516        self.commit('Modify the file on trunk')
517
518        # modify the file on the branch
519        self.switch(ticket_id)
520        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
521        self.commit('Modify the file on branch')
522
[57]523        # rebranch, make sure it shows a conflict
524        self._tester.rebranch_conflict(ticket_id, 'stuff')
[54]525
526
[62]527class MergeBotTestRebranchWithPropertyConflict(FunctionalSvnTestCaseSetup):
528    def runTest(self):
529        """Verify that the 'rebranch' button detects property conflicts between the branch and trunk"""
530        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
531            info={'component':'stuff', 'version':'trunk'})
532        basename = self.__class__.__name__
533
534        self.checkout()
535        self.propset('svn:ignore', basename, '.')
536        self.commit('set property on trunk')
537
538        # create the branch
539        self._tester.branch(ticket_id, 'stuff')
540
541        # modify the property on trunk
542        self.propset('svn:ignore', basename + '\ntrunk', '.')
543        self.commit('Modify the property on trunk')
544
545        # modify the property on the branch
546        self.switch(ticket_id)
547        self.propset('svn:ignore', basename + '\nbranch', '.')
548        self.commit('Modify the property on branch')
549
550        # rebranch, make sure it shows a conflict
551        self._tester.rebranch_conflict(ticket_id, 'stuff')
552
553
[57]554class MergeBotTestRebranchWithBranchRenameConflict(FunctionalSvnTestCaseSetup):
555    def runTest(self):
[59]556        """Verify that the 'rebranch' button detects a conflict when a file renamed on the branch was modified on trunk"""
[57]557        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
558            info={'component':'stuff', 'version':'trunk'})
559        basename = self.__class__.__name__
560
561        # create a file in which to have conflicts
562        self.checkout()
563        self.add_new_file(basename)
564        self.commit('Add a new file on trunk')
565
566        # create the branch
567        self._tester.branch(ticket_id, 'stuff')
568
569        # modify the file on trunk
570        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
571        self.commit('Modify the file on trunk')
572
573        # rename the file on the branch
574        self.switch(ticket_id)
575        self.mv(basename, basename + '-renamed')
[58]576        self.commit('Rename the file on the branch')
[57]577
578        self._tester.rebranch_conflict(ticket_id, 'stuff')
579
580
[58]581class MergeBotTestRebranchWithTrunkRenameConflict(FunctionalSvnTestCaseSetup):
582    def runTest(self):
[59]583        """Verify that the 'rebranch' button detects conflicts when a file renamed on trunk was modified on the branch"""
[58]584        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
585            info={'component':'stuff', 'version':'trunk'})
586        basename = self.__class__.__name__
587
588        # create a file in which to have conflicts
589        self.checkout()
590        self.add_new_file(basename)
591        self.commit('Add a new file on trunk')
592
593        # create the branch
594        self._tester.branch(ticket_id, 'stuff')
595
596        # rename the file on trunk
597        self.mv(basename, basename + '-renamed')
598        self.commit('Rename the file on trunk')
599
600        # rename the file on the branch
601        self.switch(ticket_id)
602        open(os.path.join(self.get_workdir(), basename), 'a').write(random_sentence())
603        self.commit('Modify the file on the branch')
604
605        # make sure it finds the conflict
606        self._tester.rebranch_conflict(ticket_id, 'stuff')
607
608
[17]609class MergeBotTestSingleUseCase(FunctionalTwillTestCaseSetup):
[16]610    def runTest(self):
611        """Create a branch, make a change, checkmerge, and merge it."""
612        ticket_id = self._tester.create_ticket(summary=self.__class__.__name__,
613            info={'component':'stuff', 'version':'trunk'})
614        self._tester.branch(ticket_id, 'stuff')
615        # checkout a working copy & make a change
616        svnurl = self._testenv.repo_url()
617        workdir = os.path.join(self._testenv.dirname, self.__class__.__name__)
618        retval = call(['svn', 'checkout', svnurl + '/stuff/branches/ticket-%s' % ticket_id, workdir],
619            stdout=logfile, stderr=logfile)
620        self.assertEqual(retval, 0, "svn checkout failed with error %s" % (retval))
621        # Create & add a new file
622        newfile = os.path.join(workdir, self.__class__.__name__)
623        open(newfile, 'w').write(random_page())
624        retval = call(['svn', 'add', self.__class__.__name__],
625            cwd=workdir,
626            stdout=logfile, stderr=logfile)
627        self.assertEqual(retval, 0, "svn add failed with error %s" % (retval))
628        retval = call(['svn', 'commit', '-m', 'Add a new file', self.__class__.__name__],
629            cwd=workdir,
630            stdout=logfile, stderr=logfile)
631        self.assertEqual(retval, 0, "svn commit failed with error %s" % (retval))
632
633        self._tester.checkmerge(ticket_id, 'stuff')
634        self._tester.merge(ticket_id, 'stuff')
635
636        shutil.rmtree(workdir) # cleanup working copy
637
638
639def suite():
640    suite = MergeBotTestSuite()
641    suite.addTest(MergeBotTestEnabled())
642    suite.addTest(MergeBotTestNoVersion())
643    suite.addTest(MergeBotTestBranch())
[45]644    suite.addTest(MergeBotTestRebranch())
[16]645    suite.addTest(MergeBotTestCheckMerge())
[45]646    suite.addTest(MergeBotTestMerge())
[46]647    suite.addTest(MergeBotTestRebranchWithChange())
[51]648    suite.addTest(MergeBotTestRebranchWithChangeAndTrunkChange())
[54]649    suite.addTest(MergeBotTestRebranchWithConflict())
[62]650    suite.addTest(MergeBotTestRebranchWithPropertyConflict())
[57]651    suite.addTest(MergeBotTestRebranchWithBranchRenameConflict())
[58]652    suite.addTest(MergeBotTestRebranchWithTrunkRenameConflict())
[59]653    suite.addTest(MergeBotTestMergeWithChange())
654    suite.addTest(MergeBotTestMergeWithChangeAndTrunkChange())
655    suite.addTest(MergeBotTestMergeWithConflict())
[62]656    suite.addTest(MergeBotTestMergeWithPropertyConflict())
[59]657    suite.addTest(MergeBotTestMergeWithBranchRenameConflict())
658    suite.addTest(MergeBotTestMergeWithTrunkRenameConflict())
[16]659    suite.addTest(MergeBotTestSingleUseCase())
660    return suite
661
662if __name__ == '__main__':
663    unittest.main(defaultTest='suite')
Note: See TracBrowser for help on using the repository browser.