Merge lp:~diegosarmentero/ubuntuone-client/darwin-tests-refactoring into lp:ubuntuone-client
- darwin-tests-refactoring
- Merge into trunk
| Status: | Merged |
|---|---|
| Approved by: | Alejandro J. Cura on 2012-08-07 |
| Approved revision: | 1289 |
| Merged at revision: | 1287 |
| Proposed branch: | lp:~diegosarmentero/ubuntuone-client/darwin-tests-refactoring |
| Merge into: | lp:ubuntuone-client |
| Prerequisite: | lp:~diegosarmentero/ubuntuone-client/darwin4-fsevents |
| Diff against target: |
2036 lines (+569/-694) 11 files modified
run-mac-tests (+1/-1) tests/platform/filesystem_notifications/common.py (+122/-303) tests/platform/filesystem_notifications/test_darwin.py (+84/-388) tests/platform/filesystem_notifications/test_windows.py (+344/-0) ubuntuone/platform/filesystem_notifications/monitor/__init__.py (+3/-0) ubuntuone/platform/filesystem_notifications/monitor/common.py (+1/-0) ubuntuone/platform/os_helper/__init__.py (+1/-0) ubuntuone/platform/os_helper/darwin.py (+5/-2) ubuntuone/platform/os_helper/linux.py (+1/-0) ubuntuone/platform/os_helper/unix.py (+5/-0) ubuntuone/platform/os_helper/windows.py (+2/-0) |
| To merge this branch: | bzr merge lp:~diegosarmentero/ubuntuone-client/darwin-tests-refactoring |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Alejandro J. Cura (community) | 2012-07-03 | Approve on 2012-08-02 | |
| Manuel de la Peña (community) | Approve on 2012-07-19 | ||
|
Review via email:
|
|||
Commit Message
- Refactoring test for filesystem notifications
Description of the Change
Put together the shared code between darwin and windows.
| Manuel de la Peña (mandel) wrote : | # |
Lint:
PYTHONPATH=
== Python Lint Notices ==
./ubuntuone/
37: 'IN_MODIFY' imported but unused
make: *** [lint] Error 1
| Manuel de la Peña (mandel) wrote : | # |
Why are there some tests that are raising a not implemented error? Should they either be implemented (the tests) or not be there or be skipped?
| Manuel de la Peña (mandel) wrote : | # |
Do we still need the mask in the common code?
79 + self.mask = None
I mean, we never test on windows different masks, maybe a good way to simplify and unify the tests is to simply remove its need, right?
I really don't like code doing thins like this:
54 +filesystem_
55 +NotifyProcessor = None
56 +Watch = None
57 +WatchManager = None
58 +get_os_valid_path = lambda x: x
59 +create_fake_event = None
60 +custom_
This is the same issue we had with the common.py implementation, can't we do the same? Having windows and darwin set those values smells a little.
| Manuel de la Peña (mandel) wrote : | # |
Minor things:
+for key, value in filesystem_
can we use items, is less efficient but will make the work to port it to python3 easier.
The following confuses me:
+from ubuntuone.platform import os_helper
+get_os_valid_path = os_helper.
Can't we do:
from ubuntuone.
Same comment for:
4 +NotifyProcessor = filesystem_
55 +Watch = filesystem_
56 +WatchManager = filesystem_
Can't we just import either common or wach of the objects form common?
Why was the timeout removed?
757 - timeout = 5
Ae we going to use the defaul twisted trial timeout, that is too long right?
Why is this back in common?
2306 + IN_MODIFY as in_modify,
2307 IN_MOVED_FROM,
2308 IN_MOVED_TO,
2309 )
2310 @@ -66,6 +67,12 @@
2311 else:
2312 raise ImportError('Not supported platform')
2313
2314 +
2315 +# This is done to avoid lint issues with pyflakes.
2316 +# And because all the other IN_* are being consumed from this module,
2317 +# it would be best if we do the same with IN_MODIFY.
2318 +IN_MODIFY = in_modify
I though we removed it and we not longer had issues with it.
| Diego Sarmentero (diegosarmentero) wrote : | # |
> Minor things:
>
> +for key, value in filesystem_
>
> can we use items, is less efficient but will make the work to port it to
> python3 easier.
>
> The following confuses me:
>
> +from ubuntuone.platform import os_helper
> +get_os_valid_path = os_helper.
>
> Can't we do:
>
> from ubuntuone.
>
> Same comment for:
>
> 4 +NotifyProcessor = filesystem_
> 55 +Watch = filesystem_
> 56 +WatchManager = filesystem_
>
> Can't we just import either common or wach of the objects form common?
>
> Why was the timeout removed?
>
> 757 - timeout = 5
>
> Ae we going to use the defaul twisted trial timeout, that is too long right?
Fixed!
>
> Why is this back in common?
>
> 2306 + IN_MODIFY as in_modify,
> 2307 IN_MOVED_FROM,
> 2308 IN_MOVED_TO,
> 2309 )
> 2310 @@ -66,6 +67,12 @@
> 2311 else:
> 2312 raise ImportError('Not supported platform')
> 2313
> 2314 +
> 2315 +# This is done to avoid lint issues with pyflakes.
> 2316 +# And because all the other IN_* are being consumed from this module,
> 2317 +# it would be best if we do the same with IN_MODIFY.
> 2318 +IN_MODIFY = in_modify
>
> I though we removed it and we not longer had issues with it.
That should be there, if we remove that we are going to have pyflakes issues.
| Alejandro J. Cura (alecu) wrote : | # |
After recent branches that landed on trunk this branch is giving merge errors.
| Alejandro J. Cura (alecu) wrote : | # |
Branch looks good now. Thanks a lot for working on this!
| Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~diegosarmentero/ubuntuone-client/darwin-tests-refactoring into lp:ubuntuone-client failed. Below is the output from the failed tests.
/usr/bin/
checking for autoconf >= 2.53...
testing autoconf2.50... not found.
testing autoconf... found 2.69
checking for automake >= 1.10...
testing automake-1.11... found 1.11.5
checking for libtool >= 1.5...
testing libtoolize... found 2.4.2
checking for intltool >= 0.30...
testing intltoolize... found 0.50.2
checking for pkg-config >= 0.14.0...
testing pkg-config... found 0.26
checking for gtk-doc >= 1.0...
testing gtkdocize... found 1.18
Checking for required M4 macros...
Checking for forbidden M4 macros...
Processing ./configure.ac
Running libtoolize...
libtoolize: putting auxiliary files in `.'.
libtoolize: copying file `./ltmain.sh'
libtoolize: putting macros in AC_CONFIG_
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
Running intltoolize...
Running gtkdocize...
Running aclocal-1.11...
Running autoconf...
Running autoheader...
Running automake-1.11...
Running ./configure --enable-gtk-doc --enable-debug ...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking how to create a ustar tar archive... gnutar
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking for library containing strerror... none required
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking build system type... x86_64-
checking host system type... x86_64-
checking how to print strings... printf
checking for a sed that does not truncate output... /bin/sed
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI ...
| Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Preview Diff
| 1 | === modified file 'run-mac-tests' |
| 2 | --- run-mac-tests 2012-07-30 19:31:32 +0000 |
| 3 | +++ run-mac-tests 2012-08-06 16:57:22 +0000 |
| 4 | @@ -27,7 +27,7 @@ |
| 5 | # version. If you delete this exception statement from all source |
| 6 | # files in the program, then also delete it here. |
| 7 | |
| 8 | -PYTHONPATH=../ubuntu-sso-client/:../ubuntuone-storage-protocol:../ubuntuone-dev-tools:$PYTHONPATH |
| 9 | +PYTHONPATH=../ubuntu-sso-client/:../ubuntuone-storage-protocol:../ubuntuone-dev-tools:../ubuntuone-fsevents-daemon/python:$PYTHONPATH |
| 10 | |
| 11 | set -e |
| 12 | if [ $# -ne 0 ]; then |
| 13 | |
| 14 | === renamed file 'tests/platform/filesystem_notifications/test_windows.py' => 'tests/platform/filesystem_notifications/common.py' |
| 15 | --- tests/platform/filesystem_notifications/test_windows.py 2012-07-18 15:18:04 +0000 |
| 16 | +++ tests/platform/filesystem_notifications/common.py 2012-08-06 16:57:22 +0000 |
| 17 | @@ -38,42 +38,45 @@ |
| 18 | import itertools |
| 19 | |
| 20 | from twisted.internet import defer |
| 21 | -from win32file import FILE_NOTIFY_INFORMATION |
| 22 | - |
| 23 | from contrib.testing.testcase import BaseTwistedTestCase |
| 24 | from ubuntuone.devtools.handlers import MementoHandler |
| 25 | -from ubuntuone.platform.os_helper import windows as os_helper |
| 26 | from ubuntuone.platform.filesystem_notifications.pyinotify_agnostic import ( |
| 27 | + EventsCodes, |
| 28 | ProcessEvent, |
| 29 | IN_CLOSE_WRITE, |
| 30 | IN_CREATE, |
| 31 | IN_DELETE, |
| 32 | IN_OPEN, |
| 33 | ) |
| 34 | -from ubuntuone.platform.filesystem_notifications.monitor import ( |
| 35 | - windows as filesystem_notifications, |
| 36 | -) |
| 37 | from ubuntuone.platform.filesystem_notifications import notify_processor |
| 38 | from ubuntuone.platform.filesystem_notifications.monitor.common import ( |
| 39 | FilesystemMonitor, |
| 40 | Watch, |
| 41 | WatchManager, |
| 42 | ) |
| 43 | -from ubuntuone.platform.filesystem_notifications.monitor.windows import ( |
| 44 | - ACTIONS, |
| 45 | - FILE_NOTIFY_CHANGE_FILE_NAME, |
| 46 | - FILE_NOTIFY_CHANGE_DIR_NAME, |
| 47 | - FILE_NOTIFY_CHANGE_ATTRIBUTES, |
| 48 | - FILE_NOTIFY_CHANGE_SIZE, |
| 49 | - FILE_NOTIFY_CHANGE_LAST_WRITE, |
| 50 | - FILE_NOTIFY_CHANGE_SECURITY, |
| 51 | - FILE_NOTIFY_CHANGE_LAST_ACCESS, |
| 52 | -) |
| 53 | +from ubuntuone.platform.filesystem_notifications.monitor import ACTIONS |
| 54 | +from ubuntuone.platform.os_helper import get_os_valid_path |
| 55 | + |
| 56 | +OP_FLAGS = EventsCodes.FLAG_COLLECTIONS['OP_FLAGS'] |
| 57 | +IS_DIR = EventsCodes.FLAG_COLLECTIONS['SPECIAL_FLAGS']['IN_ISDIR'] |
| 58 | |
| 59 | #create a rever mapping to use it in the tests. |
| 60 | -REVERSE_WINDOWS_ACTIONS = {} |
| 61 | -for key, value in ACTIONS.iteritems(): |
| 62 | - REVERSE_WINDOWS_ACTIONS[value] = key |
| 63 | +REVERSE_OS_ACTIONS = {} |
| 64 | +for key, value in ACTIONS.items(): |
| 65 | + REVERSE_OS_ACTIONS[value] = key |
| 66 | + |
| 67 | + |
| 68 | +class FakeEventsProcessor(object): |
| 69 | + |
| 70 | + """Handle fake events creation and processing.""" |
| 71 | + |
| 72 | + def create_fake_event(self): |
| 73 | + """Create a fake filesystem event.""" |
| 74 | + raise NotImplementedError |
| 75 | + |
| 76 | + def custom_process_events(self): |
| 77 | + """Process a fake event.""" |
| 78 | + raise NotImplementedError |
| 79 | |
| 80 | |
| 81 | class FakeException(Exception): |
| 82 | @@ -127,32 +130,17 @@ |
| 83 | @defer.inlineCallbacks |
| 84 | def setUp(self): |
| 85 | yield super(TestWatch, self).setUp() |
| 86 | + self.path = '' |
| 87 | + self.invalid_path = '' |
| 88 | + self.common_path = '' |
| 89 | self.basedir = self.mktemp('test_root') |
| 90 | - self.mask = FILE_NOTIFY_CHANGE_FILE_NAME | \ |
| 91 | - FILE_NOTIFY_CHANGE_DIR_NAME | \ |
| 92 | - FILE_NOTIFY_CHANGE_ATTRIBUTES | \ |
| 93 | - FILE_NOTIFY_CHANGE_SIZE | \ |
| 94 | - FILE_NOTIFY_CHANGE_LAST_WRITE | \ |
| 95 | - FILE_NOTIFY_CHANGE_SECURITY | \ |
| 96 | - FILE_NOTIFY_CHANGE_LAST_ACCESS |
| 97 | + self.mask = None |
| 98 | self.memento = MementoHandler() |
| 99 | self.memento.setLevel(logging.DEBUG) |
| 100 | self.raw_events = [] |
| 101 | self.paths_checked = [] |
| 102 | old_is_dir = Watch._path_is_dir |
| 103 | - |
| 104 | - def file_notify_information_wrapper(buf, data): |
| 105 | - """Wrapper that gets the events and adds them to the list.""" |
| 106 | - events = FILE_NOTIFY_INFORMATION(buf, data) |
| 107 | - # we want to append the list because that is what will be logged. |
| 108 | - # If we use extend we wont have the same logging because it will |
| 109 | - # group all events in a single lists which is not what the COM API |
| 110 | - # does. |
| 111 | - str_events = [ |
| 112 | - (filesystem_notifications.ACTIONS_NAMES[action], path) for action, path in |
| 113 | - events] |
| 114 | - self.raw_events.append(str_events) |
| 115 | - return events |
| 116 | + self.fake_events_processor = FakeEventsProcessor() |
| 117 | |
| 118 | def path_is_dir_wrapper(watch, path): |
| 119 | """Wrapper that gets the checked paths.""" |
| 120 | @@ -160,8 +148,6 @@ |
| 121 | self.paths_checked.append((path, result)) |
| 122 | return result |
| 123 | |
| 124 | - self.patch(filesystem_notifications, 'FILE_NOTIFY_INFORMATION', |
| 125 | - file_notify_information_wrapper) |
| 126 | self.patch(Watch, '_path_is_dir', path_is_dir_wrapper) |
| 127 | |
| 128 | @defer.inlineCallbacks |
| 129 | @@ -169,7 +155,7 @@ |
| 130 | """Perform the file operations and returns the recorded events.""" |
| 131 | handler = TestCaseHandler(number_events=number_events) |
| 132 | manager = WatchManager(handler) |
| 133 | - yield manager.add_watch(os_helper.get_windows_valid_path(path), mask) |
| 134 | + yield manager.add_watch(get_os_valid_path(path), mask) |
| 135 | # change the logger so that we can check the logs if we wanted |
| 136 | manager._wdm[0].log.addHandler(self.memento) |
| 137 | # clean logger later |
| 138 | @@ -198,7 +184,7 @@ |
| 139 | create_file, 1) |
| 140 | event = events[0] |
| 141 | self.assertFalse(event.dir) |
| 142 | - self.assertEqual(0x100, event.mask) |
| 143 | + self.assertEqual(OP_FLAGS['IN_CREATE'], event.mask) |
| 144 | self.assertEqual('IN_CREATE', event.maskname) |
| 145 | self.assertEqual(os.path.split(file_name)[1], event.name) |
| 146 | self.assertEqual('.', event.path) |
| 147 | @@ -218,7 +204,7 @@ |
| 148 | create_dir, 1) |
| 149 | event = events[0] |
| 150 | self.assertTrue(event.dir) |
| 151 | - self.assertEqual(0x40000100, event.mask) |
| 152 | + self.assertEqual(OP_FLAGS['IN_CREATE'] | IS_DIR, event.mask) |
| 153 | self.assertEqual('IN_CREATE|IN_ISDIR', event.maskname) |
| 154 | self.assertEqual(os.path.split(dir_name)[1], event.name) |
| 155 | self.assertEqual('.', event.path) |
| 156 | @@ -240,7 +226,7 @@ |
| 157 | remove_file, 1) |
| 158 | event = events[0] |
| 159 | self.assertFalse(event.dir) |
| 160 | - self.assertEqual(0x200, event.mask) |
| 161 | + self.assertEqual(OP_FLAGS['IN_DELETE'], event.mask) |
| 162 | self.assertEqual('IN_DELETE', event.maskname) |
| 163 | self.assertEqual(os.path.split(file_name)[1], event.name) |
| 164 | self.assertEqual('.', event.path) |
| 165 | @@ -262,36 +248,15 @@ |
| 166 | remove_dir, 1) |
| 167 | event = events[0] |
| 168 | self.assertTrue(event.dir) |
| 169 | - self.assertEqual(0x40000200, event.mask) |
| 170 | + self.assertEqual(OP_FLAGS['IN_DELETE'] | IS_DIR, event.mask) |
| 171 | self.assertEqual('IN_DELETE|IN_ISDIR', event.maskname) |
| 172 | self.assertEqual('.', event.path) |
| 173 | self.assertEqual(os.path.join(self.basedir, dir_name), event.pathname) |
| 174 | self.assertEqual(0, event.wd) |
| 175 | |
| 176 | - @defer.inlineCallbacks |
| 177 | def test_file_write(self): |
| 178 | """Test that the correct event is raised when a file is written.""" |
| 179 | - file_name = os.path.join(self.basedir, 'test_file_write') |
| 180 | - # create the file before recording |
| 181 | - fd = open(file_name, 'w') |
| 182 | - # clean behind us by removing the file |
| 183 | - self.addCleanup(os.remove, file_name) |
| 184 | - |
| 185 | - def write_file(): |
| 186 | - """Action for the test.""" |
| 187 | - fd.write('test') |
| 188 | - fd.close() |
| 189 | - |
| 190 | - events = yield self._perform_operations(self.basedir, self.mask, |
| 191 | - write_file, 1) |
| 192 | - event = events[0] |
| 193 | - self.assertFalse(event.dir) |
| 194 | - self.assertEqual(0x2, event.mask) |
| 195 | - self.assertEqual('IN_MODIFY', event.maskname) |
| 196 | - self.assertEqual(os.path.split(file_name)[1], event.name) |
| 197 | - self.assertEqual('.', event.path) |
| 198 | - self.assertEqual(os.path.join(self.basedir, file_name), event.pathname) |
| 199 | - self.assertEqual(0, event.wd) |
| 200 | + raise NotImplementedError |
| 201 | |
| 202 | @defer.inlineCallbacks |
| 203 | def test_file_moved_to_watched_dir_same_watcher(self): |
| 204 | @@ -313,7 +278,7 @@ |
| 205 | move_to_event = events[1] |
| 206 | # first test the move from |
| 207 | self.assertFalse(move_from_event.dir) |
| 208 | - self.assertEqual(0x40, move_from_event.mask) |
| 209 | + self.assertEqual(OP_FLAGS['IN_MOVED_FROM'], move_from_event.mask) |
| 210 | self.assertEqual('IN_MOVED_FROM', move_from_event.maskname) |
| 211 | self.assertEqual(os.path.split(from_file_name)[1], |
| 212 | move_from_event.name) |
| 213 | @@ -323,7 +288,7 @@ |
| 214 | self.assertEqual(0, move_from_event.wd) |
| 215 | # test the move to |
| 216 | self.assertFalse(move_to_event.dir) |
| 217 | - self.assertEqual(0x80, move_to_event.mask) |
| 218 | + self.assertEqual(OP_FLAGS['IN_MOVED_TO'], move_to_event.mask) |
| 219 | self.assertEqual('IN_MOVED_TO', move_to_event.maskname) |
| 220 | self.assertEqual(os.path.split(to_file_name)[1], move_to_event.name) |
| 221 | self.assertEqual('.', move_to_event.path) |
| 222 | @@ -354,7 +319,7 @@ |
| 223 | move_file, 1) |
| 224 | event = events[0] |
| 225 | self.assertFalse(event.dir) |
| 226 | - self.assertEqual(0x200, event.mask) |
| 227 | + self.assertEqual(OP_FLAGS['IN_DELETE'], event.mask) |
| 228 | self.assertEqual('IN_DELETE', event.maskname) |
| 229 | self.assertEqual(os.path.split(from_file_name)[1], event.name) |
| 230 | self.assertEqual('.', event.path) |
| 231 | @@ -382,7 +347,7 @@ |
| 232 | move_files, 1) |
| 233 | event = events[0] |
| 234 | self.assertFalse(event.dir) |
| 235 | - self.assertEqual(0x100, event.mask) |
| 236 | + self.assertEqual(OP_FLAGS['IN_CREATE'], event.mask) |
| 237 | self.assertEqual('IN_CREATE', event.maskname) |
| 238 | self.assertEqual(os.path.split(to_file_name)[1], event.name) |
| 239 | self.assertEqual('.', event.path) |
| 240 | @@ -409,7 +374,8 @@ |
| 241 | move_to_event = events[1] |
| 242 | # first test the move from |
| 243 | self.assertTrue(move_from_event.dir) |
| 244 | - self.assertEqual(0x40000040, move_from_event.mask) |
| 245 | + self.assertEqual(OP_FLAGS['IN_MOVED_FROM'] | IS_DIR, |
| 246 | + move_from_event.mask) |
| 247 | self.assertEqual('IN_MOVED_FROM|IN_ISDIR', move_from_event.maskname) |
| 248 | self.assertEqual(os.path.split(from_dir_name)[1], move_from_event.name) |
| 249 | self.assertEqual('.', move_from_event.path) |
| 250 | @@ -418,7 +384,7 @@ |
| 251 | self.assertEqual(0, move_from_event.wd) |
| 252 | # test the move to |
| 253 | self.assertTrue(move_to_event.dir) |
| 254 | - self.assertEqual(0x40000080, move_to_event.mask) |
| 255 | + self.assertEqual(OP_FLAGS['IN_MOVED_TO'] | IS_DIR, move_to_event.mask) |
| 256 | self.assertEqual('IN_MOVED_TO|IN_ISDIR', move_to_event.maskname) |
| 257 | self.assertEqual(os.path.split(to_dir_name)[1], move_to_event.name) |
| 258 | self.assertEqual('.', move_to_event.path) |
| 259 | @@ -447,7 +413,7 @@ |
| 260 | move_dir, 1) |
| 261 | event = events[0] |
| 262 | self.assertTrue(event.dir) |
| 263 | - self.assertEqual(0x40000200, event.mask) |
| 264 | + self.assertEqual(OP_FLAGS['IN_DELETE'] | IS_DIR, event.mask) |
| 265 | self.assertEqual('IN_DELETE|IN_ISDIR', event.maskname) |
| 266 | self.assertEqual('.', event.path) |
| 267 | self.assertEqual(os.path.join(self.basedir, dir_name), event.pathname) |
| 268 | @@ -471,7 +437,7 @@ |
| 269 | move_dir, 1) |
| 270 | event = events[0] |
| 271 | self.assertTrue(event.dir) |
| 272 | - self.assertEqual(0x40000100, event.mask) |
| 273 | + self.assertEqual(OP_FLAGS['IN_CREATE'] | IS_DIR, event.mask) |
| 274 | self.assertEqual('IN_CREATE|IN_ISDIR', event.maskname) |
| 275 | self.assertEqual(os.path.split(from_dir_name)[1], event.name) |
| 276 | self.assertEqual('.', event.path) |
| 277 | @@ -484,8 +450,9 @@ |
| 278 | handler = TestCaseHandler(number_events=0) |
| 279 | manager = WatchManager(handler) |
| 280 | # add a watch that will always exclude all actions |
| 281 | - manager.add_watch(os_helper.get_windows_valid_path(self.basedir), |
| 282 | - self.mask, exclude_filter=lambda x: True) |
| 283 | + manager.add_watch(get_os_valid_path(self.basedir), |
| 284 | + self.mask, auto_add=True, |
| 285 | + exclude_filter=lambda x: True) |
| 286 | # execution the actions |
| 287 | file_name = os.path.join(self.basedir, 'test_file_create') |
| 288 | open(file_name, 'w').close() |
| 289 | @@ -502,16 +469,18 @@ |
| 290 | """Memorize the processed events.""" |
| 291 | events.append(event) |
| 292 | |
| 293 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 294 | - child = u'child' |
| 295 | - watch = Watch(1, path, fake_processor) |
| 296 | - watch.ignore_path(os.path.join(path, child)) |
| 297 | + child = 'child' |
| 298 | + watch = Watch(1, self.path, None) |
| 299 | + watch.ignore_path(os.path.join(self.path, child)) |
| 300 | paths_to_ignore = [] |
| 301 | for file_name in 'abcdef': |
| 302 | - paths_to_ignore.append((1, os.path.join(child, file_name))) |
| 303 | + paths_to_ignore.append( |
| 304 | + self.fake_events_processor.create_fake_event( |
| 305 | + os.path.join(child, file_name))) |
| 306 | # ensure that the watch is watching |
| 307 | - watch._watching = True |
| 308 | - watch.platform_watch._process_events(paths_to_ignore) |
| 309 | + watch.platform_watch.watching = True |
| 310 | + self.fake_events_processor.custom_process_events( |
| 311 | + watch, paths_to_ignore) |
| 312 | self.assertEqual(0, len(events), |
| 313 | 'All events should have been ignored.') |
| 314 | |
| 315 | @@ -523,17 +492,18 @@ |
| 316 | """Memorize the processed events.""" |
| 317 | events.append(event) |
| 318 | |
| 319 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 320 | - child = u'child' |
| 321 | - watch = Watch(1, path, fake_processor) |
| 322 | - watch.ignore_path(os.path.join(path, child)) |
| 323 | + child = 'child' |
| 324 | + watch = Watch(1, self.path, fake_processor) |
| 325 | + watch.ignore_path(os.path.join(self.path, child)) |
| 326 | paths_not_to_ignore = [] |
| 327 | for file_name in 'abcdef': |
| 328 | - paths_not_to_ignore.append((1, os.path.join( |
| 329 | - child + file_name, file_name))) |
| 330 | + event = self.fake_events_processor.create_fake_event( |
| 331 | + os.path.join(child + file_name, file_name)) |
| 332 | + paths_not_to_ignore.append(event) |
| 333 | # ensure that the watch is watching |
| 334 | watch.platform_watch.watching = True |
| 335 | - watch.platform_watch._process_events(paths_not_to_ignore) |
| 336 | + self.fake_events_processor.custom_process_events( |
| 337 | + watch, paths_not_to_ignore) |
| 338 | self.assertEqual(len(paths_not_to_ignore), len(events), |
| 339 | 'No events should have been ignored.') |
| 340 | |
| 341 | @@ -545,21 +515,22 @@ |
| 342 | """Memorize the processed events.""" |
| 343 | events.append(event.pathname) |
| 344 | |
| 345 | - child = u'child' |
| 346 | - path = u'\\\\?\\C:\\path\\' # a valid windows path |
| 347 | - watch = Watch(1, path, fake_processor) |
| 348 | - watch.ignore_path(os.path.join(path, child)) |
| 349 | + child = 'child' |
| 350 | + watch = Watch(1, self.path, fake_processor) |
| 351 | + watch.ignore_path(os.path.join(self.path, child)) |
| 352 | paths_not_to_ignore = [] |
| 353 | paths_to_ignore = [] |
| 354 | expected_events = [] |
| 355 | for file_name in 'abcdef': |
| 356 | valid = os.path.join(child + file_name, file_name) |
| 357 | paths_to_ignore.append((1, os.path.join(child, file_name))) |
| 358 | - paths_not_to_ignore.append((1, valid)) |
| 359 | - expected_events.append(os.path.join('C:\\path', valid)) |
| 360 | + paths_not_to_ignore.append( |
| 361 | + self.fake_events_processor.create_fake_event(valid)) |
| 362 | + expected_events.append(os.path.join(self.common_path, valid)) |
| 363 | # ensure that the watch is watching |
| 364 | watch.platform_watch.watching = True |
| 365 | - watch.platform_watch._process_events(paths_not_to_ignore) |
| 366 | + self.fake_events_processor.custom_process_events( |
| 367 | + watch, paths_not_to_ignore) |
| 368 | self.assertEqual(len(paths_not_to_ignore), len(events), |
| 369 | 'Wrong number of events ignored.') |
| 370 | self.assertTrue(all([event in expected_events for event in events]), |
| 371 | @@ -573,17 +544,19 @@ |
| 372 | """Memorize the processed events.""" |
| 373 | events.append(event) |
| 374 | |
| 375 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 376 | - child = u'child' |
| 377 | - watch = Watch(1, path, fake_processor) |
| 378 | - watch.ignore_path(os.path.join(path, child)) |
| 379 | - watch.remove_ignored_path(os.path.join(path, child)) |
| 380 | + child = 'child' |
| 381 | + watch = Watch(1, self.path, fake_processor) |
| 382 | + watch.ignore_path(os.path.join(self.path, child)) |
| 383 | + watch.remove_ignored_path(os.path.join(self.path, child)) |
| 384 | paths_not_to_ignore = [] |
| 385 | for file_name in 'abcdef': |
| 386 | - paths_not_to_ignore.append((1, os.path.join(child, file_name))) |
| 387 | + event = self.fake_events_processor.create_fake_event( |
| 388 | + os.path.join(child, file_name)) |
| 389 | + paths_not_to_ignore.append(event) |
| 390 | # ensure that the watch is watching |
| 391 | watch.platform_watch.watching = True |
| 392 | - watch.platform_watch._process_events(paths_not_to_ignore) |
| 393 | + self.fake_events_processor.custom_process_events( |
| 394 | + watch, paths_not_to_ignore) |
| 395 | self.assertEqual(len(paths_not_to_ignore), len(events), |
| 396 | 'All events should have been accepted.') |
| 397 | |
| 398 | @@ -595,190 +568,98 @@ |
| 399 | """Memorize the processed events.""" |
| 400 | events.append(event.pathname) |
| 401 | |
| 402 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 403 | - child_a = u'childa' |
| 404 | - child_b = u'childb' |
| 405 | - watch = Watch(1, path, fake_processor) |
| 406 | - watch.ignore_path(os.path.join(path, child_a)) |
| 407 | - watch.ignore_path(os.path.join(path, child_b)) |
| 408 | - watch.remove_ignored_path(os.path.join(path, child_a)) |
| 409 | + child_a = 'childa' |
| 410 | + child_b = 'childb' |
| 411 | + watch = Watch(1, self.path, fake_processor) |
| 412 | + watch.ignore_path(os.path.join(self.path, child_a)) |
| 413 | + watch.ignore_path(os.path.join(self.path, child_b)) |
| 414 | + watch.remove_ignored_path(os.path.join(self.path, child_a)) |
| 415 | paths_to_ignore = [] |
| 416 | paths_not_to_ignore = [] |
| 417 | expected_events = [] |
| 418 | for file_name in 'abcdef': |
| 419 | paths_to_ignore.append((1, os.path.join(child_b, file_name))) |
| 420 | valid = os.path.join(child_a, file_name) |
| 421 | - paths_not_to_ignore.append((1, valid)) |
| 422 | - expected_events.append(os.path.join('C:\\path', valid)) |
| 423 | + event = self.fake_events_processor.create_fake_event(valid) |
| 424 | + paths_not_to_ignore.append(event) |
| 425 | + expected_events.append(os.path.join(self.common_path, valid)) |
| 426 | # ensure that the watch is watching |
| 427 | watch.platform_watch.watching = True |
| 428 | - watch.platform_watch._process_events(paths_not_to_ignore) |
| 429 | + self.fake_events_processor.custom_process_events( |
| 430 | + watch, paths_not_to_ignore) |
| 431 | self.assertEqual(len(paths_not_to_ignore), len(events), |
| 432 | 'All events should have been accepted.') |
| 433 | self.assertTrue(all([event in expected_events for event in events]), |
| 434 | 'Paths ignored that should have not been ignored.') |
| 435 | |
| 436 | - @defer.inlineCallbacks |
| 437 | - def test_call_deferred_already_called(self): |
| 438 | - """Test that the function is not called.""" |
| 439 | - method_args = [] |
| 440 | - |
| 441 | - def fake_call(*args, **kwargs): |
| 442 | - """Execute the call.""" |
| 443 | - method_args.append((args, kwargs),) |
| 444 | - |
| 445 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 446 | - watch = Watch(1, path, None) |
| 447 | - yield watch.platform_watch._watch_started_deferred.callback(True) |
| 448 | - watch.platform_watch._call_deferred(fake_call, None) |
| 449 | - self.assertEqual(0, len(method_args)) |
| 450 | - |
| 451 | - def test_call_deferred_not_called(self): |
| 452 | - """Test that is indeed called.""" |
| 453 | - method_args = [] |
| 454 | - |
| 455 | - def fake_call(*args, **kwargs): |
| 456 | - """Execute the call.""" |
| 457 | - method_args.append((args, kwargs),) |
| 458 | - |
| 459 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 460 | - watch = Watch(1, path, None) |
| 461 | - watch.platform_watch._call_deferred(fake_call, None) |
| 462 | - self.assertEqual(1, len(method_args)) |
| 463 | - |
| 464 | - def test_started_property(self): |
| 465 | - """Test that the started property returns the started deferred.""" |
| 466 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 467 | - watch = Watch(1, path, None) |
| 468 | - self.assertEqual(watch.started, watch.platform_watch._watch_started_deferred) |
| 469 | - |
| 470 | - def test_stopped_property(self): |
| 471 | - """Test that the stopped property returns the stopped deferred.""" |
| 472 | - path = u'\\\\?\\C:\\path' # a valid windows path |
| 473 | - watch = Watch(1, path, None) |
| 474 | - self.assertEqual(watch.stopped, watch.platform_watch._watch_stopped_deferred) |
| 475 | - |
| 476 | def random_error(self, *args): |
| 477 | """Throw a fake exception.""" |
| 478 | raise FakeException() |
| 479 | |
| 480 | - @defer.inlineCallbacks |
| 481 | - def test_start_watching_fails_early_in_thread(self): |
| 482 | - """An early failure inside the thread should errback the deferred.""" |
| 483 | - test_path = self.mktemp("test_directory") |
| 484 | - self.patch(filesystem_notifications, "CreateFileW", self.random_error) |
| 485 | - watch = Watch(1, test_path, None) |
| 486 | - d = watch.start_watching() |
| 487 | - yield self.assertFailure(d, FakeException) |
| 488 | - |
| 489 | - @defer.inlineCallbacks |
| 490 | - def test_start_watching_fails_late_in_thread(self): |
| 491 | - """A late failure inside the thread should errback the deferred.""" |
| 492 | - test_path = self.mktemp("test_directory") |
| 493 | - self.patch(filesystem_notifications, "ReadDirectoryChangesW", |
| 494 | - self.random_error) |
| 495 | - watch = Watch(1, test_path, None) |
| 496 | - d = watch.start_watching() |
| 497 | - yield self.assertFailure(d, FakeException) |
| 498 | - |
| 499 | - @defer.inlineCallbacks |
| 500 | - def test_close_handle_is_called_on_error(self): |
| 501 | - """CloseHandle is called when there's an error in the watch thread.""" |
| 502 | - test_path = self.mktemp("test_directory") |
| 503 | - close_called = [] |
| 504 | - self.patch(filesystem_notifications, "CreateFileW", lambda *_: None) |
| 505 | - self.patch(filesystem_notifications, "CloseHandle", |
| 506 | - close_called.append) |
| 507 | - self.patch(filesystem_notifications, "ReadDirectoryChangesW", |
| 508 | - self.random_error) |
| 509 | - watch = Watch(1, test_path, None) |
| 510 | - d = watch.start_watching() |
| 511 | - yield self.assertFailure(d, FakeException) |
| 512 | - self.assertEqual(len(close_called), 1) |
| 513 | - yield watch.stop_watching() |
| 514 | - |
| 515 | - @defer.inlineCallbacks |
| 516 | - def test_stop_watching_fired_when_watch_thread_finishes(self): |
| 517 | - """The deferred returned is fired when the watch thread finishes.""" |
| 518 | - test_path = self.mktemp("another_test_directory") |
| 519 | - watch = Watch(1, test_path, None) |
| 520 | - yield watch.start_watching() |
| 521 | - self.assertNotEqual(watch.platform_watch._watch_handle, None) |
| 522 | - yield watch.stop_watching() |
| 523 | - self.assertEqual(watch.platform_watch._watch_handle, None) |
| 524 | - |
| 525 | def test_is_path_dir_missing_no_subdir(self): |
| 526 | """Test when the path does not exist and is no a subdir.""" |
| 527 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 528 | test_path = self.mktemp("test_directory") |
| 529 | self.patch(os.path, 'exists', lambda path: False) |
| 530 | watch = Watch(1, test_path, None) |
| 531 | - self.assertFalse(watch._path_is_dir(path)) |
| 532 | + self.assertFalse(watch._path_is_dir(self.invalid_path)) |
| 533 | |
| 534 | def test_is_path_dir_missing_in_subdir(self): |
| 535 | """Test when the path does not exist and is a subdir.""" |
| 536 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 537 | test_path = self.mktemp("test_directory") |
| 538 | self.patch(os.path, 'exists', lambda path: False) |
| 539 | watch = Watch(1, test_path, None) |
| 540 | - watch._subdirs.add(path) |
| 541 | - self.assertTrue(watch._path_is_dir(path)) |
| 542 | + watch._subdirs.add(self.invalid_path) |
| 543 | + self.assertTrue(watch._path_is_dir(self.invalid_path)) |
| 544 | |
| 545 | def test_is_path_dir_present_is_dir(self): |
| 546 | """Test when the path is present and is dir.""" |
| 547 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 548 | test_path = self.mktemp("test_directory") |
| 549 | self.patch(os.path, 'exists', lambda path: True) |
| 550 | self.patch(os.path, 'isdir', lambda path: True) |
| 551 | watch = Watch(1, test_path, None) |
| 552 | - watch._subdirs.add(path) |
| 553 | - self.assertTrue(watch._path_is_dir(path)) |
| 554 | + watch._subdirs.add(self.invalid_path) |
| 555 | + self.assertTrue(watch._path_is_dir(self.invalid_path)) |
| 556 | |
| 557 | def test_is_path_dir_present_no_dir(self): |
| 558 | """Test when the path is present but not a dir.""" |
| 559 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 560 | test_path = self.mktemp("test_directory") |
| 561 | self.patch(os.path, 'exists', lambda path: True) |
| 562 | self.patch(os.path, 'isdir', lambda path: False) |
| 563 | watch = Watch(1, test_path, None) |
| 564 | - watch._subdirs.add(path) |
| 565 | - self.assertFalse(watch._path_is_dir(path)) |
| 566 | + watch._subdirs.add(self.invalid_path) |
| 567 | + self.assertFalse(watch._path_is_dir(self.invalid_path)) |
| 568 | |
| 569 | def test_update_subdirs_create_not_present(self): |
| 570 | """Test when we update on a create event and not present.""" |
| 571 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 572 | test_path = self.mktemp("test_directory") |
| 573 | watch = Watch(1, test_path, None) |
| 574 | - watch._update_subdirs(path, REVERSE_WINDOWS_ACTIONS[IN_CREATE]) |
| 575 | - self.assertTrue(path in watch._subdirs) |
| 576 | + watch._update_subdirs(self.invalid_path, REVERSE_OS_ACTIONS[IN_CREATE]) |
| 577 | + self.assertTrue(self.invalid_path in watch._subdirs) |
| 578 | |
| 579 | def test_update_subdirs_create_present(self): |
| 580 | """Test when we update on a create event and is present.""" |
| 581 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 582 | test_path = self.mktemp("test_directory") |
| 583 | watch = Watch(1, test_path, None) |
| 584 | - watch._subdirs.add(path) |
| 585 | + watch._subdirs.add(self.invalid_path) |
| 586 | old_length = len(watch._subdirs) |
| 587 | - watch._update_subdirs(path, REVERSE_WINDOWS_ACTIONS[IN_CREATE]) |
| 588 | - self.assertTrue(path in watch._subdirs) |
| 589 | + watch._update_subdirs(self.invalid_path, REVERSE_OS_ACTIONS[IN_CREATE]) |
| 590 | + self.assertTrue(self.invalid_path in watch._subdirs) |
| 591 | self.assertEqual(old_length, len(watch._subdirs)) |
| 592 | |
| 593 | def test_update_subdirs_delete_not_present(self): |
| 594 | """Test when we delete and is not present.""" |
| 595 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 596 | test_path = self.mktemp("test_directory") |
| 597 | watch = Watch(1, test_path, None) |
| 598 | - watch._update_subdirs(path, REVERSE_WINDOWS_ACTIONS[IN_DELETE]) |
| 599 | - self.assertTrue(path not in watch._subdirs) |
| 600 | + watch._update_subdirs(self.invalid_path, REVERSE_OS_ACTIONS[IN_DELETE]) |
| 601 | + self.assertTrue(self.invalid_path not in watch._subdirs) |
| 602 | |
| 603 | def test_update_subdirs_delete_present(self): |
| 604 | """Test when we delete and is present.""" |
| 605 | - path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 606 | test_path = self.mktemp("test_directory") |
| 607 | watch = Watch(1, test_path, None) |
| 608 | - watch._subdirs.add(path) |
| 609 | - watch._update_subdirs(path, REVERSE_WINDOWS_ACTIONS[IN_DELETE]) |
| 610 | - self.assertTrue(path not in watch._subdirs) |
| 611 | + watch._subdirs.add(self.invalid_path) |
| 612 | + watch._update_subdirs(self.invalid_path, REVERSE_OS_ACTIONS[IN_DELETE]) |
| 613 | + self.assertTrue(self.invalid_path not in watch._subdirs) |
| 614 | |
| 615 | |
| 616 | class TestWatchManager(BaseTwistedTestCase): |
| 617 | @@ -788,11 +669,8 @@ |
| 618 | def setUp(self): |
| 619 | """Set each of the tests.""" |
| 620 | yield super(TestWatchManager, self).setUp() |
| 621 | - self.parent_path = u'\\\\?\\C:\\' # a valid windows path |
| 622 | - self.path = self.parent_path + u'path' |
| 623 | - self.watch = Watch(1, self.path, None) |
| 624 | self.manager = WatchManager(None) |
| 625 | - self.manager._wdm = {1: self.watch} |
| 626 | + self.fake_events_processor = FakeEventsProcessor() |
| 627 | |
| 628 | @defer.inlineCallbacks |
| 629 | def test_stop(self): |
| 630 | @@ -808,25 +686,9 @@ |
| 631 | yield self.manager.stop() |
| 632 | self.assertTrue(self.was_called, 'The watch stop should be called.') |
| 633 | |
| 634 | - @defer.inlineCallbacks |
| 635 | def test_stop_multiple(self): |
| 636 | """Test that stop is fired when *all* watches have stopped.""" |
| 637 | - |
| 638 | - def fake_stop_watching(watch): |
| 639 | - """Another fake stop watch.""" |
| 640 | - return watch.stopped |
| 641 | - |
| 642 | - self.patch(Watch, "stop_watching", fake_stop_watching) |
| 643 | - second_path = self.parent_path + u"second_path" |
| 644 | - second_watch = Watch(2, second_path, None) |
| 645 | - self.manager._wdm[2] = second_watch |
| 646 | - d = self.manager.stop() |
| 647 | - self.assertFalse(d.called, "Not fired before all watches end") |
| 648 | - self.watch.stopped.callback(None) |
| 649 | - self.assertFalse(d.called, "Not fired before all watches end") |
| 650 | - second_watch.stopped.callback(None) |
| 651 | - yield d |
| 652 | - self.assertTrue(d.called, "Fired after the watches ended") |
| 653 | + raise NotImplementedError |
| 654 | |
| 655 | def test_get_present_watch(self): |
| 656 | """Test that we can get a Watch using is wd.""" |
| 657 | @@ -836,7 +698,6 @@ |
| 658 | """Test that we get an error when trying to get a missing wd.""" |
| 659 | self.assertRaises(KeyError, self.manager.get_watch, (1,)) |
| 660 | |
| 661 | - @defer.inlineCallbacks |
| 662 | def test_delete_present_watch(self): |
| 663 | """Test that we can remove a present watch.""" |
| 664 | self.was_called = False |
| 665 | @@ -865,7 +726,6 @@ |
| 666 | self.manager.add_watch(self.path, mask) |
| 667 | self.assertEqual(1, len(self.manager._wdm)) |
| 668 | self.assertTrue(self.was_called, 'The watch start was not called.') |
| 669 | - self.assertEqual(self.path + os.path.sep, self.manager._wdm[0].path) |
| 670 | |
| 671 | def test_get_watch_present_wd(self): |
| 672 | """Test that the correct path is returned.""" |
| 673 | @@ -889,10 +749,8 @@ |
| 674 | """A watch on an unwatched path returns None.""" |
| 675 | self.assertEqual(None, self.manager.get_wd(self.parent_path)) |
| 676 | |
| 677 | - @defer.inlineCallbacks |
| 678 | def test_rm_present_wd(self): |
| 679 | """Test the removal of a present watch.""" |
| 680 | - |
| 681 | def fake_stop_watching(): |
| 682 | """Fake stop watch.""" |
| 683 | return defer.succeed(True) |
| 684 | @@ -913,8 +771,9 @@ |
| 685 | self.manager.rm_path(self.path) |
| 686 | self.assertEqual(self.watch, self.manager._wdm.get(1)) |
| 687 | self.watch._watching = True |
| 688 | - self.watch.platform_watch._process_events( |
| 689 | - [(1, os.path.join(self.path, 'test'))]) |
| 690 | + event = self.fake_events_processor.create_fake_event( |
| 691 | + os.path.join(self.path, 'test')) |
| 692 | + self.fake_events_processor.custom_process_events(self.watch, [event]) |
| 693 | self.assertEqual(0, len(events)) |
| 694 | |
| 695 | def test_rm_child_path(self): |
| 696 | @@ -926,41 +785,27 @@ |
| 697 | events.append(event.pathname) |
| 698 | |
| 699 | self.watch._processor = fake_processor |
| 700 | - child = os.path.join(self.path, u'child') |
| 701 | + child = os.path.join(self.path, 'child') |
| 702 | self.manager.rm_path(child) |
| 703 | self.assertEqual(self.watch, self.manager._wdm[1]) |
| 704 | # assert that the correct event is ignored |
| 705 | self.watch.platform_watch.watching = True |
| 706 | - self.watch.platform_watch._process_events( |
| 707 | - [(1, os.path.join('child', 'test'))]) |
| 708 | + event = self.fake_events_processor.create_fake_event( |
| 709 | + os.path.join('child', 'test')) |
| 710 | + self.fake_events_processor.custom_process_events(self.watch, [event]) |
| 711 | self.assertEqual(0, len(events)) |
| 712 | # assert that other events are not ignored |
| 713 | - self.watch.platform_watch._process_events([(1, 'test')]) |
| 714 | + event2 = self.fake_events_processor.create_fake_event('test') |
| 715 | + self.fake_events_processor.custom_process_events(self.watch, [event2]) |
| 716 | self.assertEqual(1, len(events)) |
| 717 | |
| 718 | |
| 719 | class TestWatchManagerAddWatches(BaseTwistedTestCase): |
| 720 | """Test the watch manager.""" |
| 721 | - timeout = 5 |
| 722 | |
| 723 | def test_add_watch_twice(self): |
| 724 | """Adding a watch twice succeeds when the watch is running.""" |
| 725 | - self.patch(Watch, "start_watching", lambda self: self.started) |
| 726 | - manager = WatchManager(None) |
| 727 | - # no need to stop watching because start_watching is fake |
| 728 | - |
| 729 | - path = u'\\\\?\\C:\\test' # a valid windows path |
| 730 | - mask = 'fake bit mask' |
| 731 | - d1 = manager.add_watch(path, mask) |
| 732 | - d2 = manager.add_watch(path, mask) |
| 733 | - |
| 734 | - self.assertFalse(d1.called, "Should not be called yet.") |
| 735 | - self.assertFalse(d2.called, "Should not be called yet.") |
| 736 | - |
| 737 | - manager._wdm.values()[0].started.callback(True) |
| 738 | - |
| 739 | - self.assertTrue(d1.called, "Should already be called.") |
| 740 | - self.assertTrue(d2.called, "Should already be called.") |
| 741 | + raise NotImplementedError |
| 742 | |
| 743 | |
| 744 | class FakeEvent(object): |
| 745 | @@ -1083,16 +928,6 @@ |
| 746 | self.assertEqual(event, self.general.called_methods[0][1]) |
| 747 | self.assertEqual(paths, self.general.called_methods[0][2]) |
| 748 | |
| 749 | - def test_platform_is_ignored(self): |
| 750 | - """Test that we do indeed ignore the correct paths.""" |
| 751 | - not_ignored = 'test' |
| 752 | - ignored = not_ignored + '.lnk' |
| 753 | - path_is_ignored = notify_processor.common.path_is_ignored |
| 754 | - self.assertFalse(path_is_ignored(not_ignored), |
| 755 | - 'Only links should be ignored.') |
| 756 | - self.assertTrue(path_is_ignored(ignored), |
| 757 | - 'Links should be ignored.') |
| 758 | - |
| 759 | def test_is_ignored(self): |
| 760 | """Test that we do ensure that the path is ignored.""" |
| 761 | path = 'path' |
| 762 | @@ -1406,31 +1241,15 @@ |
| 763 | |
| 764 | class FilesystemMonitorTestCase(BaseTwistedTestCase): |
| 765 | """Tests for the FilesystemMonitor.""" |
| 766 | + |
| 767 | timeout = 5 |
| 768 | |
| 769 | def test_add_watch_twice(self): |
| 770 | """Check the deferred returned by a second add_watch.""" |
| 771 | - self.patch(Watch, "start_watching", lambda self: self.started) |
| 772 | - monitor = FilesystemMonitor(None, None) |
| 773 | - # no need to stop watching because start_watching is fake |
| 774 | - |
| 775 | - parent_path = 'C:\\test' # a valid windows path in utf-8 bytes |
| 776 | - child_path = parent_path + "\\child" |
| 777 | - d1 = monitor.add_watch(parent_path) |
| 778 | - d2 = monitor.add_watch(child_path) |
| 779 | - |
| 780 | - self.assertFalse(d1.called, "Should not be called yet.") |
| 781 | - self.assertFalse(d2.called, "Should not be called yet.") |
| 782 | - |
| 783 | - monitor._watch_manager._wdm.values()[0].started.callback(True) |
| 784 | - |
| 785 | - self.assertTrue(d1.called, "Should already be called.") |
| 786 | - self.assertTrue(d2.called, "Should already be called.") |
| 787 | - |
| 788 | - @defer.inlineCallbacks |
| 789 | + raise NotImplementedError |
| 790 | + |
| 791 | def test_add_watches_to_udf_ancestors(self): |
| 792 | """Test that the ancestor watches are not added.""" |
| 793 | - |
| 794 | class FakeVolume(object): |
| 795 | """A fake UDF.""" |
| 796 | |
| 797 | |
| 798 | === modified file 'tests/platform/filesystem_notifications/test_darwin.py' |
| 799 | --- tests/platform/filesystem_notifications/test_darwin.py 2012-07-18 15:18:04 +0000 |
| 800 | +++ tests/platform/filesystem_notifications/test_darwin.py 2012-08-06 16:57:22 +0000 |
| 801 | @@ -28,16 +28,13 @@ |
| 802 | # files in the program, then also delete it here. |
| 803 | """Test the filesystem notifications on MAC OS.""" |
| 804 | |
| 805 | +import itertools |
| 806 | import logging |
| 807 | import os |
| 808 | import tempfile |
| 809 | import thread |
| 810 | -import itertools |
| 811 | |
| 812 | -import fsevents |
| 813 | from twisted.internet import defer |
| 814 | - |
| 815 | -from contrib.testing.testcase import BaseTwistedTestCase |
| 816 | from ubuntuone.devtools.handlers import MementoHandler |
| 817 | from ubuntuone.platform.filesystem_notifications.monitor import ( |
| 818 | common, |
| 819 | @@ -51,7 +48,6 @@ |
| 820 | WatchManager, |
| 821 | ) |
| 822 | from ubuntuone.platform.filesystem_notifications.pyinotify_agnostic import ( |
| 823 | - EventsCodes, |
| 824 | ProcessEvent, |
| 825 | IN_CLOSE_WRITE, |
| 826 | IN_CREATE, |
| 827 | @@ -59,6 +55,7 @@ |
| 828 | IN_OPEN, |
| 829 | ) |
| 830 | from tests.platform.filesystem_notifications import BaseFSMonitorTestCase |
| 831 | +from tests.platform.filesystem_notifications import common as common_tests |
| 832 | |
| 833 | |
| 834 | # A reverse mapping for the tests |
| 835 | @@ -67,23 +64,18 @@ |
| 836 | REVERSE_MACOS_ACTIONS[value] = key |
| 837 | |
| 838 | |
| 839 | -OP_FLAGS = EventsCodes.FLAG_COLLECTIONS['OP_FLAGS'] |
| 840 | -IS_DIR = EventsCodes.FLAG_COLLECTIONS['SPECIAL_FLAGS']['IN_ISDIR'] |
| 841 | - |
| 842 | - |
| 843 | -class FakeException(Exception): |
| 844 | - """A fake Exception used in tests.""" |
| 845 | - |
| 846 | - |
| 847 | -class FakeVolume(object): |
| 848 | - """A fake volume.""" |
| 849 | - |
| 850 | - def __init__(self, path, ancestors): |
| 851 | - """Create a new instance.""" |
| 852 | - super(FakeVolume, self).__init__() |
| 853 | - self.volume_id = path |
| 854 | - self.path = path |
| 855 | - self.ancestors = ancestors |
| 856 | +class FakeEventsProcessor(object): |
| 857 | + |
| 858 | + """Handle fake events creation and processing.""" |
| 859 | + |
| 860 | + def create_fake_event(self, filename): |
| 861 | + """Create a fake file event.""" |
| 862 | + return FakeFileEvent(256, None, filename) |
| 863 | + |
| 864 | + def custom_process_events(self, watch, events): |
| 865 | + """Adapt to each platform way to process events.""" |
| 866 | + for event in events: |
| 867 | + watch.platform_watch._process_events(event) |
| 868 | |
| 869 | |
| 870 | class FakeFileEvent(object): |
| 871 | @@ -135,7 +127,7 @@ |
| 872 | assert self.main_thread_id == thread.get_ident() |
| 873 | |
| 874 | |
| 875 | -class TestWatch(BaseTwistedTestCase): |
| 876 | +class TestWatch(common_tests.TestWatch): |
| 877 | """Test the watch so that it returns the same events as pyinotify.""" |
| 878 | |
| 879 | timeout = 5 |
| 880 | @@ -143,6 +135,9 @@ |
| 881 | @defer.inlineCallbacks |
| 882 | def setUp(self): |
| 883 | yield super(TestWatch, self).setUp() |
| 884 | + self.path = '/Users/username/folder' |
| 885 | + self.common_path = '/Users/username/folder' |
| 886 | + self.invalid_path = '/Users/username/path/to/not/dir' |
| 887 | self.basedir = self.mktemp('test_root') |
| 888 | self.mask = None |
| 889 | self.stream = None |
| 890 | @@ -151,6 +146,7 @@ |
| 891 | self.raw_events = [] |
| 892 | self.paths_checked = [] |
| 893 | old_is_dir = Watch._path_is_dir |
| 894 | + self.fake_events_processor = FakeEventsProcessor() |
| 895 | |
| 896 | def path_is_dir_wrapper(watch, path): |
| 897 | """Wrapper that gets the checked paths.""" |
| 898 | @@ -158,37 +154,32 @@ |
| 899 | self.paths_checked.append((path, result)) |
| 900 | return result |
| 901 | |
| 902 | - self.patch(Watch, '_path_is_dir', |
| 903 | - path_is_dir_wrapper) |
| 904 | - |
| 905 | - @defer.inlineCallbacks |
| 906 | - def _perform_operations(self, path, mask, actions, number_events): |
| 907 | - """Perform the file operations and returns the recorded events.""" |
| 908 | - handler = TestCaseHandler(number_events=number_events) |
| 909 | - manager = WatchManager(handler) |
| 910 | - yield manager.add_watch(path, mask) |
| 911 | - # change the logger so that we can check the logs if we wanted |
| 912 | - manager._wdm[0].log.addHandler(self.memento) |
| 913 | - # clean logger later |
| 914 | - self.addCleanup(manager._wdm[0].log.removeHandler, self.memento) |
| 915 | - # execution the actions |
| 916 | - actions() |
| 917 | - # process the recorded events |
| 918 | - ret = yield handler.deferred |
| 919 | - self.addCleanup(manager.stop) |
| 920 | - defer.returnValue(ret) |
| 921 | - |
| 922 | - def _assert_logs(self, events): |
| 923 | - """Assert the debug logs.""" |
| 924 | - logs = [] |
| 925 | - msg = 'Is path %r a dir? %s' |
| 926 | - logs.extend([msg % data for data in self.paths_checked]) |
| 927 | - msg = 'Pushing event %r to processor.' |
| 928 | - logs.extend([msg % e for e in events]) |
| 929 | - for msg in logs: |
| 930 | - self.assertTrue(self.memento.check_debug(msg)) |
| 931 | - |
| 932 | - @defer.inlineCallbacks |
| 933 | + self.patch(Watch, '_path_is_dir', path_is_dir_wrapper) |
| 934 | + |
| 935 | + def test_not_ignore_path(self): |
| 936 | + """Test that we do get the events when they do not match.""" |
| 937 | + self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 938 | + lambda x, e: x(e)) |
| 939 | + super(TestWatch, self).test_not_ignore_path() |
| 940 | + |
| 941 | + def test_undo_ignore_path_ignored(self): |
| 942 | + """Test that we do deal with events from and old ignored path.""" |
| 943 | + self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 944 | + lambda x, e: x(e)) |
| 945 | + super(TestWatch, self).test_not_ignore_path() |
| 946 | + |
| 947 | + def test_undo_ignore_path_other_ignored(self): |
| 948 | + """Test that we can undo and the other path is ignored.""" |
| 949 | + self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 950 | + lambda x, e: x(e)) |
| 951 | + super(TestWatch, self).test_not_ignore_path() |
| 952 | + |
| 953 | + def test_mixed_ignore_path(self): |
| 954 | + """Test that we do get the correct events.""" |
| 955 | + self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 956 | + lambda x, e: x(e)) |
| 957 | + super(TestWatch, self).test_mixed_ignore_path() |
| 958 | + |
| 959 | def test_file_create(self): |
| 960 | """Test that the correct event is returned on a file create.""" |
| 961 | file_name = os.path.join(self.basedir, 'test_file_create') |
| 962 | @@ -205,14 +196,12 @@ |
| 963 | create_file, 1) |
| 964 | event = events[0] |
| 965 | self.assertFalse(event.dir) |
| 966 | - self.assertEqual(OP_FLAGS['IN_CREATE'], event.mask) |
| 967 | + self.assertEqual(common_tests.OP_FLAGS['IN_CREATE'], event.mask) |
| 968 | self.assertEqual('IN_CREATE', event.maskname) |
| 969 | self.assertEqual(os.path.split(file_name)[1], event.name) |
| 970 | self.assertEqual('.', event.path) |
| 971 | self.assertEqual(os.path.join(self.basedir, file_name), event.pathname) |
| 972 | self.assertEqual(0, event.wd) |
| 973 | - # assert the logging |
| 974 | - self._assert_logs(events) |
| 975 | |
| 976 | @defer.inlineCallbacks |
| 977 | def test_dir_create(self): |
| 978 | @@ -227,14 +216,13 @@ |
| 979 | create_dir, 1) |
| 980 | event = events[0] |
| 981 | self.assertTrue(event.dir) |
| 982 | - self.assertEqual(OP_FLAGS['IN_CREATE'] | IS_DIR, event.mask) |
| 983 | + self.assertEqual(common_tests.OP_FLAGS['IN_CREATE'] | |
| 984 | + common_tests.IS_DIR, event.mask) |
| 985 | self.assertEqual('IN_CREATE|IN_ISDIR', event.maskname) |
| 986 | self.assertEqual(os.path.split(dir_name)[1], event.name) |
| 987 | self.assertEqual('.', event.path) |
| 988 | self.assertEqual(os.path.join(self.basedir, dir_name), event.pathname) |
| 989 | self.assertEqual(0, event.wd) |
| 990 | - # assert the logging |
| 991 | - self._assert_logs(events) |
| 992 | |
| 993 | @defer.inlineCallbacks |
| 994 | def test_file_remove(self): |
| 995 | @@ -251,14 +239,12 @@ |
| 996 | remove_file, 1) |
| 997 | event = events[0] |
| 998 | self.assertFalse(event.dir) |
| 999 | - self.assertEqual(OP_FLAGS['IN_DELETE'], event.mask) |
| 1000 | + self.assertEqual(common_tests.OP_FLAGS['IN_DELETE'], event.mask) |
| 1001 | self.assertEqual('IN_DELETE', event.maskname) |
| 1002 | self.assertEqual(os.path.split(file_name)[1], event.name) |
| 1003 | self.assertEqual('.', event.path) |
| 1004 | self.assertEqual(os.path.join(self.basedir, file_name), event.pathname) |
| 1005 | self.assertEqual(0, event.wd) |
| 1006 | - # assert the logging |
| 1007 | - self._assert_logs(events) |
| 1008 | |
| 1009 | @defer.inlineCallbacks |
| 1010 | def test_dir_remove(self): |
| 1011 | @@ -275,13 +261,12 @@ |
| 1012 | remove_dir, 1) |
| 1013 | event = events[0] |
| 1014 | self.assertTrue(event.dir) |
| 1015 | - self.assertEqual(OP_FLAGS['IN_DELETE'] | IS_DIR, event.mask) |
| 1016 | + self.assertEqual(common_tests.OP_FLAGS['IN_DELETE'] | |
| 1017 | + common_tests.IS_DIR, event.mask) |
| 1018 | self.assertEqual('IN_DELETE|IN_ISDIR', event.maskname) |
| 1019 | self.assertEqual('.', event.path) |
| 1020 | self.assertEqual(os.path.join(self.basedir, dir_name), event.pathname) |
| 1021 | self.assertEqual(0, event.wd) |
| 1022 | - # assert the logging |
| 1023 | - self._assert_logs(events) |
| 1024 | |
| 1025 | @defer.inlineCallbacks |
| 1026 | def test_file_write(self): |
| 1027 | @@ -301,14 +286,12 @@ |
| 1028 | write_file, 1) |
| 1029 | event = events[0] |
| 1030 | self.assertFalse(event.dir) |
| 1031 | - self.assertEqual(OP_FLAGS['IN_CREATE'], event.mask) |
| 1032 | + self.assertEqual(common_tests.OP_FLAGS['IN_CREATE'], event.mask) |
| 1033 | self.assertEqual('IN_CREATE', event.maskname) |
| 1034 | self.assertEqual(os.path.split(file_name)[1], event.name) |
| 1035 | self.assertEqual('.', event.path) |
| 1036 | self.assertEqual(os.path.join(self.basedir, file_name), event.pathname) |
| 1037 | self.assertEqual(0, event.wd) |
| 1038 | - # assert the logging |
| 1039 | - self._assert_logs(events) |
| 1040 | |
| 1041 | @defer.inlineCallbacks |
| 1042 | def test_file_moved_to_watched_dir_same_watcher(self): |
| 1043 | @@ -330,7 +313,8 @@ |
| 1044 | move_to_event = events[1] |
| 1045 | # first test the move from |
| 1046 | self.assertFalse(move_from_event.dir) |
| 1047 | - self.assertEqual(OP_FLAGS['IN_MOVED_FROM'], move_from_event.mask) |
| 1048 | + self.assertEqual(common_tests.OP_FLAGS['IN_MOVED_FROM'], |
| 1049 | + move_from_event.mask) |
| 1050 | self.assertEqual('IN_MOVED_FROM', move_from_event.maskname) |
| 1051 | self.assertEqual(os.path.split(from_file_name)[1], |
| 1052 | move_from_event.name) |
| 1053 | @@ -340,7 +324,8 @@ |
| 1054 | self.assertEqual(0, move_from_event.wd) |
| 1055 | # test the move to |
| 1056 | self.assertFalse(move_to_event.dir) |
| 1057 | - self.assertEqual(OP_FLAGS['IN_MOVED_TO'], move_to_event.mask) |
| 1058 | + self.assertEqual(common_tests.OP_FLAGS['IN_MOVED_TO'], |
| 1059 | + move_to_event.mask) |
| 1060 | self.assertEqual('IN_MOVED_TO', move_to_event.maskname) |
| 1061 | self.assertEqual(os.path.split(to_file_name)[1], move_to_event.name) |
| 1062 | self.assertEqual('.', move_to_event.path) |
| 1063 | @@ -351,8 +336,6 @@ |
| 1064 | self.assertEqual(0, move_to_event.wd) |
| 1065 | # assert that both cookies are the same |
| 1066 | self.assertEqual(move_from_event.cookie, move_to_event.cookie) |
| 1067 | - # assert the logging |
| 1068 | - self._assert_logs(events) |
| 1069 | |
| 1070 | @defer.inlineCallbacks |
| 1071 | def test_file_moved_to_not_watched_dir(self): |
| 1072 | @@ -372,15 +355,13 @@ |
| 1073 | move_file, 1) |
| 1074 | event = events[0] |
| 1075 | self.assertFalse(event.dir) |
| 1076 | - self.assertEqual(OP_FLAGS['IN_DELETE'], event.mask) |
| 1077 | + self.assertEqual(common_tests.OP_FLAGS['IN_DELETE'], event.mask) |
| 1078 | self.assertEqual('IN_DELETE', event.maskname) |
| 1079 | self.assertEqual(os.path.split(from_file_name)[1], event.name) |
| 1080 | self.assertEqual('.', event.path) |
| 1081 | self.assertEqual(os.path.join(self.basedir, from_file_name), |
| 1082 | event.pathname) |
| 1083 | self.assertEqual(0, event.wd) |
| 1084 | - # assert the logging |
| 1085 | - self._assert_logs(events) |
| 1086 | |
| 1087 | @defer.inlineCallbacks |
| 1088 | def test_file_move_from_not_watched_dir(self): |
| 1089 | @@ -402,15 +383,13 @@ |
| 1090 | move_files, 1) |
| 1091 | event = events[0] |
| 1092 | self.assertFalse(event.dir) |
| 1093 | - self.assertEqual(OP_FLAGS['IN_CREATE'], event.mask) |
| 1094 | + self.assertEqual(common_tests.OP_FLAGS['IN_CREATE'], event.mask) |
| 1095 | self.assertEqual('IN_CREATE', event.maskname) |
| 1096 | self.assertEqual(os.path.split(to_file_name)[1], event.name) |
| 1097 | self.assertEqual('.', event.path) |
| 1098 | self.assertEqual(os.path.join(self.basedir, to_file_name), |
| 1099 | event.pathname) |
| 1100 | self.assertEqual(0, event.wd) |
| 1101 | - # assert the logging |
| 1102 | - self._assert_logs(events) |
| 1103 | |
| 1104 | @defer.inlineCallbacks |
| 1105 | def test_dir_moved_to_watched_dir_same_watcher(self): |
| 1106 | @@ -431,7 +410,8 @@ |
| 1107 | move_to_event = events[1] |
| 1108 | # first test the move from |
| 1109 | self.assertTrue(move_from_event.dir) |
| 1110 | - self.assertEqual(OP_FLAGS['IN_MOVED_FROM'] | IS_DIR, |
| 1111 | + self.assertEqual(common_tests.OP_FLAGS['IN_MOVED_FROM'] | |
| 1112 | + common_tests.IS_DIR, |
| 1113 | move_from_event.mask) |
| 1114 | self.assertEqual('IN_MOVED_FROM|IN_ISDIR', move_from_event.maskname) |
| 1115 | self.assertEqual(os.path.split(from_dir_name)[1], move_from_event.name) |
| 1116 | @@ -441,7 +421,8 @@ |
| 1117 | self.assertEqual(0, move_from_event.wd) |
| 1118 | # test the move to |
| 1119 | self.assertTrue(move_to_event.dir) |
| 1120 | - self.assertEqual(OP_FLAGS['IN_MOVED_TO'] | IS_DIR, move_to_event.mask) |
| 1121 | + self.assertEqual(common_tests.OP_FLAGS['IN_MOVED_TO'] | |
| 1122 | + common_tests.IS_DIR, move_to_event.mask) |
| 1123 | self.assertEqual('IN_MOVED_TO|IN_ISDIR', move_to_event.maskname) |
| 1124 | self.assertEqual(os.path.split(to_dir_name)[1], move_to_event.name) |
| 1125 | self.assertEqual('.', move_to_event.path) |
| 1126 | @@ -452,8 +433,6 @@ |
| 1127 | self.assertEqual(0, move_to_event.wd) |
| 1128 | # assert that both cookies are the same |
| 1129 | self.assertEqual(move_from_event.cookie, move_to_event.cookie) |
| 1130 | - # assert the logging |
| 1131 | - self._assert_logs(events) |
| 1132 | |
| 1133 | @defer.inlineCallbacks |
| 1134 | def test_dir_moved_to_not_watched_dir(self): |
| 1135 | @@ -473,13 +452,12 @@ |
| 1136 | move_dir, 1) |
| 1137 | event = events[0] |
| 1138 | self.assertTrue(event.dir) |
| 1139 | - self.assertEqual(OP_FLAGS['IN_DELETE'] | IS_DIR, event.mask) |
| 1140 | + self.assertEqual(common_tests.OP_FLAGS['IN_DELETE'] | |
| 1141 | + common_tests.IS_DIR, event.mask) |
| 1142 | self.assertEqual('IN_DELETE|IN_ISDIR', event.maskname) |
| 1143 | self.assertEqual('.', event.path) |
| 1144 | self.assertEqual(os.path.join(self.basedir, dir_name), event.pathname) |
| 1145 | self.assertEqual(0, event.wd) |
| 1146 | - # assert the logging |
| 1147 | - self._assert_logs(events) |
| 1148 | |
| 1149 | @defer.inlineCallbacks |
| 1150 | def test_dir_move_from_not_watched_dir(self): |
| 1151 | @@ -499,7 +477,8 @@ |
| 1152 | move_dir, 1) |
| 1153 | event = events[0] |
| 1154 | self.assertTrue(event.dir) |
| 1155 | - self.assertEqual(OP_FLAGS['IN_CREATE'] | IS_DIR, event.mask) |
| 1156 | + self.assertEqual(common_tests.OP_FLAGS['IN_CREATE'] | |
| 1157 | + common_tests.IS_DIR, event.mask) |
| 1158 | self.assertEqual('IN_CREATE|IN_ISDIR', event.maskname) |
| 1159 | self.assertEqual(os.path.split(from_dir_name)[1], event.name) |
| 1160 | self.assertEqual('.', event.path) |
| 1161 | @@ -521,149 +500,6 @@ |
| 1162 | self.assertEqual(0, len(handler.processed_events)) |
| 1163 | test_exclude_filter.skip = "we must rethink this test." |
| 1164 | |
| 1165 | - def test_ignore_path(self): |
| 1166 | - """Test that events from a path are ignored.""" |
| 1167 | - events = [] |
| 1168 | - |
| 1169 | - def fake_processor(event): |
| 1170 | - """Memorize the processed events.""" |
| 1171 | - events.append(event) |
| 1172 | - |
| 1173 | - path = '/Users/username/folder' |
| 1174 | - child = 'child' |
| 1175 | - watch = Watch(1, path, fake_processor) |
| 1176 | - watch.ignore_path(os.path.join(path, child)) |
| 1177 | - # ensure that the watch is watching |
| 1178 | - watch.platform_watch.watching = True |
| 1179 | - for file_name in 'abcdef': |
| 1180 | - event = FakeFileEvent(256, None, os.path.join(child, file_name)) |
| 1181 | - watch.platform_watch._process_events(event) |
| 1182 | - self.assertEqual(0, len(events), |
| 1183 | - 'All events should have been ignored.') |
| 1184 | - |
| 1185 | - def test_not_ignore_path(self): |
| 1186 | - """Test that we do get the events when they do not match.""" |
| 1187 | - events = [] |
| 1188 | - |
| 1189 | - def fake_processor(event): |
| 1190 | - """Memorize the processed events.""" |
| 1191 | - events.append(event) |
| 1192 | - |
| 1193 | - self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 1194 | - lambda x, e: x(e)) |
| 1195 | - |
| 1196 | - path = '/Users/username/folder' |
| 1197 | - child = 'child' |
| 1198 | - watch = Watch(1, path, fake_processor) |
| 1199 | - watch.ignore_path(os.path.join(path, child)) |
| 1200 | - paths_not_to_ignore = [] |
| 1201 | - for file_name in 'abcdef': |
| 1202 | - event = FakeFileEvent(256, None, os.path.join(child + file_name, |
| 1203 | - file_name)) |
| 1204 | - paths_not_to_ignore.append(event) |
| 1205 | - # ensure that the watch is watching |
| 1206 | - watch.platform_watch.watching = True |
| 1207 | - for event in paths_not_to_ignore: |
| 1208 | - watch.platform_watch._process_events(event) |
| 1209 | - self.assertEqual(len(paths_not_to_ignore), len(events), |
| 1210 | - 'No events should have been ignored.') |
| 1211 | - |
| 1212 | - def test_mixed_ignore_path(self): |
| 1213 | - """Test that we do get the correct events.""" |
| 1214 | - events = [] |
| 1215 | - |
| 1216 | - def fake_processor(event): |
| 1217 | - """Memorize the processed events.""" |
| 1218 | - events.append(event.pathname) |
| 1219 | - |
| 1220 | - self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 1221 | - lambda x, e: x(e)) |
| 1222 | - |
| 1223 | - child = 'child' |
| 1224 | - path = '/Users/username/folder' |
| 1225 | - watch = Watch(1, path, fake_processor) |
| 1226 | - watch.ignore_path(os.path.join(path, child)) |
| 1227 | - paths_not_to_ignore = [] |
| 1228 | - paths_to_ignore = [] |
| 1229 | - expected_events = [] |
| 1230 | - for file_name in 'abcdef': |
| 1231 | - valid = os.path.join(child + file_name, file_name) |
| 1232 | - paths_to_ignore.append((1, os.path.join(child, file_name))) |
| 1233 | - event = FakeFileEvent(256, None, valid) |
| 1234 | - paths_not_to_ignore.append(event) |
| 1235 | - expected_events.append(os.path.join(path, valid)) |
| 1236 | - # ensure that the watch is watching |
| 1237 | - watch.platform_watch.watching = True |
| 1238 | - for event in paths_not_to_ignore: |
| 1239 | - watch.platform_watch._process_events(event) |
| 1240 | - self.assertEqual(len(paths_not_to_ignore), len(events), |
| 1241 | - 'Wrong number of events ignored.') |
| 1242 | - self.assertTrue(all([event in expected_events for event in events]), |
| 1243 | - 'Paths ignored that should have not been ignored.') |
| 1244 | - |
| 1245 | - def test_undo_ignore_path_ignored(self): |
| 1246 | - """Test that we do deal with events from and old ignored path.""" |
| 1247 | - events = [] |
| 1248 | - |
| 1249 | - def fake_processor(event): |
| 1250 | - """Memorize the processed events.""" |
| 1251 | - events.append(event) |
| 1252 | - |
| 1253 | - self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 1254 | - lambda x, e: x(e)) |
| 1255 | - |
| 1256 | - path = '/Users/username/folder' |
| 1257 | - child = 'child' |
| 1258 | - watch = Watch(1, path, fake_processor) |
| 1259 | - watch.ignore_path(os.path.join(path, child)) |
| 1260 | - watch.remove_ignored_path(os.path.join(path, child)) |
| 1261 | - paths_not_to_ignore = [] |
| 1262 | - for file_name in 'abcdef': |
| 1263 | - event = FakeFileEvent(256, None, os.path.join(child, file_name)) |
| 1264 | - paths_not_to_ignore.append(event) |
| 1265 | - # ensure that the watch is watching |
| 1266 | - watch.platform_watch.watching = True |
| 1267 | - for event in paths_not_to_ignore: |
| 1268 | - watch.platform_watch._process_events(event) |
| 1269 | - self.assertEqual(len(paths_not_to_ignore), len(events), |
| 1270 | - 'All events should have been accepted.') |
| 1271 | - |
| 1272 | - def test_undo_ignore_path_other_ignored(self): |
| 1273 | - """Test that we can undo and the other path is ignored.""" |
| 1274 | - events = [] |
| 1275 | - |
| 1276 | - def fake_processor(event): |
| 1277 | - """Memorize the processed events.""" |
| 1278 | - events.append(event.pathname) |
| 1279 | - |
| 1280 | - self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 1281 | - lambda x, e: x(e)) |
| 1282 | - |
| 1283 | - path = '/Users/username/folder' |
| 1284 | - child_a = 'childa' |
| 1285 | - child_b = 'childb' |
| 1286 | - watch = Watch(1, path, fake_processor) |
| 1287 | - watch.ignore_path(os.path.join(path, child_a)) |
| 1288 | - watch.ignore_path(os.path.join(path, child_b)) |
| 1289 | - watch.remove_ignored_path(os.path.join(path, child_a)) |
| 1290 | - paths_to_ignore = [] |
| 1291 | - paths_not_to_ignore = [] |
| 1292 | - expected_events = [] |
| 1293 | - for file_name in 'abcdef': |
| 1294 | - paths_to_ignore.append((1, os.path.join(child_b, file_name))) |
| 1295 | - valid = os.path.join(child_a, file_name) |
| 1296 | - event = FakeFileEvent(256, None, valid) |
| 1297 | - paths_not_to_ignore.append(event) |
| 1298 | - expected_events.append(os.path.join(path, valid)) |
| 1299 | - # ensure that the watch is watching |
| 1300 | - watch.platform_watch.watching = True |
| 1301 | - for event in paths_not_to_ignore: |
| 1302 | - watch.platform_watch._process_events(event) |
| 1303 | - self.assertEqual(len(paths_not_to_ignore), len(events), |
| 1304 | - 'All events should have been accepted.') |
| 1305 | - self.assertTrue(all([event in expected_events for event in events]), |
| 1306 | - 'Paths ignored that should have not been ignored.') |
| 1307 | - |
| 1308 | def test_stream_created(self): |
| 1309 | """Test that the stream is created.""" |
| 1310 | def fake_call(*args, **kwargs): |
| 1311 | @@ -684,7 +520,7 @@ |
| 1312 | |
| 1313 | def random_error(self, *args): |
| 1314 | """Throw a fake exception.""" |
| 1315 | - raise FakeException() |
| 1316 | + raise common_tests.FakeException() |
| 1317 | |
| 1318 | def test_is_path_dir_missing_no_subdir(self): |
| 1319 | """Test when the path does not exist and is no a subdir.""" |
| 1320 | @@ -760,7 +596,7 @@ |
| 1321 | self.assertTrue(path not in watch._subdirs) |
| 1322 | |
| 1323 | |
| 1324 | -class TestWatchManager(BaseTwistedTestCase): |
| 1325 | +class TestWatchManager(common_tests.TestWatchManager): |
| 1326 | """Test the watch manager.""" |
| 1327 | |
| 1328 | @defer.inlineCallbacks |
| 1329 | @@ -772,24 +608,19 @@ |
| 1330 | self.watch = Watch(1, self.path, None) |
| 1331 | self.manager = WatchManager(None) |
| 1332 | self.manager._wdm = {1: self.watch} |
| 1333 | + self.stream = None |
| 1334 | + self.fake_events_processor = FakeEventsProcessor() |
| 1335 | |
| 1336 | @defer.inlineCallbacks |
| 1337 | def test_stop(self): |
| 1338 | """Test that the different watches are stopped.""" |
| 1339 | - self.was_called = False |
| 1340 | - |
| 1341 | - def fake_stop_watching(watch): |
| 1342 | - """Fake stop watch.""" |
| 1343 | - self.was_called = True |
| 1344 | - return defer.succeed(True) |
| 1345 | - |
| 1346 | - self.patch(Watch, "stop_watching", fake_stop_watching) |
| 1347 | + self.patch(self.manager.manager.observer, "unschedule", |
| 1348 | + lambda x: None) |
| 1349 | self.patch(self.manager.manager.observer, "unschedule", lambda x: None) |
| 1350 | - yield self.manager.stop() |
| 1351 | - self.assertTrue(self.was_called, 'The watch stop should be called.') |
| 1352 | + yield super(TestWatchManager, self).test_stop() |
| 1353 | |
| 1354 | def test_stop_multiple(self): |
| 1355 | - """The watches should became watching=False and the observer stopped.""" |
| 1356 | + """Watches should became watching=False and the observer stopped.""" |
| 1357 | self.patch(self.manager.manager.observer, "unschedule", lambda x: None) |
| 1358 | second_path = self.parent_path + "second_path" |
| 1359 | second_watch = Watch(2, second_path, None) |
| 1360 | @@ -810,28 +641,6 @@ |
| 1361 | """Test that we get an error when trying to get a missing wd.""" |
| 1362 | self.assertRaises(KeyError, self.manager.get_watch, (1,)) |
| 1363 | |
| 1364 | - @defer.inlineCallbacks |
| 1365 | - def test_delete_present_watch(self): |
| 1366 | - """Test that we can remove a present watch.""" |
| 1367 | - self.was_called = False |
| 1368 | - |
| 1369 | - def stop_watching(): |
| 1370 | - """Fake stop watch.""" |
| 1371 | - self.was_called = True |
| 1372 | - return defer.succeed(True) |
| 1373 | - |
| 1374 | - def fake_unschedule(s): |
| 1375 | - """Fake function that should receive a Stream object.""" |
| 1376 | - self.stream = s |
| 1377 | - |
| 1378 | - self.patch(self.manager.manager.observer, "unschedule", |
| 1379 | - fake_unschedule) |
| 1380 | - |
| 1381 | - self.watch.stop_watching = stop_watching |
| 1382 | - yield self.manager.del_watch(1) |
| 1383 | - self.assertIsInstance(self.stream, fsevents.Stream) |
| 1384 | - self.assertRaises(KeyError, self.manager.get_watch, (1,)) |
| 1385 | - |
| 1386 | def test_add_single_watch(self): |
| 1387 | """Test the addition of a new single watch.""" |
| 1388 | self.was_called = False |
| 1389 | @@ -849,10 +658,6 @@ |
| 1390 | self.assertTrue(self.was_called, 'The watch start was not called.') |
| 1391 | self.assertEqual(self.path + os.path.sep, self.manager._wdm[0].path) |
| 1392 | |
| 1393 | - def test_get_watch_present_wd(self): |
| 1394 | - """Test that the correct path is returned.""" |
| 1395 | - self.assertEqual(self.path + os.path.sep, self.manager.get_path(1)) |
| 1396 | - |
| 1397 | def test_get_watch_missing_wd(self): |
| 1398 | """Test that the correct path is returned.""" |
| 1399 | self.manager._wdm = {} |
| 1400 | @@ -873,60 +678,24 @@ |
| 1401 | |
| 1402 | def test_rm_present_wd(self): |
| 1403 | """Test the removal of a present watch.""" |
| 1404 | - self.patch(self.watch, "stop_watching", lambda: None) |
| 1405 | self.patch(self.manager.manager.observer, "unschedule", lambda x: None) |
| 1406 | - self.manager.rm_watch(1) |
| 1407 | - self.assertEqual(None, self.manager._wdm.get(1)) |
| 1408 | - |
| 1409 | - def test_rm_root_path(self): |
| 1410 | - """Test the removal of a root path.""" |
| 1411 | - events = [] |
| 1412 | - |
| 1413 | - def fake_processor(event): |
| 1414 | - """Memorize the processed events.""" |
| 1415 | - events.append(event.pathname) |
| 1416 | - |
| 1417 | - self.watch._processor = fake_processor |
| 1418 | - self.manager.rm_path(self.path) |
| 1419 | - self.assertEqual(self.watch, self.manager._wdm.get(1)) |
| 1420 | - self.watch._watching = True |
| 1421 | - event = FakeFileEvent(256, None, os.path.join(self.path, 'test')) |
| 1422 | - self.watch.platform_watch._process_events(event) |
| 1423 | - self.assertEqual(0, len(events)) |
| 1424 | + super(TestWatchManager, self).test_rm_present_wd() |
| 1425 | |
| 1426 | def test_rm_child_path(self): |
| 1427 | """Test the removal of a child path.""" |
| 1428 | - events = [] |
| 1429 | - |
| 1430 | - def fake_processor(event): |
| 1431 | - """Memorize the processed events.""" |
| 1432 | - events.append(event.pathname) |
| 1433 | - |
| 1434 | self.patch(filesystem_notifications.reactor, 'callFromThread', |
| 1435 | lambda x, e: x(e)) |
| 1436 | - |
| 1437 | - self.watch._processor = fake_processor |
| 1438 | - child = os.path.join(self.path, 'child') |
| 1439 | - self.manager.rm_path(child) |
| 1440 | - self.assertEqual(self.watch, self.manager._wdm[1]) |
| 1441 | - # assert that the correct event is ignored |
| 1442 | - self.watch.platform_watch.watching = True |
| 1443 | - event = FakeFileEvent(256, None, os.path.join('child', 'test')) |
| 1444 | - self.watch.platform_watch._process_events(event) |
| 1445 | - self.assertEqual(0, len(events)) |
| 1446 | - # assert that other events are not ignored |
| 1447 | - event2 = FakeFileEvent(256, None, 'test') |
| 1448 | - self.watch.platform_watch._process_events(event2) |
| 1449 | - self.assertEqual(1, len(events)) |
| 1450 | - |
| 1451 | - |
| 1452 | -class TestWatchManagerAddWatches(BaseTwistedTestCase): |
| 1453 | + super(TestWatchManager, self).test_rm_child_path() |
| 1454 | + |
| 1455 | + |
| 1456 | +class TestWatchManagerAddWatches(common_tests.TestWatchManagerAddWatches): |
| 1457 | """Test the watch manager.""" |
| 1458 | timeout = 5 |
| 1459 | |
| 1460 | def test_add_watch_twice(self): |
| 1461 | """Adding a watch twice succeeds when the watch is running.""" |
| 1462 | self.patch(Watch, "start_watching", lambda self: None) |
| 1463 | + self.patch(Watch, "started", lambda self: True) |
| 1464 | manager = WatchManager(None) |
| 1465 | # no need to stop watching because start_watching is fake |
| 1466 | |
| 1467 | @@ -936,7 +705,7 @@ |
| 1468 | d2 = manager.add_watch(path, mask) |
| 1469 | |
| 1470 | self.assertTrue(d1.result, "Should not be called yet.") |
| 1471 | - self.assertFalse(d2.result, "Should not be called yet.") |
| 1472 | + self.assertTrue(d2, "Should not be called yet.") |
| 1473 | |
| 1474 | |
| 1475 | class FakeEvent(object): |
| 1476 | @@ -953,88 +722,15 @@ |
| 1477 | self.cookie = cookie |
| 1478 | |
| 1479 | |
| 1480 | -class FakeLog(object): |
| 1481 | - """A fake log that is used by the general processor.""" |
| 1482 | - |
| 1483 | - def __init__(self): |
| 1484 | - """Create the fake.""" |
| 1485 | - self.called_methods = [] |
| 1486 | - |
| 1487 | - def info(self, *args): |
| 1488 | - """Fake the info call.""" |
| 1489 | - self.called_methods.append(('info', args)) |
| 1490 | - |
| 1491 | - |
| 1492 | -class FakeGeneralProcessor(object): |
| 1493 | - """Fake implementation of the general processor.""" |
| 1494 | - |
| 1495 | - def __init__(self): |
| 1496 | - """Create the fake.""" |
| 1497 | - self.called_methods = [] |
| 1498 | - self.paths_to_return = [] |
| 1499 | - self.log = FakeLog() |
| 1500 | - self.share_id = None |
| 1501 | - self.ignore = False |
| 1502 | - |
| 1503 | - def rm_from_mute_filter(self, event, paths): |
| 1504 | - """Fake rm_from_mute_filter.""" |
| 1505 | - self.called_methods.append(('rm_from_mute_filter', event, paths)) |
| 1506 | - |
| 1507 | - def add_to_mute_filter(self, event, paths): |
| 1508 | - """Fake add_to_move_filter.""" |
| 1509 | - self.called_methods.append(('add_to_mute_filter', event, paths)) |
| 1510 | - |
| 1511 | - def is_ignored(self, path): |
| 1512 | - """Fake is_ignored.""" |
| 1513 | - self.called_methods.append(('is_ignored', path)) |
| 1514 | - return self.ignore |
| 1515 | - |
| 1516 | - def push_event(self, event): |
| 1517 | - """Fake push event.""" |
| 1518 | - self.called_methods.append(('push_event', event)) |
| 1519 | - |
| 1520 | - def eq_push(self, event, path=None, path_to=None, path_from=None): |
| 1521 | - """Fake event to push event.""" |
| 1522 | - self.called_methods.append(('eq_push', event, path, path_to, |
| 1523 | - path_from)) |
| 1524 | - |
| 1525 | - def get_paths_starting_with(self, fullpath, include_base=False): |
| 1526 | - """Fake get_paths_starting_with.""" |
| 1527 | - self.called_methods.append(('get_paths_starting_with', fullpath, |
| 1528 | - include_base)) |
| 1529 | - return self.paths_to_return |
| 1530 | - |
| 1531 | - def get_path_share_id(self, path): |
| 1532 | - """Fake get_path_share_id.""" |
| 1533 | - self.called_methods.append(('get_path_share_id', path)) |
| 1534 | - return self.share_id |
| 1535 | - |
| 1536 | - def rm_watch(self, path): |
| 1537 | - """Fake the remove watch.""" |
| 1538 | - self.called_methods.append(('rm_watch', path)) |
| 1539 | - |
| 1540 | - def freeze_begin(self, path): |
| 1541 | - """Fake freeze_begin""" |
| 1542 | - self.called_methods.append(('freeze_begin', path)) |
| 1543 | - |
| 1544 | - def freeze_rollback(self): |
| 1545 | - """Fake rollback.""" |
| 1546 | - self.called_methods.append(('freeze_rollback',)) |
| 1547 | - |
| 1548 | - def freeze_commit(self, path): |
| 1549 | - """Fake freeze commit.""" |
| 1550 | - self.called_methods.append(('freeze_commit', path)) |
| 1551 | - |
| 1552 | - |
| 1553 | -class TestNotifyProcessor(BaseTwistedTestCase): |
| 1554 | +class TestNotifyProcessor(common_tests.TestNotifyProcessor): |
| 1555 | """Test the notify processor.""" |
| 1556 | |
| 1557 | @defer.inlineCallbacks |
| 1558 | def setUp(self): |
| 1559 | - """set up the diffeent tests.""" |
| 1560 | + """set up the different tests.""" |
| 1561 | yield super(TestNotifyProcessor, self).setUp() |
| 1562 | self.processor = notify_processor.NotifyProcessor(None) |
| 1563 | - self.general = FakeGeneralProcessor() |
| 1564 | + self.general = common_tests.FakeGeneralProcessor() |
| 1565 | self.processor.general_processor = self.general |
| 1566 | |
| 1567 | def test_rm_from_mute_filter(self): |
| 1568 | |
| 1569 | === added file 'tests/platform/filesystem_notifications/test_windows.py' |
| 1570 | --- tests/platform/filesystem_notifications/test_windows.py 1970-01-01 00:00:00 +0000 |
| 1571 | +++ tests/platform/filesystem_notifications/test_windows.py 2012-08-06 16:57:22 +0000 |
| 1572 | @@ -0,0 +1,344 @@ |
| 1573 | +# |
| 1574 | +# Authors: Manuel de la Pena <manuel@canonical.com> |
| 1575 | +# Alejandro J. Cura <alecu@canonical.com> |
| 1576 | +# |
| 1577 | +# Copyright 2011-2012 Canonical Ltd. |
| 1578 | +# |
| 1579 | +# This program is free software: you can redistribute it and/or modify it |
| 1580 | +# under the terms of the GNU General Public License version 3, as published |
| 1581 | +# by the Free Software Foundation. |
| 1582 | +# |
| 1583 | +# This program is distributed in the hope that it will be useful, but |
| 1584 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
| 1585 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
| 1586 | +# PURPOSE. See the GNU General Public License for more details. |
| 1587 | +# |
| 1588 | +# You should have received a copy of the GNU General Public License along |
| 1589 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
| 1590 | +# |
| 1591 | +# In addition, as a special exception, the copyright holders give |
| 1592 | +# permission to link the code of portions of this program with the |
| 1593 | +# OpenSSL library under certain conditions as described in each |
| 1594 | +# individual source file, and distribute linked combinations |
| 1595 | +# including the two. |
| 1596 | +# You must obey the GNU General Public License in all respects |
| 1597 | +# for all of the code used other than OpenSSL. If you modify |
| 1598 | +# file(s) with this exception, you may extend this exception to your |
| 1599 | +# version of the file(s), but you are not obligated to do so. If you |
| 1600 | +# do not wish to do so, delete this exception statement from your |
| 1601 | +# version. If you delete this exception statement from all source |
| 1602 | +# files in the program, then also delete it here. |
| 1603 | +"""Test the filesystem notifications on windows.""" |
| 1604 | + |
| 1605 | +import os |
| 1606 | + |
| 1607 | +from twisted.internet import defer |
| 1608 | +from win32file import FILE_NOTIFY_INFORMATION |
| 1609 | + |
| 1610 | +from ubuntuone.platform.filesystem_notifications.monitor import ( |
| 1611 | + common, |
| 1612 | + windows as filesystem_notifications, |
| 1613 | +) |
| 1614 | +from ubuntuone.platform.filesystem_notifications.monitor.common import ( |
| 1615 | + FilesystemMonitor, |
| 1616 | + Watch, |
| 1617 | + WatchManager, |
| 1618 | +) |
| 1619 | +from ubuntuone.platform.filesystem_notifications.monitor.windows import ( |
| 1620 | + FILE_NOTIFY_CHANGE_FILE_NAME, |
| 1621 | + FILE_NOTIFY_CHANGE_DIR_NAME, |
| 1622 | + FILE_NOTIFY_CHANGE_ATTRIBUTES, |
| 1623 | + FILE_NOTIFY_CHANGE_SIZE, |
| 1624 | + FILE_NOTIFY_CHANGE_LAST_WRITE, |
| 1625 | + FILE_NOTIFY_CHANGE_SECURITY, |
| 1626 | + FILE_NOTIFY_CHANGE_LAST_ACCESS, |
| 1627 | +) |
| 1628 | +from tests.platform.filesystem_notifications import common as common_tests |
| 1629 | + |
| 1630 | + |
| 1631 | +class FakeEventsProcessor(object): |
| 1632 | + |
| 1633 | + """Handle fake events creation and processing.""" |
| 1634 | + |
| 1635 | + def create_fake_event(self, filename): |
| 1636 | + """Create a fake file event.""" |
| 1637 | + return (1, filename) |
| 1638 | + |
| 1639 | + def custom_process_events(self, watch, events): |
| 1640 | + """Adapt to each platform way to process events.""" |
| 1641 | + watch.platform_watch._process_events(events) |
| 1642 | + |
| 1643 | + |
| 1644 | +class TestWatch(common_tests.TestWatch): |
| 1645 | + """Test the watch so that it returns the same events as pyinotify.""" |
| 1646 | + |
| 1647 | + timeout = 5 |
| 1648 | + |
| 1649 | + @defer.inlineCallbacks |
| 1650 | + def setUp(self): |
| 1651 | + yield super(TestWatch, self).setUp() |
| 1652 | + self.path = u'\\\\?\\C:\\path' # a valid windows path |
| 1653 | + self.common_path = u'C:\\path' |
| 1654 | + self.invalid_path = u'\\\\?\\C:\\path\\to\\no\\dir' |
| 1655 | + self.mask = FILE_NOTIFY_CHANGE_FILE_NAME | \ |
| 1656 | + FILE_NOTIFY_CHANGE_DIR_NAME | \ |
| 1657 | + FILE_NOTIFY_CHANGE_ATTRIBUTES | \ |
| 1658 | + FILE_NOTIFY_CHANGE_SIZE | \ |
| 1659 | + FILE_NOTIFY_CHANGE_LAST_WRITE | \ |
| 1660 | + FILE_NOTIFY_CHANGE_SECURITY | \ |
| 1661 | + FILE_NOTIFY_CHANGE_LAST_ACCESS |
| 1662 | + self.fake_events_processor = FakeEventsProcessor() |
| 1663 | + |
| 1664 | + def file_notify_information_wrapper(buf, data): |
| 1665 | + """Wrapper that gets the events and adds them to the list.""" |
| 1666 | + events = FILE_NOTIFY_INFORMATION(buf, data) |
| 1667 | + # we want to append the list because that is what will be logged. |
| 1668 | + # If we use extend we wont have the same logging because it will |
| 1669 | + # group all events in a single lists which is not what the COM API |
| 1670 | + # does. |
| 1671 | + str_events = [ |
| 1672 | + (common.ACTIONS_NAMES[action], path) for action, path in |
| 1673 | + events] |
| 1674 | + self.raw_events.append(str_events) |
| 1675 | + return events |
| 1676 | + |
| 1677 | + self.patch(filesystem_notifications, 'FILE_NOTIFY_INFORMATION', |
| 1678 | + file_notify_information_wrapper) |
| 1679 | + |
| 1680 | + @defer.inlineCallbacks |
| 1681 | + def test_file_write(self): |
| 1682 | + """Test that the correct event is raised when a file is written.""" |
| 1683 | + file_name = os.path.join(self.basedir, 'test_file_write') |
| 1684 | + # create the file before recording |
| 1685 | + fd = open(file_name, 'w') |
| 1686 | + # clean behind us by removing the file |
| 1687 | + self.addCleanup(os.remove, file_name) |
| 1688 | + |
| 1689 | + def write_file(): |
| 1690 | + """Action for the test.""" |
| 1691 | + fd.write('test') |
| 1692 | + fd.close() |
| 1693 | + |
| 1694 | + events = yield self._perform_operations(self.basedir, self.mask, |
| 1695 | + write_file, 1) |
| 1696 | + event = events[0] |
| 1697 | + self.assertFalse(event.dir) |
| 1698 | + self.assertEqual(0x2, event.mask) |
| 1699 | + self.assertEqual('IN_MODIFY', event.maskname) |
| 1700 | + self.assertEqual(os.path.split(file_name)[1], event.name) |
| 1701 | + self.assertEqual('.', event.path) |
| 1702 | + self.assertEqual(os.path.join(self.basedir, file_name), event.pathname) |
| 1703 | + self.assertEqual(0, event.wd) |
| 1704 | + |
| 1705 | + @defer.inlineCallbacks |
| 1706 | + def test_call_deferred_already_called(self): |
| 1707 | + """Test that the function is not called.""" |
| 1708 | + method_args = [] |
| 1709 | + |
| 1710 | + def fake_call(*args, **kwargs): |
| 1711 | + """Execute the call.""" |
| 1712 | + method_args.append((args, kwargs),) |
| 1713 | + |
| 1714 | + watch = Watch(1, self.path, None) |
| 1715 | + yield watch.platform_watch._watch_started_deferred.callback(True) |
| 1716 | + watch.platform_watch._call_deferred(fake_call, None) |
| 1717 | + self.assertEqual(0, len(method_args)) |
| 1718 | + |
| 1719 | + def test_call_deferred_not_called(self): |
| 1720 | + """Test that is indeed called.""" |
| 1721 | + method_args = [] |
| 1722 | + |
| 1723 | + def fake_call(*args, **kwargs): |
| 1724 | + """Execute the call.""" |
| 1725 | + method_args.append((args, kwargs),) |
| 1726 | + |
| 1727 | + watch = Watch(1, self.path, None) |
| 1728 | + watch.platform_watch._call_deferred(fake_call, None) |
| 1729 | + self.assertEqual(1, len(method_args)) |
| 1730 | + |
| 1731 | + def test_started_property(self): |
| 1732 | + """Test that the started property returns the started deferred.""" |
| 1733 | + watch = Watch(1, self.path, None) |
| 1734 | + self.assertEqual(watch.started, |
| 1735 | + watch.platform_watch._watch_started_deferred) |
| 1736 | + |
| 1737 | + def test_stopped_property(self): |
| 1738 | + """Test that the stopped property returns the stopped deferred.""" |
| 1739 | + watch = Watch(1, self.path, None) |
| 1740 | + self.assertEqual(watch.stopped, |
| 1741 | + watch.platform_watch._watch_stopped_deferred) |
| 1742 | + |
| 1743 | + @defer.inlineCallbacks |
| 1744 | + def test_start_watching_fails_early_in_thread(self): |
| 1745 | + """An early failure inside the thread should errback the deferred.""" |
| 1746 | + test_path = self.mktemp("test_directory") |
| 1747 | + self.patch(filesystem_notifications, "CreateFileW", self.random_error) |
| 1748 | + watch = Watch(1, test_path, None) |
| 1749 | + d = watch.start_watching() |
| 1750 | + yield self.assertFailure(d, common_tests.FakeException) |
| 1751 | + |
| 1752 | + @defer.inlineCallbacks |
| 1753 | + def test_start_watching_fails_late_in_thread(self): |
| 1754 | + """A late failure inside the thread should errback the deferred.""" |
| 1755 | + test_path = self.mktemp("test_directory") |
| 1756 | + self.patch(filesystem_notifications, "ReadDirectoryChangesW", |
| 1757 | + self.random_error) |
| 1758 | + watch = Watch(1, test_path, None) |
| 1759 | + d = watch.start_watching() |
| 1760 | + yield self.assertFailure(d, common_tests.FakeException) |
| 1761 | + |
| 1762 | + @defer.inlineCallbacks |
| 1763 | + def test_close_handle_is_called_on_error(self): |
| 1764 | + """CloseHandle is called when there's an error in the watch thread.""" |
| 1765 | + test_path = self.mktemp("test_directory") |
| 1766 | + close_called = [] |
| 1767 | + self.patch(filesystem_notifications, "CreateFileW", lambda *_: None) |
| 1768 | + self.patch(filesystem_notifications, "CloseHandle", |
| 1769 | + close_called.append) |
| 1770 | + self.patch(filesystem_notifications, "ReadDirectoryChangesW", |
| 1771 | + self.random_error) |
| 1772 | + watch = Watch(1, test_path, self.mask) |
| 1773 | + d = watch.start_watching() |
| 1774 | + yield self.assertFailure(d, common_tests.FakeException) |
| 1775 | + self.assertEqual(len(close_called), 1) |
| 1776 | + yield watch.stop_watching() |
| 1777 | + |
| 1778 | + @defer.inlineCallbacks |
| 1779 | + def test_stop_watching_fired_when_watch_thread_finishes(self): |
| 1780 | + """The deferred returned is fired when the watch thread finishes.""" |
| 1781 | + test_path = self.mktemp("another_test_directory") |
| 1782 | + watch = Watch(1, test_path, self.mask) |
| 1783 | + yield watch.start_watching() |
| 1784 | + self.assertNotEqual(watch.platform_watch._watch_handle, None) |
| 1785 | + yield watch.stop_watching() |
| 1786 | + self.assertEqual(watch.platform_watch._watch_handle, None) |
| 1787 | + |
| 1788 | + |
| 1789 | +class TestWatchManager(common_tests.TestWatchManager): |
| 1790 | + """Test the watch manager.""" |
| 1791 | + |
| 1792 | + @defer.inlineCallbacks |
| 1793 | + def setUp(self): |
| 1794 | + """Set each of the tests.""" |
| 1795 | + yield super(TestWatchManager, self).setUp() |
| 1796 | + self.parent_path = u'\\\\?\\C:\\' # a valid windows path |
| 1797 | + self.path = self.parent_path + u'path' |
| 1798 | + self.watch = Watch(1, self.path, None) |
| 1799 | + self.manager._wdm = {1: self.watch} |
| 1800 | + self.fake_events_processor = FakeEventsProcessor() |
| 1801 | + |
| 1802 | + def test_add_single_watch(self): |
| 1803 | + """Test the addition of a new single watch.""" |
| 1804 | + self.was_called = False |
| 1805 | + |
| 1806 | + def fake_start_watching(*args): |
| 1807 | + """Fake start watch.""" |
| 1808 | + self.was_called = True |
| 1809 | + |
| 1810 | + self.patch(Watch, "start_watching", fake_start_watching) |
| 1811 | + self.manager._wdm = {} |
| 1812 | + |
| 1813 | + mask = 'bit_mask' |
| 1814 | + self.manager.add_watch(self.path, mask) |
| 1815 | + self.assertEqual(1, len(self.manager._wdm)) |
| 1816 | + self.assertTrue(self.was_called, 'The watch start was not called.') |
| 1817 | + self.assertEqual(self.path + os.path.sep, self.manager._wdm[0].path) |
| 1818 | + self.assertEqual(filesystem_notifications.FILESYSTEM_MONITOR_MASK, |
| 1819 | + self.manager._wdm[0].platform_watch._mask) |
| 1820 | + |
| 1821 | + @defer.inlineCallbacks |
| 1822 | + def test_stop_multiple(self): |
| 1823 | + """Test that stop is fired when *all* watches have stopped.""" |
| 1824 | + |
| 1825 | + def fake_stop_watching(watch): |
| 1826 | + """Another fake stop watch.""" |
| 1827 | + return watch.stopped |
| 1828 | + |
| 1829 | + self.patch(Watch, "stop_watching", fake_stop_watching) |
| 1830 | + second_path = self.parent_path + u"second_path" |
| 1831 | + second_watch = Watch(2, second_path, None) |
| 1832 | + self.manager._wdm[2] = second_watch |
| 1833 | + d = self.manager.stop() |
| 1834 | + self.assertFalse(d.called, "Not fired before all watches end") |
| 1835 | + self.watch.stopped.callback(None) |
| 1836 | + self.assertFalse(d.called, "Not fired before all watches end") |
| 1837 | + second_watch.stopped.callback(None) |
| 1838 | + yield d |
| 1839 | + self.assertTrue(d.called, "Fired after the watches ended") |
| 1840 | + |
| 1841 | + |
| 1842 | +class TestWatchManagerAddWatches(common_tests.TestWatchManagerAddWatches): |
| 1843 | + """Test the watch manager.""" |
| 1844 | + timeout = 5 |
| 1845 | + |
| 1846 | + def test_add_watch_twice(self): |
| 1847 | + """Adding a watch twice succeeds when the watch is running.""" |
| 1848 | + self.patch(Watch, "start_watching", lambda self: self.started) |
| 1849 | + manager = WatchManager(None) |
| 1850 | + # no need to stop watching because start_watching is fake |
| 1851 | + |
| 1852 | + path = u'\\\\?\\C:\\test' # a valid windows path |
| 1853 | + mask = 'fake bit mask' |
| 1854 | + d1 = manager.add_watch(path, mask) |
| 1855 | + d2 = manager.add_watch(path, mask) |
| 1856 | + |
| 1857 | + self.assertFalse(d1.called, "Should not be called yet.") |
| 1858 | + self.assertFalse(d2.called, "Should not be called yet.") |
| 1859 | + |
| 1860 | + manager._wdm.values()[0].started.callback(True) |
| 1861 | + |
| 1862 | + self.assertTrue(d1.called, "Should already be called.") |
| 1863 | + self.assertTrue(d2.called, "Should already be called.") |
| 1864 | + |
| 1865 | + |
| 1866 | +class TestNotifyProcessor(common_tests.TestNotifyProcessor): |
| 1867 | + """Test the notify processor.""" |
| 1868 | + |
| 1869 | + @defer.inlineCallbacks |
| 1870 | + def setUp(self): |
| 1871 | + """set up the diffeent tests.""" |
| 1872 | + yield super(TestNotifyProcessor, self).setUp() |
| 1873 | + |
| 1874 | + |
| 1875 | +class FilesystemMonitorTestCase(common_tests.FilesystemMonitorTestCase): |
| 1876 | + """Tests for the FilesystemMonitor.""" |
| 1877 | + timeout = 5 |
| 1878 | + |
| 1879 | + def test_add_watch_twice(self): |
| 1880 | + """Check the deferred returned by a second add_watch.""" |
| 1881 | + self.patch(Watch, "start_watching", lambda self: self.started) |
| 1882 | + monitor = FilesystemMonitor(None, None) |
| 1883 | + # no need to stop watching because start_watching is fake |
| 1884 | + |
| 1885 | + parent_path = 'C:\\test' # a valid windows path in utf-8 bytes |
| 1886 | + child_path = parent_path + "\\child" |
| 1887 | + d1 = monitor.add_watch(parent_path) |
| 1888 | + d2 = monitor.add_watch(child_path) |
| 1889 | + |
| 1890 | + self.assertFalse(d1.called, "Should not be called yet.") |
| 1891 | + self.assertFalse(d2.called, "Should not be called yet.") |
| 1892 | + |
| 1893 | + monitor._watch_manager._wdm.values()[0].started.callback(True) |
| 1894 | + |
| 1895 | + self.assertTrue(d1.called, "Should already be called.") |
| 1896 | + self.assertTrue(d2.called, "Should already be called.") |
| 1897 | + |
| 1898 | + @defer.inlineCallbacks |
| 1899 | + def test_add_watches_to_udf_ancestors(self): |
| 1900 | + """Test that the ancestor watches are not added.""" |
| 1901 | + |
| 1902 | + class FakeVolume(object): |
| 1903 | + """A fake UDF.""" |
| 1904 | + |
| 1905 | + def __init__(self, ancestors): |
| 1906 | + """Create a new instance.""" |
| 1907 | + self.ancestors = ancestors |
| 1908 | + |
| 1909 | + ancestors = ['~', '~\\Pictures', '~\\Pictures\\Home', ] |
| 1910 | + volume = FakeVolume(ancestors) |
| 1911 | + monitor = FilesystemMonitor(None, None) |
| 1912 | + added = yield monitor.add_watches_to_udf_ancestors(volume) |
| 1913 | + self.assertTrue(added, 'We should always return true.') |
| 1914 | + # lets ensure that we never added the watches |
| 1915 | + self.assertEqual(0, len(monitor._watch_manager._wdm.values()), |
| 1916 | + 'No watches should have been added.') |
| 1917 | |
| 1918 | === modified file 'ubuntuone/platform/filesystem_notifications/monitor/__init__.py' |
| 1919 | --- ubuntuone/platform/filesystem_notifications/monitor/__init__.py 2012-07-18 15:18:04 +0000 |
| 1920 | +++ ubuntuone/platform/filesystem_notifications/monitor/__init__.py 2012-08-06 16:57:22 +0000 |
| 1921 | @@ -42,11 +42,13 @@ |
| 1922 | if sys.platform == 'win32': |
| 1923 | from ubuntuone.platform.filesystem_notifications.monitor import ( |
| 1924 | common, |
| 1925 | + windows, |
| 1926 | ) |
| 1927 | |
| 1928 | FILEMONITOR_IDS = { |
| 1929 | DEFAULT_MONITOR: common.FilesystemMonitor, |
| 1930 | } |
| 1931 | + ACTIONS = windows.ACTIONS |
| 1932 | |
| 1933 | elif sys.platform == 'darwin': |
| 1934 | from ubuntuone.platform.filesystem_notifications.monitor import darwin |
| 1935 | @@ -58,6 +60,7 @@ |
| 1936 | DEFAULT_MONITOR: common.FilesystemMonitor, |
| 1937 | 'daemon': darwin.fsevents_daemon.FilesystemMonitor, |
| 1938 | } |
| 1939 | + ACTIONS = darwin.fsevents_client.ACTIONS |
| 1940 | else: |
| 1941 | from ubuntuone.platform.filesystem_notifications.monitor import ( |
| 1942 | linux, |
| 1943 | |
| 1944 | === modified file 'ubuntuone/platform/filesystem_notifications/monitor/common.py' |
| 1945 | --- ubuntuone/platform/filesystem_notifications/monitor/common.py 2012-07-18 09:05:26 +0000 |
| 1946 | +++ ubuntuone/platform/filesystem_notifications/monitor/common.py 2012-08-06 16:57:22 +0000 |
| 1947 | @@ -65,6 +65,7 @@ |
| 1948 | else: |
| 1949 | raise ImportError('Not supported platform') |
| 1950 | |
| 1951 | + |
| 1952 | # a map between the few events that we have on common platforms and those |
| 1953 | # found in pyinotify |
| 1954 | ACTIONS = source.ACTIONS |
| 1955 | |
| 1956 | === modified file 'ubuntuone/platform/os_helper/__init__.py' |
| 1957 | --- ubuntuone/platform/os_helper/__init__.py 2012-06-22 19:37:36 +0000 |
| 1958 | +++ ubuntuone/platform/os_helper/__init__.py 2012-08-06 16:57:22 +0000 |
| 1959 | @@ -73,6 +73,7 @@ |
| 1960 | |
| 1961 | # Decorators |
| 1962 | |
| 1963 | +get_os_valid_path = source.get_os_valid_path |
| 1964 | is_valid_syncdaemon_path = source.is_valid_syncdaemon_path |
| 1965 | is_valid_os_path = source.is_valid_os_path |
| 1966 | os_path = source.os_path |
| 1967 | |
| 1968 | === modified file 'ubuntuone/platform/os_helper/darwin.py' |
| 1969 | --- ubuntuone/platform/os_helper/darwin.py 2012-07-10 18:41:15 +0000 |
| 1970 | +++ ubuntuone/platform/os_helper/darwin.py 2012-08-06 16:57:22 +0000 |
| 1971 | @@ -29,8 +29,8 @@ |
| 1972 | """ |
| 1973 | Darwin import for ubuntuone-client |
| 1974 | |
| 1975 | -This module has to have all darwin specific modules and provide the api required |
| 1976 | -to support the darwin platform. |
| 1977 | +This module has to have all darwin specific modules and provide the |
| 1978 | +api required to support the darwin platform. |
| 1979 | """ |
| 1980 | |
| 1981 | import errno |
| 1982 | @@ -70,6 +70,7 @@ |
| 1983 | is_root = unix.is_root |
| 1984 | get_path_list = unix.get_path_list |
| 1985 | normpath = unix.normpath |
| 1986 | +get_os_valid_path = unix.get_os_valid_path |
| 1987 | |
| 1988 | |
| 1989 | def move_to_trash(path): |
| 1990 | @@ -121,6 +122,8 @@ |
| 1991 | def is_valid_os_path(path_indexes=None): |
| 1992 | def decorator(func): |
| 1993 | def wrapped(*args, **kwargs): |
| 1994 | + for i in path_indexes: |
| 1995 | + assert isinstance(args[i], str), 'Path %r should be str.' |
| 1996 | return func(*args, **kwargs) |
| 1997 | return wrapped |
| 1998 | return decorator |
| 1999 | |
| 2000 | === modified file 'ubuntuone/platform/os_helper/linux.py' |
| 2001 | --- ubuntuone/platform/os_helper/linux.py 2012-06-27 12:51:20 +0000 |
| 2002 | +++ ubuntuone/platform/os_helper/linux.py 2012-08-06 16:57:22 +0000 |
| 2003 | @@ -123,6 +123,7 @@ |
| 2004 | is_root = unix.is_root |
| 2005 | get_path_list = unix.get_path_list |
| 2006 | normpath = unix.normpath |
| 2007 | +get_os_valid_path = unix.get_os_valid_path |
| 2008 | is_valid_syncdaemon_path = None |
| 2009 | is_valid_os_path = None |
| 2010 | os_path = None |
| 2011 | |
| 2012 | === modified file 'ubuntuone/platform/os_helper/unix.py' |
| 2013 | --- ubuntuone/platform/os_helper/unix.py 2012-06-27 14:02:14 +0000 |
| 2014 | +++ ubuntuone/platform/os_helper/unix.py 2012-08-06 16:57:22 +0000 |
| 2015 | @@ -185,3 +185,8 @@ |
| 2016 | def normpath(path): |
| 2017 | """Normalize path, eliminating double slashes, etc.""" |
| 2018 | return os.path.normpath(path) |
| 2019 | + |
| 2020 | + |
| 2021 | +def get_os_valid_path(path): |
| 2022 | + """Return a valid os path.""" |
| 2023 | + return os.path.abspath(path) |
| 2024 | |
| 2025 | === modified file 'ubuntuone/platform/os_helper/windows.py' |
| 2026 | --- ubuntuone/platform/os_helper/windows.py 2012-07-03 17:16:57 +0000 |
| 2027 | +++ ubuntuone/platform/os_helper/windows.py 2012-08-06 16:57:22 +0000 |
| 2028 | @@ -249,6 +249,8 @@ |
| 2029 | assert_windows_path(result) |
| 2030 | return result |
| 2031 | |
| 2032 | +get_os_valid_path = get_windows_valid_path |
| 2033 | + |
| 2034 | |
| 2035 | def _unicode_to_bytes(path): |
| 2036 | """Convert a unicode path to a bytes path.""" |


Great branch so far!
A few comments:
---
Why is self._assert_logs removed from many places in darwin.py?
---
There is no need for the empty setUp in TestNotifyProce ssor.