613
618
watch = Watch(1, path, None, True, None)
614
619
self.assertEqual(watch.started, watch._watch_started_deferred)
621
def test_stopped_property(self):
622
"""Test that the stopped property returns the stopped deferred."""
623
path = u'\\\\?\\C:\\path' # a valid windows path
624
watch = Watch(1, path, None, True, None)
625
self.assertEqual(watch.stopped, watch._watch_stopped_deferred)
627
def random_error(self, *args):
628
"""Throw a fake exception."""
629
raise FakeException()
631
@defer.inlineCallbacks
632
def test_start_watching_fails_early_in_thread(self):
633
"""An early failure inside the thread should errback the deferred."""
634
test_path = self.mktemp("test_directory")
635
self.patch(filesystem_notifications, "CreateFileW", self.random_error)
636
watch = Watch(1, test_path, None, True, None)
637
d = watch.start_watching()
638
yield self.assertFailure(d, FakeException)
640
@defer.inlineCallbacks
641
def test_start_watching_fails_late_in_thread(self):
642
"""A late failure inside the thread should errback the deferred."""
643
test_path = self.mktemp("test_directory")
644
self.patch(filesystem_notifications, "ReadDirectoryChangesW",
646
watch = Watch(1, test_path, None, True, None)
647
d = watch.start_watching()
648
yield self.assertFailure(d, FakeException)
650
@defer.inlineCallbacks
651
def test_close_handle_is_called_on_error(self):
652
"""CloseHandle is called when there's an error in the watch thread."""
653
test_path = self.mktemp("test_directory")
655
self.patch(filesystem_notifications, "CreateFileW", lambda *_: None)
656
self.patch(filesystem_notifications, "CloseHandle",
658
self.patch(filesystem_notifications, "ReadDirectoryChangesW",
660
watch = Watch(1, test_path, self.mask, True, None)
661
d = watch.start_watching()
662
yield self.assertFailure(d, FakeException)
663
self.assertEqual(len(close_called), 1)
664
yield watch.stop_watching()
666
@defer.inlineCallbacks
667
def test_stop_watching_fired_when_watch_thread_finishes(self):
668
"""The deferred returned is fired when the watch thread finishes."""
670
test_path = self.mktemp("another_test_directory")
671
fake_processor = events.append
672
watch = Watch(1, test_path, self.mask, True, fake_processor)
673
yield watch.start_watching()
674
self.assertNotEqual(watch._watch_handle, None)
675
yield watch.stop_watching()
676
self.assertEqual(watch._watch_handle, None)
617
679
class TestWatchManager(BaseTwistedTestCase):
618
680
"""Test the watch manager."""
626
688
self.manager = WatchManager(None)
627
689
self.manager._wdm = {1: self.watch}
691
@defer.inlineCallbacks
629
692
def test_stop(self):
630
"""Test that the different watches are stoppe."""
693
"""Test that the different watches are stopped."""
631
694
self.was_called = False
696
def fake_stop_watching(watch):
634
697
"""Fake stop watch."""
635
698
self.was_called = True
637
self.watch.stop_watching = stop_watching
639
self.assertTrue(self.was_called, 'The watch stop was not called.')
699
return defer.succeed(True)
701
self.patch(Watch, "stop_watching", fake_stop_watching)
702
yield self.manager.stop()
703
self.assertTrue(self.was_called, 'The watch stop should be called.')
705
@defer.inlineCallbacks
706
def test_stop_multiple(self):
707
"""Test that stop is fired when *all* watches have stopped."""
709
def fake_stop_watching(watch):
710
"""Another fake stop watch."""
713
self.patch(Watch, "stop_watching", fake_stop_watching)
714
second_path = self.parent_path + u"second_path"
715
second_watch = Watch(2, second_path, None, True, None)
716
self.manager._wdm[2] = second_watch
717
d = self.manager.stop()
718
self.assertFalse(d.called, "Not fired before all watches end")
719
self.watch.stopped.callback(None)
720
self.assertFalse(d.called, "Not fired before all watches end")
721
second_watch.stopped.callback(None)
723
self.assertTrue(d.called, "Fired after the watches ended")
641
725
def test_get_present_watch(self):
642
726
"""Test that we can get a Watch using is wd."""
653
738
def stop_watching():
654
739
"""Fake stop watch."""
655
740
self.was_called = True
741
return defer.succeed(True)
657
743
self.watch.stop_watching = stop_watching
658
self.manager.del_watch(1)
744
yield self.manager.del_watch(1)
659
745
self.assertRaises(KeyError, self.manager.get_watch, (1,))
661
747
def test_add_single_watch(self):
662
748
"""Test the addition of a new single watch."""
663
749
self.was_called = False
665
def start_watching(*args):
666
"""Fake stop watch."""
751
def fake_start_watching(*args):
752
"""Fake start watch."""
667
753
self.was_called = True
669
Watch.start_watching = start_watching
755
self.patch(Watch, "start_watching", fake_start_watching)
670
756
self.manager._wdm = {}
672
758
mask = 'bit_mask'
706
792
"""A watch on an unwatched path returns None."""
707
793
self.assertEqual(None, self.manager.get_wd(self.parent_path))
795
@defer.inlineCallbacks
709
796
def test_rm_present_wd(self):
710
797
"""Test the removal of a present watch."""
711
self.manager.rm_watch(1)
799
def fake_stop_watching():
800
"""Fake stop watch."""
801
return defer.succeed(True)
803
self.patch(self.watch, "stop_watching", fake_stop_watching)
804
yield self.manager.rm_watch(1)
712
805
self.assertEqual(None, self.manager._wdm.get(1))
714
807
def test_rm_root_path(self):
750
843
class TestWatchManagerAddWatches(BaseTwistedTestCase):
751
844
"""Test the watch manager."""
753
847
def test_add_watch_twice(self):
754
848
"""Adding a watch twice succeeds when the watch is running."""
755
849
self.patch(Watch, "start_watching", lambda self: self.started)
756
850
manager = WatchManager(None)
757
self.addCleanup(manager.stop)
851
# no need to stop watching because start_watching is fake
759
853
path = u'\\\\?\\C:\\test' # a valid windows path
760
854
mask = 'fake bit mask'
1202
1296
class FilesystemMonitorTestCase(BaseTwistedTestCase):
1203
1297
"""Tests for the FilesystemMonitor."""
1205
1300
def test_add_watch_twice(self):
1206
1301
"""Check the deferred returned by a second add_watch."""
1207
1302
self.patch(Watch, "start_watching", lambda self: self.started)
1208
1303
monitor = FilesystemMonitor(None, None)
1209
self.addCleanup(monitor.shutdown)
1304
# no need to stop watching because start_watching is fake
1211
1306
parent_path = 'C:\\test' # a valid windows path in utf-8 bytes
1212
1307
child_path = parent_path + "\\child"