~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_lockdir.py

  • Committer: Vincent Ladeuil
  • Date: 2009-07-02 13:07:14 UTC
  • mto: (4524.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4525.
  • Revision ID: v.ladeuil+lp@free.fr-20090702130714-hsyqfusi8vn3a11m
Use tree.has_changes() where appropriate (the test suite caught a
bug in has_changes() (not filtering out the root) in an impressive
number of tests)

* bzrlib/send.py:
(send): Use tree.has_changes() instead of tree.changes_from().

* bzrlib/reconfigure.py:
(Reconfigure._check): Use tree.has_changes() instead of
tree.changes_from().

* bzrlib/merge.py:
(Merger.ensure_revision_trees, Merger.compare_basis): Use
tree.has_changes() instead of tree.changes_from().

* bzrlib/builtins.py:
(cmd_remove_tree.run, cmd_push.run, cmd_merge.run): Use
tree.has_changes() instead of tree.changes_from().

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for LockDir"""
18
18
 
126
126
        lf1.attempt_lock()
127
127
        lf2 = LockDir(t, 'test_lock')
128
128
        try:
129
 
            # locking is between LockDir instances; aliases within 
 
129
            # locking is between LockDir instances; aliases within
130
130
            # a single process are not detected
131
131
            lf2.attempt_lock()
132
132
            self.fail('Failed to detect lock collision')
142
142
        lf1 = LockDir(t, 'test_lock')
143
143
        lf1.create()
144
144
        lf1.attempt_lock()
 
145
        self.addCleanup(lf1.unlock)
145
146
        # lock is held, should get some info on it
146
147
        info1 = lf1.peek()
147
148
        self.assertEqual(set(info1.keys()),
161
162
        lf2 = LockDir(self.get_readonly_transport(), 'test_lock')
162
163
        self.assertEqual(lf2.peek(), None)
163
164
        lf1.attempt_lock()
 
165
        self.addCleanup(lf1.unlock)
164
166
        info2 = lf2.peek()
165
167
        self.assertTrue(info2)
166
168
        self.assertEqual(info2['nonce'], lf1.nonce)
167
169
 
168
170
    def test_30_lock_wait_fail(self):
169
171
        """Wait on a lock, then fail
170
 
        
 
172
 
171
173
        We ask to wait up to 400ms; this should fail within at most one
172
174
        second.  (Longer times are more realistic but we don't want the test
173
175
        suite to take too long, and this should do for now.)
185
187
            after = time.time()
186
188
            # it should only take about 0.4 seconds, but we allow more time in
187
189
            # case the machine is heavily loaded
188
 
            self.assertTrue(after - before <= 8.0, 
 
190
            self.assertTrue(after - before <= 8.0,
189
191
                    "took %f seconds to detect lock contention" % (after - before))
190
192
        finally:
191
193
            lf1.unlock()
226
228
    def test_32_lock_wait_succeed(self):
227
229
        """Succeed when trying to acquire a lock that gets released
228
230
 
229
 
        One thread holds on a lock and then releases it; another 
 
231
        One thread holds on a lock and then releases it; another
230
232
        tries to lock it.
231
233
        """
232
234
        # This test sometimes fails like this:
277
279
        self.assertContainsRe(args[4], r'\d\d:\d\d:\d\d')
278
280
 
279
281
    def test_34_lock_write_waits(self):
280
 
        """LockDir.lock_write() will wait for the lock.""" 
 
282
        """LockDir.lock_write() will wait for the lock."""
281
283
        # the test suite sets the default to 0 to make deadlocks fail fast.
282
284
        # change it for this test, as we want to try a manual deadlock.
283
285
        raise tests.TestSkipped('Timing-sensitive test')
320
322
 
321
323
    def test_35_wait_lock_changing(self):
322
324
        """LockDir.wait_lock() will report if the lock changes underneath.
323
 
        
 
325
 
324
326
        This is the stages we want to happen:
325
327
 
326
328
        0) Synchronization locks are created and locked.
327
329
        1) Lock1 obtains the lockdir, and releases the 'check' lock.
328
330
        2) Lock2 grabs the 'check' lock, and checks the lockdir.
329
 
           It sees the lockdir is already acquired, reports the fact, 
 
331
           It sees the lockdir is already acquired, reports the fact,
330
332
           and unsets the 'checked' lock.
331
333
        3) Thread1 blocks on acquiring the 'checked' lock, and then tells
332
334
           Lock1 to release and acquire the lockdir. This resets the 'check'
333
335
           lock.
334
336
        4) Lock2 acquires the 'check' lock, and checks again. It notices
335
 
           that the holder of the lock has changed, and so reports a new 
 
337
           that the holder of the lock has changed, and so reports a new
336
338
           lock holder.
337
339
        5) Thread1 blocks on the 'checked' lock, this time, it completely
338
340
           unlocks the lockdir, allowing Lock2 to acquire the lock.
451
453
        lf1 = LockDir(t, 'test_lock')
452
454
        lf1.create()
453
455
        lf1.attempt_lock()
 
456
        self.addCleanup(lf1.unlock)
454
457
        lf1.confirm()
455
458
 
456
459
    def test_41_confirm_not_held(self):
468
471
        lf1.attempt_lock()
469
472
        t.move('test_lock', 'lock_gone_now')
470
473
        self.assertRaises(LockBroken, lf1.confirm)
 
474
        # Clean up
 
475
        t.move('lock_gone_now', 'test_lock')
 
476
        lf1.unlock()
471
477
 
472
478
    def test_43_break(self):
473
479
        """Break a lock whose caller has forgotten it"""
484
490
        lf2.force_break(holder_info)
485
491
        # now we should be able to take it
486
492
        lf2.attempt_lock()
 
493
        self.addCleanup(lf2.unlock)
487
494
        lf2.confirm()
488
495
 
489
496
    def test_44_break_already_released(self):
501
508
        lf2.force_break(holder_info)
502
509
        # now we should be able to take it
503
510
        lf2.attempt_lock()
 
511
        self.addCleanup(lf2.unlock)
504
512
        lf2.confirm()
505
513
 
506
514
    def test_45_break_mismatch(self):
532
540
        """Check the on-disk representation of LockDirs is as expected.
533
541
 
534
542
        There should always be a top-level directory named by the lock.
535
 
        When the lock is held, there should be a lockname/held directory 
 
543
        When the lock is held, there should be a lockname/held directory
536
544
        containing an info file.
537
545
        """
538
546
        t = self.get_transport()
621
629
    def test_lock_by_token(self):
622
630
        ld1 = self.get_lock()
623
631
        token = ld1.lock_write()
 
632
        self.addCleanup(ld1.unlock)
624
633
        self.assertNotEqual(None, token)
625
634
        ld2 = self.get_lock()
626
635
        t2 = ld2.lock_write(token)
 
636
        self.addCleanup(ld2.unlock)
627
637
        self.assertEqual(token, t2)
628
638
 
629
639
    def test_lock_with_buggy_rename(self):
654
664
        check_dir([])
655
665
        # when held, that's all we see
656
666
        ld1.attempt_lock()
 
667
        self.addCleanup(ld1.unlock)
657
668
        check_dir(['held'])
658
669
        # second guy should fail
659
670
        self.assertRaises(errors.LockContention, ld2.attempt_lock)
660
671
        # no kibble
661
672
        check_dir(['held'])
662
673
 
 
674
 
 
675
class TestLockDirHooks(TestCaseWithTransport):
 
676
 
 
677
    def setUp(self):
 
678
        super(TestLockDirHooks, self).setUp()
 
679
        self._calls = []
 
680
 
 
681
    def get_lock(self):
 
682
        return LockDir(self.get_transport(), 'test_lock')
 
683
 
663
684
    def record_hook(self, result):
664
685
        self._calls.append(result)
665
686
 
666
 
    def reset_hooks(self):
667
 
        self._old_hooks = lock.Lock.hooks
668
 
        self.addCleanup(self.restore_hooks)
669
 
        lock.Lock.hooks = lock.LockHooks()
670
 
 
671
 
    def restore_hooks(self):
672
 
        lock.Lock.hooks = self._old_hooks
673
 
 
674
687
    def test_LockDir_acquired_success(self):
675
688
        # the LockDir.lock_acquired hook fires when a lock is acquired.
676
 
        self._calls = []
677
 
        self.reset_hooks()
678
689
        LockDir.hooks.install_named_hook('lock_acquired',
679
 
            self.record_hook, 'record_hook')
 
690
                                         self.record_hook, 'record_hook')
680
691
        ld = self.get_lock()
681
692
        ld.create()
682
693
        self.assertEqual([], self._calls)
688
699
 
689
700
    def test_LockDir_acquired_fail(self):
690
701
        # the LockDir.lock_acquired hook does not fire on failure.
691
 
        self._calls = []
692
 
        self.reset_hooks()
693
702
        ld = self.get_lock()
694
703
        ld.create()
695
704
        ld2 = self.get_lock()
696
705
        ld2.attempt_lock()
697
706
        # install a lock hook now, when the disk lock is locked
698
707
        LockDir.hooks.install_named_hook('lock_acquired',
699
 
            self.record_hook, 'record_hook')
 
708
                                         self.record_hook, 'record_hook')
700
709
        self.assertRaises(errors.LockContention, ld.attempt_lock)
701
710
        self.assertEqual([], self._calls)
702
711
        ld2.unlock()
704
713
 
705
714
    def test_LockDir_released_success(self):
706
715
        # the LockDir.lock_released hook fires when a lock is acquired.
707
 
        self._calls = []
708
 
        self.reset_hooks()
709
716
        LockDir.hooks.install_named_hook('lock_released',
710
 
            self.record_hook, 'record_hook')
 
717
                                         self.record_hook, 'record_hook')
711
718
        ld = self.get_lock()
712
719
        ld.create()
713
720
        self.assertEqual([], self._calls)
719
726
 
720
727
    def test_LockDir_released_fail(self):
721
728
        # the LockDir.lock_released hook does not fire on failure.
722
 
        self._calls = []
723
 
        self.reset_hooks()
724
729
        ld = self.get_lock()
725
730
        ld.create()
726
731
        ld2 = self.get_lock()
727
732
        ld.attempt_lock()
728
733
        ld2.force_break(ld2.peek())
729
734
        LockDir.hooks.install_named_hook('lock_released',
730
 
            self.record_hook, 'record_hook')
 
735
                                         self.record_hook, 'record_hook')
731
736
        self.assertRaises(LockBroken, ld.unlock)
732
737
        self.assertEqual([], self._calls)
 
738
 
 
739
    def test_LockDir_broken_success(self):
 
740
        # the LockDir.lock_broken hook fires when a lock is broken.
 
741
        ld = self.get_lock()
 
742
        ld.create()
 
743
        ld2 = self.get_lock()
 
744
        result = ld.attempt_lock()
 
745
        LockDir.hooks.install_named_hook('lock_broken',
 
746
                                         self.record_hook, 'record_hook')
 
747
        ld2.force_break(ld2.peek())
 
748
        lock_path = ld.transport.abspath(ld.path)
 
749
        self.assertEqual([lock.LockResult(lock_path, result)], self._calls)
 
750
 
 
751
    def test_LockDir_broken_failure(self):
 
752
        # the LockDir.lock_broken hook does not fires when a lock is already
 
753
        # released.
 
754
        ld = self.get_lock()
 
755
        ld.create()
 
756
        ld2 = self.get_lock()
 
757
        result = ld.attempt_lock()
 
758
        holder_info = ld2.peek()
 
759
        ld.unlock()
 
760
        LockDir.hooks.install_named_hook('lock_broken',
 
761
                                         self.record_hook, 'record_hook')
 
762
        ld2.force_break(holder_info)
 
763
        lock_path = ld.transport.abspath(ld.path)
 
764
        self.assertEqual([], self._calls)