Merge lp:~mandel/ubuntuone-client/fix-fsm into lp:ubuntuone-client

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
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.
lp:~mandel/ubuntuone-client/fix-fsm updated
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 :
Download full text (6.4 KiB)

===============================================================================
[ERROR]
Traceback (most recent call last):
Failure: twisted.internet.defer.TimeoutError: <tests.platform.test_filesystem_notifications.MutedSignalsTests testMethod=test_dir_create> (test_dir_create) still running at 2.0 secs

tests.platform.test_filesystem_notifications.MutedSignalsTests.test_dir_create
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 793, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "E:\u1\client\review_fix-fsm\tests\platform\test_filesystem_notifications.py", line 205, in check_filter
    self.assertFalse(self.monitor._processor.mute_filter._cnt)
twisted.trial.unittest.FailTest: None

tests.platform.test_filesystem_notifications.MutedSignalsTests.test_dir_create
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_dir_delete
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_dir_moved_inside
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_create_close_write
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_delete
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_moved_from_conflict
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_moved_from_partial
tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_moved_inside
===============================================================================
[ERROR]
Traceback (most recent call last):
Failure: twisted.internet.defer.TimeoutError: <tests.platform.test_filesystem_notifications.MutedSignalsTests testMethod=test_dir_delete> (test_dir_delete) still running at 2.0 secs

tests.platform.test_filesystem_notifications.MutedSignalsTests.test_dir_delete
===============================================================================
[ERROR]
Traceback (most recent call last):
Failure: twisted.internet.defer.TimeoutError: <tests.platform.test_filesystem_notifications.MutedSignalsTests testMethod=test_dir_moved_inside> (test_dir_moved_inside) still running at 2.0 secs

tests.platform.test_filesystem_notifications.MutedSignalsTests.test_dir_moved_inside
===============================================================================
[ERROR]
Traceback (most recent call last):
Failure: twisted.internet.defer.TimeoutError: <tests.platform.test_filesystem_notifications.MutedSignalsTests testMethod=test_file_create_close_write> (test_file_create_close_write) still running at 2.0 secs

tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_create_close_write
===============================================================================
[ERROR]
Traceback (most recent call last):
Failure: twisted.internet.defer.TimeoutError: <tests.platform.test_filesystem_notifications.MutedSignalsTests testMethod=test_file_delete> (test_file_delete) still running at 2.0 secs

tests.platform.test_filesystem_notifications.MutedSignalsTests.test_file_delete
=============================================================...

Read more...

review: Needs Fixing
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Failing tests will be solved in a incoming branch.

review: Approve
lp:~mandel/ubuntuone-client/fix-fsm updated
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

Subscribers

People subscribed via source and target branches