/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/tests/test_lockdir.py

  • Committer: Andrew Bennetts
  • Date: 2010-09-06 06:13:52 UTC
  • mto: (4634.158.5 2.0)
  • mto: This revision was merged to the branch mainline in revision 5419.
  • Revision ID: andrew.bennetts@canonical.com-20100906061352-ef2rw40pa5wte5oj
Add LockCorrupt error, and use it to provide nicer handling of unparseable lock/held/info files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
568
568
        finally:
569
569
            bzrlib.ui.ui_factory = orig_factory
570
570
 
 
571
    def test_break_lock_corrupt_info(self):
 
572
        """break_lock works even if the info file is corrupt (and tells the UI
 
573
        that it is corrupt).
 
574
        """
 
575
        ld = self.get_lock()
 
576
        ld2 = self.get_lock()
 
577
        ld.create()
 
578
        ld.lock_write()
 
579
        ld.transport.put_bytes_non_atomic('test_lock/held/info', '\0')
 
580
        class LoggingUIFactory(bzrlib.ui.SilentUIFactory):
 
581
            def __init__(self):
 
582
                self.prompts = []
 
583
            def get_boolean(self, prompt):
 
584
                self.prompts.append(('boolean', prompt))
 
585
                return True
 
586
        ui = LoggingUIFactory()
 
587
        orig_factory = bzrlib.ui.ui_factory
 
588
        bzrlib.ui.ui_factory = ui
 
589
        try:
 
590
            ld2.break_lock()
 
591
            self.assertLength(1, ui.prompts)
 
592
            self.assertEqual('boolean', ui.prompts[0][0])
 
593
            self.assertStartsWith(ui.prompts[0][1], 'Break (corrupt LockDir')
 
594
            self.assertRaises(LockBroken, ld.unlock)
 
595
        finally:
 
596
            bzrlib.ui.ui_factory = orig_factory
 
597
 
 
598
    def test_break_lock_missing_info(self):
 
599
        """break_lock works even if the info file is missing (and tells the UI
 
600
        that it is corrupt).
 
601
        """
 
602
        ld = self.get_lock()
 
603
        ld2 = self.get_lock()
 
604
        ld.create()
 
605
        ld.lock_write()
 
606
        ld.transport.delete('test_lock/held/info')
 
607
        class LoggingUIFactory(bzrlib.ui.SilentUIFactory):
 
608
            def __init__(self):
 
609
                self.prompts = []
 
610
            def get_boolean(self, prompt):
 
611
                self.prompts.append(('boolean', prompt))
 
612
                return True
 
613
        ui = LoggingUIFactory()
 
614
        orig_factory = bzrlib.ui.ui_factory
 
615
        bzrlib.ui.ui_factory = ui
 
616
        try:
 
617
            ld2.break_lock()
 
618
            self.assertRaises(LockBroken, ld.unlock)
 
619
            self.assertLength(0, ui.prompts)
 
620
        finally:
 
621
            bzrlib.ui.ui_factory = orig_factory
 
622
        # Suppress warnings due to ld not being unlocked
 
623
        # XXX: if lock_broken hook was invoked in this case, this hack would
 
624
        # not be necessary.  - Andrew Bennetts, 2010-09-06.
 
625
        del self._lock_actions[:]
 
626
 
571
627
    def test_create_missing_base_directory(self):
572
628
        """If LockDir.path doesn't exist, it can be created
573
629
 
688
744
             'locked (unknown)'],
689
745
            formatted_info)
690
746
 
 
747
    def test_corrupt_lockdir_info(self):
 
748
        """We can cope with corrupt (and thus unparseable) info files."""
 
749
        # This seems like a fairly common failure case too - see
 
750
        # <https://bugs.edge.launchpad.net/bzr/+bug/619872> for instance.
 
751
        # In particular some systems tend to fill recently created files with
 
752
        # nul bytes after recovering from a system crash.
 
753
        t = self.get_transport()
 
754
        t.mkdir('test_lock')
 
755
        t.mkdir('test_lock/held')
 
756
        t.put_bytes('test_lock/held/info', '\0')
 
757
        lf = LockDir(t, 'test_lock')
 
758
        self.assertRaises(errors.LockCorrupt, lf.peek)
 
759
        # Currently attempt_lock gives LockContention, but LockCorrupt would be
 
760
        # a reasonable result too.
 
761
        self.assertRaises(
 
762
            (errors.LockCorrupt, errors.LockContention), lf.attempt_lock)
 
763
        self.assertRaises(errors.LockCorrupt, lf.validate_token, 'fake token')
 
764
 
 
765
    def test_missing_lockdir_info(self):
 
766
        """We can cope with absent info files."""
 
767
        t = self.get_transport()
 
768
        t.mkdir('test_lock')
 
769
        t.mkdir('test_lock/held')
 
770
        lf = LockDir(t, 'test_lock')
 
771
        # In this case we expect the 'not held' result from peek, because peek
 
772
        # cannot be expected to notice that there is a 'held' directory with no
 
773
        # 'info' file.
 
774
        self.assertEqual(None, lf.peek())
 
775
        # And lock/unlock may work or give LockContention (but not any other
 
776
        # error).
 
777
        try:
 
778
            lf.attempt_lock()
 
779
        except LockContention:
 
780
            # LockContention is ok, and expected on Windows
 
781
            pass
 
782
        else:
 
783
            # no error is ok, and expected on POSIX (because POSIX allows
 
784
            # os.rename over an empty directory).
 
785
            lf.unlock()
 
786
        # Currently raises TokenMismatch, but LockCorrupt would be reasonable
 
787
        # too.
 
788
        self.assertRaises(
 
789
            (errors.TokenMismatch, errors.LockCorrupt),
 
790
            lf.validate_token, 'fake token')
 
791
 
691
792
 
692
793
class TestLockDirHooks(TestCaseWithTransport):
693
794