| Index: base/message_loop/message_loop_unittest.cc
|
| diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
|
| index fe2d728fe408c8cd3baef46d692e920cee8e3571..f378db268936f716a12b8f40b8980641e1ff1c1a 100644
|
| --- a/base/message_loop/message_loop_unittest.cc
|
| +++ b/base/message_loop/message_loop_unittest.cc
|
| @@ -23,6 +23,8 @@
|
|
|
| #if defined(OS_WIN)
|
| #include "base/message_loop/message_pump_win.h"
|
| +#include "base/process/memory.h"
|
| +#include "base/strings/string16.h"
|
| #include "base/win/scoped_handle.h"
|
| #endif
|
|
|
| @@ -1080,4 +1082,92 @@ TEST(MessageLoopTest, IsType) {
|
| EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT));
|
| }
|
|
|
| +#if defined(OS_WIN)
|
| +void EmptyFunction() {}
|
| +
|
| +void PostMultipleTasks() {
|
| + MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
|
| + MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&EmptyFunction));
|
| +}
|
| +
|
| +static const int kSignalMsg = WM_USER + 2;
|
| +
|
| +void PostWindowsMessage(HWND message_hwnd) {
|
| + PostMessage(message_hwnd, kSignalMsg, 0, 2);
|
| +}
|
| +
|
| +void EndTest(bool* did_run, HWND hwnd) {
|
| + *did_run = true;
|
| + PostMessage(hwnd, WM_CLOSE, 0, 0);
|
| +}
|
| +
|
| +int kMyMessageFilterCode = 0x5002;
|
| +
|
| +LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
|
| + WPARAM wparam, LPARAM lparam) {
|
| + if (message == WM_CLOSE)
|
| + EXPECT_TRUE(DestroyWindow(hwnd));
|
| + if (message != kSignalMsg)
|
| + return DefWindowProc(hwnd, message, wparam, lparam);
|
| +
|
| + switch (lparam) {
|
| + case 1:
|
| + // First, we post a task that will post multiple no-op tasks to make sure
|
| + // that the pump's incoming task queue does not become empty during the
|
| + // test.
|
| + MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&PostMultipleTasks));
|
| + // Next, we post a task that posts a windows message to trigger the second
|
| + // stage of the test.
|
| + MessageLoop::current()->PostTask(FROM_HERE,
|
| + base::Bind(&PostWindowsMessage, hwnd));
|
| + break;
|
| + case 2:
|
| + // Since we're about to enter a modal loop, tell the message loop that we
|
| + // intend to nest tasks.
|
| + MessageLoop::current()->SetNestableTasksAllowed(true);
|
| + bool did_run = false;
|
| + MessageLoop::current()->PostTask(FROM_HERE,
|
| + base::Bind(&EndTest, &did_run, hwnd));
|
| + // Run a nested windows-style message loop and verify that our task runs. If
|
| + // it doesn't, then we'll loop here until the test times out.
|
| + MSG msg;
|
| + while (GetMessage(&msg, 0, 0, 0)) {
|
| + if (!CallMsgFilter(&msg, kMyMessageFilterCode))
|
| + DispatchMessage(&msg);
|
| + // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting
|
| + // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats
|
| + // WM_QUIT messages even when running inside a modal loop.
|
| + if (msg.message == WM_CLOSE)
|
| + break;
|
| + }
|
| + EXPECT_TRUE(did_run);
|
| + MessageLoop::current()->Quit();
|
| + break;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +TEST(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) {
|
| + MessageLoop loop(MessageLoop::TYPE_UI);
|
| + HINSTANCE instance = GetModuleFromAddress(&TestWndProcThunk);
|
| + WNDCLASSEX wc = {0};
|
| + wc.cbSize = sizeof(wc);
|
| + wc.lpfnWndProc = TestWndProcThunk;
|
| + wc.hInstance = instance;
|
| + wc.lpszClassName = L"MessageLoopTest_HWND";
|
| + ATOM atom = RegisterClassEx(&wc);
|
| + ASSERT_TRUE(atom);
|
| +
|
| + HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
|
| + HWND_MESSAGE, 0, instance, 0);
|
| + ASSERT_TRUE(message_hwnd) << GetLastError();
|
| +
|
| + ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
|
| +
|
| + loop.Run();
|
| +
|
| + ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
|
| +}
|
| +#endif // defined(OS_WIN)
|
| +
|
| } // namespace base
|
|
|