~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_lockdir.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-08-27 02:27:19 UTC
  • mfrom: (4634.3.19 gc-batching)
  • Revision ID: pqm@pqm.ubuntu.com-20090827022719-bl2yoqhpj3fcfczu
(andrew) Fix #402657: 2a fetch over dumb transport reads one group at
        a time.

Show diffs side-by-side

added added

removed removed

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