def test_with_no_change(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') ctypes.windll.kernel32.CreateFileW( mox_c('/tmp'), mox_c(1), mox_c(3), None, mox_c(3), mox_c(win32_file_watcher._FILE_FLAG_BACKUP_SEMANTICS), None).AndReturn(31415) # pylint: disable=unused-argument def found_nothing(handle, buff, size, recursive, change_type, size_returned_by_ref, unused1, unused2): ctypes.cast(size_returned_by_ref, ctypes.POINTER(ctypes.c_ulong))[0] = 0 ctypes.windll.kernel32.ReadDirectoryChangesW( 31415, mox.IgnoreArg(), mox_c(4096), True, mox_c(351), mox.IgnoreArg(), None, None).WithSideEffects(found_nothing).AndReturn(-1) ctypes.windll.kernel32.CancelIoEx(31415, None) ctypes.windll.kernel32.CloseHandle(31415) self.mox.ReplayAll() watcher.start() watcher.quit() self.assertEqual(watcher.changes(), set()) self.mox.VerifyAll()
def get_file_watcher(directories, use_mtime_file_watcher): """Returns an instance that monitors a hierarchy of directories. Args: directories: A list representing the paths of the directories to monitor. use_mtime_file_watcher: A bool containing whether to use mtime polling to monitor file changes even if other options are available on the current platform. Returns: A FileWatcher appropriate for the current platform. start() must be called before has_changes(). """ assert not isinstance(directories, types.StringTypes), 'expected list got str' if len(directories) != 1: return _MultipleFileWatcher(directories, use_mtime_file_watcher) directory = directories[0] if use_mtime_file_watcher: return mtime_file_watcher.MtimeFileWatcher(directory) elif sys.platform.startswith('linux'): return inotify_file_watcher.InotifyFileWatcher(directory) elif sys.platform.startswith('win'): return win32_file_watcher.Win32FileWatcher(directory) return mtime_file_watcher.MtimeFileWatcher(directory)
def test_changes_wait_failed(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') watcher._find_change_handle = 5 ctypes.windll.kernel32.WaitForSingleObject(5, 0).AndReturn( win32_file_watcher.WAIT_FAILED) self.mox.ReplayAll() self.assertRaises(WinError, watcher.changes) self.mox.VerifyAll()
def test_changes_no_changes(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') watcher._find_change_handle = 5 ctypes.windll.kernel32.WaitForSingleObject(5, 0).AndReturn( win32_file_watcher.WAIT_TIMEOUT) self.mox.ReplayAll() self.assertFalse(watcher.changes()) self.mox.VerifyAll()
def test_with_error(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') ctypes.windll.kernel32.CreateFileW( mox_c('/tmp'), mox_c(1), mox_c(3), None, mox_c(3), mox_c(win32_file_watcher._FILE_FLAG_BACKUP_SEMANTICS), None).AndReturn(win32_file_watcher._INVALID_HANDLE_VALUE) self.mox.ReplayAll() self.assertRaises(WinError, watcher.start) self.mox.VerifyAll()
def test_start_find_next_change_notification_failed(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') ctypes.windll.kernel32.FindFirstChangeNotificationA( os.path.abspath('/tmp'), True, win32_file_watcher._INTERESTING_NOTIFICATIONS).AndReturn(5) ctypes.windll.kernel32.FindNextChangeNotification(5).AndReturn(False) self.mox.ReplayAll() self.assertRaises(WinError, watcher.start) self.mox.VerifyAll()
def test_start_successful(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') ctypes.windll.kernel32.FindFirstChangeNotificationA( os.path.abspath('/tmp'), True, win32_file_watcher._INTERESTING_NOTIFICATIONS).AndReturn(5) ctypes.windll.kernel32.FindNextChangeNotification(5).AndReturn(True) self.mox.ReplayAll() watcher.start() self.mox.VerifyAll()
def test_changes_find_next_change_notification_failed(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') watcher._find_change_handle = 5 ctypes.windll.kernel32.WaitForSingleObject(5, 0).AndReturn( win32_file_watcher.WAIT_OBJECT_0) ctypes.windll.kernel32.FindNextChangeNotification(5).AndReturn(False) self.mox.ReplayAll() self.assertRaises(WinError, watcher.changes) self.mox.VerifyAll()
def test_changes_with_changes(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') watcher._find_change_handle = 5 ctypes.windll.kernel32.WaitForSingleObject(5, 0).AndReturn( win32_file_watcher.WAIT_OBJECT_0) ctypes.windll.kernel32.FindNextChangeNotification(5).AndReturn(True) ctypes.windll.kernel32.WaitForSingleObject(5, 0).AndReturn( win32_file_watcher.WAIT_TIMEOUT) self.mox.ReplayAll() self.assertTrue(watcher.changes()) self.mox.VerifyAll()
def test_with_change(self): watcher = win32_file_watcher.Win32FileWatcher('/tmp') ctypes.windll.kernel32.CreateFileW( mox_c('/tmp'), mox_c(1), mox_c(3), None, mox_c(3), mox_c(win32_file_watcher._FILE_FLAG_BACKUP_SEMANTICS), None).AndReturn(31415) # pylint: disable=unused-argument def found_something(handle, buff, size, recursive, change_type, size_returned_by_ref, unused1, unused2): parray = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # next offset = 0 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Action 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 4 * 10 chrs 0x74, 0x00, 0x00, 0x00, # 't' 0x65, 0x00, 0x00, 0x00, # 'e' 0x73, 0x00, 0x00, 0x00, # 's' 0x74, 0x00, 0x00, 0x00, # 't' 0x20, 0x00, 0x00, 0x00, # ' ' 0x73, 0x00, 0x00, 0x00, # 's' 0x74, 0x00, 0x00, 0x00, # 't' 0x75, 0x00, 0x00, 0x00, # 'u' 0x66, 0x00, 0x00, 0x00, # 'f' 0x66, 0x00, 0x00, 0x00 ] # 'f' nbuff = (ctypes.c_ubyte * len(parray))(*parray) ctypes.memmove(buff, ctypes.addressof(nbuff), ctypes.sizeof(nbuff)) psize = ctypes.cast(size_returned_by_ref, ctypes.POINTER(ctypes.c_ulong)) psize[0] = ctypes.sizeof(nbuff) ctypes.windll.kernel32.ReadDirectoryChangesW( 31415, mox.IgnoreArg(), mox_c(win32_file_watcher._BUFF_SIZE), True, mox_c(351), mox.IgnoreArg(), None, None).WithSideEffects(found_something).AndReturn(1) ctypes.windll.kernel32.CancelIoEx(31415, None) ctypes.windll.kernel32.CloseHandle(31415) self.mox.ReplayAll() watcher.start() watcher.quit() self.assertEqual(watcher.changes(), {'test stuff'}) self.mox.VerifyAll()