cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / content / browser / renderer_host / text_input_client_mac_unittest.mm
bloba3c87b59e3ccd10deb5ed6676d27e1b557ef4434
1 // Copyright (c) 2012 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.
5 #import "content/browser/renderer_host/text_input_client_mac.h"
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/threading/thread.h"
10 #include "content/browser/gpu/gpu_surface_tracker.h"
11 #include "content/browser/renderer_host/render_process_host_impl.h"
12 #include "content/browser/renderer_host/render_widget_host_delegate.h"
13 #include "content/browser/renderer_host/render_widget_host_impl.h"
14 #include "content/browser/renderer_host/text_input_client_message_filter.h"
15 #include "content/common/text_input_client_messages.h"
16 #include "content/public/test/mock_render_process_host.h"
17 #include "content/public/test/test_browser_context.h"
18 #include "ipc/ipc_test_sink.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "testing/gtest_mac.h"
22 namespace content {
24 namespace {
25 const int64 kTaskDelayMs = 200;
27 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
28  public:
29   MockRenderWidgetHostDelegate() {}
30   ~MockRenderWidgetHostDelegate() override {}
32  private:
33   void Cut() override {}
34   void Copy() override {}
35   void Paste() override {}
36   void SelectAll() override {}
39 // This test does not test the WebKit side of the dictionary system (which
40 // performs the actual data fetching), but rather this just tests that the
41 // service's signaling system works.
42 class TextInputClientMacTest : public testing::Test {
43  public:
44   TextInputClientMacTest()
45       : browser_context_(),
46         process_factory_(),
47         delegate_(),
48         thread_("TextInputClientMacTestThread") {
49     RenderProcessHost* rph =
50         process_factory_.CreateRenderProcessHost(&browser_context_, nullptr);
51     int32 routing_id = rph->GetNextRoutingID();
52     int32 surface_id = GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
53         rph->GetID(), routing_id);
54     widget_.reset(new RenderWidgetHostImpl(&delegate_, rph, routing_id,
55                                            surface_id, false));
56   }
58   // Accessor for the TextInputClientMac instance.
59   TextInputClientMac* service() {
60     return TextInputClientMac::GetInstance();
61   }
63   // Helper method to post a task on the testing thread's MessageLoop after
64   // a short delay.
65   void PostTask(const tracked_objects::Location& from_here,
66                 const base::Closure& task) {
67     PostTask(from_here, task, base::TimeDelta::FromMilliseconds(kTaskDelayMs));
68   }
70   void PostTask(const tracked_objects::Location& from_here,
71                 const base::Closure& task,
72                 const base::TimeDelta delay) {
73     thread_.message_loop()->PostDelayedTask(from_here, task, delay);
74   }
76   RenderWidgetHostImpl* widget() { return widget_.get(); }
78   IPC::TestSink& ipc_sink() {
79     return static_cast<MockRenderProcessHost*>(widget()->GetProcess())->sink();
80   }
82  private:
83   friend class ScopedTestingThread;
85   base::MessageLoopForUI message_loop_;
86   TestBrowserContext browser_context_;
88   // Gets deleted when the last RWH in the "process" gets destroyed.
89   MockRenderProcessHostFactory process_factory_;
90   MockRenderWidgetHostDelegate delegate_;
91   scoped_ptr<RenderWidgetHostImpl> widget_;
93   base::Thread thread_;
96 ////////////////////////////////////////////////////////////////////////////////
98 // Helper class that Start()s and Stop()s a thread according to the scope of the
99 // object.
100 class ScopedTestingThread {
101  public:
102   ScopedTestingThread(TextInputClientMacTest* test) : thread_(test->thread_) {
103     thread_.Start();
104   }
105   ~ScopedTestingThread() {
106     thread_.Stop();
107   }
109  private:
110   base::Thread& thread_;
113 // Adapter for OnMessageReceived to ignore return type so it can be posted
114 // to a MessageLoop.
115 void CallOnMessageReceived(scoped_refptr<TextInputClientMessageFilter> filter,
116                            const IPC::Message& message) {
117   filter->OnMessageReceived(message);
120 }  // namespace
122 // Test Cases //////////////////////////////////////////////////////////////////
124 TEST_F(TextInputClientMacTest, GetCharacterIndex) {
125   ScopedTestingThread thread(this);
126   const NSUInteger kSuccessValue = 42;
128   PostTask(FROM_HERE,
129            base::Bind(&TextInputClientMac::SetCharacterIndexAndSignal,
130                       base::Unretained(service()), kSuccessValue));
131   NSUInteger index = service()->GetCharacterIndexAtPoint(
132       widget(), gfx::Point(2, 2));
134   EXPECT_EQ(1U, ipc_sink().message_count());
135   EXPECT_TRUE(ipc_sink().GetUniqueMessageMatching(
136       TextInputClientMsg_CharacterIndexForPoint::ID));
137   EXPECT_EQ(kSuccessValue, index);
140 TEST_F(TextInputClientMacTest, TimeoutCharacterIndex) {
141   NSUInteger index = service()->GetCharacterIndexAtPoint(
142       widget(), gfx::Point(2, 2));
143   EXPECT_EQ(1U, ipc_sink().message_count());
144   EXPECT_TRUE(ipc_sink().GetUniqueMessageMatching(
145       TextInputClientMsg_CharacterIndexForPoint::ID));
146   EXPECT_EQ(NSNotFound, index);
149 TEST_F(TextInputClientMacTest, NotFoundCharacterIndex) {
150   ScopedTestingThread thread(this);
151   const NSUInteger kPreviousValue = 42;
152   const size_t kNotFoundValue = static_cast<size_t>(-1);
154   // Set an arbitrary value to ensure the index is not |NSNotFound|.
155   PostTask(FROM_HERE,
156            base::Bind(&TextInputClientMac::SetCharacterIndexAndSignal,
157                       base::Unretained(service()), kPreviousValue));
159   scoped_refptr<TextInputClientMessageFilter> filter(
160       new TextInputClientMessageFilter(widget()->GetProcess()->GetID()));
161   scoped_ptr<IPC::Message> message(
162       new TextInputClientReplyMsg_GotCharacterIndexForPoint(
163           widget()->GetRoutingID(), kNotFoundValue));
164   // Set |WTF::notFound| to the index |kTaskDelayMs| after the previous
165   // setting.
166   PostTask(FROM_HERE,
167            base::Bind(&CallOnMessageReceived, filter, *message),
168            base::TimeDelta::FromMilliseconds(kTaskDelayMs) * 2);
170   NSUInteger index = service()->GetCharacterIndexAtPoint(
171       widget(), gfx::Point(2, 2));
172   EXPECT_EQ(kPreviousValue, index);
173   index = service()->GetCharacterIndexAtPoint(widget(), gfx::Point(2, 2));
174   EXPECT_EQ(NSNotFound, index);
176   EXPECT_EQ(2U, ipc_sink().message_count());
177   for (size_t i = 0; i < ipc_sink().message_count(); ++i) {
178     const IPC::Message* ipc_message = ipc_sink().GetMessageAt(i);
179     EXPECT_EQ(ipc_message->type(),
180               TextInputClientMsg_CharacterIndexForPoint::ID);
181   }
184 TEST_F(TextInputClientMacTest, GetRectForRange) {
185   ScopedTestingThread thread(this);
186   const NSRect kSuccessValue = NSMakeRect(42, 43, 44, 45);
188   PostTask(FROM_HERE,
189            base::Bind(&TextInputClientMac::SetFirstRectAndSignal,
190                       base::Unretained(service()), kSuccessValue));
191   NSRect rect = service()->GetFirstRectForRange(widget(), NSMakeRange(0, 32));
193   EXPECT_EQ(1U, ipc_sink().message_count());
194   EXPECT_TRUE(ipc_sink().GetUniqueMessageMatching(
195       TextInputClientMsg_FirstRectForCharacterRange::ID));
196   EXPECT_NSEQ(kSuccessValue, rect);
199 TEST_F(TextInputClientMacTest, TimeoutRectForRange) {
200   NSRect rect = service()->GetFirstRectForRange(widget(), NSMakeRange(0, 32));
201   EXPECT_EQ(1U, ipc_sink().message_count());
202   EXPECT_TRUE(ipc_sink().GetUniqueMessageMatching(
203       TextInputClientMsg_FirstRectForCharacterRange::ID));
204   EXPECT_NSEQ(NSZeroRect, rect);
207 TEST_F(TextInputClientMacTest, GetSubstring) {
208   ScopedTestingThread thread(this);
209   NSDictionary* attributes =
210       [NSDictionary dictionaryWithObject:[NSColor purpleColor]
211                                   forKey:NSForegroundColorAttributeName];
212   base::scoped_nsobject<NSMutableAttributedString> kSuccessValue(
213       [[NSMutableAttributedString alloc]
214           initWithString:@"Barney is a purple dinosaur"
215               attributes:attributes]);
217   PostTask(FROM_HERE,
218            base::Bind(&TextInputClientMac::SetSubstringAndSignal,
219                       base::Unretained(service()),
220                       base::Unretained(kSuccessValue.get())));
221   NSAttributedString* string = service()->GetAttributedSubstringFromRange(
222       widget(), NSMakeRange(0, 32));
224   EXPECT_NSEQ(kSuccessValue, string);
225   EXPECT_NE(kSuccessValue.get(), string);  // |string| should be a copy.
226   EXPECT_EQ(1U, ipc_sink().message_count());
227   EXPECT_TRUE(ipc_sink().GetUniqueMessageMatching(
228       TextInputClientMsg_StringForRange::ID));
231 TEST_F(TextInputClientMacTest, TimeoutSubstring) {
232   NSAttributedString* string = service()->GetAttributedSubstringFromRange(
233       widget(), NSMakeRange(0, 32));
234   EXPECT_EQ(nil, string);
235   EXPECT_EQ(1U, ipc_sink().message_count());
236   EXPECT_TRUE(ipc_sink().GetUniqueMessageMatching(
237       TextInputClientMsg_StringForRange::ID));
240 }  // namespace content