| Index: base/message_loop_unittest.cc
|
| ===================================================================
|
| --- base/message_loop_unittest.cc (revision 4870)
|
| +++ base/message_loop_unittest.cc (working copy)
|
| @@ -1056,68 +1056,6 @@
|
|
|
| #if defined(OS_WIN)
|
|
|
| -class AutoresetWatcher : public MessageLoopForIO::Watcher {
|
| - public:
|
| - explicit AutoresetWatcher(HANDLE signal) : signal_(signal) {
|
| - }
|
| - virtual void OnObjectSignaled(HANDLE object);
|
| - private:
|
| - HANDLE signal_;
|
| -};
|
| -
|
| -void AutoresetWatcher::OnObjectSignaled(HANDLE object) {
|
| - MessageLoopForIO::current()->WatchObject(object, NULL);
|
| - ASSERT_TRUE(SetEvent(signal_));
|
| -}
|
| -
|
| -class AutoresetTask : public Task {
|
| - public:
|
| - AutoresetTask(HANDLE object, MessageLoopForIO::Watcher* watcher)
|
| - : object_(object), watcher_(watcher) {}
|
| - virtual void Run() {
|
| - MessageLoopForIO::current()->WatchObject(object_, watcher_);
|
| - }
|
| -
|
| - private:
|
| - HANDLE object_;
|
| - MessageLoopForIO::Watcher* watcher_;
|
| -};
|
| -
|
| -void RunTest_AutoresetEvents(MessageLoop::Type message_loop_type) {
|
| - MessageLoop loop(message_loop_type);
|
| -
|
| - SECURITY_ATTRIBUTES attributes;
|
| - attributes.nLength = sizeof(attributes);
|
| - attributes.bInheritHandle = false;
|
| - attributes.lpSecurityDescriptor = NULL;
|
| -
|
| - // Init an autoreset and a manual reset events.
|
| - HANDLE autoreset = CreateEvent(&attributes, FALSE, FALSE, NULL);
|
| - HANDLE callback_called = CreateEvent(&attributes, TRUE, FALSE, NULL);
|
| - ASSERT_TRUE(NULL != autoreset);
|
| - ASSERT_TRUE(NULL != callback_called);
|
| -
|
| - Thread thread("Autoreset test");
|
| - Thread::Options options;
|
| - options.message_loop_type = message_loop_type;
|
| - ASSERT_TRUE(thread.StartWithOptions(options));
|
| -
|
| - MessageLoop* thread_loop = thread.message_loop();
|
| - ASSERT_TRUE(NULL != thread_loop);
|
| -
|
| - AutoresetWatcher watcher(callback_called);
|
| - AutoresetTask* task = new AutoresetTask(autoreset, &watcher);
|
| - thread_loop->PostTask(FROM_HERE, task);
|
| - Sleep(100); // Make sure the thread runs and sleeps for lack of work.
|
| -
|
| - ASSERT_TRUE(SetEvent(autoreset));
|
| -
|
| - DWORD result = WaitForSingleObject(callback_called, 1000);
|
| - EXPECT_EQ(WAIT_OBJECT_0, result);
|
| -
|
| - thread.Stop();
|
| -}
|
| -
|
| class DispatcherImpl : public MessageLoopForUI::Dispatcher {
|
| public:
|
| DispatcherImpl() : dispatch_count_(0) {}
|
| @@ -1150,68 +1088,68 @@
|
|
|
| class TestIOHandler : public MessageLoopForIO::IOHandler {
|
| public:
|
| - TestIOHandler(const wchar_t* name, HANDLE signal);
|
| + TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
|
|
|
| - virtual void OnIOCompleted(OVERLAPPED* context, DWORD bytes_transfered,
|
| - DWORD error);
|
| + virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
|
| + DWORD bytes_transfered, DWORD error);
|
|
|
| - HANDLE file() { return file_.Get(); }
|
| - void* buffer() { return buffer_; }
|
| - OVERLAPPED* context() { return &context_; }
|
| + void Init();
|
| + void WaitForIO();
|
| + OVERLAPPED* context() { return &context_.overlapped; }
|
| DWORD size() { return sizeof(buffer_); }
|
|
|
| private:
|
| char buffer_[48];
|
| - OVERLAPPED context_;
|
| + MessageLoopForIO::IOContext context_;
|
| HANDLE signal_;
|
| ScopedHandle file_;
|
| - ScopedHandle event_;
|
| + bool wait_;
|
| };
|
|
|
| -TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal)
|
| - : signal_(signal) {
|
| +TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
|
| + : signal_(signal), wait_(wait) {
|
| memset(buffer_, 0, sizeof(buffer_));
|
| memset(&context_, 0, sizeof(context_));
|
| + context_.handler = this;
|
|
|
| - event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
|
| - EXPECT_TRUE(event_.IsValid());
|
| - context_.hEvent = event_.Get();
|
| -
|
| file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
| FILE_FLAG_OVERLAPPED, NULL));
|
| EXPECT_TRUE(file_.IsValid());
|
| }
|
|
|
| -void TestIOHandler::OnIOCompleted(OVERLAPPED* context, DWORD bytes_transfered,
|
| - DWORD error) {
|
| +void TestIOHandler::Init() {
|
| + MessageLoopForIO::current()->RegisterIOHandler(file_, this);
|
| +
|
| + DWORD read;
|
| + EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context()));
|
| + EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
|
| + if (wait_)
|
| + WaitForIO();
|
| +}
|
| +
|
| +void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
|
| + DWORD bytes_transfered, DWORD error) {
|
| ASSERT_TRUE(context == &context_);
|
| - MessageLoopForIO::current()->RegisterIOContext(context, NULL);
|
| ASSERT_TRUE(SetEvent(signal_));
|
| }
|
|
|
| +void TestIOHandler::WaitForIO() {
|
| + EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
|
| + EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
|
| +}
|
| +
|
| class IOHandlerTask : public Task {
|
| public:
|
| explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {}
|
| - virtual void Run();
|
| + virtual void Run() {
|
| + handler_->Init();
|
| + }
|
|
|
| private:
|
| TestIOHandler* handler_;
|
| };
|
|
|
| -void IOHandlerTask::Run() {
|
| - MessageLoopForIO::current()->RegisterIOHandler(handler_->file(), handler_);
|
| - MessageLoopForIO::current()->RegisterIOContext(handler_->context(), handler_);
|
| -
|
| - DWORD read;
|
| - EXPECT_FALSE(ReadFile(handler_->file(), handler_->buffer(), handler_->size(),
|
| - &read, handler_->context()));
|
| - EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
|
| -}
|
| -
|
| void RunTest_IOHandler() {
|
| - // This test requires an IO loop.
|
| - MessageLoop loop(MessageLoop::TYPE_IO);
|
| -
|
| ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
|
| ASSERT_TRUE(callback_called.IsValid());
|
|
|
| @@ -1228,7 +1166,7 @@
|
| MessageLoop* thread_loop = thread.message_loop();
|
| ASSERT_TRUE(NULL != thread_loop);
|
|
|
| - TestIOHandler handler(kPipeName, callback_called);
|
| + TestIOHandler handler(kPipeName, callback_called, false);
|
| IOHandlerTask* task = new IOHandlerTask(&handler);
|
| thread_loop->PostTask(FROM_HERE, task);
|
| Sleep(100); // Make sure the thread runs and sleeps for lack of work.
|
| @@ -1243,6 +1181,57 @@
|
| thread.Stop();
|
| }
|
|
|
| +void RunTest_WaitForIO() {
|
| + ScopedHandle callback1_called(CreateEvent(NULL, TRUE, FALSE, NULL));
|
| + ScopedHandle callback2_called(CreateEvent(NULL, TRUE, FALSE, NULL));
|
| + ASSERT_TRUE(callback1_called.IsValid());
|
| + ASSERT_TRUE(callback2_called.IsValid());
|
| +
|
| + const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
|
| + const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
|
| + ScopedHandle server1(CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1,
|
| + 0, 0, 0, NULL));
|
| + ScopedHandle server2(CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1,
|
| + 0, 0, 0, NULL));
|
| + ASSERT_TRUE(server1.IsValid());
|
| + ASSERT_TRUE(server2.IsValid());
|
| +
|
| + Thread thread("IOHandler test");
|
| + Thread::Options options;
|
| + options.message_loop_type = MessageLoop::TYPE_IO;
|
| + ASSERT_TRUE(thread.StartWithOptions(options));
|
| +
|
| + MessageLoop* thread_loop = thread.message_loop();
|
| + ASSERT_TRUE(NULL != thread_loop);
|
| +
|
| + TestIOHandler handler1(kPipeName1, callback1_called, false);
|
| + TestIOHandler handler2(kPipeName2, callback2_called, true);
|
| + IOHandlerTask* task1 = new IOHandlerTask(&handler1);
|
| + IOHandlerTask* task2 = new IOHandlerTask(&handler2);
|
| + thread_loop->PostTask(FROM_HERE, task1);
|
| + Sleep(100); // Make sure the thread runs and sleeps for lack of work.
|
| + thread_loop->PostTask(FROM_HERE, task2);
|
| + Sleep(100);
|
| +
|
| + // At this time handler1 is waiting to be called, and the thread is waiting
|
| + // on the Init method of handler2, filtering only handler2 callbacks.
|
| +
|
| + const char buffer[] = "Hello there!";
|
| + DWORD written;
|
| + EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL));
|
| + Sleep(200);
|
| + EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) <<
|
| + "handler1 has not been called";
|
| +
|
| + EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL));
|
| +
|
| + HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
|
| + DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
|
| + EXPECT_EQ(WAIT_OBJECT_0, result);
|
| +
|
| + thread.Stop();
|
| +}
|
| +
|
| #endif // defined(OS_WIN)
|
|
|
| } // namespace
|
| @@ -1379,11 +1368,6 @@
|
| }
|
|
|
| #if defined(OS_WIN)
|
| -TEST(MessageLoopTest, AutoresetEvents) {
|
| - // This test requires an IO loop
|
| - RunTest_AutoresetEvents(MessageLoop::TYPE_IO);
|
| -}
|
| -
|
| TEST(MessageLoopTest, Dispatcher) {
|
| // This test requires a UI loop
|
| RunTest_Dispatcher(MessageLoop::TYPE_UI);
|
| @@ -1392,4 +1376,8 @@
|
| TEST(MessageLoopTest, IOHandler) {
|
| RunTest_IOHandler();
|
| }
|
| +
|
| +TEST(MessageLoopTest, WaitForIO) {
|
| + RunTest_WaitForIO();
|
| +}
|
| #endif // defined(OS_WIN)
|
|
|