Merge lp:~mandel/ubuntuone-client/fix-fsm into lp:ubuntuone-client
- fix-fsm
- Merge into trunk
Proposed by
Manuel de la Peña
Status: | Merged |
---|---|
Approved by: | Alejandro J. Cura |
Approved revision: | 1116 |
Merged at revision: | 1079 |
Proposed branch: | lp:~mandel/ubuntuone-client/fix-fsm |
Merge into: | lp:ubuntuone-client |
Prerequisite: | lp:~mandel/ubuntuone-client/fix-rm-path |
Diff against target: |
640 lines (+481/-51) 2 files modified
tests/platform/windows/test_filesystem_notifications.py (+436/-1) ubuntuone/platform/windows/filesystem_notifications.py (+45/-50) |
To merge this branch: | bzr merge lp:~mandel/ubuntuone-client/fix-fsm |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Approve | ||
Natalia Bidart (community) | Approve | ||
Review via email: mp+69814@code.launchpad.net |
Commit message
Improve the test coverage for fsm on windows.
Description of the change
Improve the test coverage for fsm on windows.
To post a comment you must log in.
- 1114. By Manuel de la Peña
-
Merged with trunk.
- 1115. By Manuel de la Peña
-
Fixed according to the comments from the reviews.
Revision history for this message
Natalia Bidart (nataliabidart) wrote : | # |
Failing tests will be solved in a incoming branch.
review:
Approve
- 1116. By Manuel de la Peña
-
Merged with trunk and ensured that the criss-cross does not brake a thing.
Revision history for this message
Alejandro J. Cura (alecu) wrote : | # |
Launchpad above complains about conflicts, and bzr complains about criss-cross.
I've just verified with bzr merge and bzr merge --weave, and the results are the same, so the base branch may be off, but the resulting merge is fine.
So I'm approving. Great branch!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'tests/platform/windows/test_filesystem_notifications.py' |
2 | --- tests/platform/windows/test_filesystem_notifications.py 2011-07-29 13:32:31 +0000 |
3 | +++ tests/platform/windows/test_filesystem_notifications.py 2011-07-29 17:34:51 +0000 |
4 | @@ -21,13 +21,19 @@ |
5 | import tempfile |
6 | import thread |
7 | import time |
8 | +import itertools |
9 | |
10 | from twisted.internet import defer |
11 | |
12 | from contrib.testing.testcase import BaseTwistedTestCase |
13 | from ubuntuone.platform.windows import os_helper |
14 | -from ubuntuone.platform.windows.pyinotify import ProcessEvent |
15 | +from ubuntuone.platform.windows.pyinotify import ( |
16 | + ProcessEvent, |
17 | + IN_OPEN, |
18 | + IN_CLOSE_WRITE |
19 | +) |
20 | from ubuntuone.platform.windows.filesystem_notifications import ( |
21 | + NotifyProcessor, |
22 | Watch, |
23 | WatchManager, |
24 | FILE_NOTIFY_CHANGE_FILE_NAME, |
25 | @@ -699,3 +705,432 @@ |
26 | # assert that other events are not ignored |
27 | self.watch._process_events([(1, 'test')]) |
28 | self.assertEqual(1, len(events)) |
29 | + |
30 | + |
31 | +class FakeEvent(object): |
32 | + """Fake event.""" |
33 | + |
34 | + def __init__(self, wd=0, dir=True, name=None, path=None, pathname=None, |
35 | + cookie=None): |
36 | + """Create fake event.""" |
37 | + self.dir = dir |
38 | + self.wd = wd |
39 | + self.name = name |
40 | + self.path = path |
41 | + self.pathname = pathname |
42 | + self.cookie = cookie |
43 | + |
44 | + |
45 | +class FakeLog(object): |
46 | + """A fake log that is used by the general processor.""" |
47 | + |
48 | + def __init__(self): |
49 | + """Create the fake.""" |
50 | + self.called_methods = [] |
51 | + |
52 | + def info(self, *args): |
53 | + """Fake the info call.""" |
54 | + self.called_methods.append(('info', args)) |
55 | + |
56 | + |
57 | +class FakeGeneralProcessor(object): |
58 | + """Fake implementation of the general processor.""" |
59 | + |
60 | + def __init__(self): |
61 | + """Create the fake.""" |
62 | + self.called_methods = [] |
63 | + self.paths_to_return = [] |
64 | + self.log = FakeLog() |
65 | + self.share_id = None |
66 | + self.ignore = False |
67 | + |
68 | + def rm_from_mute_filter(self, event, paths): |
69 | + """Fake rm_from_mute_filter.""" |
70 | + self.called_methods.append(('rm_from_mute_filter', event, paths)) |
71 | + |
72 | + def add_to_mute_filter(self, event, paths): |
73 | + """Fake add_to_move_filter.""" |
74 | + self.called_methods.append(('add_to_mute_filter', event, paths)) |
75 | + |
76 | + def is_ignored(self, path): |
77 | + """Fake is_ignored.""" |
78 | + self.called_methods.append(('is_ignored', path)) |
79 | + return self.ignore |
80 | + |
81 | + def push_event(self, event): |
82 | + """Fake push event.""" |
83 | + self.called_methods.append(('push_event', event)) |
84 | + |
85 | + def eq_push(self, event, path=None, path_to=None, path_from=None): |
86 | + """Fake event to push event.""" |
87 | + self.called_methods.append(('eq_push', event, path, path_to, |
88 | + path_from)) |
89 | + |
90 | + def get_paths_starting_with(self, fullpath, include_base=False): |
91 | + """Fake get_paths_starting_with.""" |
92 | + self.called_methods.append(('get_paths_starting_with', fullpath, |
93 | + include_base)) |
94 | + return self.paths_to_return |
95 | + |
96 | + def get_path_share_id(self, path): |
97 | + """Fake get_path_share_id.""" |
98 | + self.called_methods.append(('get_path_share_id', path)) |
99 | + return self.share_id |
100 | + |
101 | + def rm_watch(self, path): |
102 | + """Fake the remove watch.""" |
103 | + self.called_methods.append(('rm_watch', path)) |
104 | + |
105 | + def freeze_begin(self, path): |
106 | + """Fake freeze_begin""" |
107 | + self.called_methods.append(('freeze_begin', path)) |
108 | + |
109 | + def freeze_rollback(self): |
110 | + """Fake rollback.""" |
111 | + self.called_methods.append(('freeze_rollback',)) |
112 | + |
113 | + def freeze_commit(self, path): |
114 | + """Fake freeze commit.""" |
115 | + self.called_methods.append(('freeze_commit', path)) |
116 | + |
117 | + |
118 | +class TestNotifyProcessor(BaseTwistedTestCase): |
119 | + """Test the notify processor.""" |
120 | + |
121 | + def setUp(self): |
122 | + """set up the diffeent tests.""" |
123 | + super(TestNotifyProcessor, self).setUp() |
124 | + self.processor = NotifyProcessor(None) |
125 | + self.general = FakeGeneralProcessor() |
126 | + self.processor.general_processor = self.general |
127 | + |
128 | + def test_rm_from_mute_filter(self): |
129 | + """Test that we remove the event from the mute filter.""" |
130 | + event = 'event' |
131 | + paths = 'paths' |
132 | + self.processor.rm_from_mute_filter(event, paths) |
133 | + self.assertEqual(1, len(self.general.called_methods)) |
134 | + self.assertEqual('rm_from_mute_filter', |
135 | + self.general.called_methods[0][0]) |
136 | + self.assertEqual(event, self.general.called_methods[0][1]) |
137 | + self.assertEqual(paths, self.general.called_methods[0][2]) |
138 | + |
139 | + def test_add_to_mute_filter(self): |
140 | + """Test that we add the path to the mute filter.""" |
141 | + event = 'event' |
142 | + paths = 'paths' |
143 | + self.processor.add_to_mute_filter(event, paths) |
144 | + self.assertEqual(1, len(self.general.called_methods)) |
145 | + self.assertEqual('add_to_mute_filter', |
146 | + self.general.called_methods[0][0]) |
147 | + self.assertEqual(event, self.general.called_methods[0][1]) |
148 | + self.assertEqual(paths, self.general.called_methods[0][2]) |
149 | + |
150 | + def test_platform_is_ignored(self): |
151 | + """Test that we do indeed ignore the correct paths.""" |
152 | + not_ignored = 'test' |
153 | + ignored = not_ignored + '.lnk' |
154 | + self.assertFalse(self.processor.platform_is_ignored(not_ignored), |
155 | + 'Only links should be ignored.') |
156 | + self.assertTrue(self.processor.platform_is_ignored(ignored), |
157 | + 'Links should be ignored.') |
158 | + |
159 | + def test_is_ignored(self): |
160 | + """Test that we do ensure that the path is ignored.""" |
161 | + path = 'path' |
162 | + self.processor.is_ignored(path) |
163 | + self.assertEqual(1, len(self.general.called_methods)) |
164 | + self.assertEqual('is_ignored', |
165 | + self.general.called_methods[0][0]) |
166 | + self.assertEqual(path, self.general.called_methods[0][1]) |
167 | + |
168 | + def test_release_held_event(self): |
169 | + """Test that we do release the held event.""" |
170 | + event = 'event' |
171 | + # set the held event to assert that is pushed |
172 | + self.processor.held_event = event |
173 | + self.processor.release_held_event() |
174 | + self.assertEqual('push_event', |
175 | + self.general.called_methods[0][0]) |
176 | + self.assertEqual(event, self.general.called_methods[0][1]) |
177 | + |
178 | + def test_process_IN_MODIFY_dir(self): |
179 | + """Test that the modify works as exepcted with dirs.""" |
180 | + event = FakeEvent(dir=True) |
181 | + self.processor.process_IN_MODIFY(event) |
182 | + # no method should be called |
183 | + self.assertEqual(0, len(self.general.called_methods)) |
184 | + |
185 | + def test_process_IN_MODIFY_file(self): |
186 | + """Test that the modify works as expected with files.""" |
187 | + event = FakeEvent(dir=False, wd=0, name='name', |
188 | + path='path', pathname='pathname') |
189 | + self.processor.process_IN_MODIFY(event) |
190 | + # we should be getting two different method, and open and a close |
191 | + self.assertEqual(2, len(self.general.called_methods)) |
192 | + self.assertEqual('push_event', |
193 | + self.general.called_methods[0][0]) |
194 | + self.assertEqual('push_event', |
195 | + self.general.called_methods[1][0]) |
196 | + self.assertEqual(event.dir, self.general.called_methods[0][1].dir) |
197 | + self.assertEqual(event.wd, self.general.called_methods[0][1].wd) |
198 | + self.assertEqual(event.name, self.general.called_methods[0][1].name) |
199 | + self.assertEqual(event.path, self.general.called_methods[0][1].path) |
200 | + self.assertEqual(event.pathname, |
201 | + self.general.called_methods[0][1].pathname) |
202 | + self.assertEqual(IN_OPEN, |
203 | + self.general.called_methods[0][1].mask) |
204 | + self.assertEqual(event.dir, self.general.called_methods[1][1].dir) |
205 | + self.assertEqual(event.wd, self.general.called_methods[1][1].wd) |
206 | + self.assertEqual(event.name, self.general.called_methods[1][1].name) |
207 | + self.assertEqual(event.path, self.general.called_methods[1][1].path) |
208 | + self.assertEqual(event.pathname, |
209 | + self.general.called_methods[1][1].pathname) |
210 | + self.assertEqual(IN_CLOSE_WRITE, |
211 | + self.general.called_methods[1][1].mask) |
212 | + |
213 | + def test_process_IN_MOVED_FROM(self): |
214 | + """Test that the in moved from works as expected.""" |
215 | + event = FakeEvent(dir=False, wd=0, name='name', |
216 | + path='path', pathname='pathname') |
217 | + self.processor.process_IN_MOVED_FROM(event) |
218 | + self.assertEqual(event, self.processor.held_event) |
219 | + |
220 | + def test_process_IN_MOVED_TO_dir(self): |
221 | + """Test that the in moved to works as expected.""" |
222 | + event = FakeEvent(wd=0, dir=True, name='name', path='path', |
223 | + pathname=os.path.join('test', 'pathname'), |
224 | + cookie='cookie') |
225 | + held_event = FakeEvent(wd=0, dir=True, name='hname', path='hpath', |
226 | + pathname=os.path.join('test', 'hpathname'), |
227 | + cookie='cookie') |
228 | + self.general.share_id = 'my_share_id' |
229 | + self.processor.held_event = held_event |
230 | + self.processor.process_IN_MOVED_TO(event) |
231 | + self.assertEqual(5, len(self.general.called_methods)) |
232 | + # assert that the ignores are called |
233 | + self.assertEqual('is_ignored', self.general.called_methods[0][0]) |
234 | + self.assertEqual(held_event.pathname, self.general.called_methods[0][1]) |
235 | + self.assertEqual('is_ignored', self.general.called_methods[1][0]) |
236 | + self.assertEqual(event.pathname, self.general.called_methods[1][1]) |
237 | + # assert that we do request the share_id |
238 | + self.assertEqual('get_path_share_id', self.general.called_methods[2][0]) |
239 | + self.assertEqual(os.path.split(event.pathname)[0], |
240 | + self.general.called_methods[2][1], |
241 | + 'Get the share_id for event') |
242 | + self.assertEqual('get_path_share_id', self.general.called_methods[3][0]) |
243 | + self.assertEqual(os.path.split(held_event.pathname)[0], |
244 | + self.general.called_methods[3][1], |
245 | + 'Get the share_id for held event.') |
246 | + |
247 | + self.assertEqual('eq_push', self.general.called_methods[4][0]) |
248 | + self.assertEqual('FS_DIR_MOVE', self.general.called_methods[4][1]) |
249 | + self.assertEqual(event.pathname, self.general.called_methods[4][3]) |
250 | + self.assertEqual(held_event.pathname, self.general.called_methods[4][4]) |
251 | + |
252 | + def test_process_IN_MOVED_TO_file(self): |
253 | + """Test that the in moved to works as expected.""" |
254 | + event = FakeEvent(wd=0, dir=False, name='name', path='path', |
255 | + pathname=os.path.join('test', 'pathname'), |
256 | + cookie='cookie') |
257 | + held_event = FakeEvent(wd=0, dir=False, name='hname', path='hpath', |
258 | + pathname=os.path.join('test', 'hpathname'), |
259 | + cookie='cookie') |
260 | + self.general.share_id = 'my_share_id' |
261 | + self.processor.held_event = held_event |
262 | + self.processor.process_IN_MOVED_TO(event) |
263 | + self.assertEqual(5, len(self.general.called_methods)) |
264 | + # assert that the ignores are called |
265 | + self.assertEqual('is_ignored', self.general.called_methods[0][0]) |
266 | + self.assertEqual(held_event.pathname, self.general.called_methods[0][1]) |
267 | + self.assertEqual('is_ignored', self.general.called_methods[1][0]) |
268 | + self.assertEqual(event.pathname, self.general.called_methods[1][1]) |
269 | + # assert that we do request the share_id |
270 | + self.assertEqual('get_path_share_id', self.general.called_methods[2][0]) |
271 | + self.assertEqual(os.path.split(event.pathname)[0], |
272 | + self.general.called_methods[2][1], |
273 | + 'Get the share_id for event') |
274 | + self.assertEqual('get_path_share_id', self.general.called_methods[3][0]) |
275 | + self.assertEqual(os.path.split(held_event.pathname)[0], |
276 | + self.general.called_methods[3][1], |
277 | + 'Get the share_id for held event.') |
278 | + |
279 | + self.assertEqual('eq_push', self.general.called_methods[4][0]) |
280 | + self.assertEqual('FS_FILE_MOVE', self.general.called_methods[4][1]) |
281 | + self.assertEqual(event.pathname, self.general.called_methods[4][3]) |
282 | + self.assertEqual(held_event.pathname, self.general.called_methods[4][4]) |
283 | + |
284 | + def test_fake_create_event_dir(self): |
285 | + """Test that the in moved to works as expected.""" |
286 | + event = FakeEvent(wd=0, dir=True, name='name', path='path', |
287 | + pathname='pathname') |
288 | + self.processor._fake_create_event(event) |
289 | + self.assertEqual(1, len(self.general.called_methods)) |
290 | + self.assertEqual('eq_push', self.general.called_methods[0][0]) |
291 | + self.assertEqual('FS_DIR_CREATE', self.general.called_methods[0][1]) |
292 | + self.assertEqual(event.pathname, self.general.called_methods[0][2]) |
293 | + |
294 | + def test_fake_create_event_file(self): |
295 | + """Test that the in moved to works as expected.""" |
296 | + event = FakeEvent(wd=0, dir=False, name='name', path='path', |
297 | + pathname='pathname') |
298 | + self.processor._fake_create_event(event) |
299 | + self.assertEqual(2, len(self.general.called_methods)) |
300 | + self.assertEqual('eq_push', self.general.called_methods[0][0]) |
301 | + self.assertEqual('FS_FILE_CREATE', self.general.called_methods[0][1]) |
302 | + self.assertEqual(event.pathname, self.general.called_methods[0][2]) |
303 | + self.assertEqual('eq_push', self.general.called_methods[1][0]) |
304 | + self.assertEqual('FS_FILE_CLOSE_WRITE', |
305 | + self.general.called_methods[1][1]) |
306 | + self.assertEqual(event.pathname, self.general.called_methods[1][2]) |
307 | + |
308 | + def test_fake_delete_create_event_dir(self): |
309 | + """Test that we do fake a delete and a later delete.""" |
310 | + event = FakeEvent(wd=0, dir=True, name='name', path='path', |
311 | + pathname='pathname') |
312 | + held_event = FakeEvent(wd=0, dir=True, name='hname', path='hpath', |
313 | + pathname='hpathname') |
314 | + self.processor.held_event = held_event |
315 | + self.processor._fake_delete_create_event(event) |
316 | + self.assertEqual(2, len(self.general.called_methods)) |
317 | + self.assertEqual('eq_push', self.general.called_methods[0][0]) |
318 | + self.assertEqual('FS_DIR_DELETE', self.general.called_methods[0][1]) |
319 | + self.assertEqual(held_event.pathname, self.general.called_methods[0][2]) |
320 | + self.assertEqual('eq_push', self.general.called_methods[1][0]) |
321 | + self.assertEqual('FS_DIR_CREATE', self.general.called_methods[1][1]) |
322 | + self.assertEqual(event.pathname, self.general.called_methods[1][2]) |
323 | + |
324 | + def test_fake_delete_create_event_file(self): |
325 | + """Test that we do fake a delete and a later delete.""" |
326 | + event = FakeEvent(wd=0, dir=False, name='name', path='path', |
327 | + pathname='pathname') |
328 | + held_event = FakeEvent(wd=0, dir=False, name='hname', path='hpath', |
329 | + pathname='hpathname') |
330 | + self.processor.held_event = held_event |
331 | + self.processor._fake_delete_create_event(event) |
332 | + self.assertEqual(3, len(self.general.called_methods)) |
333 | + self.assertEqual('eq_push', self.general.called_methods[0][0]) |
334 | + self.assertEqual('FS_FILE_DELETE', self.general.called_methods[0][1]) |
335 | + self.assertEqual(held_event.pathname, self.general.called_methods[0][2]) |
336 | + self.assertEqual('eq_push', self.general.called_methods[1][0]) |
337 | + self.assertEqual('FS_FILE_CREATE', self.general.called_methods[1][1]) |
338 | + self.assertEqual(event.pathname, self.general.called_methods[1][2]) |
339 | + self.assertEqual('eq_push', self.general.called_methods[2][0]) |
340 | + self.assertEqual('FS_FILE_CLOSE_WRITE', |
341 | + self.general.called_methods[2][1]) |
342 | + self.assertEqual(event.pathname, self.general.called_methods[2][2]) |
343 | + |
344 | + def test_process_default_no_held(self): |
345 | + """Test that the process default works as expected.""" |
346 | + event = 'event' |
347 | + self.processor.process_default(event) |
348 | + self.assertEqual(1, len(self.general.called_methods)) |
349 | + self.assertEqual('push_event', |
350 | + self.general.called_methods[0][0]) |
351 | + self.assertEqual(event, |
352 | + self.general.called_methods[0][1]) |
353 | + |
354 | + def test_process_default_with_held(self): |
355 | + """Test that the process default works as expected.""" |
356 | + event = 'event' |
357 | + held_event = 'held_event' |
358 | + self.processor.held_event = held_event |
359 | + self.processor.process_default(event) |
360 | + self.assertEqual(2, len(self.general.called_methods)) |
361 | + self.assertEqual('push_event', |
362 | + self.general.called_methods[0][0]) |
363 | + self.assertEqual(held_event, |
364 | + self.general.called_methods[0][1]) |
365 | + self.assertEqual('push_event', |
366 | + self.general.called_methods[1][0]) |
367 | + self.assertEqual(event, |
368 | + self.general.called_methods[1][1]) |
369 | + |
370 | + def test_handle_dir_delete_files(self): |
371 | + """Test that the handle dir delete works as expected.""" |
372 | + path = 'path' |
373 | + present_files = 'abcde' |
374 | + # create files and dirs to be returned from the get paths |
375 | + for file_name in present_files: |
376 | + self.general.paths_to_return.append((file_name, False)) |
377 | + self.processor.handle_dir_delete(path) |
378 | + # there are calls for, rm the wathc, get paths and then one per file |
379 | + self.assertEqual(len(present_files) + 2, |
380 | + len(self.general.called_methods)) |
381 | + rm_call = self.general.called_methods.pop(0) |
382 | + self.assertEqual('rm_watch', rm_call[0]) |
383 | + self.assertEqual(path, rm_call[1]) |
384 | + paths_call = self.general.called_methods.pop(0) |
385 | + self.assertEqual('get_paths_starting_with', paths_call[0]) |
386 | + self.assertEqual(path, paths_call[1]) |
387 | + self.assertFalse(paths_call[2]) |
388 | + # we need to push the delete events in reverse order because we want |
389 | + # to delete children before we delete parents |
390 | + present_files = present_files[::-1] |
391 | + for i, called_method in enumerate(self.general.called_methods): |
392 | + self.assertEqual('eq_push', called_method[0]) |
393 | + self.assertEqual('FS_FILE_DELETE', called_method[1]) |
394 | + self.assertEqual(present_files[i], called_method[2]) |
395 | + |
396 | + def test_handle_dir_delete_dirs(self): |
397 | + """Test that the handle dir delete works as expected.""" |
398 | + path = 'path' |
399 | + present_files = 'abcde' |
400 | + # create files and dirs to be returned from the get paths |
401 | + for file_name in present_files: |
402 | + self.general.paths_to_return.append((file_name, True)) |
403 | + self.processor.handle_dir_delete(path) |
404 | + # there are calls for, rm the wathc, get paths and then one per file |
405 | + self.assertEqual(2 * len(present_files) + 2, |
406 | + len(self.general.called_methods)) |
407 | + rm_call = self.general.called_methods.pop(0) |
408 | + self.assertEqual('rm_watch', rm_call[0]) |
409 | + self.assertEqual(path, rm_call[1]) |
410 | + paths_call = self.general.called_methods.pop(0) |
411 | + self.assertEqual('get_paths_starting_with', paths_call[0]) |
412 | + self.assertEqual(path, paths_call[1]) |
413 | + self.assertFalse(paths_call[2]) |
414 | + # we need to push the delete events in reverse order because we want |
415 | + # to delete children before we delete parents |
416 | + present_files = present_files[::-1] |
417 | + |
418 | + # from http://docs.python.org/library/itertools.html#recipes |
419 | + def grouper(n, iterable, fillvalue=None): |
420 | + "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" |
421 | + args = [iter(iterable)] * n |
422 | + return itertools.izip_longest(fillvalue=fillvalue, *args) |
423 | + |
424 | + for i, called_methods in enumerate(grouper(2, |
425 | + self.general.called_methods)): |
426 | + rm_call = called_methods[0] |
427 | + self.assertEqual('rm_watch', rm_call[0]) |
428 | + self.assertEqual(present_files[i], rm_call[1]) |
429 | + push_call = called_methods[1] |
430 | + self.assertEqual('eq_push', push_call[0]) |
431 | + self.assertEqual('FS_DIR_DELETE', push_call[1]) |
432 | + self.assertEqual(present_files[i], push_call[2]) |
433 | + |
434 | + def test_freeze_begin(self): |
435 | + """Test that the freeze being works as expected.""" |
436 | + path = 'path' |
437 | + self.processor.freeze_begin(path) |
438 | + self.assertEqual(1, len(self.general.called_methods)) |
439 | + self.assertEqual('freeze_begin', |
440 | + self.general.called_methods[0][0]) |
441 | + self.assertEqual(path, self.general.called_methods[0][1]) |
442 | + |
443 | + def test_freeze_rollback(self): |
444 | + """Test that the freeze rollback works as expected.""" |
445 | + self.processor.freeze_rollback() |
446 | + self.assertEqual(1, len(self.general.called_methods)) |
447 | + self.assertEqual('freeze_rollback', |
448 | + self.general.called_methods[0][0]) |
449 | + |
450 | + def test_freeze_commit(self): |
451 | + """Test that the freeze commit works as expected.""" |
452 | + path = 'path' |
453 | + self.processor.freeze_commit(path) |
454 | + self.assertEqual(1, len(self.general.called_methods)) |
455 | + self.assertEqual('freeze_commit', |
456 | + self.general.called_methods[0][0]) |
457 | + self.assertEqual(path, self.general.called_methods[0][1]) |
458 | |
459 | === modified file 'ubuntuone/platform/windows/filesystem_notifications.py' |
460 | --- ubuntuone/platform/windows/filesystem_notifications.py 2011-07-29 13:32:31 +0000 |
461 | +++ ubuntuone/platform/windows/filesystem_notifications.py 2011-07-29 17:34:51 +0000 |
462 | @@ -152,11 +152,6 @@ |
463 | # a directory from a thread |
464 | self._watch_started_deferred = defer.Deferred() |
465 | |
466 | - def _is_excluded(self, event): |
467 | - """Return if an event is ignored.""" |
468 | - return event.mask == IN_OPEN | IN_ISDIR |
469 | - |
470 | - # XXX: confirm is using this decorator is correct!!! (nessita) |
471 | @is_valid_windows_path(path_indexes=[1]) |
472 | def _path_is_dir(self, path): |
473 | """Check if the path is a dir and update the local subdir list.""" |
474 | @@ -223,9 +218,7 @@ |
475 | # the exclude filter returns False, that is, the event will not |
476 | # be excluded |
477 | self.log.debug('Event is %s.', event) |
478 | - if not self._is_excluded(event): |
479 | - self.log.debug('Processing event %r', event) |
480 | - self._processor(event) |
481 | + self._processor(event) |
482 | |
483 | def _watch(self): |
484 | """Watch a path that is a directory.""" |
485 | @@ -500,6 +493,9 @@ |
486 | |
487 | def process_IN_MODIFY(self, event): |
488 | """Capture a modify event and fake an open ^ close write events.""" |
489 | + # lets ignore dir changes |
490 | + if event.dir: |
491 | + return |
492 | # on windows we just get IN_MODIFY, lets always fake |
493 | # an OPEN & CLOSE_WRITE couple |
494 | raw_open = raw_close = { |
495 | @@ -508,20 +504,13 @@ |
496 | 'name': event.name, |
497 | 'path': event.path} |
498 | # caculate the open mask |
499 | - if event.dir: |
500 | - raw_open['mask'] = IN_OPEN | IN_ISDIR |
501 | - else: |
502 | - raw_open['mask'] = IN_OPEN |
503 | + raw_open['mask'] = IN_OPEN |
504 | # create the event using the raw data, then fix the pathname param |
505 | open_event = Event(raw_open) |
506 | open_event.pathname = event.pathname |
507 | # push the open |
508 | self.general_processor.push_event(open_event) |
509 | - # calculate the close mask |
510 | - if event.dir: |
511 | - raw_close['mask'] = IN_CLOSE_WRITE | IN_ISDIR |
512 | - else: |
513 | - raw_close['mask'] = IN_CLOSE_WRITE |
514 | + raw_close['mask'] = IN_CLOSE_WRITE |
515 | close_event = Event(raw_close) |
516 | close_event.pathname = event.pathname |
517 | # push the close event |
518 | @@ -534,6 +523,36 @@ |
519 | self.held_event) |
520 | self.held_event = event |
521 | |
522 | + def _fake_create_event(self, event): |
523 | + """Fake the creation of an event.""" |
524 | + # this is the case of a MOVE from an ignored path (links for example) |
525 | + # to a valid path |
526 | + if event.dir: |
527 | + evtname = "FS_DIR_" |
528 | + else: |
529 | + evtname = "FS_FILE_" |
530 | + self.general_processor.eq_push(evtname + "CREATE", path=event.pathname) |
531 | + if not event.dir: |
532 | + self.general_processor.eq_push('FS_FILE_CLOSE_WRITE', |
533 | + path=event.pathname) |
534 | + |
535 | + def _fake_delete_create_event(self, event): |
536 | + """Fake the deletion and the creation.""" |
537 | + # this is the case of a MOVE from a watch UDF to a diff UDF which |
538 | + # means that we have to copy the way linux works. |
539 | + if event.dir: |
540 | + evtname = "FS_DIR_" |
541 | + else: |
542 | + evtname = "FS_FILE_" |
543 | + m = "Delete because of different shares: %r" |
544 | + self.log.info(m, self.held_event.pathname) |
545 | + self.general_processor.eq_push(evtname + "DELETE", |
546 | + path=self.held_event.pathname) |
547 | + self.general_processor.eq_push(evtname + "CREATE", path=event.pathname) |
548 | + if not event.dir: |
549 | + self.general_processor.eq_push('FS_FILE_CLOSE_WRITE', |
550 | + path=event.pathname) |
551 | + |
552 | def process_IN_MOVED_TO(self, event): |
553 | """Capture the MOVED_TO to maybe syntethize FILE_MOVED.""" |
554 | if self.held_event is not None: |
555 | @@ -548,37 +567,21 @@ |
556 | f_path_dir) |
557 | t_share_id = self.general_processor.get_path_share_id( |
558 | t_path_dir) |
559 | - if event.dir: |
560 | - evtname = "FS_DIR_" |
561 | - else: |
562 | - evtname = "FS_FILE_" |
563 | if f_share_id != t_share_id: |
564 | # if the share_id are != push a delete/create |
565 | - m = "Delete because of different shares: %r" |
566 | - self.log.info(m, self.held_event.pathname) |
567 | - self.general_processor.eq_push( |
568 | - evtname + "DELETE", path=self.held_event.pathname) |
569 | - self.general_processor.eq_push( |
570 | - evtname + "CREATE", path=event.pathname) |
571 | - if not event.dir: |
572 | - self.general_processor.eq_push( |
573 | - 'FS_FILE_CLOSE_WRITE', path=event.pathname) |
574 | + self._fake_delete_create_event(event) |
575 | else: |
576 | + if event.dir: |
577 | + evtname = "FS_DIR_" |
578 | + else: |
579 | + evtname = "FS_FILE_" |
580 | self.general_processor.eq_push(evtname + "MOVE", |
581 | path_from=self.held_event.pathname, |
582 | path_to=event.pathname) |
583 | elif is_to_forreal: |
584 | # this is the case of a MOVE from something ignored |
585 | # to a valid filename |
586 | - if event.dir: |
587 | - evtname = "FS_DIR_" |
588 | - else: |
589 | - evtname = "FS_FILE_" |
590 | - self.general_processor.eq_push(evtname + "CREATE", |
591 | - path=event.pathname) |
592 | - if not event.dir: |
593 | - self.general_processor.eq_push('FS_FILE_CLOSE_WRITE', |
594 | - path=event.pathname) |
595 | + self._fake_create_event(event) |
596 | |
597 | self.held_event = None |
598 | return |
599 | @@ -601,7 +604,8 @@ |
600 | @is_valid_syncdaemon_path(path_indexes=[1]) |
601 | def handle_dir_delete(self, fullpath): |
602 | """Some special work when a directory is deleted.""" |
603 | - # remove the watch on that dir from our structures |
604 | + # remove the watch on that dir from our structures, this mainly tells |
605 | + # the monitor to remove the watch which is fowaded to a watch manager. |
606 | self.general_processor.rm_watch(fullpath) |
607 | |
608 | # handle the case of move a dir to a non-watched directory |
609 | @@ -613,6 +617,7 @@ |
610 | m = "Pushing deletion because of parent dir move: (is_dir=%s) %r" |
611 | self.general_processor.log.info(m, is_dir, path) |
612 | if is_dir: |
613 | + # same as the above remove |
614 | self.general_processor.rm_watch(path) |
615 | self.general_processor.eq_push('FS_DIR_DELETE', path=path) |
616 | else: |
617 | @@ -661,10 +666,6 @@ |
618 | self.log.setLevel(TRACE) |
619 | self.fs = fs |
620 | self.eq = eq |
621 | - # XXX: We need to find a decent time for the time out, is 0.2 seconds |
622 | - # too little? |
623 | - self.timeout = timeout |
624 | - # general inotify |
625 | self._processor = NotifyProcessor(self, ignore_config) |
626 | self._watch_manager = WatchManager(self._processor) |
627 | |
628 | @@ -697,12 +698,6 @@ |
629 | self._watch_manager.add_watch(dirpath, FILESYSTEM_MONITOR_MASK, |
630 | auto_add=True) |
631 | |
632 | - @windowspath(path_indexes=[1]) |
633 | - def has_watch(self, dirpath): |
634 | - """Check if a dirpath is watched.""" |
635 | - wd = self._watch_manager.get_wd(dirpath) |
636 | - return wd is not None |
637 | - |
638 | def is_frozen(self): |
639 | """Checks if there's something frozen.""" |
640 | return self._processor.frozen_path is not None |
======= ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == internet. defer.TimeoutEr ror: <tests. platform. test_filesystem _notifications. MutedSignalsTes ts testMethod= test_dir_ create> (test_dir_create) still running at 2.0 secs
[ERROR]
Traceback (most recent call last):
Failure: twisted.
tests.platform. test_filesystem _notifications. MutedSignalsTes ts.test_ dir_create ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == lib\site- packages\ twisted\ internet\ base.py" , line 793, in runUntilCurrent func(*call. args, **call.kw) client\ review_ fix-fsm\ tests\platform\ test_filesystem _notifications. py", line 205, in check_filter assertFalse( self.monitor. _processor. mute_filter. _cnt) trial.unittest. FailTest: None
=======
[ERROR]
Traceback (most recent call last):
File "C:\Python27\
call.
File "E:\u1\
self.
twisted.
tests.platform. test_filesystem _notifications. MutedSignalsTes ts.test_ dir_create test_filesystem _notifications. MutedSignalsTes ts.test_ dir_delete test_filesystem _notifications. MutedSignalsTes ts.test_ dir_moved_ inside test_filesystem _notifications. MutedSignalsTes ts.test_ file_create_ close_write test_filesystem _notifications. MutedSignalsTes ts.test_ file_delete test_filesystem _notifications. MutedSignalsTes ts.test_ file_moved_ from_conflict test_filesystem _notifications. MutedSignalsTes ts.test_ file_moved_ from_partial test_filesystem _notifications. MutedSignalsTes ts.test_ file_moved_ inside ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == internet. defer.TimeoutEr ror: <tests. platform. test_filesystem _notifications. MutedSignalsTes ts testMethod= test_dir_ delete> (test_dir_delete) still running at 2.0 secs
tests.platform.
tests.platform.
tests.platform.
tests.platform.
tests.platform.
tests.platform.
tests.platform.
=======
[ERROR]
Traceback (most recent call last):
Failure: twisted.
tests.platform. test_filesystem _notifications. MutedSignalsTes ts.test_ dir_delete ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == internet. defer.TimeoutEr ror: <tests. platform. test_filesystem _notifications. MutedSignalsTes ts testMethod= test_dir_ moved_inside> (test_dir_ moved_inside) still running at 2.0 secs
=======
[ERROR]
Traceback (most recent call last):
Failure: twisted.
tests.platform. test_filesystem _notifications. MutedSignalsTes ts.test_ dir_moved_ inside ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == internet. defer.TimeoutEr ror: <tests. platform. test_filesystem _notifications. MutedSignalsTes ts testMethod= test_file_ create_ close_write> (test_file_ create_ close_write) still running at 2.0 secs
=======
[ERROR]
Traceback (most recent call last):
Failure: twisted.
tests.platform. test_filesystem _notifications. MutedSignalsTes ts.test_ file_create_ close_write ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == internet. defer.TimeoutEr ror: <tests. platform. test_filesystem _notifications. MutedSignalsTes ts testMethod= test_file_ delete> (test_file_delete) still running at 2.0 secs
=======
[ERROR]
Traceback (most recent call last):
Failure: twisted.
tests.platform. test_filesystem _notifications. MutedSignalsTes ts.test_ file_delete ======= ======= ======= ======= ======= ======= ======= =====.. .
=======