X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2b6d227c12faf602c09c1d31a1891ab68ac51c55..f321d0bc0caf4d78ccc5426e926fc25c46297439:/tests/fswatcher/fswatchertest.cpp diff --git a/tests/fswatcher/fswatchertest.cpp b/tests/fswatcher/fswatchertest.cpp index b923095379..5b238a49d5 100644 --- a/tests/fswatcher/fswatchertest.cpp +++ b/tests/fswatcher/fswatchertest.cpp @@ -190,8 +190,9 @@ class EventHandler : public wxEvtHandler public: enum { WAIT_DURATION = 3 }; - EventHandler() : - eg(EventGenerator::Get()), m_loop(0), m_count(0), m_watcher(0) + EventHandler(int types = wxFSW_EVENT_ALL) : + eg(EventGenerator::Get()), m_loop(0), m_count(0), m_watcher(0), + m_eventTypes(types) { m_loop = new wxEventLoop(); Connect(wxEVT_IDLE, wxIdleEventHandler(EventHandler::OnIdle)); @@ -289,7 +290,7 @@ public: // add dir to be watched wxFileName dir = EventGenerator::GetWatchDir(); - CPPUNIT_ASSERT(m_watcher->Add(dir, wxFSW_EVENT_ALL)); + CPPUNIT_ASSERT(m_watcher->Add(dir, m_eventTypes)); return true; } @@ -389,6 +390,7 @@ protected: int m_count; // idle events count wxFileSystemWatcher* m_watcher; + 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" @@ -417,7 +419,9 @@ private: CPPUNIT_TEST_SUITE( FileSystemWatcherTestCase ); CPPUNIT_TEST( TestEventCreate ); CPPUNIT_TEST( TestEventDelete ); +#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7) CPPUNIT_TEST( TestTrees ); +#endif // kqueue-based implementation doesn't collapse create/delete pairs in // renames and doesn't detect neither modifications nor access to the @@ -434,6 +438,11 @@ private: #endif // __WINDOWS__ #endif // !wxHAS_KQUEUE +#ifdef wxHAS_INOTIFY + CPPUNIT_TEST( TestEventAttribute ); + CPPUNIT_TEST( TestSingleWatchtypeEvent ); +#endif // wxHAS_INOTIFY + CPPUNIT_TEST( TestNoEventsAfterRemove ); CPPUNIT_TEST_SUITE_END(); @@ -442,8 +451,13 @@ private: void TestEventRename(); void TestEventModify(); void TestEventAccess(); - void TestTrees(); - +#ifdef wxHAS_INOTIFY + void TestEventAttribute(); + void TestSingleWatchtypeEvent(); +#endif // wxHAS_INOTIFY +#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7) + void TestTrees(); // Visual C++ 6 can't build this +#endif void TestNoEventsAfterRemove(); DECLARE_NO_COPY_CLASS(FileSystemWatcherTestCase) @@ -632,9 +646,80 @@ void FileSystemWatcherTestCase::TestEventAccess() tester.Run(); } +#ifdef wxHAS_INOTIFY +// ---------------------------------------------------------------------------- +// TestEventAttribute +// ---------------------------------------------------------------------------- +void FileSystemWatcherTestCase::TestEventAttribute() +{ + wxLogDebug("TestEventAttribute()"); + + class EventTester : public EventHandler + { + public: + virtual void GenerateEvent() + { + CPPUNIT_ASSERT(eg.TouchFile()); + } + + virtual wxFileSystemWatcherEvent ExpectedEvent() + { + wxFileSystemWatcherEvent event(wxFSW_EVENT_ATTRIB); + event.SetPath(eg.m_file); + event.SetNewPath(eg.m_file); + return event; + } + }; + + // we need to create a file to touch + EventGenerator::Get().CreateFile(); + + EventTester tester; + tester.Run(); +} + +// ---------------------------------------------------------------------------- +// TestSingleWatchtypeEvent: Watch only wxFSW_EVENT_ACCESS +// ---------------------------------------------------------------------------- +void FileSystemWatcherTestCase::TestSingleWatchtypeEvent() +{ + wxLogDebug("TestSingleWatchtypeEvent()"); + + class EventTester : public EventHandler + { + public: + // We could pass wxFSW_EVENT_CREATE or MODIFY instead, but not RENAME or + // DELETE as the event path fields would be wrong in CheckResult() + EventTester() : EventHandler(wxFSW_EVENT_ACCESS) {} + + virtual void GenerateEvent() + { + // As wxFSW_EVENT_ACCESS is passed to the ctor only ReadFile() will + // generate an event. Without it they all will, and the test fails + CPPUNIT_ASSERT(eg.CreateFile()); + CPPUNIT_ASSERT(eg.ModifyFile()); + CPPUNIT_ASSERT(eg.ReadFile()); + } + + virtual wxFileSystemWatcherEvent ExpectedEvent() + { + wxFileSystemWatcherEvent event(wxFSW_EVENT_ACCESS); + event.SetPath(eg.m_file); + event.SetNewPath(eg.m_file); + return event; + } + }; + + EventTester tester; + tester.Run(); +} +#endif // wxHAS_INOTIFY + // ---------------------------------------------------------------------------- // TestTrees // ---------------------------------------------------------------------------- + +#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7) void FileSystemWatcherTestCase::TestTrees() { class TreeTester : public EventHandler @@ -645,9 +730,17 @@ void FileSystemWatcherTestCase::TestTrees() public: TreeTester() : subdirs(5), files(3) {} - void GrowTree(wxFileName dir) + void GrowTree(wxFileName dir +#ifdef __UNIX__ + , bool withSymlinks = false +#endif + ) { CPPUNIT_ASSERT(dir.Mkdir()); + // Now add a subdir with an easy name to remember in WatchTree() + dir.AppendDir("child"); + CPPUNIT_ASSERT(dir.Mkdir()); + wxFileName child(dir); // Create a copy to which to symlink // Create a branch of 5 numbered subdirs, each containing 3 // numbered files @@ -657,12 +750,25 @@ void FileSystemWatcherTestCase::TestTrees() CPPUNIT_ASSERT(dir.Mkdir()); const wxString prefix = dir.GetPathWithSep(); + const wxString ext[] = { ".txt", ".log", "" }; for ( unsigned f = 0; f < files; ++f ) { // Just create the files. - wxFile(prefix + wxString::Format("file%u", f+1), + wxFile(prefix + wxString::Format("file%u", f+1) + ext[f], wxFile::write); } +#if defined(__UNIX__) + if ( withSymlinks ) + { + // Create a symlink to a files, and another to 'child' + CPPUNIT_ASSERT_EQUAL(0, + symlink(wxString(prefix + "file1").c_str(), + wxString(prefix + "file.lnk").c_str())); + CPPUNIT_ASSERT_EQUAL(0, + symlink(child.GetFullPath().c_str(), + wxString(prefix + "dir.lnk").c_str())); + } +#endif // __UNIX__ } } @@ -700,8 +806,13 @@ void FileSystemWatcherTestCase::TestTrees() { CPPUNIT_ASSERT(m_watcher); - const size_t - treeitems = (subdirs*files) + subdirs + 1; // +1 for the trunk + size_t treeitems = 1; // the trunk +#ifndef __WINDOWS__ + // When there's no file mask, wxMSW sets a single watch + // on the trunk which is implemented recursively. + // wxGTK always sets an additional watch for each subdir + treeitems += subdirs + 1; // +1 for 'child' +#endif // __WINDOWS__ // Store the initial count; there may already be some watches const int initial = m_watcher->GetWatchedPathsCount(); @@ -715,6 +826,65 @@ void FileSystemWatcherTestCase::TestTrees() m_watcher->RemoveTree(dir); CPPUNIT_ASSERT_EQUAL(initial, m_watcher->GetWatchedPathsCount()); + + // Now test the refcount mechanism by watching items more than once + wxFileName child(dir); + child.AppendDir("child"); + m_watcher->AddTree(child); + // Check some watches were added; we don't care about the number + CPPUNIT_ASSERT(initial < m_watcher->GetWatchedPathsCount()); + // Now watch the whole tree and check that the count is the same + // as it was the first time, despite also adding 'child' separately + // Except that in wxMSW this isn't true: each watch will be a + // single, recursive dir; so fudge the count + size_t fudge = 0; +#ifdef __WINDOWS__ + fudge = 1; +#endif // __WINDOWS__ + m_watcher->AddTree(dir); + CPPUNIT_ASSERT_EQUAL(plustree + fudge, m_watcher->GetWatchedPathsCount()); + m_watcher->RemoveTree(child); + CPPUNIT_ASSERT(initial < m_watcher->GetWatchedPathsCount()); + m_watcher->RemoveTree(dir); + CPPUNIT_ASSERT_EQUAL(initial, m_watcher->GetWatchedPathsCount()); +#if defined(__UNIX__) + // Finally, test a tree containing internal symlinks + RmDir(dir); + GrowTree(dir, true /* test symlinks */); + + // Without the DontFollowLink() call AddTree() would now assert + // (and without the assert, it would infinitely loop) + wxFileName fn = dir; + fn.DontFollowLink(); + CPPUNIT_ASSERT(m_watcher->AddTree(fn)); + CPPUNIT_ASSERT(m_watcher->RemoveTree(fn)); + + // Regrow the tree without symlinks, ready for the next test + RmDir(dir); + GrowTree(dir, false); +#endif // __UNIX__ + } + + void WatchTreeWithFilespec(const wxFileName& dir) + { + CPPUNIT_ASSERT(m_watcher); + CPPUNIT_ASSERT(dir.DirExists()); // Was built in WatchTree() + + // Store the initial count; there may already be some watches + const int initial = m_watcher->GetWatchedPathsCount(); + + // When we use a filter, both wxMSW and wxGTK implementations set + // an additional watch for each subdir (+1 for the root dir itself + // and another +1 for "child"). + const size_t treeitems = subdirs + 2; + m_watcher->AddTree(dir, wxFSW_EVENT_ALL, "*.txt"); + + const int plustree = m_watcher->GetWatchedPathsCount(); + CPPUNIT_ASSERT_EQUAL(initial + treeitems, plustree); + + // RemoveTree should try to remove only those files that were added + m_watcher->RemoveTree(dir); + CPPUNIT_ASSERT_EQUAL(initial, m_watcher->GetWatchedPathsCount()); } void RemoveAllWatches() @@ -743,6 +913,12 @@ void FileSystemWatcherTestCase::TestTrees() WatchDir(singledir); WatchTree(treedir); + // Now test adding and removing a tree using a filespec + // wxMSW uses the generic method to add matching files; which fails + // as it doesn't support adding files :/ So disable the test +#ifndef __WINDOWS__ + WatchTreeWithFilespec(treedir); +#endif // __WINDOWS__ RemoveSingleWatch(singledir); // Add it back again, ready to test RemoveAll() @@ -774,6 +950,8 @@ void FileSystemWatcherTestCase::TestTrees() TreeTester tester; tester.Run(); } +#endif // !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7) + namespace {