1 #include "gmock/gmock.h" 2 3 #include <fcntl.h> 4 5 #include <memory> 6 #include <condition_variable> 7 #include <thread> 8 #include <mutex> 9 #include <chrono> 10 11 #include "inotifywatchtower.h" 12 13 using namespace std; 14 using namespace testing; 15 16 class WatchTowerBehaviour: public testing::Test { 17 public: 18 INotifyWatchTower watch_tower; 19 20 void SetUp() override { 21 #ifdef _WIN32 22 file_watcher = make_shared<WinFileWatcher>(); 23 #endif 24 } 25 26 string createTempEmptyFile() { 27 // I know tmpnam is bad but I need control over the file 28 // and it is the only one which exits on Windows. 29 char* file_name = tmpnam( nullptr ); 30 int fd = creat( file_name, S_IRUSR | S_IWUSR ); 31 close( fd ); 32 33 return string( file_name ); 34 } 35 36 string getNonExistingFileName() { 37 return string( tmpnam( nullptr ) ); 38 } 39 }; 40 41 TEST_F( WatchTowerBehaviour, AcceptsAnExistingFileToWatch ) { 42 auto file_name = createTempEmptyFile(); 43 auto registration = watch_tower.addFile( file_name, [] (void) { } ); 44 } 45 46 TEST_F( WatchTowerBehaviour, AcceptsANonExistingFileToWatch ) { 47 auto registration = watch_tower.addFile( getNonExistingFileName(), [] (void) { } ); 48 } 49 50 class WatchTowerSingleFile: public WatchTowerBehaviour { 51 public: 52 static const int TIMEOUT = 100; 53 54 string file_name; 55 INotifyWatchTower::Registration registration; 56 57 mutex mutex_; 58 condition_variable cv_; 59 bool notification_received = false; 60 61 void SetUp() override { 62 file_name = createTempEmptyFile(); 63 registration = watch_tower.addFile( file_name, [this] (void) { 64 unique_lock<mutex> lock(mutex_); 65 notification_received = true; 66 cv_.notify_one(); } ); 67 } 68 69 bool waitNotificationReceived() { 70 unique_lock<mutex> lock(mutex_); 71 return cv_.wait_for( lock, std::chrono::milliseconds(100), 72 [this] { return notification_received; } ); 73 } 74 75 void appendDataToFile( const string& file_name ) { 76 static const char* string = "Test line\n"; 77 int fd = open( file_name.c_str(), O_WRONLY | O_APPEND ); 78 write( fd, (void*) string, strlen( string ) ); 79 close( fd ); 80 } 81 }; 82 83 TEST_F( WatchTowerSingleFile, SignalsWhenAWatchedFileIsAppended ) { 84 appendDataToFile( file_name ); 85 ASSERT_TRUE( waitNotificationReceived() ); 86 } 87 88 TEST_F( WatchTowerSingleFile, StopSignalingWhenWatchDeleted ) { 89 remove( file_name.c_str() ); 90 ASSERT_TRUE( waitNotificationReceived() ); 91 } 92