file_descriptor_watcher_posix_unittest.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/files/file_descriptor_watcher_posix.h"
  5. #include <unistd.h>
  6. #include <memory>
  7. #include "base/bind.h"
  8. #include "base/containers/span.h"
  9. #include "base/files/file_util.h"
  10. #include "base/memory/ptr_util.h"
  11. #include "base/message_loop/message_pump_type.h"
  12. #include "base/posix/eintr_wrapper.h"
  13. #include "base/run_loop.h"
  14. #include "base/test/task_environment.h"
  15. #include "base/test/test_timeouts.h"
  16. #include "base/threading/platform_thread.h"
  17. #include "base/threading/thread.h"
  18. #include "base/threading/thread_checker_impl.h"
  19. #include "base/threading/thread_task_runner_handle.h"
  20. #include "build/build_config.h"
  21. #include "testing/gmock/include/gmock/gmock.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. namespace base {
  24. namespace {
  25. class Mock {
  26. public:
  27. Mock() = default;
  28. Mock(const Mock&) = delete;
  29. Mock& operator=(const Mock&) = delete;
  30. MOCK_METHOD0(ReadableCallback, void());
  31. MOCK_METHOD0(WritableCallback, void());
  32. };
  33. enum class FileDescriptorWatcherTestType {
  34. MESSAGE_PUMP_FOR_IO_ON_MAIN_THREAD,
  35. MESSAGE_PUMP_FOR_IO_ON_OTHER_THREAD,
  36. };
  37. class FileDescriptorWatcherTest
  38. : public testing::TestWithParam<FileDescriptorWatcherTestType> {
  39. public:
  40. FileDescriptorWatcherTest()
  41. : task_environment_(std::make_unique<test::TaskEnvironment>(
  42. GetParam() == FileDescriptorWatcherTestType::
  43. MESSAGE_PUMP_FOR_IO_ON_MAIN_THREAD
  44. ? test::TaskEnvironment::MainThreadType::IO
  45. : test::TaskEnvironment::MainThreadType::DEFAULT)),
  46. other_thread_("FileDescriptorWatcherTest_OtherThread") {}
  47. FileDescriptorWatcherTest(const FileDescriptorWatcherTest&) = delete;
  48. FileDescriptorWatcherTest& operator=(const FileDescriptorWatcherTest&) =
  49. delete;
  50. ~FileDescriptorWatcherTest() override = default;
  51. void SetUp() override {
  52. ASSERT_EQ(0, pipe(pipe_fds_));
  53. scoped_refptr<SingleThreadTaskRunner> io_thread_task_runner;
  54. if (GetParam() ==
  55. FileDescriptorWatcherTestType::MESSAGE_PUMP_FOR_IO_ON_OTHER_THREAD) {
  56. Thread::Options options;
  57. options.message_pump_type = MessagePumpType::IO;
  58. ASSERT_TRUE(other_thread_.StartWithOptions(std::move(options)));
  59. file_descriptor_watcher_ =
  60. std::make_unique<FileDescriptorWatcher>(other_thread_.task_runner());
  61. }
  62. }
  63. void TearDown() override {
  64. if (GetParam() ==
  65. FileDescriptorWatcherTestType::MESSAGE_PUMP_FOR_IO_ON_MAIN_THREAD &&
  66. task_environment_) {
  67. // Allow the delete task posted by the Controller's destructor to run.
  68. base::RunLoop().RunUntilIdle();
  69. }
  70. // Ensure that OtherThread is done processing before closing fds.
  71. other_thread_.Stop();
  72. EXPECT_EQ(0, IGNORE_EINTR(close(pipe_fds_[0])));
  73. EXPECT_EQ(0, IGNORE_EINTR(close(pipe_fds_[1])));
  74. }
  75. protected:
  76. int read_file_descriptor() const { return pipe_fds_[0]; }
  77. int write_file_descriptor() const { return pipe_fds_[1]; }
  78. // Waits for a short delay and run pending tasks.
  79. void WaitAndRunPendingTasks() {
  80. PlatformThread::Sleep(TestTimeouts::tiny_timeout());
  81. RunLoop().RunUntilIdle();
  82. }
  83. // Registers ReadableCallback() to be called on |mock_| when
  84. // read_file_descriptor() is readable without blocking.
  85. std::unique_ptr<FileDescriptorWatcher::Controller> WatchReadable() {
  86. std::unique_ptr<FileDescriptorWatcher::Controller> controller =
  87. FileDescriptorWatcher::WatchReadable(
  88. read_file_descriptor(),
  89. BindRepeating(&Mock::ReadableCallback, Unretained(&mock_)));
  90. EXPECT_TRUE(controller);
  91. // Unless read_file_descriptor() was readable before the callback was
  92. // registered, this shouldn't do anything.
  93. WaitAndRunPendingTasks();
  94. return controller;
  95. }
  96. // Registers WritableCallback() to be called on |mock_| when
  97. // write_file_descriptor() is writable without blocking.
  98. std::unique_ptr<FileDescriptorWatcher::Controller> WatchWritable() {
  99. std::unique_ptr<FileDescriptorWatcher::Controller> controller =
  100. FileDescriptorWatcher::WatchWritable(
  101. write_file_descriptor(),
  102. BindRepeating(&Mock::WritableCallback, Unretained(&mock_)));
  103. EXPECT_TRUE(controller);
  104. return controller;
  105. }
  106. void WriteByte() {
  107. constexpr char kByte = '!';
  108. ASSERT_TRUE(WriteFileDescriptor(write_file_descriptor(),
  109. as_bytes(make_span(&kByte, 1))));
  110. }
  111. void ReadByte() {
  112. // This is always called as part of the WatchReadable() callback, which
  113. // should run on the main thread.
  114. EXPECT_TRUE(thread_checker_.CalledOnValidThread());
  115. char buffer;
  116. ASSERT_TRUE(ReadFromFD(read_file_descriptor(), &buffer, sizeof(buffer)));
  117. }
  118. // Mock on wich callbacks are invoked.
  119. testing::StrictMock<Mock> mock_;
  120. // Task environment bound to the main thread.
  121. std::unique_ptr<test::TaskEnvironment> task_environment_;
  122. // Thread running an IO message pump. Used when the test type is
  123. // MESSAGE_PUMP_FOR_IO_ON_OTHER_THREAD.
  124. Thread other_thread_;
  125. private:
  126. // Used to listen for file descriptor events on |other_thread_|. The scoped
  127. // task environment implements a watcher for the main thread case.
  128. std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_;
  129. // Watched file descriptors.
  130. int pipe_fds_[2];
  131. // Used to verify that callbacks run on the thread on which they are
  132. // registered.
  133. ThreadCheckerImpl thread_checker_;
  134. };
  135. } // namespace
  136. TEST_P(FileDescriptorWatcherTest, WatchWritable) {
  137. auto controller = WatchWritable();
  138. // The write end of a newly created pipe is immediately writable.
  139. RunLoop run_loop;
  140. EXPECT_CALL(mock_, WritableCallback())
  141. .WillOnce(testing::Invoke(&run_loop, &RunLoop::Quit));
  142. run_loop.Run();
  143. }
  144. TEST_P(FileDescriptorWatcherTest, WatchReadableOneByte) {
  145. auto controller = WatchReadable();
  146. // Write 1 byte to the pipe, making it readable without blocking. Expect one
  147. // call to ReadableCallback() which will read 1 byte from the pipe.
  148. WriteByte();
  149. RunLoop run_loop;
  150. EXPECT_CALL(mock_, ReadableCallback())
  151. .WillOnce(testing::Invoke([this, &run_loop]() {
  152. ReadByte();
  153. run_loop.Quit();
  154. }));
  155. run_loop.Run();
  156. testing::Mock::VerifyAndClear(&mock_);
  157. // No more call to ReadableCallback() is expected.
  158. WaitAndRunPendingTasks();
  159. }
  160. TEST_P(FileDescriptorWatcherTest, WatchReadableTwoBytes) {
  161. auto controller = WatchReadable();
  162. // Write 2 bytes to the pipe. Expect two calls to ReadableCallback() which
  163. // will each read 1 byte from the pipe.
  164. WriteByte();
  165. WriteByte();
  166. RunLoop run_loop;
  167. EXPECT_CALL(mock_, ReadableCallback())
  168. .WillOnce(testing::Invoke([this]() { ReadByte(); }))
  169. .WillOnce(testing::Invoke([this, &run_loop]() {
  170. ReadByte();
  171. run_loop.Quit();
  172. }));
  173. run_loop.Run();
  174. testing::Mock::VerifyAndClear(&mock_);
  175. // No more call to ReadableCallback() is expected.
  176. WaitAndRunPendingTasks();
  177. }
  178. TEST_P(FileDescriptorWatcherTest, WatchReadableByteWrittenFromCallback) {
  179. auto controller = WatchReadable();
  180. // Write 1 byte to the pipe. Expect one call to ReadableCallback() from which
  181. // 1 byte is read and 1 byte is written to the pipe. Then, expect another call
  182. // to ReadableCallback() from which the remaining byte is read from the pipe.
  183. WriteByte();
  184. RunLoop run_loop;
  185. EXPECT_CALL(mock_, ReadableCallback())
  186. .WillOnce(testing::Invoke([this]() {
  187. ReadByte();
  188. WriteByte();
  189. }))
  190. .WillOnce(testing::Invoke([this, &run_loop]() {
  191. ReadByte();
  192. run_loop.Quit();
  193. }));
  194. run_loop.Run();
  195. testing::Mock::VerifyAndClear(&mock_);
  196. // No more call to ReadableCallback() is expected.
  197. WaitAndRunPendingTasks();
  198. }
  199. TEST_P(FileDescriptorWatcherTest, DeleteControllerFromCallback) {
  200. auto controller = WatchReadable();
  201. // Write 1 byte to the pipe. Expect one call to ReadableCallback() from which
  202. // |controller| is deleted.
  203. WriteByte();
  204. RunLoop run_loop;
  205. EXPECT_CALL(mock_, ReadableCallback())
  206. .WillOnce(testing::Invoke([&run_loop, &controller]() {
  207. controller = nullptr;
  208. run_loop.Quit();
  209. }));
  210. run_loop.Run();
  211. testing::Mock::VerifyAndClear(&mock_);
  212. // Since |controller| has been deleted, no call to ReadableCallback() is
  213. // expected even though the pipe is still readable without blocking.
  214. WaitAndRunPendingTasks();
  215. }
  216. TEST_P(FileDescriptorWatcherTest,
  217. DeleteControllerBeforeFileDescriptorReadable) {
  218. auto controller = WatchReadable();
  219. // Cancel the watch.
  220. controller = nullptr;
  221. // Write 1 byte to the pipe to make it readable without blocking.
  222. WriteByte();
  223. // No call to ReadableCallback() is expected.
  224. WaitAndRunPendingTasks();
  225. }
  226. TEST_P(FileDescriptorWatcherTest, DeleteControllerAfterFileDescriptorReadable) {
  227. auto controller = WatchReadable();
  228. // Write 1 byte to the pipe to make it readable without blocking.
  229. WriteByte();
  230. // Cancel the watch.
  231. controller = nullptr;
  232. // No call to ReadableCallback() is expected.
  233. WaitAndRunPendingTasks();
  234. }
  235. TEST_P(FileDescriptorWatcherTest, DeleteControllerAfterDeleteMessagePumpForIO) {
  236. auto controller = WatchReadable();
  237. // Delete the task environment.
  238. if (GetParam() ==
  239. FileDescriptorWatcherTestType::MESSAGE_PUMP_FOR_IO_ON_MAIN_THREAD) {
  240. task_environment_.reset();
  241. } else {
  242. other_thread_.Stop();
  243. }
  244. // Deleting |controller| shouldn't crash even though that causes a task to be
  245. // posted to the message pump thread.
  246. controller = nullptr;
  247. }
  248. INSTANTIATE_TEST_SUITE_P(
  249. MessagePumpForIOOnMainThread,
  250. FileDescriptorWatcherTest,
  251. ::testing::Values(
  252. FileDescriptorWatcherTestType::MESSAGE_PUMP_FOR_IO_ON_MAIN_THREAD));
  253. INSTANTIATE_TEST_SUITE_P(
  254. MessagePumpForIOOnOtherThread,
  255. FileDescriptorWatcherTest,
  256. ::testing::Values(
  257. FileDescriptorWatcherTestType::MESSAGE_PUMP_FOR_IO_ON_OTHER_THREAD));
  258. } // namespace base