Daniele Bartolini 2 лет назад
Родитель
Сommit
12427efbb9
1 измененных файлов с 171 добавлено и 1 удалено
  1. 171 1
      src/core/unit_tests.cpp

+ 171 - 1
src/core/unit_tests.cpp

@@ -11,6 +11,8 @@
 #include "core/containers/hash_map.inl"
 #include "core/containers/hash_set.inl"
 #include "core/containers/vector.inl"
+#include "core/filesystem/file_monitor.h"
+#include "core/filesystem/filesystem_disk.h"
 #include "core/filesystem/path.h"
 #include "core/guid.inl"
 #include "core/json/json.h"
@@ -30,15 +32,17 @@
 #include "core/memory/memory.inl"
 #include "core/memory/temp_allocator.inl"
 #include "core/murmur.h"
+#include "core/option.inl"
 #include "core/os.h"
 #include "core/process.h"
 #include "core/strings/dynamic_string.inl"
 #include "core/strings/string.inl"
 #include "core/strings/string_id.inl"
 #include "core/strings/string_view.inl"
+#include "core/thread/condition_variable.h"
+#include "core/thread/mutex.h"
 #include "core/thread/thread.h"
 #include "core/time.h"
-#include "core/option.inl"
 #include "resource/lua_resource.h"
 #include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
 #include <stdio.h>  // printf
@@ -1557,6 +1561,171 @@ static void test_filesystem()
 #endif // if CROWN_PLATFORM_POSIX
 }
 
+static void test_file_monitor()
+{
+#if !CROWN_PLATFORM_EMSCRIPTEN
+	struct UserData
+	{
+		bool done;
+		Mutex m;
+		ConditionVariable cv;
+		FileMonitorFunction check;
+
+		UserData()
+			: done(false)
+		{
+		}
+
+		void wait(u32 ms)
+		{
+			m.lock();
+			while (!done)
+				cv.wait(m, ms);
+			m.unlock();
+			ENSURE(done);
+		}
+
+		static void callback(void *user_data, FileMonitorEvent::Enum fme, bool is_dir, const char *path, const char *path_modified)
+		{
+			UserData *ud = (UserData *)user_data;
+			ud->done = false;
+			ud->check(user_data, fme, is_dir, path, path_modified);
+			ud->done = true;
+			ud->cv.signal();
+		}
+	};
+
+	struct ScopedUniqueWorkingDir
+	{
+		char _workdir[1024];
+
+		ScopedUniqueWorkingDir()
+		{
+			os::getcwd(_workdir, sizeof(_workdir));
+
+			char unique_name[GUID_BUF_LEN];
+			guid::to_string(unique_name, sizeof(unique_name), guid::new_guid());
+			os::create_directory(unique_name);
+			os::setcwd(unique_name);
+		}
+
+		~ScopedUniqueWorkingDir()
+		{
+			os::setcwd(_workdir);
+		}
+	};
+
+	memory_globals::init();
+	guid_globals::init();
+	{
+		ScopedUniqueWorkingDir uwd;
+
+		FilesystemDisk fs(default_allocator());
+		fs.set_prefix("dir");
+		fs.create_directory("");
+
+		const char *paths[] = { "dir" };
+		UserData state;
+		FileMonitor fm(default_allocator());
+		fm.start(countof(paths), paths, true, state.callback, &state);
+
+		state.check = [](auto user_data, auto fme, auto is_dir, auto path, auto path_modified) {
+			CE_UNUSED_2(user_data, path_modified);
+			ENSURE(fme == FileMonitorEvent::CREATED);
+			ENSURE(is_dir == true);
+			DynamicString os_path(default_allocator());
+			path::join(os_path, "dir", "foo");
+			ENSURE(strcmp(path, os_path.c_str()) == 0);
+		};
+		fs.create_directory("foo");
+		state.wait(500);
+
+		fm.stop();
+	}
+	{
+		ScopedUniqueWorkingDir uwd;
+
+		FilesystemDisk fs1(default_allocator());
+		fs1.set_prefix("dir1");
+		fs1.create_directory("");
+		FilesystemDisk fs2(default_allocator());
+		fs2.set_prefix("dir2");
+		fs2.create_directory("");
+		fs2.create_directory("foo");
+
+		const char *paths[] = { "dir1" };
+		UserData state;
+		FileMonitor fm(default_allocator());
+		fm.start(countof(paths), paths, true, state.callback, &state);
+
+		state.check = [](auto user_data, auto fme, auto is_dir, auto path, auto path_modified) {
+			CE_UNUSED_2(user_data, path_modified);
+			ENSURE(fme == FileMonitorEvent::CREATED);
+			ENSURE(is_dir == true);
+			DynamicString os_path(default_allocator());
+			path::join(os_path, "dir1", "foo");
+			ENSURE(strcmp(path, os_path.c_str()) == 0);
+		};
+		DynamicString old_name(default_allocator());
+		DynamicString new_name(default_allocator());
+		path::join(old_name, "dir2", "foo");
+		path::join(new_name, "dir1", "foo");
+		os::rename(old_name.c_str(), new_name.c_str());
+		state.wait(500);
+
+		state.check = [](auto user_data, auto fme, auto is_dir, auto path, auto path_modified) {
+			CE_UNUSED_2(user_data, path_modified);
+			ENSURE(fme == FileMonitorEvent::DELETED);
+#if !CROWN_PLATFORM_WINDOWS
+			ENSURE(is_dir == true);
+#endif
+			DynamicString os_path(default_allocator());
+			path::join(os_path, "dir1", "foo");
+			ENSURE(strcmp(path, os_path.c_str()) == 0);
+		};
+		os::rename(new_name.c_str(), old_name.c_str());
+		state.wait(500);
+
+		fm.stop();
+	}
+	{
+		ScopedUniqueWorkingDir uwd;
+
+		FilesystemDisk fs(default_allocator());
+		fs.set_prefix("dir");
+		fs.create_directory("");
+		fs.create_directory("foo");
+
+		const char *paths[] = { "dir" };
+		UserData state;
+		FileMonitor fm(default_allocator());
+		fm.start(countof(paths), paths, true, state.callback, &state);
+
+		state.check = [](auto user_data, auto fme, auto is_dir, auto path, auto path_modified) {
+			CE_UNUSED(user_data);
+			ENSURE(fme == FileMonitorEvent::RENAMED);
+			ENSURE(is_dir == true);
+			DynamicString os_path(default_allocator());
+			DynamicString os_path_modified(default_allocator());
+			path::join(os_path, "dir", "foo");
+			path::join(os_path_modified, "dir", "bar");
+			ENSURE(strcmp(path, os_path.c_str()) == 0);
+			ENSURE(strcmp(path_modified, os_path_modified.c_str()) == 0);
+		};
+		DynamicString old_name(default_allocator());
+		DynamicString new_name(default_allocator());
+		path::join(old_name, "dir", "foo");
+		path::join(new_name, "dir", "bar");
+		os::rename(old_name.c_str(), new_name.c_str());
+		state.wait(500);
+
+		fm.stop();
+	}
+	guid_globals::shutdown();
+	memory_globals::shutdown();
+#endif // if !CROWN_PLATFORM_EMSCRIPTEN
+}
+
 static void test_option()
 {
 	memory_globals::init();
@@ -1767,6 +1936,7 @@ int main_unit_tests()
 	RUN_TEST(test_thread);
 	RUN_TEST(test_process);
 	RUN_TEST(test_filesystem);
+	RUN_TEST(test_file_monitor);
 	RUN_TEST(test_option);
 	RUN_TEST(test_lua_resource);