Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(316)

Side by Side Diff: base/message_loop_unittest.cc

Issue 8156: Switch MessagePumpForIO to use completion ports on Windows.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/message_loop.cc ('k') | base/message_pump_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h" 5 #include "base/logging.h"
6 #include "base/message_loop.h" 6 #include "base/message_loop.h"
7 #include "base/platform_thread.h" 7 #include "base/platform_thread.h"
8 #include "base/ref_counted.h" 8 #include "base/ref_counted.h"
9 #include "base/thread.h" 9 #include "base/thread.h"
10 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 EXPECT_EQ(order[ 4], TaskItem(ORDERERD, 4, false)); 1049 EXPECT_EQ(order[ 4], TaskItem(ORDERERD, 4, false));
1050 EXPECT_EQ(order[ 5], TaskItem(PUMPS, 1, false)); 1050 EXPECT_EQ(order[ 5], TaskItem(PUMPS, 1, false));
1051 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 2, true)); 1051 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 2, true));
1052 EXPECT_EQ(order[ 7], TaskItem(ORDERERD, 2, false)); 1052 EXPECT_EQ(order[ 7], TaskItem(ORDERERD, 2, false));
1053 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true)); 1053 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true));
1054 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false)); 1054 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false));
1055 } 1055 }
1056 1056
1057 #if defined(OS_WIN) 1057 #if defined(OS_WIN)
1058 1058
1059 class AutoresetWatcher : public MessageLoopForIO::Watcher {
1060 public:
1061 explicit AutoresetWatcher(HANDLE signal) : signal_(signal) {
1062 }
1063 virtual void OnObjectSignaled(HANDLE object);
1064 private:
1065 HANDLE signal_;
1066 };
1067
1068 void AutoresetWatcher::OnObjectSignaled(HANDLE object) {
1069 MessageLoopForIO::current()->WatchObject(object, NULL);
1070 ASSERT_TRUE(SetEvent(signal_));
1071 }
1072
1073 class AutoresetTask : public Task {
1074 public:
1075 AutoresetTask(HANDLE object, MessageLoopForIO::Watcher* watcher)
1076 : object_(object), watcher_(watcher) {}
1077 virtual void Run() {
1078 MessageLoopForIO::current()->WatchObject(object_, watcher_);
1079 }
1080
1081 private:
1082 HANDLE object_;
1083 MessageLoopForIO::Watcher* watcher_;
1084 };
1085
1086 void RunTest_AutoresetEvents(MessageLoop::Type message_loop_type) {
1087 MessageLoop loop(message_loop_type);
1088
1089 SECURITY_ATTRIBUTES attributes;
1090 attributes.nLength = sizeof(attributes);
1091 attributes.bInheritHandle = false;
1092 attributes.lpSecurityDescriptor = NULL;
1093
1094 // Init an autoreset and a manual reset events.
1095 HANDLE autoreset = CreateEvent(&attributes, FALSE, FALSE, NULL);
1096 HANDLE callback_called = CreateEvent(&attributes, TRUE, FALSE, NULL);
1097 ASSERT_TRUE(NULL != autoreset);
1098 ASSERT_TRUE(NULL != callback_called);
1099
1100 Thread thread("Autoreset test");
1101 Thread::Options options;
1102 options.message_loop_type = message_loop_type;
1103 ASSERT_TRUE(thread.StartWithOptions(options));
1104
1105 MessageLoop* thread_loop = thread.message_loop();
1106 ASSERT_TRUE(NULL != thread_loop);
1107
1108 AutoresetWatcher watcher(callback_called);
1109 AutoresetTask* task = new AutoresetTask(autoreset, &watcher);
1110 thread_loop->PostTask(FROM_HERE, task);
1111 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1112
1113 ASSERT_TRUE(SetEvent(autoreset));
1114
1115 DWORD result = WaitForSingleObject(callback_called, 1000);
1116 EXPECT_EQ(WAIT_OBJECT_0, result);
1117
1118 thread.Stop();
1119 }
1120
1121 class DispatcherImpl : public MessageLoopForUI::Dispatcher { 1059 class DispatcherImpl : public MessageLoopForUI::Dispatcher {
1122 public: 1060 public:
1123 DispatcherImpl() : dispatch_count_(0) {} 1061 DispatcherImpl() : dispatch_count_(0) {}
1124 1062
1125 virtual bool Dispatch(const MSG& msg) { 1063 virtual bool Dispatch(const MSG& msg) {
1126 ::TranslateMessage(&msg); 1064 ::TranslateMessage(&msg);
1127 ::DispatchMessage(&msg); 1065 ::DispatchMessage(&msg);
1128 return (++dispatch_count_ != 2); 1066 return (++dispatch_count_ != 2);
1129 } 1067 }
1130 1068
(...skipping 12 matching lines...) Expand all
1143 }; 1081 };
1144 Task* task = new MyTask(); 1082 Task* task = new MyTask();
1145 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); 1083 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
1146 DispatcherImpl dispatcher; 1084 DispatcherImpl dispatcher;
1147 MessageLoopForUI::current()->Run(&dispatcher); 1085 MessageLoopForUI::current()->Run(&dispatcher);
1148 ASSERT_EQ(2, dispatcher.dispatch_count_); 1086 ASSERT_EQ(2, dispatcher.dispatch_count_);
1149 } 1087 }
1150 1088
1151 class TestIOHandler : public MessageLoopForIO::IOHandler { 1089 class TestIOHandler : public MessageLoopForIO::IOHandler {
1152 public: 1090 public:
1153 TestIOHandler(const wchar_t* name, HANDLE signal); 1091 TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
1154 1092
1155 virtual void OnIOCompleted(OVERLAPPED* context, DWORD bytes_transfered, 1093 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
1156 DWORD error); 1094 DWORD bytes_transfered, DWORD error);
1157 1095
1158 HANDLE file() { return file_.Get(); } 1096 void Init();
1159 void* buffer() { return buffer_; } 1097 void WaitForIO();
1160 OVERLAPPED* context() { return &context_; } 1098 OVERLAPPED* context() { return &context_.overlapped; }
1161 DWORD size() { return sizeof(buffer_); } 1099 DWORD size() { return sizeof(buffer_); }
1162 1100
1163 private: 1101 private:
1164 char buffer_[48]; 1102 char buffer_[48];
1165 OVERLAPPED context_; 1103 MessageLoopForIO::IOContext context_;
1166 HANDLE signal_; 1104 HANDLE signal_;
1167 ScopedHandle file_; 1105 ScopedHandle file_;
1168 ScopedHandle event_; 1106 bool wait_;
1169 }; 1107 };
1170 1108
1171 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal) 1109 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
1172 : signal_(signal) { 1110 : signal_(signal), wait_(wait) {
1173 memset(buffer_, 0, sizeof(buffer_)); 1111 memset(buffer_, 0, sizeof(buffer_));
1174 memset(&context_, 0, sizeof(context_)); 1112 memset(&context_, 0, sizeof(context_));
1175 1113 context_.handler = this;
1176 event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
1177 EXPECT_TRUE(event_.IsValid());
1178 context_.hEvent = event_.Get();
1179 1114
1180 file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 1115 file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1181 FILE_FLAG_OVERLAPPED, NULL)); 1116 FILE_FLAG_OVERLAPPED, NULL));
1182 EXPECT_TRUE(file_.IsValid()); 1117 EXPECT_TRUE(file_.IsValid());
1183 } 1118 }
1184 1119
1185 void TestIOHandler::OnIOCompleted(OVERLAPPED* context, DWORD bytes_transfered, 1120 void TestIOHandler::Init() {
1186 DWORD error) { 1121 MessageLoopForIO::current()->RegisterIOHandler(file_, this);
1122
1123 DWORD read;
1124 EXPECT_FALSE(ReadFile(file_, buffer_, size(), &read, context()));
1125 EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
1126 if (wait_)
1127 WaitForIO();
1128 }
1129
1130 void TestIOHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
1131 DWORD bytes_transfered, DWORD error) {
1187 ASSERT_TRUE(context == &context_); 1132 ASSERT_TRUE(context == &context_);
1188 MessageLoopForIO::current()->RegisterIOContext(context, NULL);
1189 ASSERT_TRUE(SetEvent(signal_)); 1133 ASSERT_TRUE(SetEvent(signal_));
1190 } 1134 }
1191 1135
1136 void TestIOHandler::WaitForIO() {
1137 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this));
1138 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this));
1139 }
1140
1192 class IOHandlerTask : public Task { 1141 class IOHandlerTask : public Task {
1193 public: 1142 public:
1194 explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {} 1143 explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {}
1195 virtual void Run(); 1144 virtual void Run() {
1145 handler_->Init();
1146 }
1196 1147
1197 private: 1148 private:
1198 TestIOHandler* handler_; 1149 TestIOHandler* handler_;
1199 }; 1150 };
1200 1151
1201 void IOHandlerTask::Run() {
1202 MessageLoopForIO::current()->RegisterIOHandler(handler_->file(), handler_);
1203 MessageLoopForIO::current()->RegisterIOContext(handler_->context(), handler_);
1204
1205 DWORD read;
1206 EXPECT_FALSE(ReadFile(handler_->file(), handler_->buffer(), handler_->size(),
1207 &read, handler_->context()));
1208 EXPECT_EQ(ERROR_IO_PENDING, GetLastError());
1209 }
1210
1211 void RunTest_IOHandler() { 1152 void RunTest_IOHandler() {
1212 // This test requires an IO loop.
1213 MessageLoop loop(MessageLoop::TYPE_IO);
1214
1215 ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); 1153 ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1216 ASSERT_TRUE(callback_called.IsValid()); 1154 ASSERT_TRUE(callback_called.IsValid());
1217 1155
1218 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; 1156 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
1219 ScopedHandle server(CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 1157 ScopedHandle server(CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1,
1220 0, 0, 0, NULL)); 1158 0, 0, 0, NULL));
1221 ASSERT_TRUE(server.IsValid()); 1159 ASSERT_TRUE(server.IsValid());
1222 1160
1223 Thread thread("IOHandler test"); 1161 Thread thread("IOHandler test");
1224 Thread::Options options; 1162 Thread::Options options;
1225 options.message_loop_type = MessageLoop::TYPE_IO; 1163 options.message_loop_type = MessageLoop::TYPE_IO;
1226 ASSERT_TRUE(thread.StartWithOptions(options)); 1164 ASSERT_TRUE(thread.StartWithOptions(options));
1227 1165
1228 MessageLoop* thread_loop = thread.message_loop(); 1166 MessageLoop* thread_loop = thread.message_loop();
1229 ASSERT_TRUE(NULL != thread_loop); 1167 ASSERT_TRUE(NULL != thread_loop);
1230 1168
1231 TestIOHandler handler(kPipeName, callback_called); 1169 TestIOHandler handler(kPipeName, callback_called, false);
1232 IOHandlerTask* task = new IOHandlerTask(&handler); 1170 IOHandlerTask* task = new IOHandlerTask(&handler);
1233 thread_loop->PostTask(FROM_HERE, task); 1171 thread_loop->PostTask(FROM_HERE, task);
1234 Sleep(100); // Make sure the thread runs and sleeps for lack of work. 1172 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1235 1173
1236 const char buffer[] = "Hello there!"; 1174 const char buffer[] = "Hello there!";
1237 DWORD written; 1175 DWORD written;
1238 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); 1176 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL));
1239 1177
1240 DWORD result = WaitForSingleObject(callback_called, 1000); 1178 DWORD result = WaitForSingleObject(callback_called, 1000);
1241 EXPECT_EQ(WAIT_OBJECT_0, result); 1179 EXPECT_EQ(WAIT_OBJECT_0, result);
1242 1180
1243 thread.Stop(); 1181 thread.Stop();
1244 } 1182 }
1245 1183
1184 void RunTest_WaitForIO() {
1185 ScopedHandle callback1_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1186 ScopedHandle callback2_called(CreateEvent(NULL, TRUE, FALSE, NULL));
1187 ASSERT_TRUE(callback1_called.IsValid());
1188 ASSERT_TRUE(callback2_called.IsValid());
1189
1190 const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
1191 const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
1192 ScopedHandle server1(CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1,
1193 0, 0, 0, NULL));
1194 ScopedHandle server2(CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1,
1195 0, 0, 0, NULL));
1196 ASSERT_TRUE(server1.IsValid());
1197 ASSERT_TRUE(server2.IsValid());
1198
1199 Thread thread("IOHandler test");
1200 Thread::Options options;
1201 options.message_loop_type = MessageLoop::TYPE_IO;
1202 ASSERT_TRUE(thread.StartWithOptions(options));
1203
1204 MessageLoop* thread_loop = thread.message_loop();
1205 ASSERT_TRUE(NULL != thread_loop);
1206
1207 TestIOHandler handler1(kPipeName1, callback1_called, false);
1208 TestIOHandler handler2(kPipeName2, callback2_called, true);
1209 IOHandlerTask* task1 = new IOHandlerTask(&handler1);
1210 IOHandlerTask* task2 = new IOHandlerTask(&handler2);
1211 thread_loop->PostTask(FROM_HERE, task1);
1212 Sleep(100); // Make sure the thread runs and sleeps for lack of work.
1213 thread_loop->PostTask(FROM_HERE, task2);
1214 Sleep(100);
1215
1216 // At this time handler1 is waiting to be called, and the thread is waiting
1217 // on the Init method of handler2, filtering only handler2 callbacks.
1218
1219 const char buffer[] = "Hello there!";
1220 DWORD written;
1221 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL));
1222 Sleep(200);
1223 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) <<
1224 "handler1 has not been called";
1225
1226 EXPECT_TRUE(WriteFile(server2, buffer, sizeof(buffer), &written, NULL));
1227
1228 HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
1229 DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
1230 EXPECT_EQ(WAIT_OBJECT_0, result);
1231
1232 thread.Stop();
1233 }
1234
1246 #endif // defined(OS_WIN) 1235 #endif // defined(OS_WIN)
1247 1236
1248 } // namespace 1237 } // namespace
1249 1238
1250 //----------------------------------------------------------------------------- 1239 //-----------------------------------------------------------------------------
1251 // Each test is run against each type of MessageLoop. That way we are sure 1240 // Each test is run against each type of MessageLoop. That way we are sure
1252 // that message loops work properly in all configurations. Of course, in some 1241 // that message loops work properly in all configurations. Of course, in some
1253 // cases, a unit test may only be for a particular type of loop. 1242 // cases, a unit test may only be for a particular type of loop.
1254 1243
1255 TEST(MessageLoopTest, PostTask) { 1244 TEST(MessageLoopTest, PostTask) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO); 1361 RunTest_NonNestableWithNoNesting(MessageLoop::TYPE_IO);
1373 } 1362 }
1374 1363
1375 TEST(MessageLoopTest, NonNestableInNestedLoop) { 1364 TEST(MessageLoopTest, NonNestableInNestedLoop) {
1376 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT); 1365 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT);
1377 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI); 1366 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI);
1378 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO); 1367 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO);
1379 } 1368 }
1380 1369
1381 #if defined(OS_WIN) 1370 #if defined(OS_WIN)
1382 TEST(MessageLoopTest, AutoresetEvents) {
1383 // This test requires an IO loop
1384 RunTest_AutoresetEvents(MessageLoop::TYPE_IO);
1385 }
1386
1387 TEST(MessageLoopTest, Dispatcher) { 1371 TEST(MessageLoopTest, Dispatcher) {
1388 // This test requires a UI loop 1372 // This test requires a UI loop
1389 RunTest_Dispatcher(MessageLoop::TYPE_UI); 1373 RunTest_Dispatcher(MessageLoop::TYPE_UI);
1390 } 1374 }
1391 1375
1392 TEST(MessageLoopTest, IOHandler) { 1376 TEST(MessageLoopTest, IOHandler) {
1393 RunTest_IOHandler(); 1377 RunTest_IOHandler();
1394 } 1378 }
1379
1380 TEST(MessageLoopTest, WaitForIO) {
1381 RunTest_WaitForIO();
1382 }
1395 #endif // defined(OS_WIN) 1383 #endif // defined(OS_WIN)
OLDNEW
« no previous file with comments | « base/message_loop.cc ('k') | base/message_pump_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698