TestLibCInodeWatcher.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/NumericLimits.h>
  7. #include <Kernel/API/InodeWatcherEvent.h>
  8. #include <Kernel/API/InodeWatcherFlags.h>
  9. #include <LibTest/TestCase.h>
  10. #include <errno.h>
  11. #include <fcntl.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15. #include <utime.h>
  16. u8 buffer[MAXIMUM_EVENT_SIZE];
  17. InodeWatcherEvent* event = reinterpret_cast<InodeWatcherEvent*>(buffer);
  18. static int read_event(int fd)
  19. {
  20. int rc = read(fd, &buffer, MAXIMUM_EVENT_SIZE);
  21. return rc;
  22. }
  23. static String get_event_name()
  24. {
  25. if (event->name_length == 0)
  26. return String();
  27. return String { event->name, event->name_length - 1 };
  28. }
  29. TEST_CASE(inode_watcher_metadata_modified_event)
  30. {
  31. int fd = create_inode_watcher(0);
  32. EXPECT_NE(fd, -1);
  33. int test_fd = creat("/tmp/testfile", 0777);
  34. EXPECT_NE(test_fd, -1);
  35. int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::MetadataModified));
  36. EXPECT_NE(wd, -1);
  37. // "touch" the file
  38. int rc = utime("/tmp/testfile", nullptr);
  39. EXPECT_NE(rc, -1);
  40. rc = read_event(fd);
  41. EXPECT_EQ(event->watch_descriptor, wd);
  42. EXPECT_EQ(event->type, InodeWatcherEvent::Type::MetadataModified);
  43. close(fd);
  44. close(test_fd);
  45. unlink("/tmp/testfile");
  46. }
  47. TEST_CASE(inode_watcher_content_modified_event)
  48. {
  49. int fd = create_inode_watcher(0);
  50. EXPECT_NE(fd, -1);
  51. int test_fd = creat("/tmp/testfile", 0777);
  52. EXPECT_NE(test_fd, -1);
  53. int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::ContentModified));
  54. EXPECT_NE(wd, -1);
  55. int rc = write(test_fd, "test", 4);
  56. EXPECT_NE(rc, -1);
  57. rc = read_event(fd);
  58. EXPECT_NE(rc, -1);
  59. EXPECT_EQ(event->watch_descriptor, wd);
  60. EXPECT_EQ(event->type, InodeWatcherEvent::Type::ContentModified);
  61. close(fd);
  62. close(test_fd);
  63. unlink("/tmp/testfile");
  64. }
  65. TEST_CASE(inode_watcher_deleted_event)
  66. {
  67. int fd = create_inode_watcher(0);
  68. EXPECT_NE(fd, -1);
  69. int test_fd = creat("/tmp/testfile", 0777);
  70. EXPECT_NE(test_fd, -1);
  71. int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::Deleted));
  72. EXPECT_NE(wd, -1);
  73. int rc = unlink("/tmp/testfile");
  74. EXPECT_NE(rc, -1);
  75. rc = read_event(fd);
  76. EXPECT_NE(rc, -1);
  77. EXPECT_EQ(event->watch_descriptor, wd);
  78. EXPECT_EQ(event->type, InodeWatcherEvent::Type::Deleted);
  79. close(fd);
  80. close(test_fd);
  81. }
  82. TEST_CASE(inode_watcher_child_events)
  83. {
  84. int fd = create_inode_watcher(0);
  85. EXPECT_NE(fd, -1);
  86. int wd = inode_watcher_add_watch(fd, "/tmp/", 5, static_cast<unsigned>(InodeWatcherEvent::Type::ChildCreated | InodeWatcherEvent::Type::ChildDeleted));
  87. EXPECT_NE(fd, -1);
  88. int rc = creat("/tmp/testfile", 0777);
  89. EXPECT_NE(rc, -1);
  90. rc = read_event(fd);
  91. EXPECT_NE(rc, -1);
  92. EXPECT_EQ(event->watch_descriptor, wd);
  93. EXPECT_EQ(event->type, InodeWatcherEvent::Type::ChildCreated);
  94. VERIFY(event->name_length > 0);
  95. EXPECT_EQ(get_event_name(), "testfile");
  96. rc = unlink("/tmp/testfile");
  97. EXPECT_NE(rc, -1);
  98. rc = read_event(fd);
  99. EXPECT_NE(rc, -1);
  100. EXPECT_EQ(event->watch_descriptor, wd);
  101. EXPECT_EQ(event->type, InodeWatcherEvent::Type::ChildDeleted);
  102. VERIFY(event->name_length > 0);
  103. EXPECT_EQ(get_event_name(), "testfile");
  104. close(fd);
  105. }
  106. TEST_CASE(inode_watcher_closes_children_on_close)
  107. {
  108. int fd = create_inode_watcher(0);
  109. EXPECT_NE(fd, -1);
  110. int test_fd = creat("/tmp/testfile", 0777);
  111. EXPECT_NE(test_fd, -1);
  112. int wd = inode_watcher_add_watch(fd, "/tmp/testfile", 13, static_cast<unsigned>(InodeWatcherEvent::Type::MetadataModified));
  113. EXPECT_NE(wd, -1);
  114. int rc = utime("/tmp/testfile", nullptr);
  115. EXPECT_NE(rc, -1);
  116. close(fd);
  117. rc = read_event(fd);
  118. EXPECT_EQ(rc, -1);
  119. EXPECT_EQ(errno, EBADF);
  120. close(test_fd);
  121. unlink("/tmp/testfile");
  122. }
  123. TEST_CASE(inode_watcher_nonblock)
  124. {
  125. int fd = create_inode_watcher(static_cast<unsigned>(InodeWatcherFlags::Nonblock));
  126. EXPECT_NE(fd, -1);
  127. int rc = read_event(fd);
  128. EXPECT_EQ(rc, -1);
  129. EXPECT_EQ(errno, EAGAIN);
  130. close(fd);
  131. }