138
138
except LockContention as e:
139
139
self.assertEqual(e.lock, lf2)
140
140
self.assertContainsRe(str(e),
141
r'^Could not acquire.*test_lock.*$')
141
r'^Could not acquire.*test_lock.*$')
144
144
def test_20_lock_peek(self):
151
151
# lock is held, should get some info on it
152
152
info1 = lf1.peek()
153
153
self.assertEqual(set(info1.info_dict.keys()),
154
{'user', 'nonce', 'hostname', 'pid', 'start_time'})
154
{'user', 'nonce', 'hostname', 'pid', 'start_time'})
155
155
# should get the same info if we look at it through a different
157
157
info2 = LockDir(t, 'test_lock').peek()
193
193
# it should only take about 0.4 seconds, but we allow more time in
194
194
# case the machine is heavily loaded
195
195
self.assertTrue(after - before <= 8.0,
196
"took %f seconds to detect lock contention" % (after - before))
196
"took %f seconds to detect lock contention" % (after - before))
199
199
self.assertEqual(1, len(self._logged_reports))
200
200
self.assertContainsRe(self._logged_reports[0][0],
201
r'Unable to obtain lock .* held by jrandom@example\.com on .*'
202
r' \(process #\d+\), acquired .* ago\.\n'
203
r'Will continue to try until \d{2}:\d{2}:\d{2}, unless '
204
r'you press Ctrl-C.\n'
205
r'See "brz help break-lock" for more.')
201
r'Unable to obtain lock .* held by jrandom@example\.com on .*'
202
r' \(process #\d+\), acquired .* ago\.\n'
203
r'Will continue to try until \d{2}:\d{2}:\d{2}, unless '
204
r'you press Ctrl-C.\n'
205
r'See "brz help break-lock" for more.')
207
207
def test_31_lock_wait_easy(self):
208
208
"""Succeed when waiting on a lock with no contention.
669
669
def test_unicode(self):
670
670
info = LockHeldInfo.for_this_process(None)
671
671
self.assertContainsRe(text_type(info),
672
r'held by .* on .* \(process #\d+\), acquired .* ago')
672
r'held by .* on .* \(process #\d+\), acquired .* ago')
674
674
def test_is_locked_by_this_process(self):
675
675
info = LockHeldInfo.for_this_process(None)
688
688
def test_lock_holder_dead_process(self):
689
689
"""Detect that the holder (this process) is still running."""
690
690
self.overrideAttr(lockdir, 'get_host_name',
691
lambda: 'aproperhostname')
691
lambda: 'aproperhostname')
692
692
info = LockHeldInfo.for_this_process(None)
693
693
info.info_dict['pid'] = '123123123'
694
694
self.assertTrue(info.is_lock_holder_known_dead())
718
718
self.overrideAttr(lockdir, 'get_host_name',
720
720
info = LockHeldInfo.for_this_process(None)
721
721
info.info_dict['pid'] = '123123123'
722
722
self.assertFalse(info.is_lock_holder_known_dead())
734
734
This generates a warning but no other user interaction.
736
736
self.overrideAttr(lockdir, 'get_host_name',
737
lambda: 'aproperhostname')
738
# Stealing dead locks is enabled by default.
737
lambda: 'aproperhostname')
738
# This is off by default at present; see the discussion in the bug.
739
# If you change the default, don't forget to update the docs.
740
config.GlobalStack().set('locks.steal_dead', True)
739
741
# Create a lock pretending to come from a different nonexistent
740
742
# process on the same machine.
741
743
l1 = LockDir(self.get_transport(), 'a',
742
extra_holder_info={'pid': '12312313'})
744
extra_holder_info={'pid': '12312313'})
743
745
token_1 = l1.attempt_lock()
744
746
l2 = LockDir(self.get_transport(), 'a')
745
747
token_2 = l2.attempt_lock()
746
748
# l1 will notice its lock was stolen.
747
749
self.assertRaises(errors.LockBroken,
751
753
def test_auto_break_stale_lock_configured_off(self):
752
754
"""Automatic breaking can be turned off"""
753
755
l1 = LockDir(self.get_transport(), 'a',
754
extra_holder_info={'pid': '12312313'})
755
# Stealing dead locks is enabled by default, so disable it.
756
config.GlobalStack().set('locks.steal_dead', False)
756
extra_holder_info={'pid': '12312313'})
757
757
token_1 = l1.attempt_lock()
758
758
self.addCleanup(l1.unlock)
759
759
l2 = LockDir(self.get_transport(), 'a')
760
# This fails now, because dead lock breaking is disabled.
760
# This fails now, because dead lock breaking is off by default.
761
761
self.assertRaises(LockContention,
763
763
# and it's in fact not broken