porting 1.4.4 rev. 1989 (except for File_WIN32(U)/FileImpl::isDeviceImpl() where GENERIC_ACCESS was left due to breaking testFileAtributes3() test case)

This commit is contained in:
Aleksandar Fabijanic 2012-08-26 03:40:12 +00:00
parent eb20f339e1
commit d384a499d5
34 changed files with 1368 additions and 41 deletions

View File

@ -28,7 +28,6 @@ Release 1.5.0 (2012-08-??)
- added IPAddress RFC 4291 compatible site-local prefix support
- fixed SF#3012166: IPv6 patch
- added SF#3558085: Add formatter to MACAddress object
- fixed SF#3535990: POCO_HAVE_IPv6 without POCO_WIN32_UTF8 conflict
- fixed SF#3552774: Don't hide default target in subordinate makefile
- fixed SF#3534307: Building IPv6 for Linux by default
- fixed SF#3516844: poco missing symbols with external >=lipcre-8.13
@ -70,6 +69,43 @@ Release 1.4.4 (2012-08-??)
response status.
- fixed a DOM parser performance bug (patch by Peter Klotz)
- fixed SF# 3559325: Util Windows broken in non-Unicode
- updated iOS build configuration to use xcode-select for finding toolchain
- Poco::Net::SecureSocketImpl::shutdown() now also shuts down the underlying socket.
- fixed SF# 3552597: Crypto des-ecb error
- fixed SF# 3550553: SecureSocketImpl::connect hangs
- fixed SF# 3543047: Poco::Timer bug for long startInterval/periodic interval
- fixed SF# 3539695: Thread attributes should be destroyed using the pthread_attr_destroy()
- fixed SF# 3532311: Not able to set socket option on ServerSocket before bind
Added Poco::Net::Socket::init(int af) which can be used to explicitely
initialize the underlying socket before calling bind(), connect(), etc.
- fixed SF# 3521347: Typo in UnWindows.h undef
- fixed SF# 3519474: WinRegistryConfiguration bug
Also added tests and fixed another potential issue with an empty root path passed to the constructor.
- fixed SF# 3516827: wrong return value of WinRegistryKey::exists()
- fixed SF# 3515284: RSA publickey format(X.509 SubjectPublicKeyInfo)
- fixed SF# 3503267: VxWorks OS prio is not set in standard constructor
- fixed SF# 3500438: HTTPResponse failure when reason is empty
- fixed SF# 3495656: numberformater, numberparser error in mingw
- fixed SF# 3496493: Reference counting broken in TaskManager postNotification
- fixed SF# 3483174: LogFile flushing behavior on Windows
Flushing is now configurable for FileChannel and SimpleFileChannel
using the "flush" property (true or false).
- fixed SF# 3479561: Subsequent IPs on a NIC is not enumerated
- fixed SF# 3478665: Permission checks in Poco::File not correct for root
- fixed SF# 3475050: Threading bug in initializeNetwork() on Windows
- fixed SF# 3552680: websocket small frames bug and proposed fix
- fixed a WebSocket interop issue with Firefox
- added Poco::Net::MessageHeader::hasToken()
- Poco::AtomicCounter now uses GCC 4.3 builtin atomics on more platforms
- fixed SF# 3555938: NetSSL: socket closed twice
- socket exceptions now include OS error code
- fixed SF# 3556975: Need to fix Shared Memory for memory map
- Poco::Net::SecureSocketImpl::close() now catches exceptions thrown by its call to shutdown().
- fixed SF# 3535990: POCO_HAVE_IPv6 without POCO_WIN32_UTF8 conflict
- fixed SF# 3559665: Poco::InflatingInputStream may not always inflate completely
- added Poco::DirectoryWatcher class
- fixed SF# 3561464: Poco::File::isDevice() can throw due to sharing violation
Release 1.4.3p1 (2012-01-23)
============================

View File

@ -33,6 +33,7 @@ SOURCES="
DigestEngine.cpp
DigestStream.cpp
DirectoryIterator.cpp
DirectoryWatcher.cpp
DynamicAny.cpp
DynamicAnyHolder.cpp
Environment.cpp

View File

@ -3229,6 +3229,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\DirectoryWatcher.cpp"
>
</File>
<File
RelativePath=".\src\File.cpp"
>
@ -3789,6 +3793,10 @@
RelativePath=".\include\Poco\DirectoryIterator_WIN32U.h"
>
</File>
<File
RelativePath=".\include\Poco\DirectoryWatcher.h"
>
</File>
<File
RelativePath=".\include\Poco\File.h"
>

View File

@ -290,6 +290,7 @@
<ClCompile Include="src\ByteOrder.cpp" />
<ClCompile Include="src\Checksum.cpp" />
<ClCompile Include="src\Debugger.cpp" />
<ClCompile Include="src\DirectoryWatcher.cpp" />
<ClCompile Include="src\Environment.cpp" />
<ClCompile Include="src\Environment_UNIX.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">true</ExcludedFromBuild>
@ -976,6 +977,7 @@
<ClInclude Include="include\Poco\ByteOrder.h" />
<ClInclude Include="include\Poco\Checksum.h" />
<ClInclude Include="include\Poco\Config.h" />
<ClInclude Include="include\Poco\DirectoryWatcher.h" />
<ClInclude Include="include\Poco\Debugger.h" />
<ClInclude Include="include\Poco\DynamicAny.h" />
<ClInclude Include="include\Poco\DynamicAnyHolder.h" />

View File

@ -861,6 +861,9 @@
<ClCompile Include="src\HashStatistic.cpp">
<Filter>Hashing\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\DirectoryWatcher.cpp">
<Filter>Filesystem\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Var.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
@ -1784,6 +1787,12 @@
<ClInclude Include="include\Poco\PriorityStrategy.h">
<Filter>Events\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\ObjectPool.h">
<Filter>Core\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\DirectoryWatcher.h">
<Filter>Filesystem\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Dynamic\Pair.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>

View File

@ -2903,6 +2903,9 @@
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\DirectoryWatcher.cpp">
</File>
<File
RelativePath=".\src\File.cpp">
</File>
@ -3246,6 +3249,9 @@
<File
RelativePath=".\include\Poco\DirectoryIterator_WIN32U.h">
</File>
<File
RelativePath=".\include\Poco\DirectoryWatcher.h">
</File>
<File
RelativePath=".\include\Poco\File.h">
</File>

View File

@ -3737,6 +3737,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\DirectoryWatcher.cpp"
>
</File>
<File
RelativePath=".\src\File.cpp"
>
@ -4193,6 +4197,10 @@
RelativePath=".\include\Poco\DirectoryIterator_WIN32U.h"
>
</File>
<File
RelativePath=".\include\Poco\DirectoryWatcher.h"
>
</File>
<File
RelativePath=".\include\Poco\File.h"
>

View File

@ -3730,6 +3730,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\DirectoryWatcher.cpp"
>
</File>
<File
RelativePath=".\src\File.cpp"
>
@ -4186,6 +4190,10 @@
RelativePath=".\include\Poco\DirectoryIterator_WIN32U.h"
>
</File>
<File
RelativePath=".\include\Poco\DirectoryWatcher.h"
>
</File>
<File
RelativePath=".\include\Poco\File.h"
>

View File

@ -300,6 +300,7 @@
<ClCompile Include="src\ByteOrder.cpp" />
<ClCompile Include="src\Checksum.cpp" />
<ClCompile Include="src\Debugger.cpp" />
<ClCompile Include="src\DirectoryWatcher.cpp" />
<ClCompile Include="src\Environment.cpp" />
<ClCompile Include="src\Environment_UNIX.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">true</ExcludedFromBuild>
@ -985,6 +986,7 @@
<ClInclude Include="include\Poco\Checksum.h" />
<ClInclude Include="include\Poco\Config.h" />
<ClInclude Include="include\Poco\Debugger.h" />
<ClInclude Include="include\Poco\DirectoryWatcher.h" />
<ClInclude Include="include\Poco\DynamicAny.h" />
<ClInclude Include="include\Poco\DynamicAnyHolder.h" />
<ClInclude Include="include\Poco\DynamicFactory.h" />

View File

@ -861,6 +861,9 @@
<ClCompile Include="src\HashStatistic.cpp">
<Filter>Hashing\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\DirectoryWatcher.cpp">
<Filter>Filesystem\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\FIFOBufferStream.cpp">
<Filter>Streams\Source Files</Filter>
</ClCompile>
@ -1805,6 +1808,12 @@
<ClInclude Include="include\Poco\Windows1250Encoding.h">
<Filter>Text\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\ObjectPool.h">
<Filter>Core\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\DirectoryWatcher.h">
<Filter>Filesystem\Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="src\pocomsg.rc">

View File

@ -3728,6 +3728,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\DirectoryWatcher.cpp"
>
</File>
<File
RelativePath=".\src\File.cpp"
>
@ -4184,6 +4188,10 @@
RelativePath=".\include\Poco\DirectoryIterator_WIN32U.h"
>
</File>
<File
RelativePath=".\include\Poco\DirectoryWatcher.h"
>
</File>
<File
RelativePath=".\include\Poco\File.h"
>

View File

@ -11,7 +11,7 @@ include $(POCO_BASE)/build/rules/global
objects = ArchiveStrategy Ascii ASCIIEncoding AsyncChannel Base64Decoder Base64Encoder \
BinaryReader BinaryWriter Bugcheck ByteOrder Channel Checksum Configurable ConsoleChannel \
CountingStream DateTime LocalDateTime DateTimeFormat DateTimeFormatter DateTimeParser \
Debugger DeflatingStream DigestEngine DigestStream DirectoryIterator \
Debugger DeflatingStream DigestEngine DigestStream DirectoryIterator DirectoryWatcher \
Environment Event EventArgs ErrorHandler Exception FIFOBufferStream FPEnvironment File \
FileChannel Formatter FormattingChannel Glob HexBinaryDecoder LineEndingConverter \
HexBinaryEncoder InflatingStream Latin1Encoding Latin2Encoding Latin9Encoding LogFile \

View File

@ -0,0 +1,243 @@
//
// DirectoryWatcher.h
//
// $Id: //poco/1.4/Foundation/include/Poco/DirectoryWatcher.h#2 $
//
// Library: Foundation
// Package: Filesystem
// Module: DirectoryWatcher
//
// Definition of the DirectoryWatcher class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef Foundation_DirectoryWatcher_INCLUDED
#define Foundation_DirectoryWatcher_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/File.h"
#include "Poco/BasicEvent.h"
#include "Poco/Runnable.h"
#include "Poco/Thread.h"
#include "Poco/AtomicCounter.h"
namespace Poco {
class DirectoryWatcherStrategy;
class Foundation_API DirectoryWatcher: protected Runnable
/// This class is used to get notifications about changes
/// to the filesystem, more specifically, to a specific
/// directory. Changes to a directory are reported via
/// events.
///
/// A thread will be created that watches the specified
/// directory for changes. Events are reported in the context
/// of this thread.
///
/// Note that changes to files in subdirectories of the watched
/// directory are not reported. Separate DirectoryWatcher objects
/// must be created for these directories if they should be watched.
///
/// Changes to file attributes are not reported.
///
/// On Windows, this class is implemented using FindFirstChangeNotification()/FindNextChangeNotification().
/// On Linux, this class is implemented using inotify.
/// On all other platforms, the watched directory is periodically scanned
/// for changes. This can negatively affect performance if done too often.
/// Therefore, the interval in which scans are done can be specified in
/// the constructor.
///
/// DW_ITEM_MOVED_FROM and DW_ITEM_MOVED_TO events will only be reported
/// on Linux. On other platforms, a file rename or move operation
/// will be reported via a DW_ITEM_REMOVED and a DW_ITEM_ADDED event.
/// The order of these two events is not defined.
///
/// An event mask can be specified to enable only certain events.
{
public:
enum DirectoryEventType
{
DW_ITEM_ADDED = 1,
/// A new item has been created and added to the directory.
DW_ITEM_REMOVED = 2,
/// An item has been removed from the directory.
DW_ITEM_MODIFIED = 4,
/// An item has been modified.
DW_ITEM_MOVED_FROM = 8,
/// An item has been renamed or moved. This event delivers the old name.
DW_ITEM_MOVED_TO = 16,
/// An item has been renamed or moved. This event delivers the new name.
};
enum DirectoryEventMask
{
DW_FILTER_ENABLE_ALL = 31,
/// Enables all event types.
DW_FILTER_DISABLE_ALL = 0
/// Disables all event types.
};
enum
{
DW_DEFAULT_SCAN_INTERVAL = 5 /// Default scan interval for platforms that don't provide a native notification mechanism.
};
struct DirectoryEvent
{
DirectoryEvent(const File& f, DirectoryEventType ev):
item(f),
event(ev)
{
}
const File& item; /// The directory or file that has been changed.
DirectoryEventType event; /// The kind of event.
};
BasicEvent<const DirectoryEvent> itemAdded;
/// Fired when a file or directory has been created or added to the directory.
BasicEvent<const DirectoryEvent> itemRemoved;
/// Fired when a file or directory has been removed from the directory.
BasicEvent<const DirectoryEvent> itemModified;
/// Fired when a file or directory has been modified.
BasicEvent<const DirectoryEvent> itemMovedFrom;
/// Fired when a file or directory has been renamed. This event delivers the old name.
BasicEvent<const DirectoryEvent> itemMovedTo;
/// Fired when a file or directory has been moved. This event delivers the new name.
BasicEvent<const Exception> scanError;
/// Fired when an error occurs while scanning for changes.
DirectoryWatcher(const std::string& path, int eventMask = DW_FILTER_ENABLE_ALL, int scanInterval = DW_DEFAULT_SCAN_INTERVAL);
/// Creates a DirectoryWatcher for the directory given in path.
/// To enable only specific events, an eventMask can be specified by
/// OR-ing the desired event IDs (e.g., DW_FILE_ADDED | DW_FILE_MODIFIED).
/// On platforms where no native filesystem notifications are available,
/// scanInterval specifies the interval in seconds between scans
/// of the directory.
DirectoryWatcher(const File& directory, int eventMask = DW_FILTER_ENABLE_ALL, int scanInterval = DW_DEFAULT_SCAN_INTERVAL);
/// Creates a DirectoryWatcher for the specified directory
/// To enable only specific events, an eventMask can be specified by
/// OR-ing the desired event IDs (e.g., DW_FILE_ADDED | DW_FILE_MODIFIED).
/// On platforms where no native filesystem notifications are available,
/// scanInterval specifies the interval in seconds between scans
/// of the directory.
~DirectoryWatcher();
/// Destroys the DirectoryWatcher.
void suspendEvents();
/// Suspends sending of events. Can be called multiple times, but every
/// call to suspendEvent() must be matched by a call to resumeEvents().
void resumeEvents();
/// Resumes events, after they have been suspended with a call to suspendEvents().
bool eventsSuspended() const;
/// Returns true iff events are suspended.
int eventMask() const;
/// Returns the value of the eventMask passed to the constructor.
int scanInterval() const;
/// Returns the scan interval in seconds.
const File& directory() const;
/// Returns the directory being watched.
bool supportsMoveEvents() const;
/// Returns true iff the platform supports DW_ITEM_MOVED_FROM/itemMovedFrom and
/// DW_ITEM_MOVED_TO/itemMovedTo events.
protected:
void init();
void stop();
void run();
private:
DirectoryWatcher();
DirectoryWatcher(const DirectoryWatcher&);
DirectoryWatcher& operator = (const DirectoryWatcher&);
Thread _thread;
File _directory;
int _eventMask;
AtomicCounter _eventsSuspended;
int _scanInterval;
DirectoryWatcherStrategy* _pStrategy;
};
//
// inlines
//
inline bool DirectoryWatcher::eventsSuspended() const
{
return _eventsSuspended.value() > 0;
}
inline int DirectoryWatcher::eventMask() const
{
return _eventMask;
}
inline int DirectoryWatcher::scanInterval() const
{
return _scanInterval;
}
inline const File& DirectoryWatcher::directory() const
{
return _directory;
}
} // namespace Poco
#endif // Foundation_DirectoryWatcher_INCLUDED

View File

@ -84,6 +84,7 @@ private:
std::string _path;
friend class DirectoryIteratorImpl;
friend class LinuxDirectoryWatcherStrategy;
};

View File

@ -86,6 +86,7 @@ private:
friend class FileHandle;
friend class DirectoryIteratorImpl;
friend class WindowsDirectoryWatcherStrategy;
};

View File

@ -87,6 +87,7 @@ private:
friend class FileHandle;
friend class DirectoryIteratorImpl;
friend class WindowsDirectoryWatcherStrategy;
};

View File

@ -109,6 +109,8 @@
#pragma warning(disable:4351) // new behavior: elements of array '...' will be default initialized
#pragma warning(disable:4675) // resolved overload was found by argument-dependent lookup
#pragma warning(disable:4275) // non dll-interface class 'std::exception' used as base for dll-interface class 'Poco::Exception'
#pragma warning(disable:4250) // VC++ 11.0: inheriting from std stream classes produces C4250 warning;
// see <http://connect.microsoft.com/VisualStudio/feedback/details/733720/inheriting-from-std-fstream-produces-c4250-warning>
#endif

View File

@ -0,0 +1,524 @@
//
// DirectoryWatcher.cpp
//
// $Id: //poco/1.4/Foundation/src/DirectoryWatcher.cpp#4 $
//
// Library: Foundation
// Package: Filesystem
// Module: DirectoryWatcher
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/DirectoryWatcher.h"
#include "Poco/Path.h"
#include "Poco/Glob.h"
#include "Poco/DirectoryIterator.h"
#include "Poco/Event.h"
#include "Poco/Exception.h"
#include "Poco/Buffer.h"
#if defined(POCO_WIN32_UTF8)
#include "Poco/UnicodeConverter.h"
#endif
#if POCO_OS == POCO_OS_LINUX
#include <sys/inotify.h>
#include <sys/select.h>
#include <unistd.h>
#endif
#include <algorithm>
#include <map>
namespace Poco {
class DirectoryWatcherStrategy
{
public:
DirectoryWatcherStrategy(DirectoryWatcher& owner):
_owner(owner)
{
}
virtual ~DirectoryWatcherStrategy()
{
}
DirectoryWatcher& owner()
{
return _owner;
}
virtual void run() = 0;
virtual void stop() = 0;
virtual bool supportsMoveEvents() const = 0;
protected:
struct ItemInfo
{
ItemInfo():
size(0)
{
}
ItemInfo(const ItemInfo& other):
path(other.path),
size(other.size),
lastModified(other.lastModified)
{
}
explicit ItemInfo(const File& f):
path(f.path()),
size(f.isFile() ? f.getSize() : 0),
lastModified(f.getLastModified())
{
}
std::string path;
File::FileSize size;
Timestamp lastModified;
};
typedef std::map<std::string, ItemInfo> ItemInfoMap;
void scan(ItemInfoMap& entries)
{
DirectoryIterator it(owner().directory());
DirectoryIterator end;
while (it != end)
{
entries[it.path().getFileName()] = ItemInfo(*it);
++it;
}
}
void compare(ItemInfoMap& oldEntries, ItemInfoMap& newEntries)
{
for (ItemInfoMap::iterator itn = newEntries.begin(); itn != newEntries.end(); ++itn)
{
ItemInfoMap::iterator ito = oldEntries.find(itn->first);
if (ito != oldEntries.end())
{
if ((owner().eventMask() & DirectoryWatcher::DW_ITEM_MODIFIED) && !owner().eventsSuspended())
{
if (itn->second.size != ito->second.size || itn->second.lastModified != ito->second.lastModified)
{
Poco::File f(itn->second.path);
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_MODIFIED);
owner().itemModified(&owner(), ev);
}
}
oldEntries.erase(ito);
}
else if ((owner().eventMask() & DirectoryWatcher::DW_ITEM_ADDED) && !owner().eventsSuspended())
{
Poco::File f(itn->second.path);
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_ADDED);
owner().itemAdded(&owner(), ev);
}
}
if ((owner().eventMask() & DirectoryWatcher::DW_ITEM_REMOVED) && !owner().eventsSuspended())
{
for (ItemInfoMap::iterator it = oldEntries.begin(); it != oldEntries.end(); ++it)
{
Poco::File f(it->second.path);
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_REMOVED);
owner().itemRemoved(&owner(), ev);
}
}
}
private:
DirectoryWatcherStrategy();
DirectoryWatcherStrategy(const DirectoryWatcherStrategy&);
DirectoryWatcherStrategy& operator = (const DirectoryWatcherStrategy&);
DirectoryWatcher& _owner;
};
#if POCO_OS == POCO_OS_WINDOWS_NT
class WindowsDirectoryWatcherStrategy: public DirectoryWatcherStrategy
{
public:
WindowsDirectoryWatcherStrategy(DirectoryWatcher& owner):
DirectoryWatcherStrategy(owner)
{
_hStopped = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!_hStopped)
throw SystemException("cannot create event");
}
~WindowsDirectoryWatcherStrategy()
{
CloseHandle(_hStopped);
}
void run()
{
ItemInfoMap entries;
scan(entries);
DWORD filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME;
if (owner().eventMask() & DirectoryWatcher::DW_ITEM_MODIFIED)
filter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
std::string path(owner().directory().path());
#if defined(POCO_WIN32_UTF8)
std::wstring upath;
Poco::UnicodeConverter::toUTF16(path.c_str(), upath);
HANDLE hChange = FindFirstChangeNotificationW(upath.c_str(), FALSE, filter);
#else
HANDLE hChange = FindFirstChangeNotificationA(path.c_str(), FALSE, filter);
#endif
if (hChange == INVALID_HANDLE_VALUE)
{
try
{
FileImpl::handleLastErrorImpl(path);
}
catch (Poco::Exception& exc)
{
owner().scanError(&owner(), exc);
}
return;
}
bool stopped = false;
while (!stopped)
{
try
{
HANDLE h[2];
h[0] = _hStopped;
h[1] = hChange;
switch (WaitForMultipleObjects(2, h, FALSE, INFINITE))
{
case WAIT_OBJECT_0:
stopped = true;
break;
case WAIT_OBJECT_0 + 1:
{
ItemInfoMap newEntries;
scan(newEntries);
compare(entries, newEntries);
std::swap(entries, newEntries);
if (FindNextChangeNotification(hChange) == FALSE)
{
FileImpl::handleLastErrorImpl(path);
}
}
break;
default:
throw SystemException("failed to wait for directory changes");
}
}
catch (Poco::Exception& exc)
{
owner().scanError(&owner(), exc);
}
}
FindCloseChangeNotification(hChange);
}
void stop()
{
SetEvent(_hStopped);
}
bool supportsMoveEvents() const
{
return false;
}
private:
HANDLE _hStopped;
};
#elif POCO_OS == POCO_OS_LINUX
class LinuxDirectoryWatcherStrategy: public DirectoryWatcherStrategy
{
public:
LinuxDirectoryWatcherStrategy(DirectoryWatcher& owner):
DirectoryWatcherStrategy(owner),
_fd(-1),
_stopped(false)
{
_fd = inotify_init();
if (_fd == -1) throw Poco::IOException("cannot initialize inotify", errno);
}
~LinuxDirectoryWatcherStrategy()
{
close(_fd);
}
void run()
{
int mask = 0;
if (owner().eventMask() & DirectoryWatcher::DW_ITEM_ADDED)
mask |= IN_CREATE;
if (owner().eventMask() & DirectoryWatcher::DW_ITEM_REMOVED)
mask |= IN_DELETE;
if (owner().eventMask() & DirectoryWatcher::DW_ITEM_MODIFIED)
mask |= IN_MODIFY;
if (owner().eventMask() & DirectoryWatcher::DW_ITEM_MOVED_FROM)
mask |= IN_MOVED_FROM;
if (owner().eventMask() & DirectoryWatcher::DW_ITEM_MOVED_TO)
mask |= IN_MOVED_TO;
int wd = inotify_add_watch(_fd, owner().directory().path().c_str(), mask);
if (wd == -1)
{
try
{
FileImpl::handleLastErrorImpl(owner().directory().path());
}
catch (Poco::Exception& exc)
{
owner().scanError(&owner(), exc);
}
}
Poco::Buffer<char> buffer(4096);
while (!_stopped)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(_fd, &fds);
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 200000;
if (select(_fd + 1, &fds, NULL, NULL, &tv) == 1)
{
int n = read(_fd, buffer.begin(), buffer.size());
int i = 0;
if (n > 0)
{
while (n > 0)
{
struct inotify_event* pEvent = reinterpret_cast<struct inotify_event*>(buffer.begin() + i);
if (pEvent->len > 0)
{
if (!owner().eventsSuspended())
{
Poco::Path p(owner().directory().path());
p.makeDirectory();
p.setFileName(pEvent->name);
Poco::File f(p.toString());
if ((pEvent->mask & IN_CREATE) && (owner().eventMask() & DirectoryWatcher::DW_ITEM_ADDED))
{
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_ADDED);
owner().itemAdded(&owner(), ev);
}
if ((pEvent->mask & IN_DELETE) && (owner().eventMask() & DirectoryWatcher::DW_ITEM_REMOVED))
{
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_REMOVED);
owner().itemRemoved(&owner(), ev);
}
if ((pEvent->mask & IN_MODIFY) && (owner().eventMask() & DirectoryWatcher::DW_ITEM_MODIFIED))
{
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_MODIFIED);
owner().itemModified(&owner(), ev);
}
if ((pEvent->mask & IN_MOVED_FROM) && (owner().eventMask() & DirectoryWatcher::DW_ITEM_MOVED_FROM))
{
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_MOVED_FROM);
owner().itemMovedFrom(&owner(), ev);
}
if ((pEvent->mask & IN_MOVED_TO) && (owner().eventMask() & DirectoryWatcher::DW_ITEM_MOVED_TO))
{
DirectoryWatcher::DirectoryEvent ev(f, DirectoryWatcher::DW_ITEM_MOVED_TO);
owner().itemMovedTo(&owner(), ev);
}
}
}
i += sizeof(inotify_event) + pEvent->len;
n -= sizeof(inotify_event) + pEvent->len;
}
}
}
}
}
void stop()
{
_stopped = true;
}
bool supportsMoveEvents() const
{
return true;
}
private:
int _fd;
bool _stopped;
};
#else
class DefaultDirectoryWatcherStrategy: public DirectoryWatcherStrategy
{
public:
DefaultDirectoryWatcherStrategy(DirectoryWatcher& owner):
DirectoryWatcherStrategy(owner)
{
}
~DefaultDirectoryWatcherStrategy()
{
}
void run()
{
ItemInfoMap entries;
scan(entries);
while (!_stopped.tryWait(1000*owner().scanInterval()))
{
try
{
ItemInfoMap newEntries;
scan(newEntries);
compare(entries, newEntries);
std::swap(entries, newEntries);
}
catch (Poco::Exception& exc)
{
owner().scanError(&owner(), exc);
}
}
}
void stop()
{
_stopped.set();
}
bool supportsMoveEvents() const
{
return false;
}
private:
Poco::Event _stopped;
};
#endif
DirectoryWatcher::DirectoryWatcher(const std::string& path, int eventMask, int scanInterval):
_directory(path),
_eventMask(eventMask),
_scanInterval(scanInterval)
{
init();
}
DirectoryWatcher::DirectoryWatcher(const Poco::File& directory, int eventMask, int scanInterval):
_directory(directory),
_eventMask(eventMask),
_scanInterval(scanInterval)
{
init();
}
DirectoryWatcher::~DirectoryWatcher()
{
stop();
delete _pStrategy;
}
void DirectoryWatcher::suspendEvents()
{
poco_assert (_eventsSuspended > 0);
_eventsSuspended--;
}
void DirectoryWatcher::resumeEvents()
{
_eventsSuspended++;
}
void DirectoryWatcher::init()
{
if (!_directory.exists())
throw Poco::FileNotFoundException(_directory.path());
if (!_directory.isDirectory())
throw Poco::InvalidArgumentException("not a directory", _directory.path());
#if POCO_OS == POCO_OS_WINDOWS_NT
_pStrategy = new WindowsDirectoryWatcherStrategy(*this);
#elif POCO_OS == POCO_OS_LINUX
_pStrategy = new LinuxDirectoryWatcherStrategy(*this);
#else
_pStrategy = new DefaultDirectoryWatcherStrategy(*this);
#endif
_thread.start(*this);
}
void DirectoryWatcher::run()
{
_pStrategy->run();
}
void DirectoryWatcher::stop()
{
_pStrategy->stop();
_thread.join();
}
bool DirectoryWatcher::supportsMoveEvents() const
{
return _pStrategy->supportsMoveEvents();
}
} // namespace Poco

View File

@ -193,7 +193,7 @@ bool FileImpl::isDeviceImpl() const
{
poco_assert (!_path.empty());
FileHandle fh(_path, GENERIC_READ, 0, OPEN_EXISTING);
FileHandle fh(_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
DWORD type = GetFileType(fh.get());
if (type == FILE_TYPE_CHAR)
return true;

View File

@ -39,7 +39,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
HashSetTest HashMapTest SharedMemoryTest \
UniqueExpireCacheTest UniqueExpireLRUCacheTest UnicodeConverterTest \
TuplesTest NamedTuplesTest TypeListTest VarTest DynamicTestSuite FileStreamTest \
MemoryStreamTest ObjectPoolTest
MemoryStreamTest ObjectPoolTest DirectoryWatcherTest
target = testrunner
target_version = 1

View File

@ -30,6 +30,7 @@ SOURCES="
DateTimeTest.cpp
DateTimeTestSuite.cpp
DigestStreamTest.cpp
DirectoryWatcherTest.cpp
Driver.cpp
DummyDelegate.cpp
DynamicAnyTest.cpp

View File

@ -1261,6 +1261,10 @@
<Filter
Name="Source Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.cpp"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.cpp"
>
@ -1281,6 +1285,10 @@
<Filter
Name="Header Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.h"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.h"
>

View File

@ -307,6 +307,7 @@
<ClCompile Include="src\ByteOrderTest.cpp" />
<ClCompile Include="src\CoreTest.cpp" />
<ClCompile Include="src\CoreTestSuite.cpp" />
<ClCompile Include="src\DirectoryWatcherTest.cpp" />
<ClCompile Include="src\DynamicFactoryTest.cpp" />
<ClCompile Include="src\FIFOBufferStreamTest.cpp" />
<ClCompile Include="src\FormatTest.cpp" />
@ -439,6 +440,7 @@
<ClInclude Include="src\ByteOrderTest.h" />
<ClInclude Include="src\CoreTest.h" />
<ClInclude Include="src\CoreTestSuite.h" />
<ClInclude Include="src\DirectoryWatcherTest.h" />
<ClInclude Include="src\DynamicFactoryTest.h" />
<ClInclude Include="src\FIFOBufferStreamTest.h" />
<ClInclude Include="src\FormatTest.h" />

View File

@ -561,6 +561,9 @@
<ClCompile Include="src\ObjectPoolTest.cpp">
<Filter>Core\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\DirectoryWatcherTest.cpp">
<Filter>Filesystem\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\VarTest.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
@ -950,6 +953,9 @@
<ClInclude Include="src\ObjectPoolTest.h">
<Filter>Core\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\DirectoryWatcherTest.h">
<Filter>Filesystem\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\VarTest.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>

View File

@ -925,6 +925,9 @@
<Filter
Name="Source Files"
Filter="">
<File
RelativePath=".\src\DirectoryWatcherTest.cpp">
</File>
<File
RelativePath=".\src\FilesystemTestSuite.cpp">
</File>
@ -941,6 +944,9 @@
<Filter
Name="Header Files"
Filter="">
<File
RelativePath=".\src\DirectoryWatcherTest.h">
</File>
<File
RelativePath=".\src\FilesystemTestSuite.h">
</File>

View File

@ -1239,6 +1239,10 @@
<Filter
Name="Source Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.cpp"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.cpp"
>
@ -1259,6 +1263,10 @@
<Filter
Name="Header Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.h"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.h"
>

View File

@ -1225,6 +1225,10 @@
<Filter
Name="Source Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.cpp"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.cpp"
>
@ -1245,6 +1249,10 @@
<Filter
Name="Header Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.h"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.h"
>

View File

@ -307,6 +307,7 @@
<ClCompile Include="src\ByteOrderTest.cpp" />
<ClCompile Include="src\CoreTest.cpp" />
<ClCompile Include="src\CoreTestSuite.cpp" />
<ClCompile Include="src\DirectoryWatcherTest.cpp" />
<ClCompile Include="src\DynamicFactoryTest.cpp" />
<ClCompile Include="src\FIFOBufferStreamTest.cpp" />
<ClCompile Include="src\FormatTest.cpp" />
@ -439,6 +440,7 @@
<ClInclude Include="src\ByteOrderTest.h" />
<ClInclude Include="src\CoreTest.h" />
<ClInclude Include="src\CoreTestSuite.h" />
<ClInclude Include="src\DirectoryWatcherTest.h" />
<ClInclude Include="src\DynamicAnyTest.h" />
<ClInclude Include="src\DynamicFactoryTest.h" />
<ClInclude Include="src\FIFOBufferStreamTest.h" />

View File

@ -561,6 +561,9 @@
<ClCompile Include="src\ObjectPoolTest.cpp">
<Filter>Core\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\DirectoryWatcherTest.cpp">
<Filter>Filesystem\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\VarTest.cpp">
<Filter>Dynamic\Source Files</Filter>
</ClCompile>
@ -953,6 +956,9 @@
<ClInclude Include="src\ObjectPoolTest.h">
<Filter>Core\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\DirectoryWatcherTest.h">
<Filter>Filesystem\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\VarTest.h">
<Filter>Dynamic\Header Files</Filter>
</ClInclude>

View File

@ -1207,6 +1207,10 @@
<Filter
Name="Source Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.cpp"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.cpp"
>
@ -1227,6 +1231,10 @@
<Filter
Name="Header Files"
>
<File
RelativePath=".\src\DirectoryWatcherTest.h"
>
</File>
<File
RelativePath=".\src\FilesystemTestSuite.h"
>

View File

@ -0,0 +1,314 @@
//
// DirectoryWatcherTest.cpp
//
// $Id: //poco/1.4/Foundation/testsuite/src/DirectoryWatcherTest.cpp#1 $
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "DirectoryWatcherTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/DirectoryWatcher.h"
#include "Poco/Delegate.h"
#include "Poco/FileStream.h"
using Poco::DirectoryWatcher;
DirectoryWatcherTest::DirectoryWatcherTest(const std::string& name):
CppUnit::TestCase(name),
_error(false)
{
}
DirectoryWatcherTest::~DirectoryWatcherTest()
{
}
void DirectoryWatcherTest::testAdded()
{
DirectoryWatcher dw(path().toString(), DirectoryWatcher::DW_FILTER_ENABLE_ALL, 2);
dw.itemAdded += Poco::delegate(this, &DirectoryWatcherTest::onItemAdded);
dw.itemRemoved += Poco::delegate(this, &DirectoryWatcherTest::onItemRemoved);
dw.itemModified += Poco::delegate(this, &DirectoryWatcherTest::onItemModified);
dw.itemMovedFrom += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedFrom);
dw.itemMovedTo += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedTo);
Poco::Thread::sleep(1000);
Poco::Path p(path());
p.setFileName("test.txt");
Poco::FileOutputStream fos(p.toString());
fos << "Hello, world!";
fos.close();
Poco::Thread::sleep(2000*dw.scanInterval());
assert (_events.size() >= 1);
assert (_events[0].callback == "onItemAdded");
assert (Poco::Path(_events[0].path).getFileName() == "test.txt");
assert (_events[0].type == DirectoryWatcher::DW_ITEM_ADDED);
assert (!_error);
}
void DirectoryWatcherTest::testRemoved()
{
Poco::Path p(path());
p.setFileName("test.txt");
Poco::FileOutputStream fos(p.toString());
fos << "Hello, world!";
fos.close();
DirectoryWatcher dw(path().toString(), DirectoryWatcher::DW_FILTER_ENABLE_ALL, 2);
dw.itemAdded += Poco::delegate(this, &DirectoryWatcherTest::onItemAdded);
dw.itemRemoved += Poco::delegate(this, &DirectoryWatcherTest::onItemRemoved);
dw.itemModified += Poco::delegate(this, &DirectoryWatcherTest::onItemModified);
dw.itemMovedFrom += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedFrom);
dw.itemMovedTo += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedTo);
Poco::Thread::sleep(1000);
Poco::File f(p.toString());
f.remove();
Poco::Thread::sleep(2000*dw.scanInterval());
assert (_events.size() >= 1);
assert (_events[0].callback == "onItemRemoved");
assert (Poco::Path(_events[0].path).getFileName() == "test.txt");
assert (_events[0].type == DirectoryWatcher::DW_ITEM_REMOVED);
assert (!_error);
}
void DirectoryWatcherTest::testModified()
{
Poco::Path p(path());
p.setFileName("test.txt");
Poco::FileOutputStream fos(p.toString());
fos << "Hello, world!";
fos.close();
DirectoryWatcher dw(path().toString(), DirectoryWatcher::DW_FILTER_ENABLE_ALL, 2);
dw.itemAdded += Poco::delegate(this, &DirectoryWatcherTest::onItemAdded);
dw.itemRemoved += Poco::delegate(this, &DirectoryWatcherTest::onItemRemoved);
dw.itemModified += Poco::delegate(this, &DirectoryWatcherTest::onItemModified);
dw.itemMovedFrom += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedFrom);
dw.itemMovedTo += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedTo);
Poco::Thread::sleep(1000);
Poco::FileOutputStream fos2(p.toString(), std::ios::app);
fos2 << "Again!";
fos2.close();
Poco::Thread::sleep(2000*dw.scanInterval());
assert (_events.size() >= 1);
assert (_events[0].callback == "onItemModified");
assert (Poco::Path(_events[0].path).getFileName() == "test.txt");
assert (_events[0].type == DirectoryWatcher::DW_ITEM_MODIFIED);
assert (!_error);
}
void DirectoryWatcherTest::testMoved()
{
Poco::Path p(path());
p.setFileName("test.txt");
Poco::FileOutputStream fos(p.toString());
fos << "Hello, world!";
fos.close();
DirectoryWatcher dw(path().toString(), DirectoryWatcher::DW_FILTER_ENABLE_ALL, 2);
dw.itemAdded += Poco::delegate(this, &DirectoryWatcherTest::onItemAdded);
dw.itemRemoved += Poco::delegate(this, &DirectoryWatcherTest::onItemRemoved);
dw.itemModified += Poco::delegate(this, &DirectoryWatcherTest::onItemModified);
dw.itemMovedFrom += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedFrom);
dw.itemMovedTo += Poco::delegate(this, &DirectoryWatcherTest::onItemMovedTo);
Poco::Thread::sleep(1000);
Poco::Path p2(path());
p2.setFileName("test2.txt");
Poco::File f(p.toString());
f.renameTo(p2.toString());
Poco::Thread::sleep(2000*dw.scanInterval());
if (dw.supportsMoveEvents())
{
assert (_events.size() >= 2);
assert (
(_events[0].callback == "onItemMovedFrom" && _events[1].callback == "onItemMovedTo") ||
(_events[1].callback == "onItemMovedFrom" && _events[0].callback == "onItemMovedTo")
);
assert (
(Poco::Path(_events[0].path).getFileName() == "test.txt" && Poco::Path(_events[1].path).getFileName() == "test2.txt") ||
(Poco::Path(_events[1].path).getFileName() == "test.txt" && Poco::Path(_events[0].path).getFileName() == "test2.txt")
);
assert (
(_events[0].type == DirectoryWatcher::DW_ITEM_MOVED_FROM && _events[1].type == DirectoryWatcher::DW_ITEM_MOVED_TO) ||
(_events[1].type == DirectoryWatcher::DW_ITEM_MOVED_FROM && _events[0].type == DirectoryWatcher::DW_ITEM_MOVED_TO)
);
}
else
{
assert (_events.size() >= 2);
assert (
(_events[0].callback == "onItemAdded" && _events[1].callback == "onItemRemoved") ||
(_events[1].callback == "onItemAdded" && _events[0].callback == "onItemRemoved")
);
assert (
(Poco::Path(_events[0].path).getFileName() == "test.txt" && Poco::Path(_events[1].path).getFileName() == "test2.txt") ||
(Poco::Path(_events[1].path).getFileName() == "test.txt" && Poco::Path(_events[0].path).getFileName() == "test2.txt")
);
assert (
(_events[0].type == DirectoryWatcher::DW_ITEM_ADDED && _events[1].type == DirectoryWatcher::DW_ITEM_REMOVED) ||
(_events[1].type == DirectoryWatcher::DW_ITEM_ADDED && _events[0].type == DirectoryWatcher::DW_ITEM_REMOVED)
);
}
assert (!_error);
}
void DirectoryWatcherTest::setUp()
{
_error = false;
_events.clear();
try
{
Poco::File d(path().toString());
d.remove(true);
}
catch (...)
{
}
Poco::File d(path().toString());
d.createDirectories();
}
void DirectoryWatcherTest::tearDown()
{
try
{
Poco::File d(path().toString());
d.remove(true);
}
catch (...)
{
}
}
void DirectoryWatcherTest::onItemAdded(const Poco::DirectoryWatcher::DirectoryEvent& ev)
{
DirEvent de;
de.callback = "onItemAdded";
de.path = ev.item.path();
de.type = ev.event;
_events.push_back(de);
}
void DirectoryWatcherTest::onItemRemoved(const Poco::DirectoryWatcher::DirectoryEvent& ev)
{
DirEvent de;
de.callback = "onItemRemoved";
de.path = ev.item.path();
de.type = ev.event;
_events.push_back(de);
}
void DirectoryWatcherTest::onItemModified(const Poco::DirectoryWatcher::DirectoryEvent& ev)
{
DirEvent de;
de.callback = "onItemModified";
de.path = ev.item.path();
de.type = ev.event;
_events.push_back(de);
}
void DirectoryWatcherTest::onItemMovedFrom(const Poco::DirectoryWatcher::DirectoryEvent& ev)
{
DirEvent de;
de.callback = "onItemMovedFrom";
de.path = ev.item.path();
de.type = ev.event;
_events.push_back(de);
}
void DirectoryWatcherTest::onItemMovedTo(const Poco::DirectoryWatcher::DirectoryEvent& ev)
{
DirEvent de;
de.callback = "onItemMovedTo";
de.path = ev.item.path();
de.type = ev.event;
_events.push_back(de);
}
void DirectoryWatcherTest::onError(const Poco::Exception& exc)
{
_error = true;
}
Poco::Path DirectoryWatcherTest::path() const
{
Poco::Path p(Poco::Path::current());
p.pushDirectory("DirectoryWatcherTest");
return p;
}
CppUnit::Test* DirectoryWatcherTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DirectoryWatcherTest");
CppUnit_addTest(pSuite, DirectoryWatcherTest, testAdded);
CppUnit_addTest(pSuite, DirectoryWatcherTest, testRemoved);
CppUnit_addTest(pSuite, DirectoryWatcherTest, testModified);
CppUnit_addTest(pSuite, DirectoryWatcherTest, testMoved);
return pSuite;
}

View File

@ -0,0 +1,83 @@
//
// DirectoryWatcherTest.h
//
// $Id: //poco/1.4/Foundation/testsuite/src/DirectoryWatcherTest.h#1 $
//
// Definition of the DirectoryWatcherTest class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef DirectoryWatcherTest_INCLUDED
#define DirectoryWatcherTest_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/DirectoryWatcher.h"
#include "Poco/Path.h"
#include "CppUnit/TestCase.h"
class DirectoryWatcherTest: public CppUnit::TestCase
{
public:
DirectoryWatcherTest(const std::string& name);
~DirectoryWatcherTest();
void testAdded();
void testRemoved();
void testModified();
void testMoved();
void setUp();
void tearDown();
static CppUnit::Test* suite();
protected:
void onItemAdded(const Poco::DirectoryWatcher::DirectoryEvent& ev);
void onItemRemoved(const Poco::DirectoryWatcher::DirectoryEvent& ev);
void onItemModified(const Poco::DirectoryWatcher::DirectoryEvent& ev);
void onItemMovedFrom(const Poco::DirectoryWatcher::DirectoryEvent& ev);
void onItemMovedTo(const Poco::DirectoryWatcher::DirectoryEvent& ev);
void onError(const Poco::Exception& exc);
Poco::Path path() const;
private:
struct DirEvent
{
Poco::DirectoryWatcher::DirectoryEventType type;
std::string callback;
std::string path;
};
std::vector<DirEvent> _events;
bool _error;
};
#endif // DirectoryWatcherTest_INCLUDED

View File

@ -34,6 +34,7 @@
#include "PathTest.h"
#include "FileTest.h"
#include "GlobTest.h"
#include "DirectoryWatcherTest.h"
CppUnit::Test* FilesystemTestSuite::suite()
@ -43,6 +44,7 @@ CppUnit::Test* FilesystemTestSuite::suite()
pSuite->addTest(PathTest::suite());
pSuite->addTest(FileTest::suite());
pSuite->addTest(GlobTest::suite());
pSuite->addTest(DirectoryWatcherTest::suite());
return pSuite;
}

View File

@ -1406,7 +1406,11 @@ void VarTest::testConversionOperator()
assert (any == i);
any = 123;
#if defined(_MSC_VER) // gcc bombs on s(any)
std::string s(any);
#else
std::string s = any;
#endif
assert (s == "123");
assert (s == any);
assert (any == s);