/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/plugins/bisect/tests.py

Bundle bisect plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007-2010 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
"Test suite for the bzr bisect plugin."
 
18
 
 
19
from cStringIO import StringIO
 
20
import os
 
21
import stat
 
22
import sys
 
23
import shutil
 
24
 
 
25
import bzrlib
 
26
from bzrlib.bzrdir import BzrDir
 
27
from bzrlib.plugins import bisect
 
28
from bzrlib.plugins.bisect import cmds
 
29
from bzrlib.tests import (
 
30
    KnownFailure,
 
31
    TestCaseWithTransport,
 
32
    TestSkipped,
 
33
    )
 
34
 
 
35
class BisectTestCase(TestCaseWithTransport):
 
36
    """Test harness specific to the bisect plugin."""
 
37
 
 
38
    def assertRevno(self, rev):
 
39
        """Make sure we're at the right revision."""
 
40
 
 
41
        rev_contents = {1: "one", 1.1: "one dot one", 1.2: "one dot two",
 
42
                        1.3: "one dot three", 2: "two", 3: "three",
 
43
                        4: "four", 5: "five"}
 
44
 
 
45
        test_file = open("test_file")
 
46
        content = test_file.read().strip()
 
47
        if content != rev_contents[rev]:
 
48
            rev_ids = dict((rev_contents[k], k) for k in rev_contents.keys())
 
49
            found_rev = rev_ids[content]
 
50
            raise AssertionError("expected rev %0.1f, found rev %0.1f"
 
51
                                 % (rev, found_rev))
 
52
 
 
53
    def setUp(self):
 
54
        """Set up tests."""
 
55
 
 
56
        # These tests assume a branch with five revisions, and
 
57
        # a branch from version 1 containing three revisions
 
58
        # merged at version 2.
 
59
 
 
60
        TestCaseWithTransport.setUp(self)
 
61
 
 
62
        self.tree = self.make_branch_and_tree(".")
 
63
 
 
64
        test_file = open("test_file", "w")
 
65
        test_file.write("one")
 
66
        test_file.close()
 
67
        self.tree.add(self.tree.relpath(os.path.join(os.getcwd(),
 
68
                                                     'test_file')))
 
69
        test_file_append = open("test_file_append", "a")
 
70
        test_file_append.write("one\n")
 
71
        test_file_append.close()
 
72
        self.tree.add(self.tree.relpath(os.path.join(os.getcwd(),
 
73
                                                     'test_file_append')))
 
74
        self.tree.commit(message = "add test files")
 
75
 
 
76
        BzrDir.open(".").sprout("../temp-clone")
 
77
        clone_bzrdir = BzrDir.open("../temp-clone")
 
78
        clone_tree = clone_bzrdir.open_workingtree()
 
79
        for content in ["one dot one", "one dot two", "one dot three"]:
 
80
            test_file = open("../temp-clone/test_file", "w")
 
81
            test_file.write(content)
 
82
            test_file.close()
 
83
            test_file_append = open("../temp-clone/test_file_append", "a")
 
84
            test_file_append.write(content + "\n")
 
85
            test_file_append.close()
 
86
            clone_tree.commit(message = "make branch test change")
 
87
            saved_subtree_revid = clone_tree.branch.last_revision()
 
88
 
 
89
        self.tree.merge_from_branch(clone_tree.branch)
 
90
        test_file = open("test_file", "w")
 
91
        test_file.write("two")
 
92
        test_file.close()
 
93
        test_file_append = open("test_file_append", "a")
 
94
        test_file_append.write("two\n")
 
95
        test_file_append.close()
 
96
        self.tree.commit(message = "merge external branch")
 
97
        shutil.rmtree("../temp-clone")
 
98
 
 
99
        self.subtree_rev = saved_subtree_revid
 
100
 
 
101
        file_contents = ["three", "four", "five"]
 
102
        for content in file_contents:
 
103
            test_file = open("test_file", "w")
 
104
            test_file.write(content)
 
105
            test_file.close()
 
106
            test_file_append = open("test_file_append", "a")
 
107
            test_file_append.write(content + "\n")
 
108
            test_file_append.close()
 
109
            self.tree.commit(message = "make test change")
 
110
 
 
111
 
 
112
class BisectHarnessTests(BisectTestCase):
 
113
    """Tests for the harness itself."""
 
114
 
 
115
    def testLastRev(self):
 
116
        """Test that the last revision is correct."""
 
117
        repo = self.tree.branch.repository
 
118
        top_revtree = repo.revision_tree(self.tree.last_revision())
 
119
        top_revtree.lock_read()
 
120
        top_file = top_revtree.get_file(top_revtree.path2id("test_file"))
 
121
        test_content = top_file.read().strip()
 
122
        top_file.close()
 
123
        top_revtree.unlock()
 
124
        assert test_content == "five"
 
125
 
 
126
    def testSubtreeRev(self):
 
127
        """Test that the last revision in a subtree is correct."""
 
128
        repo = self.tree.branch.repository
 
129
        sub_revtree = repo.revision_tree(self.subtree_rev)
 
130
        sub_revtree.lock_read()
 
131
        sub_file = sub_revtree.get_file(sub_revtree.path2id("test_file"))
 
132
        test_content = sub_file.read().strip()
 
133
        sub_file.close()
 
134
        sub_revtree.unlock()
 
135
        assert test_content == "one dot three"
 
136
 
 
137
 
 
138
class BisectMetaTests(BisectTestCase):
 
139
    """Test the metadata provided by the package."""
 
140
 
 
141
    def testVersionPresent(self):
 
142
        """Check if version_info is available for the plugin."""
 
143
        assert bisect.version_info
 
144
 
 
145
    def testBzrVersioning(self):
 
146
        """Check if API is of right version."""
 
147
        assert bisect.bzr_minimum_api <= bzrlib.api_minimum_version
 
148
        assert bisect.bzr_minimum_api <= bzrlib.version_info[:3]
 
149
 
 
150
 
 
151
class BisectCurrentUnitTests(BisectTestCase):
 
152
    """Test the BisectCurrent class."""
 
153
 
 
154
    def testShowLog(self):
 
155
        """Test that the log can be shown."""
 
156
        # Not a very good test; just makes sure the code doesn't fail,
 
157
        # not that the output makes any sense.
 
158
        sio = StringIO()
 
159
        cmds.BisectCurrent().show_rev_log(out=sio)
 
160
 
 
161
    def testShowLogSubtree(self):
 
162
        """Test that a subtree's log can be shown."""
 
163
        current = cmds.BisectCurrent()
 
164
        current.switch(self.subtree_rev)
 
165
        sio = StringIO()
 
166
        current.show_rev_log(out=sio)
 
167
 
 
168
    def testSwitchVersions(self):
 
169
        """Test switching versions."""
 
170
        current = cmds.BisectCurrent()
 
171
        self.assertRevno(5)
 
172
        current.switch(4)
 
173
        self.assertRevno(4)
 
174
 
 
175
    def testReset(self):
 
176
        """Test resetting the working tree to a non-bisected state."""
 
177
        current = cmds.BisectCurrent()
 
178
        current.switch(4)
 
179
        current.reset()
 
180
        self.assertRevno(5)
 
181
        assert not os.path.exists(cmds.bisect_rev_path)
 
182
 
 
183
    def testIsMergePoint(self):
 
184
        """Test merge point detection."""
 
185
        current = cmds.BisectCurrent()
 
186
        self.assertRevno(5)
 
187
        assert not current.is_merge_point()
 
188
        current.switch(2)
 
189
        assert current.is_merge_point()
 
190
 
 
191
 
 
192
class BisectLogUnitTests(BisectTestCase):
 
193
    """Test the BisectLog class."""
 
194
 
 
195
    def testCreateBlank(self):
 
196
        """Test creation of new log."""
 
197
        bisect_log = cmds.BisectLog()
 
198
        bisect_log.save()
 
199
        assert os.path.exists(cmds.bisect_info_path)
 
200
 
 
201
    def testLoad(self):
 
202
        """Test loading a log."""
 
203
        preloaded_log = open(cmds.bisect_info_path, "w")
 
204
        preloaded_log.write("rev1 yes\nrev2 no\nrev3 yes\n")
 
205
        preloaded_log.close()
 
206
 
 
207
        bisect_log = cmds.BisectLog()
 
208
        assert len(bisect_log._items) == 3
 
209
        assert bisect_log._items[0] == ("rev1", "yes")
 
210
        assert bisect_log._items[1] == ("rev2", "no")
 
211
        assert bisect_log._items[2] == ("rev3", "yes")
 
212
 
 
213
    def testSave(self):
 
214
        """Test saving the log."""
 
215
        bisect_log = cmds.BisectLog()
 
216
        bisect_log._items = [("rev1", "yes"), ("rev2", "no"), ("rev3", "yes")]
 
217
        bisect_log.save()
 
218
 
 
219
        logfile = open(cmds.bisect_info_path)
 
220
        assert logfile.read() == "rev1 yes\nrev2 no\nrev3 yes\n"
 
221
 
 
222
 
 
223
class BisectFuncTests(BisectTestCase):
 
224
    """Functional tests for the bisect plugin."""
 
225
 
 
226
    def testWorkflow(self):
 
227
        """Run through a basic usage scenario."""
 
228
 
 
229
        # Start up the bisection.  When the two ends are set, we should
 
230
        # end up in the middle.
 
231
 
 
232
        self.run_bzr(['bisect', 'start'])
 
233
        self.run_bzr(['bisect', 'yes'])
 
234
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
235
        self.assertRevno(3)
 
236
 
 
237
        # Mark feature as present in the middle.  Should move us
 
238
        # halfway back between the current middle and the start.
 
239
 
 
240
        self.run_bzr(['bisect', 'yes'])
 
241
        self.assertRevno(2)
 
242
 
 
243
        # Mark feature as not present.  Since this is only one
 
244
        # rev back from the lowest marked revision with the feature,
 
245
        # the process should end, with the current rev set to the
 
246
        # rev following.
 
247
 
 
248
        self.run_bzr(['bisect', 'no'])
 
249
        self.assertRevno(3)
 
250
 
 
251
        # Run again.  Since we're done, this should do nothing.
 
252
 
 
253
        self.run_bzr(['bisect', 'no'])
 
254
        self.assertRevno(3)
 
255
 
 
256
    def testWorkflowSubtree(self):
 
257
        """Run through a usage scenario where the offending change
 
258
        is in a subtree."""
 
259
 
 
260
        # Similar to testWorkflow, but make sure the plugin traverses
 
261
        # subtrees when the "final" revision is a merge point.
 
262
 
 
263
        # This part is similar to testWorkflow.
 
264
 
 
265
        self.run_bzr(['bisect', 'start'])
 
266
        self.run_bzr(['bisect', 'yes'])
 
267
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
268
        self.run_bzr(['bisect', 'yes'])
 
269
 
 
270
        # Check to make sure we're where we expect to be.
 
271
 
 
272
        self.assertRevno(2)
 
273
 
 
274
        # Now, mark the merge point revno, meaning the feature
 
275
        # appeared at a merge point.
 
276
 
 
277
        self.run_bzr(['bisect', 'yes'])
 
278
        self.assertRevno(1.2)
 
279
 
 
280
        # Continue bisecting along the subtree to the real conclusion.
 
281
 
 
282
        self.run_bzr(['bisect', 'yes'])
 
283
        self.assertRevno(1.1)
 
284
        self.run_bzr(['bisect', 'yes'])
 
285
        self.assertRevno(1.1)
 
286
 
 
287
        # Run again.  Since we're done, this should do nothing.
 
288
 
 
289
        self.run_bzr(['bisect', 'yes'])
 
290
        self.assertRevno(1.1)
 
291
 
 
292
    def testMove(self):
 
293
        """Test manually moving to a different revision during the bisection."""
 
294
 
 
295
        # Set up a bisection in progress.
 
296
 
 
297
        self.run_bzr(['bisect', 'start'])
 
298
        self.run_bzr(['bisect', 'yes'])
 
299
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
300
 
 
301
        # Move.
 
302
 
 
303
        self.run_bzr(['bisect', 'move', '-r', '2'])
 
304
        self.assertRevno(2)
 
305
 
 
306
    def testReset(self):
 
307
        """Test resetting the tree."""
 
308
 
 
309
        # Set up a bisection in progress.
 
310
 
 
311
        self.run_bzr(['bisect', 'start'])
 
312
        self.run_bzr(['bisect', 'yes'])
 
313
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
314
        self.run_bzr(['bisect', 'yes'])
 
315
 
 
316
        # Now reset.
 
317
 
 
318
        self.run_bzr(['bisect', 'reset'])
 
319
        self.assertRevno(5)
 
320
 
 
321
        # Check that reset doesn't do anything unless there's a
 
322
        # bisection in progress.
 
323
 
 
324
        test_file = open("test_file", "w")
 
325
        test_file.write("keep me")
 
326
        test_file.close()
 
327
 
 
328
        out, err = self.run_bzr(['bisect', 'reset'], retcode=3)
 
329
        self.assert_("No bisection in progress." in err)
 
330
 
 
331
        test_file = open("test_file")
 
332
        content = test_file.read().strip()
 
333
        test_file.close()
 
334
        self.failUnless(content == "keep me")
 
335
 
 
336
    def testLog(self):
 
337
        """Test saving the current bisection state, and re-loading it."""
 
338
 
 
339
        # Set up a bisection in progress.
 
340
 
 
341
        self.run_bzr(['bisect', 'start'])
 
342
        self.run_bzr(['bisect', 'yes'])
 
343
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
344
        self.run_bzr(['bisect', 'yes'])
 
345
 
 
346
        # Now save the log.
 
347
 
 
348
        self.run_bzr(['bisect', 'log', '-o', 'bisect_log'])
 
349
 
 
350
        # Reset.
 
351
 
 
352
        self.run_bzr(['bisect', 'reset'])
 
353
 
 
354
        # Read it back in.
 
355
 
 
356
        self.run_bzr(['bisect', 'replay', 'bisect_log'])
 
357
        self.assertRevno(2)
 
358
 
 
359
        # Mark another state, and see if the bisect moves in the
 
360
        # right way.
 
361
 
 
362
        self.run_bzr(['bisect', 'no'])
 
363
        self.assertRevno(3)
 
364
 
 
365
    def testRunScript(self):
 
366
        """Make a test script and run it."""
 
367
        test_script = open("test_script", "w")
 
368
        test_script.write("#!/bin/sh\n"
 
369
                          "grep -q '^four' test_file_append\n")
 
370
        test_script.close()
 
371
        os.chmod("test_script", stat.S_IRWXU)
 
372
        self.run_bzr(['bisect', 'start'])
 
373
        self.run_bzr(['bisect', 'yes'])
 
374
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
375
        self.run_bzr(['bisect', 'run', './test_script'])
 
376
        self.assertRevno(4)
 
377
 
 
378
    def testRunScriptMergePoint(self):
 
379
        """Make a test script and run it."""
 
380
        if sys.platform == "win32":
 
381
            raise TestSkipped("Unable to run shell script on windows")
 
382
        test_script = open("test_script", "w")
 
383
        test_script.write("#!/bin/sh\n"
 
384
                          "grep -q '^two' test_file_append\n")
 
385
        test_script.close()
 
386
        os.chmod("test_script", stat.S_IRWXU)
 
387
        self.run_bzr(['bisect', 'start'])
 
388
        self.run_bzr(['bisect', 'yes'])
 
389
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
390
        self.run_bzr(['bisect', 'run', './test_script'])
 
391
        try:
 
392
            self.assertRevno(2)
 
393
        except AssertionError:
 
394
            raise KnownFailure\
 
395
                ("bisect does not drill down into merge commits: "
 
396
                 "https://bugs.launchpad.net/bzr-bisect/+bug/539937")
 
397
        
 
398
    def testRunScriptSubtree(self):
 
399
        """Make a test script and run it."""
 
400
        if sys.platform == "win32":
 
401
            raise TestSkipped("Unable to run shell script on windows")
 
402
        test_script = open("test_script", "w")
 
403
        test_script.write("#!/bin/sh\n"
 
404
                          "grep -q '^one dot two' test_file_append\n")
 
405
        test_script.close()
 
406
        os.chmod("test_script", stat.S_IRWXU)
 
407
        self.run_bzr(['bisect', 'start'])
 
408
        self.run_bzr(['bisect', 'yes'])
 
409
        self.run_bzr(['bisect', 'no', '-r', '1'])
 
410
        self.run_bzr(['bisect', 'run', './test_script'])
 
411
        try:
 
412
            self.assertRevno(1.2)
 
413
        except AssertionError:
 
414
            raise KnownFailure\
 
415
                ("bisect does not drill down into merge commits: "
 
416
                 "https://bugs.launchpad.net/bzr-bisect/+bug/539937")