Merge branch 'fswatcher-test-modernize'

Modernize and clean up wxFileSystemWatcher unit test.

See https://github.com/wxWidgets/wxWidgets/pull/1307
This commit is contained in:
Vadim Zeitlin
2019-04-26 23:35:23 +02:00

View File

@@ -25,20 +25,13 @@
#include "wx/evtloop.h" #include "wx/evtloop.h"
#include "wx/filename.h" #include "wx/filename.h"
#include "wx/filefn.h" #include "wx/filefn.h"
#include "wx/stdpaths.h"
#include "wx/fswatcher.h" #include "wx/fswatcher.h"
#include "wx/scopedptr.h"
#include "wx/stdpaths.h"
#include "wx/vector.h"
#include "testfile.h" #include "testfile.h"
/*
This test used to be disabled on OS X as it hung. Work around the apparent
wxOSX differences between a non-GUI event loop and a GUI event loop (where
the tests do run fine) until this gets resolved.
*/
#ifdef __WXOSX__
#define OSX_EVENT_LOOP_WORKAROUND
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// local functions // local functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -71,7 +64,7 @@ public:
bool RenameFile() bool RenameFile()
{ {
CPPUNIT_ASSERT(m_file.FileExists()); REQUIRE(m_file.FileExists());
wxLogDebug("Renaming %s=>%s", m_file.GetFullPath(), m_new.GetFullPath()); wxLogDebug("Renaming %s=>%s", m_file.GetFullPath(), m_new.GetFullPath());
@@ -88,7 +81,7 @@ public:
bool DeleteFile() bool DeleteFile()
{ {
CPPUNIT_ASSERT(m_file.FileExists()); REQUIRE(m_file.FileExists());
bool ret = wxRemoveFile(m_file.GetFullPath()); bool ret = wxRemoveFile(m_file.GetFullPath());
if (ret) if (ret)
@@ -109,23 +102,23 @@ public:
bool ReadFile() bool ReadFile()
{ {
wxFile f(m_file.GetFullPath()); wxFile f(m_file.GetFullPath());
CPPUNIT_ASSERT(f.IsOpened()); REQUIRE(f.IsOpened());
char buf[1]; char buf[1];
ssize_t count = f.Read(buf, sizeof(buf)); ssize_t count = f.Read(buf, sizeof(buf));
CPPUNIT_ASSERT(count > 0); CHECK(count > 0);
return true; return true;
} }
bool ModifyFile() bool ModifyFile()
{ {
CPPUNIT_ASSERT(m_file.FileExists()); REQUIRE(m_file.FileExists());
wxFile file(m_file.GetFullPath(), wxFile::write_append); wxFile file(m_file.GetFullPath(), wxFile::write_append);
CPPUNIT_ASSERT(file.IsOpened()); REQUIRE(file.IsOpened());
CPPUNIT_ASSERT(file.Write("Words of Wisdom, Lloyd. Words of wisdom\n")); CHECK(file.Write("Words of Wisdom, Lloyd. Words of wisdom\n"));
return file.Close(); return file.Close();
} }
@@ -149,8 +142,8 @@ public:
// XXX look for more unique name? there is no function to generate // XXX look for more unique name? there is no function to generate
// unique filename, the file always get created... // unique filename, the file always get created...
dir.AppendDir("fswatcher_test"); dir.AppendDir("fswatcher_test");
CPPUNIT_ASSERT(!dir.DirExists()); REQUIRE(!dir.DirExists());
CPPUNIT_ASSERT(dir.Mkdir()); REQUIRE(dir.Mkdir());
return dir; return dir;
} }
@@ -158,12 +151,12 @@ public:
static void RemoveWatchDir() static void RemoveWatchDir()
{ {
wxFileName dir = GetWatchDir(); wxFileName dir = GetWatchDir();
CPPUNIT_ASSERT(dir.DirExists()); REQUIRE(dir.DirExists());
// just to be really sure we know what we remove // just to be really sure we know what we remove
CPPUNIT_ASSERT_EQUAL( "fswatcher_test", dir.GetDirs().Last() ); REQUIRE( dir.GetDirs().Last() == "fswatcher_test" );
CPPUNIT_ASSERT( dir.Rmdir(wxPATH_RMDIR_RECURSIVE) ); CHECK( dir.Rmdir(wxPATH_RMDIR_RECURSIVE) );
} }
static wxFileName RandomName(const wxFileName& base, int length = 10) static wxFileName RandomName(const wxFileName& base, int length = 10)
@@ -193,45 +186,34 @@ protected:
EventGenerator* EventGenerator::ms_instance = 0; EventGenerator* EventGenerator::ms_instance = 0;
// custom event handler // Abstract base class from which concrete event tests inherit.
class EventHandler : public wxEvtHandler //
// This class provides the common test skeleton which various virtual hooks
// that should or can be reimplemented by the derived classes.
class FSWTesterBase : public wxEvtHandler
{ {
public: public:
enum { WAIT_DURATION = 3 }; FSWTesterBase(int types = wxFSW_EVENT_ALL) :
eg(EventGenerator::Get()),
EventHandler(int types = wxFSW_EVENT_ALL) : m_eventTypes(types)
eg(EventGenerator::Get()), m_loop(0),
#ifdef OSX_EVENT_LOOP_WORKAROUND
m_loopActivator(NULL),
#endif
m_count(0), m_watcher(0), m_eventTypes(types)
{ {
m_loop = new wxEventLoop(); Bind(wxEVT_FSWATCHER, &FSWTesterBase::OnFileSystemEvent, this);
#ifdef OSX_EVENT_LOOP_WORKAROUND
m_loopActivator = new wxEventLoopActivator(m_loop); // wxFileSystemWatcher can be created only once the event loop is
#endif // running, so we can't do it from here and will do it from inside the
Connect(wxEVT_IDLE, wxIdleEventHandler(EventHandler::OnIdle)); // loop when this event handler is invoked.
Connect(wxEVT_FSWATCHER, wxFileSystemWatcherEventHandler( CallAfter(&FSWTesterBase::OnIdleInit);
EventHandler::OnFileSystemEvent));
} }
virtual ~EventHandler() virtual ~FSWTesterBase()
{ {
delete m_watcher; if (m_loop.IsRunning())
#ifdef OSX_EVENT_LOOP_WORKAROUND m_loop.Exit();
delete m_loopActivator;
#endif
if (m_loop)
{
if (m_loop->IsRunning())
m_loop->Exit();
delete m_loop;
}
} }
void Exit() void Exit()
{ {
m_loop->Exit(); m_loop.Exit();
} }
// sends idle event, so we get called in a moment // sends idle event, so we get called in a moment
@@ -239,140 +221,73 @@ public:
{ {
wxIdleEvent* e = new wxIdleEvent(); wxIdleEvent* e = new wxIdleEvent();
QueueEvent(e); QueueEvent(e);
#ifdef OSX_EVENT_LOOP_WORKAROUND
// The fs watcher test cases will hang on OS X if Yield() is not called.
// It seems that the OS X event loop and / or queueing behaves
// differently than on MSW and Linux.
m_loop->Yield(true);
#endif
} }
void Run() void Run()
{ {
SendIdle(); m_loop.Run();
m_loop->Run();
} }
void OnIdle(wxIdleEvent& /*evt*/) void OnIdleInit()
{ {
bool more = Action(); REQUIRE(Init());
m_count++;
if (more) GenerateEvent();
{
SendIdle(); // Check the result when the next idle event comes: note that we can't
} // use CallAfter() here, unfortunately, because OnIdleCheckResult()
// would then be called immediately, from the same event loop iteration
// as we're called from, because the idle/pending events are processed
// for as long as there any. Instead, we need to return to the event
// loop itself to give it a chance to dispatch wxFileSystemWatcherEvent
// and wait until our handler for it calls SendIdle() which will then
// end up calling OnIdleCheckResult() afterwards.
Bind(wxEVT_IDLE, &FSWTesterBase::OnIdleCheckResult, this);
} }
// returns whether we should produce more idle events void OnIdleCheckResult(wxIdleEvent& WXUNUSED(event))
virtual bool Action()
{ {
switch (m_count) Unbind(wxEVT_IDLE, &FSWTesterBase::OnIdleCheckResult, this);
{
case 0:
CPPUNIT_ASSERT(Init());
break;
case 1:
GenerateEvent();
break;
case 2:
// actual test
CheckResult();
Exit();
break;
// TODO a mechanism that will break the loop in case we CheckResult();
// don't receive a file system event Exit();
// this below doesn't quite work, so all tests must pass :-)
#if 0
case 2:
m_loop.Yield();
m_loop.WakeUp();
CPPUNIT_ASSERT(KeepWaiting());
m_loop.Yield();
break;
case 3:
break;
case 4:
CPPUNIT_ASSERT(AfterWait());
break;
#endif
} // switch (m_count)
return m_count <= 0;
} }
virtual bool Init() virtual bool Init()
{ {
// test we're good to go // test we're good to go
CPPUNIT_ASSERT(wxEventLoopBase::GetActive()); CHECK(wxEventLoopBase::GetActive());
// XXX only now can we construct Watcher, because we need // XXX only now can we construct Watcher, because we need
// active loop here // active loop here
m_watcher = new wxFileSystemWatcher(); m_watcher.reset(new wxFileSystemWatcher());
m_watcher->SetOwner(this); m_watcher->SetOwner(this);
// add dir to be watched // add dir to be watched
wxFileName dir = EventGenerator::GetWatchDir(); wxFileName dir = EventGenerator::GetWatchDir();
CPPUNIT_ASSERT(m_watcher->Add(dir, m_eventTypes)); CHECK(m_watcher->Add(dir, m_eventTypes));
return true; return true;
} }
virtual bool KeepWaiting()
{
// did we receive event already?
if (!tested)
{
// well, let's wait a bit more
wxSleep(WAIT_DURATION);
}
return true;
}
virtual bool AfterWait()
{
// fail if still no events
WX_ASSERT_MESSAGE
(
("No events during %d seconds!", static_cast<int>(WAIT_DURATION)),
tested
);
return true;
}
virtual void OnFileSystemEvent(wxFileSystemWatcherEvent& evt)
{
wxLogDebug("--- %s ---", evt.ToString());
m_lastEvent = wxDynamicCast(evt.Clone(), wxFileSystemWatcherEvent);
m_events.Add(m_lastEvent);
// test finished
SendIdle();
tested = true;
}
virtual void CheckResult() virtual void CheckResult()
{ {
CPPUNIT_ASSERT_MESSAGE( "No events received", !m_events.empty() ); REQUIRE( !m_events.empty() );
const wxFileSystemWatcherEvent * const e = m_events.front(); const wxFileSystemWatcherEvent * const e = m_events.front();
// this is our "reference event" // this is our "reference event"
const wxFileSystemWatcherEvent expected = ExpectedEvent(); const wxFileSystemWatcherEvent expected = ExpectedEvent();
CPPUNIT_ASSERT_EQUAL( expected.GetChangeType(), e->GetChangeType() ); CHECK( e->GetChangeType() == expected.GetChangeType() );
CPPUNIT_ASSERT_EQUAL((int)wxEVT_FSWATCHER, e->GetEventType()); CHECK( e->GetEventType() == wxEVT_FSWATCHER );
// XXX this needs change // XXX this needs change
CPPUNIT_ASSERT_EQUAL(wxEVT_CATEGORY_UNKNOWN, e->GetEventCategory()); CHECK( e->GetEventCategory() == wxEVT_CATEGORY_UNKNOWN );
CPPUNIT_ASSERT_EQUAL(expected.GetPath(), e->GetPath()); CHECK( e->GetPath() == expected.GetPath() );
CPPUNIT_ASSERT_EQUAL(expected.GetNewPath(), e->GetNewPath()); CHECK( e->GetNewPath() == expected.GetNewPath() );
// Under MSW extra modification events are sometimes reported after a // Under MSW extra modification events are sometimes reported after a
// rename and we just can't get rid of them, so ignore them in this // rename and we just can't get rid of them, so ignore them in this
@@ -412,121 +327,64 @@ public:
protected: protected:
EventGenerator& eg; EventGenerator& eg;
wxEventLoopBase* m_loop; // loop reference wxEventLoop m_loop; // loop reference
#ifdef OSX_EVENT_LOOP_WORKAROUND
wxEventLoopActivator* m_loopActivator; wxScopedPtr<wxFileSystemWatcher> m_watcher;
#endif
int m_count; // idle events count
wxFileSystemWatcher* m_watcher;
int m_eventTypes; // Which event-types to watch. Normally all of them int m_eventTypes; // Which event-types to watch. Normally all of them
bool tested; // indicates, whether we have already passed the test
#include "wx/arrimpl.cpp" wxVector<wxFileSystemWatcherEvent*> m_events;
WX_DEFINE_ARRAY_PTR(wxFileSystemWatcherEvent*, wxArrayEvent);
wxArrayEvent m_events;
wxFileSystemWatcherEvent* m_lastEvent;
};
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class FileSystemWatcherTestCase : public CppUnit::TestCase
{
public:
FileSystemWatcherTestCase() { }
virtual void setUp() wxOVERRIDE;
virtual void tearDown() wxOVERRIDE;
protected:
wxEventLoopBase* m_loop;
private: private:
CPPUNIT_TEST_SUITE( FileSystemWatcherTestCase ); void OnFileSystemEvent(wxFileSystemWatcherEvent& evt)
CPPUNIT_TEST( TestEventCreate ); {
CPPUNIT_TEST( TestEventDelete ); wxLogDebug("--- %s ---", evt.ToString());
CPPUNIT_TEST( TestTrees ); m_events.push_back(wxDynamicCast(evt.Clone(), wxFileSystemWatcherEvent));
// kqueue-based implementation doesn't collapse create/delete pairs in // test finished
// renames and doesn't detect neither modifications nor access to the SendIdle();
// files reliably currently so disable these tests }
//
// FIXME: fix the code and reenable them
#ifndef wxHAS_KQUEUE
CPPUNIT_TEST( TestEventRename );
CPPUNIT_TEST( TestEventModify );
// MSW implementation doesn't detect file access events currently
#ifndef __WINDOWS__
CPPUNIT_TEST( TestEventAccess );
#endif // __WINDOWS__
#endif // !wxHAS_KQUEUE
#ifdef wxHAS_INOTIFY
CPPUNIT_TEST( TestEventAttribute );
CPPUNIT_TEST( TestSingleWatchtypeEvent );
#endif // wxHAS_INOTIFY
CPPUNIT_TEST( TestNoEventsAfterRemove );
CPPUNIT_TEST_SUITE_END();
void TestEventCreate();
void TestEventDelete();
void TestEventRename();
void TestEventModify();
void TestEventAccess();
#ifdef wxHAS_INOTIFY
void TestEventAttribute();
void TestSingleWatchtypeEvent();
#endif // wxHAS_INOTIFY
void TestTrees();
void TestNoEventsAfterRemove();
wxDECLARE_NO_COPY_CLASS(FileSystemWatcherTestCase);
}; };
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( FileSystemWatcherTestCase );
// also include in its own registry so that these tests can be run alone // ----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FileSystemWatcherTestCase, // test fixture
"FileSystemWatcherTestCase" ); // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::setUp() class FileSystemWatcherTestCase
{ {
wxLog::AddTraceMask(wxTRACE_FSWATCHER); public:
FileSystemWatcherTestCase()
{
// Before each test, remove the dir if it exists.
// It would exist if the previous test run was aborted.
wxString tmp = wxStandardPaths::Get().GetTempDir();
wxFileName dir;
dir.AssignDir(tmp);
dir.AppendDir("fswatcher_test");
dir.Rmdir(wxPATH_RMDIR_RECURSIVE);
EventGenerator::Get().GetWatchDir();
}
// Before each test, remove the dir if it exists. ~FileSystemWatcherTestCase()
// It would exist if the previous test run was aborted. {
wxString tmp = wxStandardPaths::Get().GetTempDir(); EventGenerator::Get().RemoveWatchDir();
wxFileName dir; }
dir.AssignDir(tmp); };
dir.AppendDir("fswatcher_test");
dir.Rmdir(wxPATH_RMDIR_RECURSIVE);
EventGenerator::Get().GetWatchDir();
}
void FileSystemWatcherTestCase::tearDown()
{
EventGenerator::Get().RemoveWatchDir();
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestEventCreate // TestEventCreate
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestEventCreate()
{
wxLogDebug("TestEventCreate()");
class EventTester : public EventHandler TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::EventCreate", "[fsw]")
{
class EventTester : public FSWTesterBase
{ {
public: public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
CPPUNIT_ASSERT(eg.CreateFile()); CHECK(eg.CreateFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -540,24 +398,22 @@ void FileSystemWatcherTestCase::TestEventCreate()
EventTester tester; EventTester tester;
wxLogTrace(wxTRACE_FSWATCHER, "TestEventCreate tester created()");
tester.Run(); tester.Run();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestEventDelete // TestEventDelete
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestEventDelete()
{
wxLogDebug("TestEventDelete()");
class EventTester : public EventHandler TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::EventDelete", "[fsw]")
{
class EventTester : public FSWTesterBase
{ {
public: public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
CPPUNIT_ASSERT(eg.DeleteFile()); CHECK(eg.DeleteFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -578,19 +434,26 @@ void FileSystemWatcherTestCase::TestEventDelete()
tester.Run(); tester.Run();
} }
// kqueue-based implementation doesn't collapse create/delete pairs in
// renames and doesn't detect neither modifications nor access to the
// files reliably currently so disable these tests
//
// FIXME: fix the code and reenable them
#ifndef wxHAS_KQUEUE
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestEventRename // TestEventRename
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestEventRename()
{
wxLogDebug("TestEventRename()");
class EventTester : public EventHandler TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::EventRename", "[fsw]")
{
class EventTester : public FSWTesterBase
{ {
public: public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
CPPUNIT_ASSERT(eg.RenameFile()); CHECK(eg.RenameFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -612,16 +475,16 @@ void FileSystemWatcherTestCase::TestEventRename()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestEventModify // TestEventModify
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestEventModify()
{
wxLogDebug("TestEventModify()");
class EventTester : public EventHandler TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::EventModify", "[fsw]")
{
class EventTester : public FSWTesterBase
{ {
public: public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
CPPUNIT_ASSERT(eg.ModifyFile()); CHECK(eg.ModifyFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -640,19 +503,22 @@ void FileSystemWatcherTestCase::TestEventModify()
tester.Run(); tester.Run();
} }
// MSW implementation doesn't detect file access events currently
#ifndef __WINDOWS__
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestEventAccess // TestEventAccess
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestEventAccess()
{
wxLogDebug("TestEventAccess()");
class EventTester : public EventHandler TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::EventAccess", "[fsw]")
{
class EventTester : public FSWTesterBase
{ {
public: public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
CPPUNIT_ASSERT(eg.ReadFile()); CHECK(eg.ReadFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -672,20 +538,23 @@ void FileSystemWatcherTestCase::TestEventAccess()
tester.Run(); tester.Run();
} }
#endif // __WINDOWS__
#endif // !wxHAS_KQUEUE
#ifdef wxHAS_INOTIFY #ifdef wxHAS_INOTIFY
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestEventAttribute // TestEventAttribute
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestEventAttribute() TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::EventAttribute", "[fsw]")
{ {
wxLogDebug("TestEventAttribute()"); class EventTester : public FSWTesterBase
class EventTester : public EventHandler
{ {
public: public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
CPPUNIT_ASSERT(eg.TouchFile()); CHECK(eg.TouchFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -707,24 +576,24 @@ void FileSystemWatcherTestCase::TestEventAttribute()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestSingleWatchtypeEvent: Watch only wxFSW_EVENT_ACCESS // TestSingleWatchtypeEvent: Watch only wxFSW_EVENT_ACCESS
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestSingleWatchtypeEvent()
{
wxLogDebug("TestSingleWatchtypeEvent()");
class EventTester : public EventHandler TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::SingleWatchtypeEvent", "[fsw]")
{
class EventTester : public FSWTesterBase
{ {
public: public:
// We could pass wxFSW_EVENT_CREATE or MODIFY instead, but not RENAME or // We could pass wxFSW_EVENT_CREATE or MODIFY instead, but not RENAME or
// DELETE as the event path fields would be wrong in CheckResult() // DELETE as the event path fields would be wrong in CheckResult()
EventTester() : EventHandler(wxFSW_EVENT_ACCESS) {} EventTester() : FSWTesterBase(wxFSW_EVENT_ACCESS) {}
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
// As wxFSW_EVENT_ACCESS is passed to the ctor only ReadFile() will // As wxFSW_EVENT_ACCESS is passed to the ctor only ReadFile() will
// generate an event. Without it they all will, and the test fails // generate an event. Without it they all will, and the test fails
CPPUNIT_ASSERT(eg.CreateFile()); CHECK(eg.CreateFile());
CPPUNIT_ASSERT(eg.ModifyFile()); CHECK(eg.ModifyFile());
CPPUNIT_ASSERT(eg.ReadFile()); CHECK(eg.ReadFile());
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
@@ -745,9 +614,10 @@ void FileSystemWatcherTestCase::TestSingleWatchtypeEvent()
// TestTrees // TestTrees
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void FileSystemWatcherTestCase::TestTrees() TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::Trees", "[fsw]")
{ {
class TreeTester : public EventHandler class TreeTester : public FSWTesterBase
{ {
const size_t subdirs; const size_t subdirs;
const size_t files; const size_t files;
@@ -761,10 +631,10 @@ void FileSystemWatcherTestCase::TestTrees()
#endif #endif
) )
{ {
CPPUNIT_ASSERT(dir.Mkdir()); REQUIRE(dir.Mkdir());
// Now add a subdir with an easy name to remember in WatchTree() // Now add a subdir with an easy name to remember in WatchTree()
dir.AppendDir("child"); dir.AppendDir("child");
CPPUNIT_ASSERT(dir.Mkdir()); REQUIRE(dir.Mkdir());
wxFileName child(dir); // Create a copy to which to symlink wxFileName child(dir); // Create a copy to which to symlink
// Create a branch of 5 numbered subdirs, each containing 3 // Create a branch of 5 numbered subdirs, each containing 3
@@ -772,7 +642,7 @@ void FileSystemWatcherTestCase::TestTrees()
for ( unsigned d = 0; d < subdirs; ++d ) for ( unsigned d = 0; d < subdirs; ++d )
{ {
dir.AppendDir(wxString::Format("subdir%u", d+1)); dir.AppendDir(wxString::Format("subdir%u", d+1));
CPPUNIT_ASSERT(dir.Mkdir()); REQUIRE(dir.Mkdir());
const wxString prefix = dir.GetPathWithSep(); const wxString prefix = dir.GetPathWithSep();
const wxString ext[] = { ".txt", ".log", "" }; const wxString ext[] = { ".txt", ".log", "" };
@@ -786,12 +656,17 @@ void FileSystemWatcherTestCase::TestTrees()
if ( withSymlinks ) if ( withSymlinks )
{ {
// Create a symlink to a files, and another to 'child' // Create a symlink to a files, and another to 'child'
CPPUNIT_ASSERT_EQUAL(0, CHECK
(
symlink(wxString(prefix + "file1").c_str(), symlink(wxString(prefix + "file1").c_str(),
wxString(prefix + "file.lnk").c_str())); wxString(prefix + "file.lnk").c_str()) == 0
CPPUNIT_ASSERT_EQUAL(0, );
CHECK
(
symlink(child.GetFullPath().c_str(), symlink(child.GetFullPath().c_str(),
wxString(prefix + "dir.lnk").c_str())); wxString(prefix + "dir.lnk").c_str()) == 0
);
} }
#endif // __UNIX__ #endif // __UNIX__
} }
@@ -799,37 +674,35 @@ void FileSystemWatcherTestCase::TestTrees()
void RmDir(wxFileName dir) void RmDir(wxFileName dir)
{ {
CPPUNIT_ASSERT(dir.DirExists()); REQUIRE(dir.DirExists());
CPPUNIT_ASSERT(dir.Rmdir(wxPATH_RMDIR_RECURSIVE)); CHECK(dir.Rmdir(wxPATH_RMDIR_RECURSIVE));
} }
void WatchDir(wxFileName dir) void WatchDir(wxFileName dir)
{ {
CPPUNIT_ASSERT(m_watcher); REQUIRE(m_watcher);
// Store the initial count; there may already be some watches // Store the initial count; there may already be some watches
const int initial = m_watcher->GetWatchedPathsCount(); const int initial = m_watcher->GetWatchedPathsCount();
m_watcher->Add(dir); m_watcher->Add(dir);
CPPUNIT_ASSERT_EQUAL(initial + 1, CHECK( m_watcher->GetWatchedPathsCount() == initial + 1 );
m_watcher->GetWatchedPathsCount());
} }
void RemoveSingleWatch(wxFileName dir) void RemoveSingleWatch(wxFileName dir)
{ {
CPPUNIT_ASSERT(m_watcher); REQUIRE(m_watcher);
const int initial = m_watcher->GetWatchedPathsCount(); const int initial = m_watcher->GetWatchedPathsCount();
m_watcher->Remove(dir); m_watcher->Remove(dir);
CPPUNIT_ASSERT_EQUAL(initial - 1, CHECK( m_watcher->GetWatchedPathsCount() == initial - 1 );
m_watcher->GetWatchedPathsCount());
} }
void WatchTree(const wxFileName& dir) void WatchTree(const wxFileName& dir)
{ {
CPPUNIT_ASSERT(m_watcher); REQUIRE(m_watcher);
int treeitems = 1; // the trunk int treeitems = 1; // the trunk
#if !defined(__WINDOWS__) && !defined(wxHAVE_FSEVENTS_FILE_NOTIFICATIONS) #if !defined(__WINDOWS__) && !defined(wxHAVE_FSEVENTS_FILE_NOTIFICATIONS)
@@ -847,17 +720,17 @@ void FileSystemWatcherTestCase::TestTrees()
m_watcher->AddTree(dir); m_watcher->AddTree(dir);
const int plustree = m_watcher->GetWatchedPathsCount(); const int plustree = m_watcher->GetWatchedPathsCount();
CPPUNIT_ASSERT_EQUAL(initial + treeitems, plustree); CHECK( plustree == initial + treeitems );
m_watcher->RemoveTree(dir); m_watcher->RemoveTree(dir);
CPPUNIT_ASSERT_EQUAL(initial, m_watcher->GetWatchedPathsCount()); CHECK( m_watcher->GetWatchedPathsCount() == initial );
// Now test the refcount mechanism by watching items more than once // Now test the refcount mechanism by watching items more than once
wxFileName child(dir); wxFileName child(dir);
child.AppendDir("child"); child.AppendDir("child");
m_watcher->AddTree(child); m_watcher->AddTree(child);
// Check some watches were added; we don't care about the number // Check some watches were added; we don't care about the number
CPPUNIT_ASSERT(initial < m_watcher->GetWatchedPathsCount()); CHECK(initial < m_watcher->GetWatchedPathsCount());
// Now watch the whole tree and check that the count is the same // Now watch the whole tree and check that the count is the same
// as it was the first time, despite also adding 'child' separately // as it was the first time, despite also adding 'child' separately
// Except that in wxMSW this isn't true: each watch will be a // Except that in wxMSW this isn't true: each watch will be a
@@ -867,11 +740,11 @@ void FileSystemWatcherTestCase::TestTrees()
fudge = 1; fudge = 1;
#endif // __WINDOWS__ || wxHAVE_FSEVENTS_FILE_NOTIFICATIONS #endif // __WINDOWS__ || wxHAVE_FSEVENTS_FILE_NOTIFICATIONS
m_watcher->AddTree(dir); m_watcher->AddTree(dir);
CPPUNIT_ASSERT_EQUAL(plustree + fudge, m_watcher->GetWatchedPathsCount()); CHECK( m_watcher->GetWatchedPathsCount() == plustree + fudge );
m_watcher->RemoveTree(child); m_watcher->RemoveTree(child);
CPPUNIT_ASSERT(initial < m_watcher->GetWatchedPathsCount()); CHECK(initial < m_watcher->GetWatchedPathsCount());
m_watcher->RemoveTree(dir); m_watcher->RemoveTree(dir);
CPPUNIT_ASSERT_EQUAL(initial, m_watcher->GetWatchedPathsCount()); CHECK( m_watcher->GetWatchedPathsCount() == initial );
#if defined(__UNIX__) #if defined(__UNIX__)
// Finally, test a tree containing internal symlinks // Finally, test a tree containing internal symlinks
RmDir(dir); RmDir(dir);
@@ -881,8 +754,8 @@ void FileSystemWatcherTestCase::TestTrees()
// (and without the assert, it would infinitely loop) // (and without the assert, it would infinitely loop)
wxFileName fn = dir; wxFileName fn = dir;
fn.DontFollowLink(); fn.DontFollowLink();
CPPUNIT_ASSERT(m_watcher->AddTree(fn)); CHECK(m_watcher->AddTree(fn));
CPPUNIT_ASSERT(m_watcher->RemoveTree(fn)); CHECK(m_watcher->RemoveTree(fn));
// Regrow the tree without symlinks, ready for the next test // Regrow the tree without symlinks, ready for the next test
RmDir(dir); RmDir(dir);
@@ -892,8 +765,8 @@ void FileSystemWatcherTestCase::TestTrees()
void WatchTreeWithFilespec(const wxFileName& dir) void WatchTreeWithFilespec(const wxFileName& dir)
{ {
CPPUNIT_ASSERT(m_watcher); REQUIRE(m_watcher);
CPPUNIT_ASSERT(dir.DirExists()); // Was built in WatchTree() REQUIRE(dir.DirExists()); // Was built in WatchTree()
// Store the initial count; there may already be some watches // Store the initial count; there may already be some watches
const int initial = m_watcher->GetWatchedPathsCount(); const int initial = m_watcher->GetWatchedPathsCount();
@@ -909,20 +782,19 @@ void FileSystemWatcherTestCase::TestTrees()
#endif #endif
m_watcher->AddTree(dir, wxFSW_EVENT_ALL, "*.txt"); m_watcher->AddTree(dir, wxFSW_EVENT_ALL, "*.txt");
const int plustree = m_watcher->GetWatchedPathsCount(); CHECK( m_watcher->GetWatchedPathsCount() == initial + treeitems );
CPPUNIT_ASSERT_EQUAL(initial + treeitems, plustree);
// RemoveTree should try to remove only those files that were added // RemoveTree should try to remove only those files that were added
m_watcher->RemoveTree(dir); m_watcher->RemoveTree(dir);
CPPUNIT_ASSERT_EQUAL(initial, m_watcher->GetWatchedPathsCount()); CHECK( m_watcher->GetWatchedPathsCount() == initial );
} }
void RemoveAllWatches() void RemoveAllWatches()
{ {
CPPUNIT_ASSERT(m_watcher); REQUIRE(m_watcher);
m_watcher->RemoveAll(); m_watcher->RemoveAll();
CPPUNIT_ASSERT_EQUAL(0, m_watcher->GetWatchedPathsCount()); CHECK( m_watcher->GetWatchedPathsCount() == 0 );
} }
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
@@ -930,16 +802,16 @@ void FileSystemWatcherTestCase::TestTrees()
// We don't use this function for events. Just run the tests // We don't use this function for events. Just run the tests
wxFileName watchdir = EventGenerator::GetWatchDir(); wxFileName watchdir = EventGenerator::GetWatchDir();
CPPUNIT_ASSERT(watchdir.DirExists()); REQUIRE(watchdir.DirExists());
wxFileName treedir(watchdir); wxFileName treedir(watchdir);
treedir.AppendDir("treetrunk"); treedir.AppendDir("treetrunk");
CPPUNIT_ASSERT(!treedir.DirExists()); CHECK(!treedir.DirExists());
wxFileName singledir(watchdir); wxFileName singledir(watchdir);
singledir.AppendDir("single"); singledir.AppendDir("single");
CPPUNIT_ASSERT(!singledir.DirExists()); CHECK(!singledir.DirExists());
CPPUNIT_ASSERT(singledir.Mkdir()); CHECK(singledir.Mkdir());
WatchDir(singledir); WatchDir(singledir);
WatchTree(treedir); WatchTree(treedir);
@@ -965,7 +837,7 @@ void FileSystemWatcherTestCase::TestTrees()
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
{ {
CPPUNIT_FAIL("Shouldn't be called"); FAIL("Shouldn't be called");
return wxFileSystemWatcherEvent(wxFSW_EVENT_ERROR); return wxFileSystemWatcherEvent(wxFSW_EVENT_ERROR);
} }
@@ -979,15 +851,7 @@ void FileSystemWatcherTestCase::TestTrees()
TreeTester tester; TreeTester tester;
// The fs watcher test cases will hang on OS X if we call Run().
// This is likely due to differences between the event loop
// between OS X and the other ports.
#ifdef OSX_EVENT_LOOP_WORKAROUND
tester.Init();
tester.GenerateEvent();
#else
tester.Run(); tester.Run();
#endif
} }
@@ -1003,7 +867,7 @@ namespace
// can't be a weak_definition // can't be a weak_definition
// //
// So define this class outside the function instead. // So define this class outside the function instead.
class NoEventsAfterRemoveEventTester : public EventHandler, class NoEventsAfterRemoveEventTester : public FSWTesterBase,
public wxTimer public wxTimer
{ {
public: public:
@@ -1019,17 +883,17 @@ public:
virtual void GenerateEvent() wxOVERRIDE virtual void GenerateEvent() wxOVERRIDE
{ {
m_watcher->Remove(EventGenerator::GetWatchDir()); m_watcher->Remove(EventGenerator::GetWatchDir());
CPPUNIT_ASSERT(eg.CreateFile()); CHECK(eg.CreateFile());
} }
virtual void CheckResult() wxOVERRIDE virtual void CheckResult() wxOVERRIDE
{ {
CPPUNIT_ASSERT( m_events.empty() ); REQUIRE( m_events.empty() );
} }
virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE virtual wxFileSystemWatcherEvent ExpectedEvent() wxOVERRIDE
{ {
CPPUNIT_FAIL( "Shouldn't be called" ); FAIL( "Shouldn't be called" );
return wxFileSystemWatcherEvent(wxFSW_EVENT_ERROR); return wxFileSystemWatcherEvent(wxFSW_EVENT_ERROR);
} }
@@ -1042,7 +906,8 @@ public:
} // anonymous namespace } // anonymous namespace
void FileSystemWatcherTestCase::TestNoEventsAfterRemove() TEST_CASE_METHOD(FileSystemWatcherTestCase,
"wxFileSystemWatcher::NoEventsAfterRemove", "[fsw]")
{ {
NoEventsAfterRemoveEventTester tester; NoEventsAfterRemoveEventTester tester;
tester.Run(); tester.Run();