Merge lp:~diegosarmentero/ubuntuone-client/darwin4-fsevents into lp:ubuntuone-client
- darwin4-fsevents
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Alejandro J. Cura | ||||
Approved revision: | 1299 | ||||
Merged at revision: | 1274 | ||||
Proposed branch: | lp:~diegosarmentero/ubuntuone-client/darwin4-fsevents | ||||
Merge into: | lp:ubuntuone-client | ||||
Prerequisite: | lp:~mandel/ubuntuone-client/clean-fsevents | ||||
Diff against target: |
783 lines (+647/-9) 4 files modified
tests/platform/filesystem_notifications/test_darwin.py (+637/-0) tests/platform/filesystem_notifications/test_filesystem_notifications.py (+5/-0) tests/platform/filesystem_notifications/test_windows.py (+2/-2) ubuntuone/platform/filesystem_notifications/darwin.py (+3/-7) |
||||
To merge this branch: | bzr merge lp:~diegosarmentero/ubuntuone-client/darwin4-fsevents | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Approve | ||
Manuel de la Peña (community) | Approve | ||
Review via email: mp+114405@code.launchpad.net |
This proposal supersedes a proposal from 2012-06-25.
Commit message
- Adding filesystem notifications feature for darwin (LP: #1013323)
Description of the change
Now you can execute:
./run-mac-tests tests/platform/
Alejandro J. Cura (alecu) wrote : Posted in a previous version of this proposal | # |
Manuel de la Peña (mandel) wrote : Posted in a previous version of this proposal | # |
The diff is misleading because it should depend on lp:~mandel/ubuntuone-client/clean-fsevents. Diego can you do a resummit with the correct dependency so that we are not scared regading the size :)
Diego Sarmentero (diegosarmentero) wrote : | # |
Answering alecu:
* Why is test_file_
This is marked for fix in
There is a bug for this, in which i'm working on:
https:/
The rest of the things has been fixed.
Manuel de la Peña (mandel) wrote : | # |
Looks like there is a thread somewhere that is not killed in the tests. I'm running the tests via u1trial and once they are done the process does not stop.
- 1296. By Diego Sarmentero
-
removing time.sleep
Diego Sarmentero (diegosarmentero) wrote : | # |
> Looks like there is a thread somewhere that is not killed in the tests. I'm
> running the tests via u1trial and once they are done the process does not
> stop.
Fixed!
Alejandro J. Cura (alecu) wrote : | # |
The tearDown in TestWatchManager should not be calling self.patch.
In the same tearDown, the deferred returned by self.manager.stop() should be yielded on.
---
typos:
"""Test that we can get a Watch using is wd.""" ->
"""Test that we can get a Watch using its wd."""
---
This line should not be part of the tests; it should be part of the stopping of the watcher thread:
self.manager.
That part of the code (stopping the watcher thread) is particularly dirty: I just found that there's a __del__ in WatchManager that we missed on the review of the previous branch, and that should not be there, since the use of __del__ is discouraged in python, and much more so when it's being used to work around a thread not being correctly finished.
I think that the stop method should be returning a deferred that's fired when the join is done; but please, let's discuss together a better solution to this on IRC or Mumble.
---
Alejandro J. Cura (alecu) : | # |
- 1297. By Diego Sarmentero
-
adding join on stop
- 1298. By Diego Sarmentero
-
moving patch to setUp
- 1299. By Diego Sarmentero
-
reverting
Manuel de la Peña (mandel) wrote : | # |
Looks goo to me knowing that we will merge this tests later.
Alejandro J. Cura (alecu) wrote : | # |
I still would like better handling of the watches being stopped, so for that I'm creating a different bug: #1024102
Otherwise the code here looks ok.
Preview Diff
1 | === modified file 'tests/platform/filesystem_notifications/test_darwin.py' | |||
2 | --- tests/platform/filesystem_notifications/test_darwin.py 2012-07-10 18:43:56 +0000 | |||
3 | +++ tests/platform/filesystem_notifications/test_darwin.py 2012-07-12 13:53:19 +0000 | |||
4 | @@ -32,7 +32,9 @@ | |||
5 | 32 | import os | 32 | import os |
6 | 33 | import tempfile | 33 | import tempfile |
7 | 34 | import thread | 34 | import thread |
8 | 35 | import itertools | ||
9 | 35 | 36 | ||
10 | 37 | import fsevents | ||
11 | 36 | from twisted.internet import defer | 38 | from twisted.internet import defer |
12 | 37 | 39 | ||
13 | 38 | from contrib.testing.testcase import BaseTwistedTestCase | 40 | from contrib.testing.testcase import BaseTwistedTestCase |
14 | @@ -41,15 +43,20 @@ | |||
15 | 41 | darwin as filesystem_notifications, | 43 | darwin as filesystem_notifications, |
16 | 42 | ) | 44 | ) |
17 | 43 | from ubuntuone.platform.filesystem_notifications.common import ( | 45 | from ubuntuone.platform.filesystem_notifications.common import ( |
18 | 46 | NotifyProcessor, | ||
19 | 44 | Watch, | 47 | Watch, |
20 | 45 | WatchManager, | 48 | WatchManager, |
21 | 46 | ) | 49 | ) |
22 | 47 | from ubuntuone.platform.filesystem_notifications.pyinotify_agnostic import ( | 50 | from ubuntuone.platform.filesystem_notifications.pyinotify_agnostic import ( |
23 | 48 | EventsCodes, | 51 | EventsCodes, |
24 | 49 | ProcessEvent, | 52 | ProcessEvent, |
25 | 53 | IN_CLOSE_WRITE, | ||
26 | 50 | IN_CREATE, | 54 | IN_CREATE, |
27 | 51 | IN_DELETE, | 55 | IN_DELETE, |
28 | 56 | IN_OPEN, | ||
29 | 52 | ) | 57 | ) |
30 | 58 | from tests.platform.filesystem_notifications import BaseFSMonitorTestCase | ||
31 | 59 | |||
32 | 53 | 60 | ||
33 | 54 | # A reverse mapping for the tests | 61 | # A reverse mapping for the tests |
34 | 55 | REVERSE_MACOS_ACTIONS = {} | 62 | REVERSE_MACOS_ACTIONS = {} |
35 | @@ -135,6 +142,7 @@ | |||
36 | 135 | yield super(TestWatch, self).setUp() | 142 | yield super(TestWatch, self).setUp() |
37 | 136 | self.basedir = self.mktemp('test_root') | 143 | self.basedir = self.mktemp('test_root') |
38 | 137 | self.mask = None | 144 | self.mask = None |
39 | 145 | self.stream = None | ||
40 | 138 | self.memento = MementoHandler() | 146 | self.memento = MementoHandler() |
41 | 139 | self.memento.setLevel(logging.DEBUG) | 147 | self.memento.setLevel(logging.DEBUG) |
42 | 140 | self.raw_events = [] | 148 | self.raw_events = [] |
43 | @@ -747,3 +755,632 @@ | |||
44 | 747 | watch._subdirs.add(path) | 755 | watch._subdirs.add(path) |
45 | 748 | watch._update_subdirs(path, REVERSE_MACOS_ACTIONS[IN_DELETE]) | 756 | watch._update_subdirs(path, REVERSE_MACOS_ACTIONS[IN_DELETE]) |
46 | 749 | self.assertTrue(path not in watch._subdirs) | 757 | self.assertTrue(path not in watch._subdirs) |
47 | 758 | |||
48 | 759 | |||
49 | 760 | class TestWatchManager(BaseTwistedTestCase): | ||
50 | 761 | """Test the watch manager.""" | ||
51 | 762 | |||
52 | 763 | @defer.inlineCallbacks | ||
53 | 764 | def setUp(self): | ||
54 | 765 | """Set each of the tests.""" | ||
55 | 766 | yield super(TestWatchManager, self).setUp() | ||
56 | 767 | self.parent_path = '/Users/username/' | ||
57 | 768 | self.path = self.parent_path + 'path' | ||
58 | 769 | self.watch = Watch(1, self.path, None) | ||
59 | 770 | self.manager = WatchManager(None) | ||
60 | 771 | self.manager._wdm = {1: self.watch} | ||
61 | 772 | |||
62 | 773 | @defer.inlineCallbacks | ||
63 | 774 | def test_stop(self): | ||
64 | 775 | """Test that the different watches are stopped.""" | ||
65 | 776 | self.was_called = False | ||
66 | 777 | |||
67 | 778 | def fake_stop_watching(watch): | ||
68 | 779 | """Fake stop watch.""" | ||
69 | 780 | self.was_called = True | ||
70 | 781 | return defer.succeed(True) | ||
71 | 782 | |||
72 | 783 | self.patch(Watch, "stop_watching", fake_stop_watching) | ||
73 | 784 | self.patch(self.manager.manager.observer, "unschedule", lambda x: None) | ||
74 | 785 | yield self.manager.stop() | ||
75 | 786 | self.assertTrue(self.was_called, 'The watch stop should be called.') | ||
76 | 787 | |||
77 | 788 | def test_stop_multiple(self): | ||
78 | 789 | """The watches should became watching=False and the observer stopped.""" | ||
79 | 790 | self.patch(self.manager.manager.observer, "unschedule", lambda x: None) | ||
80 | 791 | second_path = self.parent_path + "second_path" | ||
81 | 792 | second_watch = Watch(2, second_path, None) | ||
82 | 793 | second_watch._watching = True | ||
83 | 794 | self.manager._wdm[2] = second_watch | ||
84 | 795 | self.manager.stop() | ||
85 | 796 | self.assertFalse(second_watch.platform_watch.watching) | ||
86 | 797 | self.assertEqual(second_watch._subdirs, set()) | ||
87 | 798 | # Give time to the thread to be finished. | ||
88 | 799 | self.manager.manager.observer.join() | ||
89 | 800 | self.assertFalse(self.manager.manager.observer.is_alive()) | ||
90 | 801 | |||
91 | 802 | def test_get_present_watch(self): | ||
92 | 803 | """Test that we can get a Watch using is wd.""" | ||
93 | 804 | self.assertEqual(self.watch, self.manager.get_watch(1)) | ||
94 | 805 | |||
95 | 806 | def test_get_missing_watch(self): | ||
96 | 807 | """Test that we get an error when trying to get a missing wd.""" | ||
97 | 808 | self.assertRaises(KeyError, self.manager.get_watch, (1,)) | ||
98 | 809 | |||
99 | 810 | @defer.inlineCallbacks | ||
100 | 811 | def test_delete_present_watch(self): | ||
101 | 812 | """Test that we can remove a present watch.""" | ||
102 | 813 | self.was_called = False | ||
103 | 814 | |||
104 | 815 | def stop_watching(): | ||
105 | 816 | """Fake stop watch.""" | ||
106 | 817 | self.was_called = True | ||
107 | 818 | return defer.succeed(True) | ||
108 | 819 | |||
109 | 820 | def fake_unschedule(s): | ||
110 | 821 | """Fake function that should receive a Stream object.""" | ||
111 | 822 | self.stream = s | ||
112 | 823 | |||
113 | 824 | self.patch(self.manager.manager.observer, "unschedule", | ||
114 | 825 | fake_unschedule) | ||
115 | 826 | |||
116 | 827 | self.watch.stop_watching = stop_watching | ||
117 | 828 | yield self.manager.del_watch(1) | ||
118 | 829 | self.assertIsInstance(self.stream, fsevents.Stream) | ||
119 | 830 | self.assertRaises(KeyError, self.manager.get_watch, (1,)) | ||
120 | 831 | |||
121 | 832 | def test_add_single_watch(self): | ||
122 | 833 | """Test the addition of a new single watch.""" | ||
123 | 834 | self.was_called = False | ||
124 | 835 | |||
125 | 836 | def fake_start_watching(*args): | ||
126 | 837 | """Fake start watch.""" | ||
127 | 838 | self.was_called = True | ||
128 | 839 | |||
129 | 840 | self.patch(Watch, "start_watching", fake_start_watching) | ||
130 | 841 | self.manager._wdm = {} | ||
131 | 842 | |||
132 | 843 | mask = 'bit_mask' | ||
133 | 844 | self.manager.add_watch(self.path, mask) | ||
134 | 845 | self.assertEqual(1, len(self.manager._wdm)) | ||
135 | 846 | self.assertTrue(self.was_called, 'The watch start was not called.') | ||
136 | 847 | self.assertEqual(self.path + os.path.sep, self.manager._wdm[0].path) | ||
137 | 848 | |||
138 | 849 | def test_get_watch_present_wd(self): | ||
139 | 850 | """Test that the correct path is returned.""" | ||
140 | 851 | self.assertEqual(self.path + os.path.sep, self.manager.get_path(1)) | ||
141 | 852 | |||
142 | 853 | def test_get_watch_missing_wd(self): | ||
143 | 854 | """Test that the correct path is returned.""" | ||
144 | 855 | self.manager._wdm = {} | ||
145 | 856 | self.assertEqual(None, self.manager.get_path(1)) | ||
146 | 857 | |||
147 | 858 | def test_get_wd_exact_path(self): | ||
148 | 859 | """Test the wd is returned when there is a watch for the path.""" | ||
149 | 860 | self.assertEqual(1, self.manager.get_wd(self.path)) | ||
150 | 861 | |||
151 | 862 | def test_get_wd_child_path(self): | ||
152 | 863 | """Test the wd is returned when we have a child path.""" | ||
153 | 864 | child = os.path.join(self.path, 'child') | ||
154 | 865 | self.assertEqual(1, self.manager.get_wd(child)) | ||
155 | 866 | |||
156 | 867 | def test_get_wd_unwatched(self): | ||
157 | 868 | """A watch on an unwatched path returns None.""" | ||
158 | 869 | self.assertEqual(None, self.manager.get_wd(self.parent_path)) | ||
159 | 870 | |||
160 | 871 | def test_rm_present_wd(self): | ||
161 | 872 | """Test the removal of a present watch.""" | ||
162 | 873 | self.patch(self.watch, "stop_watching", lambda: None) | ||
163 | 874 | self.patch(self.manager.manager.observer, "unschedule", lambda x: None) | ||
164 | 875 | self.manager.rm_watch(1) | ||
165 | 876 | self.assertEqual(None, self.manager._wdm.get(1)) | ||
166 | 877 | |||
167 | 878 | def test_rm_root_path(self): | ||
168 | 879 | """Test the removal of a root path.""" | ||
169 | 880 | events = [] | ||
170 | 881 | |||
171 | 882 | def fake_processor(event): | ||
172 | 883 | """Memorize the processed events.""" | ||
173 | 884 | events.append(event.pathname) | ||
174 | 885 | |||
175 | 886 | self.watch._processor = fake_processor | ||
176 | 887 | self.manager.rm_path(self.path) | ||
177 | 888 | self.assertEqual(self.watch, self.manager._wdm.get(1)) | ||
178 | 889 | self.watch._watching = True | ||
179 | 890 | event = FakeFileEvent(256, None, os.path.join(self.path, 'test')) | ||
180 | 891 | self.watch.platform_watch._process_events(event) | ||
181 | 892 | self.assertEqual(0, len(events)) | ||
182 | 893 | |||
183 | 894 | def test_rm_child_path(self): | ||
184 | 895 | """Test the removal of a child path.""" | ||
185 | 896 | events = [] | ||
186 | 897 | |||
187 | 898 | def fake_processor(event): | ||
188 | 899 | """Memorize the processed events.""" | ||
189 | 900 | events.append(event.pathname) | ||
190 | 901 | |||
191 | 902 | self.patch(filesystem_notifications.reactor, 'callFromThread', | ||
192 | 903 | lambda x, e: x(e)) | ||
193 | 904 | |||
194 | 905 | self.watch._processor = fake_processor | ||
195 | 906 | child = os.path.join(self.path, 'child') | ||
196 | 907 | self.manager.rm_path(child) | ||
197 | 908 | self.assertEqual(self.watch, self.manager._wdm[1]) | ||
198 | 909 | # assert that the correct event is ignored | ||
199 | 910 | self.watch.platform_watch.watching = True | ||
200 | 911 | event = FakeFileEvent(256, None, os.path.join('child', 'test')) | ||
201 | 912 | self.watch.platform_watch._process_events(event) | ||
202 | 913 | self.assertEqual(0, len(events)) | ||
203 | 914 | # assert that other events are not ignored | ||
204 | 915 | event2 = FakeFileEvent(256, None, 'test') | ||
205 | 916 | self.watch.platform_watch._process_events(event2) | ||
206 | 917 | self.assertEqual(1, len(events)) | ||
207 | 918 | |||
208 | 919 | |||
209 | 920 | class TestWatchManagerAddWatches(BaseTwistedTestCase): | ||
210 | 921 | """Test the watch manager.""" | ||
211 | 922 | timeout = 5 | ||
212 | 923 | |||
213 | 924 | def test_add_watch_twice(self): | ||
214 | 925 | """Adding a watch twice succeeds when the watch is running.""" | ||
215 | 926 | self.patch(Watch, "start_watching", lambda self: None) | ||
216 | 927 | manager = WatchManager(None) | ||
217 | 928 | # no need to stop watching because start_watching is fake | ||
218 | 929 | |||
219 | 930 | path = '/Users/username/path' | ||
220 | 931 | mask = 'fake bit mask' | ||
221 | 932 | d1 = manager.add_watch(path, mask) | ||
222 | 933 | d2 = manager.add_watch(path, mask) | ||
223 | 934 | |||
224 | 935 | self.assertTrue(d1.result, "Should not be called yet.") | ||
225 | 936 | self.assertFalse(d2.result, "Should not be called yet.") | ||
226 | 937 | |||
227 | 938 | |||
228 | 939 | class FakeEvent(object): | ||
229 | 940 | """Fake event.""" | ||
230 | 941 | |||
231 | 942 | def __init__(self, wd=0, dir=True, name=None, path=None, pathname=None, | ||
232 | 943 | cookie=None): | ||
233 | 944 | """Create fake event.""" | ||
234 | 945 | self.dir = dir | ||
235 | 946 | self.wd = wd | ||
236 | 947 | self.name = name | ||
237 | 948 | self.path = path | ||
238 | 949 | self.pathname = pathname | ||
239 | 950 | self.cookie = cookie | ||
240 | 951 | |||
241 | 952 | |||
242 | 953 | class FakeLog(object): | ||
243 | 954 | """A fake log that is used by the general processor.""" | ||
244 | 955 | |||
245 | 956 | def __init__(self): | ||
246 | 957 | """Create the fake.""" | ||
247 | 958 | self.called_methods = [] | ||
248 | 959 | |||
249 | 960 | def info(self, *args): | ||
250 | 961 | """Fake the info call.""" | ||
251 | 962 | self.called_methods.append(('info', args)) | ||
252 | 963 | |||
253 | 964 | |||
254 | 965 | class FakeGeneralProcessor(object): | ||
255 | 966 | """Fake implementation of the general processor.""" | ||
256 | 967 | |||
257 | 968 | def __init__(self): | ||
258 | 969 | """Create the fake.""" | ||
259 | 970 | self.called_methods = [] | ||
260 | 971 | self.paths_to_return = [] | ||
261 | 972 | self.log = FakeLog() | ||
262 | 973 | self.share_id = None | ||
263 | 974 | self.ignore = False | ||
264 | 975 | |||
265 | 976 | def rm_from_mute_filter(self, event, paths): | ||
266 | 977 | """Fake rm_from_mute_filter.""" | ||
267 | 978 | self.called_methods.append(('rm_from_mute_filter', event, paths)) | ||
268 | 979 | |||
269 | 980 | def add_to_mute_filter(self, event, paths): | ||
270 | 981 | """Fake add_to_move_filter.""" | ||
271 | 982 | self.called_methods.append(('add_to_mute_filter', event, paths)) | ||
272 | 983 | |||
273 | 984 | def is_ignored(self, path): | ||
274 | 985 | """Fake is_ignored.""" | ||
275 | 986 | self.called_methods.append(('is_ignored', path)) | ||
276 | 987 | return self.ignore | ||
277 | 988 | |||
278 | 989 | def push_event(self, event): | ||
279 | 990 | """Fake push event.""" | ||
280 | 991 | self.called_methods.append(('push_event', event)) | ||
281 | 992 | |||
282 | 993 | def eq_push(self, event, path=None, path_to=None, path_from=None): | ||
283 | 994 | """Fake event to push event.""" | ||
284 | 995 | self.called_methods.append(('eq_push', event, path, path_to, | ||
285 | 996 | path_from)) | ||
286 | 997 | |||
287 | 998 | def get_paths_starting_with(self, fullpath, include_base=False): | ||
288 | 999 | """Fake get_paths_starting_with.""" | ||
289 | 1000 | self.called_methods.append(('get_paths_starting_with', fullpath, | ||
290 | 1001 | include_base)) | ||
291 | 1002 | return self.paths_to_return | ||
292 | 1003 | |||
293 | 1004 | def get_path_share_id(self, path): | ||
294 | 1005 | """Fake get_path_share_id.""" | ||
295 | 1006 | self.called_methods.append(('get_path_share_id', path)) | ||
296 | 1007 | return self.share_id | ||
297 | 1008 | |||
298 | 1009 | def rm_watch(self, path): | ||
299 | 1010 | """Fake the remove watch.""" | ||
300 | 1011 | self.called_methods.append(('rm_watch', path)) | ||
301 | 1012 | |||
302 | 1013 | def freeze_begin(self, path): | ||
303 | 1014 | """Fake freeze_begin""" | ||
304 | 1015 | self.called_methods.append(('freeze_begin', path)) | ||
305 | 1016 | |||
306 | 1017 | def freeze_rollback(self): | ||
307 | 1018 | """Fake rollback.""" | ||
308 | 1019 | self.called_methods.append(('freeze_rollback',)) | ||
309 | 1020 | |||
310 | 1021 | def freeze_commit(self, path): | ||
311 | 1022 | """Fake freeze commit.""" | ||
312 | 1023 | self.called_methods.append(('freeze_commit', path)) | ||
313 | 1024 | |||
314 | 1025 | |||
315 | 1026 | class TestNotifyProcessor(BaseTwistedTestCase): | ||
316 | 1027 | """Test the notify processor.""" | ||
317 | 1028 | |||
318 | 1029 | @defer.inlineCallbacks | ||
319 | 1030 | def setUp(self): | ||
320 | 1031 | """set up the diffeent tests.""" | ||
321 | 1032 | yield super(TestNotifyProcessor, self).setUp() | ||
322 | 1033 | self.processor = NotifyProcessor(None) | ||
323 | 1034 | self.general = FakeGeneralProcessor() | ||
324 | 1035 | self.processor.general_processor = self.general | ||
325 | 1036 | |||
326 | 1037 | def test_rm_from_mute_filter(self): | ||
327 | 1038 | """Test that we remove the event from the mute filter.""" | ||
328 | 1039 | event = 'event' | ||
329 | 1040 | paths = 'paths' | ||
330 | 1041 | self.processor.rm_from_mute_filter(event, paths) | ||
331 | 1042 | self.assertEqual(1, len(self.general.called_methods)) | ||
332 | 1043 | self.assertEqual('rm_from_mute_filter', | ||
333 | 1044 | self.general.called_methods[0][0]) | ||
334 | 1045 | self.assertEqual(event, self.general.called_methods[0][1]) | ||
335 | 1046 | self.assertEqual(paths, self.general.called_methods[0][2]) | ||
336 | 1047 | |||
337 | 1048 | def test_add_to_mute_filter(self): | ||
338 | 1049 | """Test that we add the path to the mute filter.""" | ||
339 | 1050 | event = 'event' | ||
340 | 1051 | paths = 'paths' | ||
341 | 1052 | self.processor.add_to_mute_filter(event, paths) | ||
342 | 1053 | self.assertEqual(1, len(self.general.called_methods)) | ||
343 | 1054 | self.assertEqual('add_to_mute_filter', | ||
344 | 1055 | self.general.called_methods[0][0]) | ||
345 | 1056 | self.assertEqual(event, self.general.called_methods[0][1]) | ||
346 | 1057 | self.assertEqual(paths, self.general.called_methods[0][2]) | ||
347 | 1058 | |||
348 | 1059 | def test_is_ignored(self): | ||
349 | 1060 | """Test that we do ensure that the path is ignored.""" | ||
350 | 1061 | path = 'path' | ||
351 | 1062 | self.processor.is_ignored(path) | ||
352 | 1063 | self.assertEqual(1, len(self.general.called_methods)) | ||
353 | 1064 | self.assertEqual('is_ignored', | ||
354 | 1065 | self.general.called_methods[0][0]) | ||
355 | 1066 | self.assertEqual(path, self.general.called_methods[0][1]) | ||
356 | 1067 | |||
357 | 1068 | def test_release_held_event(self): | ||
358 | 1069 | """Test that we do release the held event.""" | ||
359 | 1070 | event = 'event' | ||
360 | 1071 | # set the held event to assert that is pushed | ||
361 | 1072 | self.processor.held_event = event | ||
362 | 1073 | self.processor.release_held_event() | ||
363 | 1074 | self.assertEqual('push_event', | ||
364 | 1075 | self.general.called_methods[0][0]) | ||
365 | 1076 | self.assertEqual(event, self.general.called_methods[0][1]) | ||
366 | 1077 | |||
367 | 1078 | def test_process_IN_MODIFY_dir(self): | ||
368 | 1079 | """Test that the modify works as exepcted with dirs.""" | ||
369 | 1080 | event = FakeEvent(dir=True) | ||
370 | 1081 | self.processor.process_IN_MODIFY(event) | ||
371 | 1082 | # no method should be called | ||
372 | 1083 | self.assertEqual(0, len(self.general.called_methods)) | ||
373 | 1084 | |||
374 | 1085 | def test_process_IN_MODIFY_file(self): | ||
375 | 1086 | """Test that the modify works as expected with files.""" | ||
376 | 1087 | event = FakeEvent(dir=False, wd=0, name='name', | ||
377 | 1088 | path='path', pathname='pathname') | ||
378 | 1089 | self.processor.process_IN_MODIFY(event) | ||
379 | 1090 | # we should be getting two different method, and open and a close | ||
380 | 1091 | self.assertEqual(2, len(self.general.called_methods)) | ||
381 | 1092 | self.assertEqual('push_event', | ||
382 | 1093 | self.general.called_methods[0][0]) | ||
383 | 1094 | self.assertEqual('push_event', | ||
384 | 1095 | self.general.called_methods[1][0]) | ||
385 | 1096 | self.assertEqual(event.dir, self.general.called_methods[0][1].dir) | ||
386 | 1097 | self.assertEqual(event.wd, self.general.called_methods[0][1].wd) | ||
387 | 1098 | self.assertEqual(event.name, self.general.called_methods[0][1].name) | ||
388 | 1099 | self.assertEqual(event.path, self.general.called_methods[0][1].path) | ||
389 | 1100 | self.assertEqual(event.pathname, | ||
390 | 1101 | self.general.called_methods[0][1].pathname) | ||
391 | 1102 | self.assertEqual(IN_OPEN, | ||
392 | 1103 | self.general.called_methods[0][1].mask) | ||
393 | 1104 | self.assertEqual(event.dir, self.general.called_methods[1][1].dir) | ||
394 | 1105 | self.assertEqual(event.wd, self.general.called_methods[1][1].wd) | ||
395 | 1106 | self.assertEqual(event.name, self.general.called_methods[1][1].name) | ||
396 | 1107 | self.assertEqual(event.path, self.general.called_methods[1][1].path) | ||
397 | 1108 | self.assertEqual(event.pathname, | ||
398 | 1109 | self.general.called_methods[1][1].pathname) | ||
399 | 1110 | self.assertEqual(IN_CLOSE_WRITE, | ||
400 | 1111 | self.general.called_methods[1][1].mask) | ||
401 | 1112 | |||
402 | 1113 | def test_process_IN_MOVED_FROM(self): | ||
403 | 1114 | """Test that the in moved from works as expected.""" | ||
404 | 1115 | event = FakeEvent(dir=False, wd=0, name='name', | ||
405 | 1116 | path='path', pathname='pathname') | ||
406 | 1117 | self.processor.process_IN_MOVED_FROM(event) | ||
407 | 1118 | self.assertEqual(event, self.processor.held_event) | ||
408 | 1119 | |||
409 | 1120 | def test_process_IN_MOVED_TO_dir(self): | ||
410 | 1121 | """Test that the in moved to works as expected.""" | ||
411 | 1122 | event = FakeEvent(wd=0, dir=True, name='name', path='path', | ||
412 | 1123 | pathname=os.path.join('test', 'pathname'), | ||
413 | 1124 | cookie='cookie') | ||
414 | 1125 | held_event = FakeEvent(wd=0, dir=True, name='hname', path='hpath', | ||
415 | 1126 | pathname=os.path.join('test', 'hpathname'), | ||
416 | 1127 | cookie='cookie') | ||
417 | 1128 | self.general.share_id = 'my_share_id' | ||
418 | 1129 | self.processor.held_event = held_event | ||
419 | 1130 | self.processor.process_IN_MOVED_TO(event) | ||
420 | 1131 | self.assertEqual(5, len(self.general.called_methods)) | ||
421 | 1132 | # assert that the ignores are called | ||
422 | 1133 | self.assertEqual('is_ignored', self.general.called_methods[0][0]) | ||
423 | 1134 | self.assertEqual(held_event.pathname, | ||
424 | 1135 | self.general.called_methods[0][1]) | ||
425 | 1136 | self.assertEqual('is_ignored', self.general.called_methods[1][0]) | ||
426 | 1137 | self.assertEqual(event.pathname, self.general.called_methods[1][1]) | ||
427 | 1138 | # assert that we do request the share_id | ||
428 | 1139 | self.assertEqual('get_path_share_id', | ||
429 | 1140 | self.general.called_methods[2][0]) | ||
430 | 1141 | self.assertEqual(os.path.split(event.pathname)[0], | ||
431 | 1142 | self.general.called_methods[2][1], | ||
432 | 1143 | 'Get the share_id for event') | ||
433 | 1144 | self.assertEqual('get_path_share_id', | ||
434 | 1145 | self.general.called_methods[3][0]) | ||
435 | 1146 | self.assertEqual(os.path.split(held_event.pathname)[0], | ||
436 | 1147 | self.general.called_methods[3][1], | ||
437 | 1148 | 'Get the share_id for held event.') | ||
438 | 1149 | |||
439 | 1150 | self.assertEqual('eq_push', self.general.called_methods[4][0]) | ||
440 | 1151 | self.assertEqual('FS_DIR_MOVE', self.general.called_methods[4][1]) | ||
441 | 1152 | self.assertEqual(event.pathname, self.general.called_methods[4][3]) | ||
442 | 1153 | self.assertEqual(held_event.pathname, | ||
443 | 1154 | self.general.called_methods[4][4]) | ||
444 | 1155 | |||
445 | 1156 | def test_process_IN_MOVED_TO_file(self): | ||
446 | 1157 | """Test that the in moved to works as expected.""" | ||
447 | 1158 | event = FakeEvent(wd=0, dir=False, name='name', path='path', | ||
448 | 1159 | pathname=os.path.join('test', 'pathname'), | ||
449 | 1160 | cookie='cookie') | ||
450 | 1161 | held_event = FakeEvent(wd=0, dir=False, name='hname', path='hpath', | ||
451 | 1162 | pathname=os.path.join('test', 'hpathname'), | ||
452 | 1163 | cookie='cookie') | ||
453 | 1164 | self.general.share_id = 'my_share_id' | ||
454 | 1165 | self.processor.held_event = held_event | ||
455 | 1166 | self.processor.process_IN_MOVED_TO(event) | ||
456 | 1167 | self.assertEqual(5, len(self.general.called_methods)) | ||
457 | 1168 | # assert that the ignores are called | ||
458 | 1169 | self.assertEqual('is_ignored', self.general.called_methods[0][0]) | ||
459 | 1170 | self.assertEqual(held_event.pathname, | ||
460 | 1171 | self.general.called_methods[0][1]) | ||
461 | 1172 | self.assertEqual('is_ignored', self.general.called_methods[1][0]) | ||
462 | 1173 | self.assertEqual(event.pathname, self.general.called_methods[1][1]) | ||
463 | 1174 | # assert that we do request the share_id | ||
464 | 1175 | self.assertEqual('get_path_share_id', | ||
465 | 1176 | self.general.called_methods[2][0]) | ||
466 | 1177 | self.assertEqual(os.path.split(event.pathname)[0], | ||
467 | 1178 | self.general.called_methods[2][1], | ||
468 | 1179 | 'Get the share_id for event') | ||
469 | 1180 | self.assertEqual('get_path_share_id', | ||
470 | 1181 | self.general.called_methods[3][0]) | ||
471 | 1182 | self.assertEqual(os.path.split(held_event.pathname)[0], | ||
472 | 1183 | self.general.called_methods[3][1], | ||
473 | 1184 | 'Get the share_id for held event.') | ||
474 | 1185 | |||
475 | 1186 | self.assertEqual('eq_push', self.general.called_methods[4][0]) | ||
476 | 1187 | self.assertEqual('FS_FILE_MOVE', self.general.called_methods[4][1]) | ||
477 | 1188 | self.assertEqual(event.pathname, self.general.called_methods[4][3]) | ||
478 | 1189 | self.assertEqual(held_event.pathname, | ||
479 | 1190 | self.general.called_methods[4][4]) | ||
480 | 1191 | |||
481 | 1192 | def test_fake_create_event_dir(self): | ||
482 | 1193 | """Test that the in moved to works as expected.""" | ||
483 | 1194 | event = FakeEvent(wd=0, dir=True, name='name', path='path', | ||
484 | 1195 | pathname='pathname') | ||
485 | 1196 | self.processor._fake_create_event(event) | ||
486 | 1197 | self.assertEqual(1, len(self.general.called_methods)) | ||
487 | 1198 | self.assertEqual('eq_push', self.general.called_methods[0][0]) | ||
488 | 1199 | self.assertEqual('FS_DIR_CREATE', self.general.called_methods[0][1]) | ||
489 | 1200 | self.assertEqual(event.pathname, self.general.called_methods[0][2]) | ||
490 | 1201 | |||
491 | 1202 | def test_fake_create_event_file(self): | ||
492 | 1203 | """Test that the in moved to works as expected.""" | ||
493 | 1204 | event = FakeEvent(wd=0, dir=False, name='name', path='path', | ||
494 | 1205 | pathname='pathname') | ||
495 | 1206 | self.processor._fake_create_event(event) | ||
496 | 1207 | self.assertEqual(2, len(self.general.called_methods)) | ||
497 | 1208 | self.assertEqual('eq_push', self.general.called_methods[0][0]) | ||
498 | 1209 | self.assertEqual('FS_FILE_CREATE', self.general.called_methods[0][1]) | ||
499 | 1210 | self.assertEqual(event.pathname, self.general.called_methods[0][2]) | ||
500 | 1211 | self.assertEqual('eq_push', self.general.called_methods[1][0]) | ||
501 | 1212 | self.assertEqual('FS_FILE_CLOSE_WRITE', | ||
502 | 1213 | self.general.called_methods[1][1]) | ||
503 | 1214 | self.assertEqual(event.pathname, self.general.called_methods[1][2]) | ||
504 | 1215 | |||
505 | 1216 | def test_fake_delete_create_event_dir(self): | ||
506 | 1217 | """Test that we do fake a delete and a later delete.""" | ||
507 | 1218 | event = FakeEvent(wd=0, dir=True, name='name', path='path', | ||
508 | 1219 | pathname='pathname') | ||
509 | 1220 | held_event = FakeEvent(wd=0, dir=True, name='hname', path='hpath', | ||
510 | 1221 | pathname='hpathname') | ||
511 | 1222 | self.processor.held_event = held_event | ||
512 | 1223 | self.processor._fake_delete_create_event(event) | ||
513 | 1224 | self.assertEqual(2, len(self.general.called_methods)) | ||
514 | 1225 | self.assertEqual('eq_push', self.general.called_methods[0][0]) | ||
515 | 1226 | self.assertEqual('FS_DIR_DELETE', self.general.called_methods[0][1]) | ||
516 | 1227 | self.assertEqual(held_event.pathname, | ||
517 | 1228 | self.general.called_methods[0][2]) | ||
518 | 1229 | self.assertEqual('eq_push', self.general.called_methods[1][0]) | ||
519 | 1230 | self.assertEqual('FS_DIR_CREATE', self.general.called_methods[1][1]) | ||
520 | 1231 | self.assertEqual(event.pathname, self.general.called_methods[1][2]) | ||
521 | 1232 | |||
522 | 1233 | def test_fake_delete_create_event_file(self): | ||
523 | 1234 | """Test that we do fake a delete and a later delete.""" | ||
524 | 1235 | event = FakeEvent(wd=0, dir=False, name='name', path='path', | ||
525 | 1236 | pathname='pathname') | ||
526 | 1237 | held_event = FakeEvent(wd=0, dir=False, name='hname', path='hpath', | ||
527 | 1238 | pathname='hpathname') | ||
528 | 1239 | self.processor.held_event = held_event | ||
529 | 1240 | self.processor._fake_delete_create_event(event) | ||
530 | 1241 | self.assertEqual(3, len(self.general.called_methods)) | ||
531 | 1242 | self.assertEqual('eq_push', self.general.called_methods[0][0]) | ||
532 | 1243 | self.assertEqual('FS_FILE_DELETE', self.general.called_methods[0][1]) | ||
533 | 1244 | self.assertEqual(held_event.pathname, | ||
534 | 1245 | self.general.called_methods[0][2]) | ||
535 | 1246 | self.assertEqual('eq_push', self.general.called_methods[1][0]) | ||
536 | 1247 | self.assertEqual('FS_FILE_CREATE', self.general.called_methods[1][1]) | ||
537 | 1248 | self.assertEqual(event.pathname, self.general.called_methods[1][2]) | ||
538 | 1249 | self.assertEqual('eq_push', self.general.called_methods[2][0]) | ||
539 | 1250 | self.assertEqual('FS_FILE_CLOSE_WRITE', | ||
540 | 1251 | self.general.called_methods[2][1]) | ||
541 | 1252 | self.assertEqual(event.pathname, self.general.called_methods[2][2]) | ||
542 | 1253 | |||
543 | 1254 | def test_process_default_no_held(self): | ||
544 | 1255 | """Test that the process default works as expected.""" | ||
545 | 1256 | event = 'event' | ||
546 | 1257 | self.processor.process_default(event) | ||
547 | 1258 | self.assertEqual(1, len(self.general.called_methods)) | ||
548 | 1259 | self.assertEqual('push_event', | ||
549 | 1260 | self.general.called_methods[0][0]) | ||
550 | 1261 | self.assertEqual(event, | ||
551 | 1262 | self.general.called_methods[0][1]) | ||
552 | 1263 | |||
553 | 1264 | def test_process_default_with_held(self): | ||
554 | 1265 | """Test that the process default works as expected.""" | ||
555 | 1266 | event = 'event' | ||
556 | 1267 | held_event = 'held_event' | ||
557 | 1268 | self.processor.held_event = held_event | ||
558 | 1269 | self.processor.process_default(event) | ||
559 | 1270 | self.assertEqual(2, len(self.general.called_methods)) | ||
560 | 1271 | self.assertEqual('push_event', | ||
561 | 1272 | self.general.called_methods[0][0]) | ||
562 | 1273 | self.assertEqual(held_event, | ||
563 | 1274 | self.general.called_methods[0][1]) | ||
564 | 1275 | self.assertEqual('push_event', | ||
565 | 1276 | self.general.called_methods[1][0]) | ||
566 | 1277 | self.assertEqual(event, | ||
567 | 1278 | self.general.called_methods[1][1]) | ||
568 | 1279 | |||
569 | 1280 | def test_handle_dir_delete_files(self): | ||
570 | 1281 | """Test that the handle dir delete works as expected.""" | ||
571 | 1282 | path = 'path' | ||
572 | 1283 | present_files = 'abcde' | ||
573 | 1284 | # create files and dirs to be returned from the get paths | ||
574 | 1285 | for file_name in present_files: | ||
575 | 1286 | self.general.paths_to_return.append((file_name, False)) | ||
576 | 1287 | self.processor.handle_dir_delete(path) | ||
577 | 1288 | # there are calls for, rm the watch, get paths and then one per file | ||
578 | 1289 | self.assertEqual(len(present_files) + 2, | ||
579 | 1290 | len(self.general.called_methods)) | ||
580 | 1291 | rm_call = self.general.called_methods.pop(0) | ||
581 | 1292 | self.assertEqual('rm_watch', rm_call[0]) | ||
582 | 1293 | self.assertEqual(path, rm_call[1]) | ||
583 | 1294 | paths_call = self.general.called_methods.pop(0) | ||
584 | 1295 | self.assertEqual('get_paths_starting_with', paths_call[0]) | ||
585 | 1296 | self.assertEqual(path, paths_call[1]) | ||
586 | 1297 | self.assertFalse(paths_call[2]) | ||
587 | 1298 | # we need to push the delete events in reverse order because we want | ||
588 | 1299 | # to delete children before we delete parents | ||
589 | 1300 | present_files = present_files[::-1] | ||
590 | 1301 | for i, called_method in enumerate(self.general.called_methods): | ||
591 | 1302 | self.assertEqual('eq_push', called_method[0]) | ||
592 | 1303 | self.assertEqual('FS_FILE_DELETE', called_method[1]) | ||
593 | 1304 | self.assertEqual(present_files[i], called_method[2]) | ||
594 | 1305 | |||
595 | 1306 | def test_handle_dir_delete_dirs(self): | ||
596 | 1307 | """Test that the handle dir delete works as expected.""" | ||
597 | 1308 | path = 'path' | ||
598 | 1309 | present_files = 'abcde' | ||
599 | 1310 | # create files and dirs to be returned from the get paths | ||
600 | 1311 | for file_name in present_files: | ||
601 | 1312 | self.general.paths_to_return.append((file_name, True)) | ||
602 | 1313 | self.processor.handle_dir_delete(path) | ||
603 | 1314 | # there are calls for, rm the watch, get paths and then one per file | ||
604 | 1315 | self.assertEqual(2 * len(present_files) + 2, | ||
605 | 1316 | len(self.general.called_methods)) | ||
606 | 1317 | rm_call = self.general.called_methods.pop(0) | ||
607 | 1318 | self.assertEqual('rm_watch', rm_call[0]) | ||
608 | 1319 | self.assertEqual(path, rm_call[1]) | ||
609 | 1320 | paths_call = self.general.called_methods.pop(0) | ||
610 | 1321 | self.assertEqual('get_paths_starting_with', paths_call[0]) | ||
611 | 1322 | self.assertEqual(path, paths_call[1]) | ||
612 | 1323 | self.assertFalse(paths_call[2]) | ||
613 | 1324 | # we need to push the delete events in reverse order because we want | ||
614 | 1325 | # to delete children before we delete parents | ||
615 | 1326 | present_files = present_files[::-1] | ||
616 | 1327 | |||
617 | 1328 | # from http://docs.python.org/library/itertools.html#recipes | ||
618 | 1329 | def grouper(n, iterable, fillvalue=None): | ||
619 | 1330 | "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" | ||
620 | 1331 | args = [iter(iterable)] * n | ||
621 | 1332 | return itertools.izip_longest(fillvalue=fillvalue, *args) | ||
622 | 1333 | |||
623 | 1334 | for i, called_methods in enumerate(grouper(2, | ||
624 | 1335 | self.general.called_methods)): | ||
625 | 1336 | rm_call = called_methods[0] | ||
626 | 1337 | self.assertEqual('rm_watch', rm_call[0]) | ||
627 | 1338 | self.assertEqual(present_files[i], rm_call[1]) | ||
628 | 1339 | push_call = called_methods[1] | ||
629 | 1340 | self.assertEqual('eq_push', push_call[0]) | ||
630 | 1341 | self.assertEqual('FS_DIR_DELETE', push_call[1]) | ||
631 | 1342 | self.assertEqual(present_files[i], push_call[2]) | ||
632 | 1343 | |||
633 | 1344 | def test_freeze_begin(self): | ||
634 | 1345 | """Test that the freeze being works as expected.""" | ||
635 | 1346 | path = 'path' | ||
636 | 1347 | self.processor.freeze_begin(path) | ||
637 | 1348 | self.assertEqual(1, len(self.general.called_methods)) | ||
638 | 1349 | self.assertEqual('freeze_begin', | ||
639 | 1350 | self.general.called_methods[0][0]) | ||
640 | 1351 | self.assertEqual(path, self.general.called_methods[0][1]) | ||
641 | 1352 | |||
642 | 1353 | def test_freeze_rollback(self): | ||
643 | 1354 | """Test that the freeze rollback works as expected.""" | ||
644 | 1355 | self.processor.freeze_rollback() | ||
645 | 1356 | self.assertEqual(1, len(self.general.called_methods)) | ||
646 | 1357 | self.assertEqual('freeze_rollback', | ||
647 | 1358 | self.general.called_methods[0][0]) | ||
648 | 1359 | |||
649 | 1360 | def test_freeze_commit(self): | ||
650 | 1361 | """Test that the freeze commit works as expected.""" | ||
651 | 1362 | path = 'path' | ||
652 | 1363 | self.processor.freeze_commit(path) | ||
653 | 1364 | self.assertEqual(1, len(self.general.called_methods)) | ||
654 | 1365 | self.assertEqual('freeze_commit', | ||
655 | 1366 | self.general.called_methods[0][0]) | ||
656 | 1367 | self.assertEqual(path, self.general.called_methods[0][1]) | ||
657 | 1368 | |||
658 | 1369 | |||
659 | 1370 | class FilesystemMonitorTestCase(BaseFSMonitorTestCase): | ||
660 | 1371 | """Tests for the FilesystemMonitor.""" | ||
661 | 1372 | |||
662 | 1373 | def test_add_watch_twice(self): | ||
663 | 1374 | """Check the deferred returned by a second add_watch.""" | ||
664 | 1375 | self.patch(Watch, "start_watching", lambda self: None) | ||
665 | 1376 | self.patch(Watch, "started", lambda self: True) | ||
666 | 1377 | manager = WatchManager(None) | ||
667 | 1378 | # no need to stop watching because start_watching is fake | ||
668 | 1379 | |||
669 | 1380 | path = '/Users/username/path' | ||
670 | 1381 | mask = 'fake bit mask' | ||
671 | 1382 | d1 = manager.add_watch(path, mask) | ||
672 | 1383 | d2 = manager.add_watch(path, mask) | ||
673 | 1384 | |||
674 | 1385 | self.assertTrue(d1.result, "Should not be called yet.") | ||
675 | 1386 | self.assertTrue(d2, "Should not be called yet.") | ||
676 | 750 | 1387 | ||
677 | === modified file 'tests/platform/filesystem_notifications/test_filesystem_notifications.py' | |||
678 | --- tests/platform/filesystem_notifications/test_filesystem_notifications.py 2012-06-28 10:26:50 +0000 | |||
679 | +++ tests/platform/filesystem_notifications/test_filesystem_notifications.py 2012-07-12 13:53:19 +0000 | |||
680 | @@ -39,6 +39,7 @@ | |||
681 | 39 | BaseTwistedTestCase, | 39 | BaseTwistedTestCase, |
682 | 40 | FakeVolumeManager, | 40 | FakeVolumeManager, |
683 | 41 | skip_if_win32_missing_fs_event, | 41 | skip_if_win32_missing_fs_event, |
684 | 42 | skip_if_darwin_missing_fs_event, | ||
685 | 42 | ) | 43 | ) |
686 | 43 | from ubuntuone.platform import ( | 44 | from ubuntuone.platform import ( |
687 | 44 | remove_file, | 45 | remove_file, |
688 | @@ -264,6 +265,7 @@ | |||
689 | 264 | mute_filter = self.monitor._processor.mute_filter | 265 | mute_filter = self.monitor._processor.mute_filter |
690 | 265 | return sum(len(x) for x in mute_filter._cnt.values()) | 266 | return sum(len(x) for x in mute_filter._cnt.values()) |
691 | 266 | 267 | ||
692 | 268 | @skip_if_darwin_missing_fs_event | ||
693 | 267 | @skip_if_win32_missing_fs_event | 269 | @skip_if_win32_missing_fs_event |
694 | 268 | @defer.inlineCallbacks | 270 | @defer.inlineCallbacks |
695 | 269 | def test_file_open(self): | 271 | def test_file_open(self): |
696 | @@ -281,6 +283,7 @@ | |||
697 | 281 | test_result = yield self._deferred | 283 | test_result = yield self._deferred |
698 | 282 | defer.returnValue(test_result) | 284 | defer.returnValue(test_result) |
699 | 283 | 285 | ||
700 | 286 | @skip_if_darwin_missing_fs_event | ||
701 | 284 | @skip_if_win32_missing_fs_event | 287 | @skip_if_win32_missing_fs_event |
702 | 285 | @defer.inlineCallbacks | 288 | @defer.inlineCallbacks |
703 | 286 | def test_file_close_nowrite(self): | 289 | def test_file_close_nowrite(self): |
704 | @@ -298,6 +301,7 @@ | |||
705 | 298 | test_result = yield self._deferred | 301 | test_result = yield self._deferred |
706 | 299 | defer.returnValue(test_result) | 302 | defer.returnValue(test_result) |
707 | 300 | 303 | ||
708 | 304 | @skip_if_darwin_missing_fs_event | ||
709 | 301 | @defer.inlineCallbacks | 305 | @defer.inlineCallbacks |
710 | 302 | def test_file_create_close_write(self): | 306 | def test_file_create_close_write(self): |
711 | 303 | """Test receiving the create and close_write signals on files.""" | 307 | """Test receiving the create and close_write signals on files.""" |
712 | @@ -423,6 +427,7 @@ | |||
713 | 423 | test_result = yield self._deferred | 427 | test_result = yield self._deferred |
714 | 424 | defer.returnValue(test_result) | 428 | defer.returnValue(test_result) |
715 | 425 | 429 | ||
716 | 430 | @skip_if_darwin_missing_fs_event | ||
717 | 426 | @defer.inlineCallbacks | 431 | @defer.inlineCallbacks |
718 | 427 | def test_file_moved_from_partial(self): | 432 | def test_file_moved_from_partial(self): |
719 | 428 | """Test the handling of the FILE_MOVE event when source is partial.""" | 433 | """Test the handling of the FILE_MOVE event when source is partial.""" |
720 | 429 | 434 | ||
721 | === modified file 'tests/platform/filesystem_notifications/test_windows.py' | |||
722 | --- tests/platform/filesystem_notifications/test_windows.py 2012-07-10 20:24:04 +0000 | |||
723 | +++ tests/platform/filesystem_notifications/test_windows.py 2012-07-12 13:53:19 +0000 | |||
724 | @@ -1321,7 +1321,7 @@ | |||
725 | 1321 | for file_name in present_files: | 1321 | for file_name in present_files: |
726 | 1322 | self.general.paths_to_return.append((file_name, False)) | 1322 | self.general.paths_to_return.append((file_name, False)) |
727 | 1323 | self.processor.handle_dir_delete(path) | 1323 | self.processor.handle_dir_delete(path) |
729 | 1324 | # there are calls for, rm the wathc, get paths and then one per file | 1324 | # there are calls for, rm the watch, get paths and then one per file |
730 | 1325 | self.assertEqual(len(present_files) + 2, | 1325 | self.assertEqual(len(present_files) + 2, |
731 | 1326 | len(self.general.called_methods)) | 1326 | len(self.general.called_methods)) |
732 | 1327 | rm_call = self.general.called_methods.pop(0) | 1327 | rm_call = self.general.called_methods.pop(0) |
733 | @@ -1347,7 +1347,7 @@ | |||
734 | 1347 | for file_name in present_files: | 1347 | for file_name in present_files: |
735 | 1348 | self.general.paths_to_return.append((file_name, True)) | 1348 | self.general.paths_to_return.append((file_name, True)) |
736 | 1349 | self.processor.handle_dir_delete(path) | 1349 | self.processor.handle_dir_delete(path) |
738 | 1350 | # there are calls for, rm the wathc, get paths and then one per file | 1350 | # there are calls for, rm the watch, get paths and then one per file |
739 | 1351 | self.assertEqual(2 * len(present_files) + 2, | 1351 | self.assertEqual(2 * len(present_files) + 2, |
740 | 1352 | len(self.general.called_methods)) | 1352 | len(self.general.called_methods)) |
741 | 1353 | rm_call = self.general.called_methods.pop(0) | 1353 | rm_call = self.general.called_methods.pop(0) |
742 | 1354 | 1354 | ||
743 | === modified file 'ubuntuone/platform/filesystem_notifications/darwin.py' | |||
744 | --- ubuntuone/platform/filesystem_notifications/darwin.py 2012-07-11 09:48:03 +0000 | |||
745 | +++ ubuntuone/platform/filesystem_notifications/darwin.py 2012-07-12 13:53:19 +0000 | |||
746 | @@ -61,7 +61,7 @@ | |||
747 | 61 | } | 61 | } |
748 | 62 | 62 | ||
749 | 63 | 63 | ||
751 | 64 | def path_is_ignored(self, path): | 64 | def path_is_ignored(path): |
752 | 65 | """Should we ignore this path in the current platform.?""" | 65 | """Should we ignore this path in the current platform.?""" |
753 | 66 | # don't support links yet | 66 | # don't support links yet |
754 | 67 | if os.path.islink(path): | 67 | if os.path.islink(path): |
755 | @@ -135,10 +135,6 @@ | |||
756 | 135 | self.observer = fsevents.Observer() | 135 | self.observer = fsevents.Observer() |
757 | 136 | self.observer.start() | 136 | self.observer.start() |
758 | 137 | 137 | ||
759 | 138 | def __del__(self): | ||
760 | 139 | """Stop the observer.""" | ||
761 | 140 | self.observer.stop() | ||
762 | 141 | |||
763 | 142 | def stop_watch(self, watch): | 138 | def stop_watch(self, watch): |
764 | 143 | """Stop a given watch.""" | 139 | """Stop a given watch.""" |
765 | 144 | watch.stop_watching() | 140 | watch.stop_watching() |
766 | @@ -148,10 +144,11 @@ | |||
767 | 148 | def stop(self): | 144 | def stop(self): |
768 | 149 | """Stop the manager.""" | 145 | """Stop the manager.""" |
769 | 150 | self.observer.stop() | 146 | self.observer.stop() |
770 | 147 | self.observer.join() | ||
771 | 151 | 148 | ||
772 | 152 | def del_watch(self, watch): | 149 | def del_watch(self, watch): |
773 | 153 | """Delete the watch and clean resources.""" | 150 | """Delete the watch and clean resources.""" |
775 | 154 | self.observer.unschedule(watch.stream) | 151 | self.observer.unschedule(watch.platform_watch.stream) |
776 | 155 | 152 | ||
777 | 156 | def add_watch(self, watch): | 153 | def add_watch(self, watch): |
778 | 157 | """This method perform actually the action of registering the watch.""" | 154 | """This method perform actually the action of registering the watch.""" |
779 | @@ -160,4 +157,3 @@ | |||
780 | 160 | 157 | ||
781 | 161 | def rm_watch(self, watch): | 158 | def rm_watch(self, watch): |
782 | 162 | """Remove the the watch with the given wd.""" | 159 | """Remove the the watch with the given wd.""" |
783 | 163 | self.observer.unschedule(watch.platform_watch.stream) |
The branch looks mostly fine.
A few questions, though:
* Why is test_file_ moved_from_ partial skipped? I think this is a critical operation that should be tested.
* Why is there a test that still uses time.sleep? As mentioned in previous branches we should not be using sleep at all in tests.
And some fixes needed, too:
It looks wrong to import fsevents in /platform/ filesystem_ notifications/ __init_ _.py, so please, move each platform specific definition of EVENT_CODES to ubuntuone. platform. filesystem_ notifications. windows and .darwin
---
Lines 827 and 828 are duplicated.
---
Please move the logic in these few lines to a function, add some unit tests for it, and use it from both places:
837 + index = 0 endswith( os.path. sep): self._path) + index:]
838 + if not self._path.
839 + index = 1
840 + path = path[len(