diff options
author | sin-ack <sin-ack@users.noreply.github.com> | 2021-05-10 09:27:04 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-12 22:38:20 +0200 |
commit | 60eb4adac2e3ceef09baef5b441990f5390503ac (patch) | |
tree | 88a1dccc5b5257ba1b2c0be6636069a08b6c0e31 /Tests/LibC | |
parent | ae9e35210404e901d2ec9c936ee00fa7dafcbadb (diff) | |
download | serenity-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.txt | 1 | ||||
-rw-r--r-- | Tests/LibC/TestLibCInodeWatcher.cpp | 170 |
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); +} |