summaryrefslogtreecommitdiff
path: root/Tests/LibC
diff options
context:
space:
mode:
authorsin-ack <sin-ack@users.noreply.github.com>2021-05-10 09:27:04 +0000
committerAndreas Kling <kling@serenityos.org>2021-05-12 22:38:20 +0200
commit60eb4adac2e3ceef09baef5b441990f5390503ac (patch)
tree88a1dccc5b5257ba1b2c0be6636069a08b6c0e31 /Tests/LibC
parentae9e35210404e901d2ec9c936ee00fa7dafcbadb (diff)
downloadserenity-60eb4adac2e3ceef09baef5b441990f5390503ac.zip
Tests: Add InodeWatcher and FileWatcher tests
This patch adds some rudimentary tests for InodeWatcher. It tests the basic functionality, but maybe there are corner cases I haven't caught. Additionally, this is our first LibCore test. :^)
Diffstat (limited to 'Tests/LibC')
-rw-r--r--Tests/LibC/CMakeLists.txt1
-rw-r--r--Tests/LibC/TestLibCInodeWatcher.cpp170
2 files changed, 171 insertions, 0 deletions
diff --git a/Tests/LibC/CMakeLists.txt b/Tests/LibC/CMakeLists.txt
index e7c5aa17d2..d18144aff4 100644
--- a/Tests/LibC/CMakeLists.txt
+++ b/Tests/LibC/CMakeLists.txt
@@ -5,6 +5,7 @@ set(TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCMkTemp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCExec.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TestLibCDirEnt.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/TestLibCInodeWatcher.cpp
)
file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
diff --git a/Tests/LibC/TestLibCInodeWatcher.cpp b/Tests/LibC/TestLibCInodeWatcher.cpp
new file mode 100644
index 0000000000..b36c3eb7ff
--- /dev/null
+++ b/Tests/LibC/TestLibCInodeWatcher.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/NumericLimits.h>
+#include <Kernel/API/InodeWatcherEvent.h>
+#include <Kernel/API/InodeWatcherFlags.h>
+#include <LibTest/TestCase.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+
+u8 buffer[MAXIMUM_EVENT_SIZE];
+InodeWatcherEvent* event = reinterpret_cast<InodeWatcherEvent*>(buffer);
+
+static int read_event(int fd)
+{
+ int rc = read(fd, &buffer, MAXIMUM_EVENT_SIZE);
+ return rc;
+}
+
+static String get_event_name()
+{
+ if (event->name_length == 0)
+ return String();
+
+ return String { event->name, event->name_length - 1 };
+}
+
+TEST_CASE(inode_watcher_metadata_modified_event)
+{
+ int fd = create_inode_watcher(0);
+ EXPECT_NE(fd, -1);
+
+ int test_fd = creat("/tmp/testfile", 0777);
+ EXPECT_NE(test_fd, -1);
+
+ int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::MetadataModified));
+ EXPECT_NE(wd, -1);
+
+ // "touch" the file
+ int rc = utime("/tmp/testfile", nullptr);
+ EXPECT_NE(rc, -1);
+
+ rc = read_event(fd);
+ EXPECT_EQ(event->watch_descriptor, wd);
+ EXPECT_EQ(event->type, InodeWatcherEvent::Type::MetadataModified);
+
+ close(fd);
+ close(test_fd);
+ unlink("/tmp/testfile");
+}
+
+TEST_CASE(inode_watcher_content_modified_event)
+{
+ int fd = create_inode_watcher(0);
+ EXPECT_NE(fd, -1);
+
+ int test_fd = creat("/tmp/testfile", 0777);
+ EXPECT_NE(test_fd, -1);
+
+ int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::ContentModified));
+ EXPECT_NE(wd, -1);
+
+ int rc = write(test_fd, "test", 4);
+ EXPECT_NE(rc, -1);
+
+ rc = read_event(fd);
+ EXPECT_NE(rc, -1);
+ EXPECT_EQ(event->watch_descriptor, wd);
+ EXPECT_EQ(event->type, InodeWatcherEvent::Type::ContentModified);
+
+ close(fd);
+ close(test_fd);
+ unlink("/tmp/testfile");
+}
+
+TEST_CASE(inode_watcher_deleted_event)
+{
+ int fd = create_inode_watcher(0);
+ EXPECT_NE(fd, -1);
+
+ int test_fd = creat("/tmp/testfile", 0777);
+ EXPECT_NE(test_fd, -1);
+
+ int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::Deleted));
+ EXPECT_NE(wd, -1);
+
+ int rc = unlink("/tmp/testfile");
+ EXPECT_NE(rc, -1);
+
+ rc = read_event(fd);
+ EXPECT_NE(rc, -1);
+ EXPECT_EQ(event->watch_descriptor, wd);
+ EXPECT_EQ(event->type, InodeWatcherEvent::Type::Deleted);
+
+ close(fd);
+ close(test_fd);
+}
+
+TEST_CASE(inode_watcher_child_events)
+{
+ int fd = create_inode_watcher(0);
+ EXPECT_NE(fd, -1);
+
+ int wd = inode_watcher_add_watch(fd, "/tmp/", 5, static_cast<unsigned>(InodeWatcherEvent::Type::ChildCreated | InodeWatcherEvent::Type::ChildDeleted));
+ EXPECT_NE(fd, -1);
+
+ int rc = creat("/tmp/testfile", 0777);
+ EXPECT_NE(rc, -1);
+
+ rc = read_event(fd);
+ EXPECT_NE(rc, -1);
+ EXPECT_EQ(event->watch_descriptor, wd);
+ EXPECT_EQ(event->type, InodeWatcherEvent::Type::ChildCreated);
+ VERIFY(event->name_length > 0);
+ EXPECT_EQ(get_event_name(), "testfile");
+
+ rc = unlink("/tmp/testfile");
+ EXPECT_NE(rc, -1);
+
+ rc = read_event(fd);
+ EXPECT_NE(rc, -1);
+ EXPECT_EQ(event->watch_descriptor, wd);
+ EXPECT_EQ(event->type, InodeWatcherEvent::Type::ChildDeleted);
+ VERIFY(event->name_length > 0);
+ EXPECT_EQ(get_event_name(), "testfile");
+
+ close(fd);
+}
+
+TEST_CASE(inode_watcher_closes_children_on_close)
+{
+ int fd = create_inode_watcher(0);
+ EXPECT_NE(fd, -1);
+
+ int test_fd = creat("/tmp/testfile", 0777);
+ EXPECT_NE(test_fd, -1);
+ int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::MetadataModified));
+ EXPECT_NE(wd, -1);
+
+ int rc = utime("/tmp/testfile", nullptr);
+ EXPECT_NE(rc, -1);
+
+ close(fd);
+
+ rc = read_event(fd);
+ EXPECT_EQ(rc, -1);
+ EXPECT_EQ(errno, EBADF);
+
+ close(test_fd);
+ unlink("/tmp/testfile");
+}
+
+TEST_CASE(inode_watcher_nonblock)
+{
+ int fd = create_inode_watcher(static_cast<unsigned>(InodeWatcherFlags::Nonblock));
+ EXPECT_NE(fd, -1);
+
+ int rc = read_event(fd);
+ EXPECT_EQ(rc, -1);
+ EXPECT_EQ(errno, EAGAIN);
+
+ close(fd);
+}