12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_io_ios.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MessagePumpIOSForIOTest : public testing::Test { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIOTest() 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : ui_loop_(MessageLoop::TYPE_UI), 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) io_thread_("MessagePumpIOSForIOTestIOThread") {} 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MessagePumpIOSForIOTest() {} 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetUp() OVERRIDE { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Thread::Options options(MessageLoop::TYPE_IO, 0); 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(io_thread_.StartWithOptions(options)); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type()); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ret = pipe(pipefds_); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(0, ret); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = pipe(alternate_pipefds_); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(0, ret); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void TearDown() OVERRIDE { 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(pipefds_[0])) < 0) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "close"; 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(pipefds_[1])) < 0) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "close"; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessageLoop* ui_loop() { return &ui_loop_; } 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessageLoopForIO* io_loop() const { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return static_cast<MessageLoopForIO*>(io_thread_.message_loop()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void HandleFdIOEvent(MessageLoopForIO::FileDescriptorWatcher* watcher) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::HandleFdIOEvent(watcher->fdref_, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) watcher); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int pipefds_[2]; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int alternate_pipefds_[2]; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessageLoop ui_loop_; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Thread io_thread_; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MessagePumpIOSForIOTest); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Concrete implementation of MessagePumpIOSForIO::Watcher that does 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// nothing useful. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class StupidWatcher : public MessagePumpIOSForIO::Watcher { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~StupidWatcher() {} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // base:MessagePumpIOSForIO::Watcher interface 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {} 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test to make sure that we catch calling WatchFileDescriptor off of the 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// wrong thread. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(MessagePumpIOSForIOTest, TestWatchingFromBadThread) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::FileDescriptorWatcher watcher; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StupidWatcher delegate; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_DEBUG_DEATH(io_loop()->WatchFileDescriptor( 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STDOUT_FILENO, false, MessageLoopForIO::WATCH_READ, &watcher, &delegate), 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Check failed: " 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "watch_file_descriptor_caller_checker_.CalledOnValidThread\\(\\)"); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class BaseWatcher : public MessagePumpIOSForIO::Watcher { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BaseWatcher(MessagePumpIOSForIO::FileDescriptorWatcher* controller) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : controller_(controller) { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(controller_); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~BaseWatcher() {} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MessagePumpIOSForIO::Watcher interface 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::FileDescriptorWatcher* controller_; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DeleteWatcher : public BaseWatcher { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit DeleteWatcher( 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::FileDescriptorWatcher* controller) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : BaseWatcher(controller) {} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~DeleteWatcher() { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!controller_); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(controller_); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete controller_; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_ = NULL; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(MessagePumpIOSForIOTest, DeleteWatcher) { 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::FileDescriptorWatcher* watcher = 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new MessagePumpIOSForIO::FileDescriptorWatcher; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DeleteWatcher delegate(watcher); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pump->WatchFileDescriptor(pipefds_[1], 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, MessagePumpIOSForIO::WATCH_READ_WRITE, watcher, &delegate); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Spoof a callback. 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HandleFdIOEvent(watcher); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class StopWatcher : public BaseWatcher { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopWatcher(MessagePumpIOSForIO::FileDescriptorWatcher* controller, 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO* pump, 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int fd_to_start_watching = -1) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : BaseWatcher(controller), 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pump_(pump), 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fd_to_start_watching_(fd_to_start_watching) {} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~StopWatcher() {} 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_->StopWatchingFileDescriptor(); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fd_to_start_watching_ >= 0) { 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pump_->WatchFileDescriptor(fd_to_start_watching_, 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, MessagePumpIOSForIO::WATCH_READ_WRITE, controller_, this); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO* pump_; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int fd_to_start_watching_; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(MessagePumpIOSForIOTest, StopWatcher) { 165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::FileDescriptorWatcher watcher; 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch StopWatcher delegate(&watcher, pump.get()); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pump->WatchFileDescriptor(pipefds_[1], 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Spoof a callback. 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HandleFdIOEvent(&watcher); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(MessagePumpIOSForIOTest, StopWatcherAndWatchSomethingElse) { 176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpIOSForIO::FileDescriptorWatcher watcher; 178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch StopWatcher delegate(&watcher, pump.get(), alternate_pipefds_[1]); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pump->WatchFileDescriptor(pipefds_[1], 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Spoof a callback. 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HandleFdIOEvent(&watcher); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace base 189