TestLibCInodeWatcher.cpp 4.2 KB

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