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

Side by Side Diff: ui/base/ime/win/tsf_text_store_unittest.cc

Issue 149073009: Remove InputMethodTSF, TSFEventRouter, TSFTextStore, TSFBridge (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: revert input_method_imm32 changes Created 6 years, 10 months 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
OLDNEW
(Empty)
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.
4
5 #include "ui/base/ime/win/tsf_text_store.h"
6
7 #include <initguid.h> // for GUID_NULL and GUID_PROP_INPUTSCOPE
8 #include <InputScope.h>
9 #include <OleCtl.h>
10
11 #include "base/memory/ref_counted.h"
12 #include "base/win/scoped_com_initializer.h"
13 #include "base/win/scoped_variant.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "ui/base/ime/text_input_client.h"
17 #include "ui/gfx/rect.h"
18
19 using testing::_;
20 using testing::Invoke;
21 using testing::Return;
22
23 namespace ui {
24 namespace {
25
26 class MockTextInputClient : public TextInputClient {
27 public:
28 ~MockTextInputClient() {}
29 MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&));
30 MOCK_METHOD0(ConfirmCompositionText, void());
31 MOCK_METHOD0(ClearCompositionText, void());
32 MOCK_METHOD1(InsertText, void(const base::string16&));
33 MOCK_METHOD2(InsertChar, void(base::char16, int));
34 MOCK_CONST_METHOD0(GetAttachedWindow, gfx::NativeWindow());
35 MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType());
36 MOCK_CONST_METHOD0(GetTextInputMode, ui::TextInputMode());
37 MOCK_CONST_METHOD0(CanComposeInline, bool());
38 MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect());
39 MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*));
40 MOCK_CONST_METHOD0(HasCompositionText, bool());
41 MOCK_CONST_METHOD1(GetTextRange, bool(gfx::Range*));
42 MOCK_CONST_METHOD1(GetCompositionTextRange, bool(gfx::Range*));
43 MOCK_CONST_METHOD1(GetSelectionRange, bool(gfx::Range*));
44 MOCK_METHOD1(SetSelectionRange, bool(const gfx::Range&));
45 MOCK_METHOD1(DeleteRange, bool(const gfx::Range&));
46 MOCK_CONST_METHOD2(GetTextFromRange, bool(const gfx::Range&,
47 base::string16*));
48 MOCK_METHOD0(OnInputMethodChanged, void());
49 MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment,
50 bool(base::i18n::TextDirection));
51 MOCK_METHOD2(ExtendSelectionAndDelete, void(size_t, size_t));
52 MOCK_METHOD1(EnsureCaretInRect, void(const gfx::Rect&));
53 MOCK_METHOD0(OnCandidateWindowShown, void());
54 MOCK_METHOD0(OnCandidateWindowUpdated, void());
55 MOCK_METHOD0(OnCandidateWindowHidden, void());
56 };
57
58 class MockStoreACPSink : public ITextStoreACPSink {
59 public:
60 MockStoreACPSink() : ref_count_(0) {}
61
62 // IUnknown
63 virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
64 return InterlockedIncrement(&ref_count_);
65 }
66 virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
67 const LONG count = InterlockedDecrement(&ref_count_);
68 if (!count) {
69 delete this;
70 return 0;
71 }
72 return static_cast<ULONG>(count);
73 }
74 virtual HRESULT STDMETHODCALLTYPE QueryInterface(
75 REFIID iid, void** report) OVERRIDE {
76 if (iid == IID_IUnknown || iid == IID_ITextStoreACPSink) {
77 *report = static_cast<ITextStoreACPSink*>(this);
78 } else {
79 *report = NULL;
80 return E_NOINTERFACE;
81 }
82 AddRef();
83 return S_OK;
84 }
85
86 // ITextStoreACPSink
87 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnTextChange,
88 HRESULT(DWORD, const TS_TEXTCHANGE*));
89 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnSelectionChange,
90 HRESULT());
91 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLayoutChange,
92 HRESULT(TsLayoutCode, TsViewCookie));
93 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStatusChange,
94 HRESULT(DWORD));
95 MOCK_METHOD4_WITH_CALLTYPE(STDMETHODCALLTYPE, OnAttrsChange,
96 HRESULT(LONG, LONG, ULONG, const TS_ATTRID*));
97 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLockGranted,
98 HRESULT(DWORD));
99 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStartEditTransaction,
100 HRESULT());
101 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnEndEditTransaction,
102 HRESULT());
103
104 private:
105 virtual ~MockStoreACPSink() {}
106
107 volatile LONG ref_count_;
108 };
109
110 const HWND kWindowHandle = reinterpret_cast<HWND>(1);
111
112 } // namespace
113
114 class TSFTextStoreTest : public testing::Test {
115 protected:
116 virtual void SetUp() OVERRIDE {
117 text_store_ = new TSFTextStore();
118 sink_ = new MockStoreACPSink();
119 EXPECT_EQ(S_OK, text_store_->AdviseSink(IID_ITextStoreACPSink,
120 sink_, TS_AS_ALL_SINKS));
121 text_store_->SetFocusedTextInputClient(kWindowHandle,
122 &text_input_client_);
123 }
124
125 virtual void TearDown() OVERRIDE {
126 EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_));
127 sink_ = NULL;
128 text_store_ = NULL;
129 }
130
131 // Accessors to the internal state of TSFTextStore.
132 base::string16* string_buffer() { return &text_store_->string_buffer_; }
133 size_t* committed_size() { return &text_store_->committed_size_; }
134
135 base::win::ScopedCOMInitializer com_initializer_;
136 MockTextInputClient text_input_client_;
137 scoped_refptr<TSFTextStore> text_store_;
138 scoped_refptr<MockStoreACPSink> sink_;
139 };
140
141 class TSFTextStoreTestCallback {
142 public:
143 explicit TSFTextStoreTestCallback(TSFTextStore* text_store)
144 : text_store_(text_store) {
145 CHECK(text_store_);
146 }
147 virtual ~TSFTextStoreTestCallback() {}
148
149 protected:
150 // Accessors to the internal state of TSFTextStore.
151 bool* edit_flag() { return &text_store_->edit_flag_; }
152 base::string16* string_buffer() { return &text_store_->string_buffer_; }
153 size_t* committed_size() { return &text_store_->committed_size_; }
154 gfx::Range* selection() { return &text_store_->selection_; }
155 CompositionUnderlines* composition_undelines() {
156 return &text_store_->composition_undelines_;
157 }
158
159 void SetInternalState(const base::string16& new_string_buffer,
160 LONG new_committed_size, LONG new_selection_start,
161 LONG new_selection_end) {
162 ASSERT_LE(0, new_committed_size);
163 ASSERT_LE(new_committed_size, new_selection_start);
164 ASSERT_LE(new_selection_start, new_selection_end);
165 ASSERT_LE(new_selection_end, static_cast<LONG>(new_string_buffer.size()));
166 *string_buffer() = new_string_buffer;
167 *committed_size() = new_committed_size;
168 selection()->set_start(new_selection_start);
169 selection()->set_end(new_selection_end);
170 }
171
172 bool HasReadLock() const { return text_store_->HasReadLock(); }
173 bool HasReadWriteLock() const { return text_store_->HasReadWriteLock(); }
174
175 void GetSelectionTest(LONG expected_acp_start, LONG expected_acp_end) {
176 TS_SELECTION_ACP selection = {};
177 ULONG fetched = 0;
178 EXPECT_EQ(S_OK, text_store_->GetSelection(0, 1, &selection, &fetched));
179 EXPECT_EQ(1, fetched);
180 EXPECT_EQ(expected_acp_start, selection.acpStart);
181 EXPECT_EQ(expected_acp_end, selection.acpEnd);
182 }
183
184 void SetSelectionTest(LONG acp_start, LONG acp_end, HRESULT expected_result) {
185 TS_SELECTION_ACP selection = {};
186 selection.acpStart = acp_start;
187 selection.acpEnd = acp_end;
188 selection.style.ase = TS_AE_NONE;
189 selection.style.fInterimChar = 0;
190 EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection));
191 if (expected_result == S_OK) {
192 GetSelectionTest(acp_start, acp_end);
193 }
194 }
195
196 void SetTextTest(LONG acp_start, LONG acp_end,
197 const base::string16& text, HRESULT error_code) {
198 TS_TEXTCHANGE change = {};
199 ASSERT_EQ(error_code,
200 text_store_->SetText(0, acp_start, acp_end,
201 text.c_str(), text.size(), &change));
202 if (error_code == S_OK) {
203 EXPECT_EQ(acp_start, change.acpStart);
204 EXPECT_EQ(acp_end, change.acpOldEnd);
205 EXPECT_EQ(acp_start + text.size(), change.acpNewEnd);
206 }
207 }
208
209 void GetTextTest(LONG acp_start, LONG acp_end,
210 const base::string16& expected_string,
211 LONG expected_next_acp) {
212 wchar_t buffer[1024] = {};
213 ULONG text_buffer_copied = 0;
214 TS_RUNINFO run_info = {};
215 ULONG run_info_buffer_copied = 0;
216 LONG next_acp = 0;
217 ASSERT_EQ(S_OK,
218 text_store_->GetText(acp_start, acp_end, buffer, 1024,
219 &text_buffer_copied,
220 &run_info, 1, &run_info_buffer_copied,
221 &next_acp));
222 ASSERT_EQ(expected_string.size(), text_buffer_copied);
223 EXPECT_EQ(expected_string,
224 base::string16(buffer, buffer + text_buffer_copied));
225 EXPECT_EQ(1, run_info_buffer_copied);
226 EXPECT_EQ(expected_string.size(), run_info.uCount);
227 EXPECT_EQ(TS_RT_PLAIN, run_info.type);
228 EXPECT_EQ(expected_next_acp, next_acp);
229 }
230
231 void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) {
232 wchar_t buffer[1024] = {};
233 ULONG text_buffer_copied = 0;
234 TS_RUNINFO run_info = {};
235 ULONG run_info_buffer_copied = 0;
236 LONG next_acp = 0;
237 EXPECT_EQ(error_code,
238 text_store_->GetText(acp_start, acp_end, buffer, 1024,
239 &text_buffer_copied,
240 &run_info, 1, &run_info_buffer_copied,
241 &next_acp));
242 }
243
244 void InsertTextAtSelectionTest(const wchar_t* buffer, ULONG buffer_size,
245 LONG expected_start, LONG expected_end,
246 LONG expected_change_start,
247 LONG expected_change_old_end,
248 LONG expected_change_new_end) {
249 LONG start = 0;
250 LONG end = 0;
251 TS_TEXTCHANGE change = {};
252 EXPECT_EQ(S_OK,
253 text_store_->InsertTextAtSelection(0, buffer, buffer_size,
254 &start, &end, &change));
255 EXPECT_EQ(expected_start, start);
256 EXPECT_EQ(expected_end, end);
257 EXPECT_EQ(expected_change_start, change.acpStart);
258 EXPECT_EQ(expected_change_old_end, change.acpOldEnd);
259 EXPECT_EQ(expected_change_new_end, change.acpNewEnd);
260 }
261
262 void InsertTextAtSelectionQueryOnlyTest(const wchar_t* buffer,
263 ULONG buffer_size,
264 LONG expected_start,
265 LONG expected_end) {
266 LONG start = 0;
267 LONG end = 0;
268 EXPECT_EQ(S_OK,
269 text_store_->InsertTextAtSelection(TS_IAS_QUERYONLY, buffer,
270 buffer_size, &start, &end,
271 NULL));
272 EXPECT_EQ(expected_start, start);
273 EXPECT_EQ(expected_end, end);
274 }
275
276 void GetTextExtTest(TsViewCookie view_cookie, LONG acp_start, LONG acp_end,
277 LONG expected_left, LONG expected_top,
278 LONG expected_right, LONG expected_bottom) {
279 RECT rect = {};
280 BOOL clipped = FALSE;
281 EXPECT_EQ(S_OK, text_store_->GetTextExt(view_cookie, acp_start, acp_end,
282 &rect, &clipped));
283 EXPECT_EQ(expected_left, rect.left);
284 EXPECT_EQ(expected_top, rect.top);
285 EXPECT_EQ(expected_right, rect.right);
286 EXPECT_EQ(expected_bottom, rect.bottom);
287 EXPECT_EQ(FALSE, clipped);
288 }
289
290 void GetTextExtNoLayoutTest(TsViewCookie view_cookie, LONG acp_start,
291 LONG acp_end) {
292 RECT rect = {};
293 BOOL clipped = FALSE;
294 EXPECT_EQ(TS_E_NOLAYOUT,
295 text_store_->GetTextExt(view_cookie, acp_start, acp_end,
296 &rect, &clipped));
297 }
298
299 scoped_refptr<TSFTextStore> text_store_;
300
301 private:
302 DISALLOW_COPY_AND_ASSIGN(TSFTextStoreTestCallback);
303 };
304
305 namespace {
306
307 const HRESULT kInvalidResult = 0x12345678;
308
309 TEST_F(TSFTextStoreTest, GetStatusTest) {
310 TS_STATUS status = {};
311 EXPECT_EQ(S_OK, text_store_->GetStatus(&status));
312 EXPECT_EQ(0, status.dwDynamicFlags);
313 EXPECT_EQ(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT, status.dwStaticFlags);
314 }
315
316 TEST_F(TSFTextStoreTest, QueryInsertTest) {
317 LONG result_start = 0;
318 LONG result_end = 0;
319 *string_buffer() = L"";
320 *committed_size() = 0;
321 EXPECT_EQ(E_INVALIDARG,
322 text_store_->QueryInsert(0, 0, 0, NULL, &result_end));
323 EXPECT_EQ(E_INVALIDARG,
324 text_store_->QueryInsert(0, 0, 0, &result_start, NULL));
325 EXPECT_EQ(S_OK,
326 text_store_->QueryInsert(0, 0, 0, &result_start, &result_end));
327 EXPECT_EQ(0, result_start);
328 EXPECT_EQ(0, result_end);
329 *string_buffer() = L"1234";
330 *committed_size() = 1;
331 EXPECT_EQ(S_OK,
332 text_store_->QueryInsert(0, 1, 0, &result_start, &result_end));
333 EXPECT_EQ(1, result_start);
334 EXPECT_EQ(1, result_end);
335 EXPECT_EQ(E_INVALIDARG,
336 text_store_->QueryInsert(1, 0, 0, &result_start, &result_end));
337 EXPECT_EQ(S_OK,
338 text_store_->QueryInsert(2, 2, 0, &result_start, &result_end));
339 EXPECT_EQ(2, result_start);
340 EXPECT_EQ(2, result_end);
341 EXPECT_EQ(S_OK,
342 text_store_->QueryInsert(2, 3, 0, &result_start, &result_end));
343 EXPECT_EQ(2, result_start);
344 EXPECT_EQ(3, result_end);
345 EXPECT_EQ(E_INVALIDARG,
346 text_store_->QueryInsert(3, 2, 0, &result_start, &result_end));
347 EXPECT_EQ(S_OK,
348 text_store_->QueryInsert(3, 4, 0, &result_start, &result_end));
349 EXPECT_EQ(3, result_start);
350 EXPECT_EQ(4, result_end);
351 EXPECT_EQ(S_OK,
352 text_store_->QueryInsert(3, 5, 0, &result_start, &result_end));
353 EXPECT_EQ(3, result_start);
354 EXPECT_EQ(4, result_end);
355 }
356
357 class SyncRequestLockTestCallback : public TSFTextStoreTestCallback {
358 public:
359 explicit SyncRequestLockTestCallback(TSFTextStore* text_store)
360 : TSFTextStoreTestCallback(text_store) {}
361
362 HRESULT LockGranted1(DWORD flags) {
363 EXPECT_TRUE(HasReadLock());
364 EXPECT_FALSE(HasReadWriteLock());
365 return S_OK;
366 }
367
368 HRESULT LockGranted2(DWORD flags) {
369 EXPECT_TRUE(HasReadLock());
370 EXPECT_TRUE(HasReadWriteLock());
371 return S_OK;
372 }
373
374 HRESULT LockGranted3(DWORD flags) {
375 EXPECT_TRUE(HasReadLock());
376 EXPECT_FALSE(HasReadWriteLock());
377 HRESULT result = kInvalidResult;
378 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
379 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
380 return S_OK;
381 }
382
383 HRESULT LockGranted4(DWORD flags) {
384 EXPECT_TRUE(HasReadLock());
385 EXPECT_FALSE(HasReadWriteLock());
386 HRESULT result = kInvalidResult;
387 EXPECT_EQ(S_OK,
388 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
389 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
390 return S_OK;
391 }
392
393 HRESULT LockGranted5(DWORD flags) {
394 EXPECT_TRUE(HasReadLock());
395 EXPECT_TRUE(HasReadWriteLock());
396 HRESULT result = kInvalidResult;
397 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
398 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
399 return S_OK;
400 }
401
402 HRESULT LockGranted6(DWORD flags) {
403 EXPECT_TRUE(HasReadLock());
404 EXPECT_TRUE(HasReadWriteLock());
405 HRESULT result = kInvalidResult;
406 EXPECT_EQ(S_OK,
407 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
408 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
409 return S_OK;
410 }
411
412 private:
413 DISALLOW_COPY_AND_ASSIGN(SyncRequestLockTestCallback);
414 };
415
416 TEST_F(TSFTextStoreTest, SynchronousRequestLockTest) {
417 SyncRequestLockTestCallback callback(text_store_);
418 EXPECT_CALL(*sink_, OnLockGranted(_))
419 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted1))
420 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted2))
421 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted3))
422 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted4))
423 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted5))
424 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted6));
425
426 HRESULT result = kInvalidResult;
427 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
428 EXPECT_EQ(S_OK, result);
429 result = kInvalidResult;
430 EXPECT_EQ(S_OK,
431 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
432 EXPECT_EQ(S_OK, result);
433
434 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
435 EXPECT_EQ(S_OK, result);
436 result = kInvalidResult;
437 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
438 EXPECT_EQ(S_OK, result);
439
440 result = kInvalidResult;
441 EXPECT_EQ(S_OK,
442 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
443 EXPECT_EQ(S_OK, result);
444 result = kInvalidResult;
445 EXPECT_EQ(S_OK,
446 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
447 EXPECT_EQ(S_OK, result);
448 }
449
450 class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback {
451 public:
452 explicit AsyncRequestLockTestCallback(TSFTextStore* text_store)
453 : TSFTextStoreTestCallback(text_store),
454 state_(0) {}
455
456 HRESULT LockGranted1(DWORD flags) {
457 EXPECT_EQ(0, state_);
458 state_ = 1;
459 EXPECT_TRUE(HasReadLock());
460 EXPECT_FALSE(HasReadWriteLock());
461 HRESULT result = kInvalidResult;
462 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
463 EXPECT_EQ(TS_S_ASYNC, result);
464 EXPECT_EQ(1, state_);
465 state_ = 2;
466 return S_OK;
467 }
468
469 HRESULT LockGranted2(DWORD flags) {
470 EXPECT_EQ(2, state_);
471 EXPECT_TRUE(HasReadLock());
472 EXPECT_FALSE(HasReadWriteLock());
473 HRESULT result = kInvalidResult;
474 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
475 EXPECT_EQ(TS_S_ASYNC, result);
476 EXPECT_EQ(2, state_);
477 state_ = 3;
478 return S_OK;
479 }
480
481 HRESULT LockGranted3(DWORD flags) {
482 EXPECT_EQ(3, state_);
483 EXPECT_TRUE(HasReadLock());
484 EXPECT_TRUE(HasReadWriteLock());
485 HRESULT result = kInvalidResult;
486 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
487 EXPECT_EQ(TS_S_ASYNC, result);
488 EXPECT_EQ(3, state_);
489 state_ = 4;
490 return S_OK;
491 }
492
493 HRESULT LockGranted4(DWORD flags) {
494 EXPECT_EQ(4, state_);
495 EXPECT_TRUE(HasReadLock());
496 EXPECT_TRUE(HasReadWriteLock());
497 HRESULT result = kInvalidResult;
498 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
499 EXPECT_EQ(TS_S_ASYNC, result);
500 EXPECT_EQ(4, state_);
501 state_ = 5;
502 return S_OK;
503 }
504
505 HRESULT LockGranted5(DWORD flags) {
506 EXPECT_EQ(5, state_);
507 EXPECT_TRUE(HasReadLock());
508 EXPECT_FALSE(HasReadWriteLock());
509 state_ = 6;
510 return S_OK;
511 }
512
513 private:
514 int state_;
515
516 DISALLOW_COPY_AND_ASSIGN(AsyncRequestLockTestCallback);
517 };
518
519 TEST_F(TSFTextStoreTest, AsynchronousRequestLockTest) {
520 AsyncRequestLockTestCallback callback(text_store_);
521 EXPECT_CALL(*sink_, OnLockGranted(_))
522 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted1))
523 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted2))
524 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted3))
525 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted4))
526 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted5));
527
528 HRESULT result = kInvalidResult;
529 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
530 EXPECT_EQ(S_OK, result);
531 }
532
533 class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback {
534 public:
535 explicit RequestLockTextChangeTestCallback(TSFTextStore* text_store)
536 : TSFTextStoreTestCallback(text_store),
537 state_(0) {}
538
539 HRESULT LockGranted1(DWORD flags) {
540 EXPECT_EQ(0, state_);
541 state_ = 1;
542 EXPECT_TRUE(HasReadLock());
543 EXPECT_TRUE(HasReadWriteLock());
544
545 *edit_flag() = true;
546 SetInternalState(L"012345", 6, 6, 6);
547 composition_undelines()->clear();
548
549 state_ = 2;
550 return S_OK;
551 }
552
553 void InsertText(const base::string16& text) {
554 EXPECT_EQ(2, state_);
555 EXPECT_EQ(L"012345", text);
556 state_ = 3;
557 }
558
559 void SetCompositionText(const ui::CompositionText& composition) {
560 EXPECT_EQ(3, state_);
561 EXPECT_EQ(L"", composition.text);
562 EXPECT_EQ(0, composition.selection.start());
563 EXPECT_EQ(0, composition.selection.end());
564 EXPECT_EQ(0, composition.underlines.size());
565 state_ = 4;
566 }
567
568 HRESULT OnTextChange(DWORD flags, const TS_TEXTCHANGE* change) {
569 EXPECT_EQ(4, state_);
570 HRESULT result = kInvalidResult;
571 state_ = 5;
572 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
573 EXPECT_EQ(S_OK, result);
574 EXPECT_EQ(6, state_);
575 state_ = 7;
576 return S_OK;
577 }
578
579 HRESULT LockGranted2(DWORD flags) {
580 EXPECT_EQ(5, state_);
581 EXPECT_TRUE(HasReadLock());
582 EXPECT_TRUE(HasReadWriteLock());
583 state_ = 6;
584 return S_OK;
585 }
586
587 private:
588 int state_;
589
590 DISALLOW_COPY_AND_ASSIGN(RequestLockTextChangeTestCallback);
591 };
592
593 TEST_F(TSFTextStoreTest, RequestLockOnTextChangeTest) {
594 RequestLockTextChangeTestCallback callback(text_store_);
595 EXPECT_CALL(*sink_, OnLockGranted(_))
596 .WillOnce(Invoke(&callback,
597 &RequestLockTextChangeTestCallback::LockGranted1))
598 .WillOnce(Invoke(&callback,
599 &RequestLockTextChangeTestCallback::LockGranted2));
600
601 EXPECT_CALL(*sink_, OnSelectionChange())
602 .WillOnce(Return(S_OK));
603 EXPECT_CALL(*sink_, OnLayoutChange(_, _))
604 .WillOnce(Return(S_OK));
605 EXPECT_CALL(*sink_, OnTextChange(_, _))
606 .WillOnce(Invoke(&callback,
607 &RequestLockTextChangeTestCallback::OnTextChange));
608 EXPECT_CALL(text_input_client_, InsertText(_))
609 .WillOnce(Invoke(&callback,
610 &RequestLockTextChangeTestCallback::InsertText));
611 EXPECT_CALL(text_input_client_, SetCompositionText(_))
612 .WillOnce(Invoke(&callback,
613 &RequestLockTextChangeTestCallback::SetCompositionText));
614
615 HRESULT result = kInvalidResult;
616 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
617 EXPECT_EQ(S_OK, result);
618 }
619
620 class SelectionTestCallback : public TSFTextStoreTestCallback {
621 public:
622 explicit SelectionTestCallback(TSFTextStore* text_store)
623 : TSFTextStoreTestCallback(text_store) {}
624
625 HRESULT ReadLockGranted(DWORD flags) {
626 SetInternalState(L"", 0, 0, 0);
627
628 GetSelectionTest(0, 0);
629 SetSelectionTest(0, 0, TF_E_NOLOCK);
630
631 SetInternalState(L"012345", 0, 0, 3);
632
633 GetSelectionTest(0, 3);
634 SetSelectionTest(0, 0, TF_E_NOLOCK);
635
636 return S_OK;
637 }
638
639 HRESULT ReadWriteLockGranted(DWORD flags) {
640 SetInternalState(L"", 0, 0, 0);
641
642 SetSelectionTest(0, 0, S_OK);
643 GetSelectionTest(0, 0);
644 SetSelectionTest(0, 1, TF_E_INVALIDPOS);
645 SetSelectionTest(1, 0, TF_E_INVALIDPOS);
646 SetSelectionTest(1, 1, TF_E_INVALIDPOS);
647
648 SetInternalState(L"0123456", 3, 3, 3);
649
650 SetSelectionTest(0, 0, TF_E_INVALIDPOS);
651 SetSelectionTest(0, 1, TF_E_INVALIDPOS);
652 SetSelectionTest(0, 3, TF_E_INVALIDPOS);
653 SetSelectionTest(0, 6, TF_E_INVALIDPOS);
654 SetSelectionTest(0, 7, TF_E_INVALIDPOS);
655 SetSelectionTest(0, 8, TF_E_INVALIDPOS);
656
657 SetSelectionTest(1, 0, TF_E_INVALIDPOS);
658 SetSelectionTest(1, 1, TF_E_INVALIDPOS);
659 SetSelectionTest(1, 3, TF_E_INVALIDPOS);
660 SetSelectionTest(1, 6, TF_E_INVALIDPOS);
661 SetSelectionTest(1, 7, TF_E_INVALIDPOS);
662 SetSelectionTest(1, 8, TF_E_INVALIDPOS);
663
664 SetSelectionTest(3, 0, TF_E_INVALIDPOS);
665 SetSelectionTest(3, 1, TF_E_INVALIDPOS);
666 SetSelectionTest(3, 3, S_OK);
667 SetSelectionTest(3, 6, S_OK);
668 SetSelectionTest(3, 7, S_OK);
669 SetSelectionTest(3, 8, TF_E_INVALIDPOS);
670
671 SetSelectionTest(6, 0, TF_E_INVALIDPOS);
672 SetSelectionTest(6, 1, TF_E_INVALIDPOS);
673 SetSelectionTest(6, 3, TF_E_INVALIDPOS);
674 SetSelectionTest(6, 6, S_OK);
675 SetSelectionTest(6, 7, S_OK);
676 SetSelectionTest(6, 8, TF_E_INVALIDPOS);
677
678 SetSelectionTest(7, 0, TF_E_INVALIDPOS);
679 SetSelectionTest(7, 1, TF_E_INVALIDPOS);
680 SetSelectionTest(7, 3, TF_E_INVALIDPOS);
681 SetSelectionTest(7, 6, TF_E_INVALIDPOS);
682 SetSelectionTest(7, 7, S_OK);
683 SetSelectionTest(7, 8, TF_E_INVALIDPOS);
684
685 SetSelectionTest(8, 0, TF_E_INVALIDPOS);
686 SetSelectionTest(8, 1, TF_E_INVALIDPOS);
687 SetSelectionTest(8, 3, TF_E_INVALIDPOS);
688 SetSelectionTest(8, 6, TF_E_INVALIDPOS);
689 SetSelectionTest(8, 7, TF_E_INVALIDPOS);
690 SetSelectionTest(8, 8, TF_E_INVALIDPOS);
691
692 return S_OK;
693 }
694 };
695
696 TEST_F(TSFTextStoreTest, SetGetSelectionTest) {
697 SelectionTestCallback callback(text_store_);
698 EXPECT_CALL(*sink_, OnLockGranted(_))
699 .WillOnce(Invoke(&callback, &SelectionTestCallback::ReadLockGranted))
700 .WillOnce(Invoke(&callback,
701 &SelectionTestCallback::ReadWriteLockGranted));
702
703 TS_SELECTION_ACP selection_buffer = {};
704 ULONG fetched_count = 0;
705 EXPECT_EQ(TS_E_NOLOCK,
706 text_store_->GetSelection(0, 1, &selection_buffer,
707 &fetched_count));
708
709 HRESULT result = kInvalidResult;
710 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
711 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
712 }
713
714 class SetGetTextTestCallback : public TSFTextStoreTestCallback {
715 public:
716 explicit SetGetTextTestCallback(TSFTextStore* text_store)
717 : TSFTextStoreTestCallback(text_store) {}
718
719 HRESULT ReadLockGranted(DWORD flags) {
720 SetTextTest(0, 0, L"", TF_E_NOLOCK);
721
722 GetTextTest(0, -1, L"", 0);
723 GetTextTest(0, 0, L"", 0);
724 GetTextErrorTest(0, 1, TF_E_INVALIDPOS);
725
726 SetInternalState(L"0123456", 3, 3, 3);
727
728 GetTextErrorTest(-1, -1, TF_E_INVALIDPOS);
729 GetTextErrorTest(-1, 0, TF_E_INVALIDPOS);
730 GetTextErrorTest(-1, 1, TF_E_INVALIDPOS);
731 GetTextErrorTest(-1, 3, TF_E_INVALIDPOS);
732 GetTextErrorTest(-1, 6, TF_E_INVALIDPOS);
733 GetTextErrorTest(-1, 7, TF_E_INVALIDPOS);
734 GetTextErrorTest(-1, 8, TF_E_INVALIDPOS);
735
736 GetTextTest(0, -1, L"0123456", 7);
737 GetTextTest(0, 0, L"", 0);
738 GetTextTest(0, 1, L"0", 1);
739 GetTextTest(0, 3, L"012", 3);
740 GetTextTest(0, 6, L"012345", 6);
741 GetTextTest(0, 7, L"0123456", 7);
742 GetTextErrorTest(0, 8, TF_E_INVALIDPOS);
743
744 GetTextTest(1, -1, L"123456", 7);
745 GetTextErrorTest(1, 0, TF_E_INVALIDPOS);
746 GetTextTest(1, 1, L"", 1);
747 GetTextTest(1, 3, L"12", 3);
748 GetTextTest(1, 6, L"12345", 6);
749 GetTextTest(1, 7, L"123456", 7);
750 GetTextErrorTest(1, 8, TF_E_INVALIDPOS);
751
752 GetTextTest(3, -1, L"3456", 7);
753 GetTextErrorTest(3, 0, TF_E_INVALIDPOS);
754 GetTextErrorTest(3, 1, TF_E_INVALIDPOS);
755 GetTextTest(3, 3, L"", 3);
756 GetTextTest(3, 6, L"345", 6);
757 GetTextTest(3, 7, L"3456", 7);
758 GetTextErrorTest(3, 8, TF_E_INVALIDPOS);
759
760 GetTextTest(6, -1, L"6", 7);
761 GetTextErrorTest(6, 0, TF_E_INVALIDPOS);
762 GetTextErrorTest(6, 1, TF_E_INVALIDPOS);
763 GetTextErrorTest(6, 3, TF_E_INVALIDPOS);
764 GetTextTest(6, 6, L"", 6);
765 GetTextTest(6, 7, L"6", 7);
766 GetTextErrorTest(6, 8, TF_E_INVALIDPOS);
767
768 GetTextTest(7, -1, L"", 7);
769 GetTextErrorTest(7, 0, TF_E_INVALIDPOS);
770 GetTextErrorTest(7, 1, TF_E_INVALIDPOS);
771 GetTextErrorTest(7, 3, TF_E_INVALIDPOS);
772 GetTextErrorTest(7, 6, TF_E_INVALIDPOS);
773 GetTextTest(7, 7, L"", 7);
774 GetTextErrorTest(7, 8, TF_E_INVALIDPOS);
775
776 GetTextErrorTest(8, -1, TF_E_INVALIDPOS);
777 GetTextErrorTest(8, 0, TF_E_INVALIDPOS);
778 GetTextErrorTest(8, 1, TF_E_INVALIDPOS);
779 GetTextErrorTest(8, 3, TF_E_INVALIDPOS);
780 GetTextErrorTest(8, 6, TF_E_INVALIDPOS);
781 GetTextErrorTest(8, 7, TF_E_INVALIDPOS);
782 GetTextErrorTest(8, 8, TF_E_INVALIDPOS);
783
784 return S_OK;
785 }
786
787 HRESULT ReadWriteLockGranted(DWORD flags) {
788 SetInternalState(L"", 0, 0, 0);
789 SetTextTest(0, 0, L"", S_OK);
790
791 SetInternalState(L"", 0, 0, 0);
792 SetTextTest(0, 1, L"", TS_E_INVALIDPOS);
793
794 SetInternalState(L"0123456", 3, 3, 3);
795
796 SetTextTest(0, 0, L"", TS_E_INVALIDPOS);
797 SetTextTest(0, 1, L"", TS_E_INVALIDPOS);
798 SetTextTest(0, 3, L"", TS_E_INVALIDPOS);
799 SetTextTest(0, 6, L"", TS_E_INVALIDPOS);
800 SetTextTest(0, 7, L"", TS_E_INVALIDPOS);
801 SetTextTest(0, 8, L"", TS_E_INVALIDPOS);
802
803 SetTextTest(1, 0, L"", TS_E_INVALIDPOS);
804 SetTextTest(1, 1, L"", TS_E_INVALIDPOS);
805 SetTextTest(1, 3, L"", TS_E_INVALIDPOS);
806 SetTextTest(1, 6, L"", TS_E_INVALIDPOS);
807 SetTextTest(1, 7, L"", TS_E_INVALIDPOS);
808 SetTextTest(1, 8, L"", TS_E_INVALIDPOS);
809
810 SetTextTest(3, 0, L"", TS_E_INVALIDPOS);
811 SetTextTest(3, 1, L"", TS_E_INVALIDPOS);
812
813 SetTextTest(3, 3, L"", S_OK);
814 GetTextTest(0, -1, L"0123456", 7);
815 GetSelectionTest(3, 3);
816 SetInternalState(L"0123456", 3, 3, 3);
817
818 SetTextTest(3, 6, L"", S_OK);
819 GetTextTest(0, -1, L"0126", 4);
820 GetSelectionTest(3, 3);
821 SetInternalState(L"0123456", 3, 3, 3);
822
823 SetTextTest(3, 7, L"", S_OK);
824 GetTextTest(0, -1, L"012", 3);
825 GetSelectionTest(3, 3);
826 SetInternalState(L"0123456", 3, 3, 3);
827
828 SetTextTest(3, 8, L"", TS_E_INVALIDPOS);
829
830 SetTextTest(6, 0, L"", TS_E_INVALIDPOS);
831 SetTextTest(6, 1, L"", TS_E_INVALIDPOS);
832 SetTextTest(6, 3, L"", TS_E_INVALIDPOS);
833
834 SetTextTest(6, 6, L"", S_OK);
835 GetTextTest(0, -1, L"0123456", 7);
836 GetSelectionTest(6, 6);
837 SetInternalState(L"0123456", 3, 3, 3);
838
839 SetTextTest(6, 7, L"", S_OK);
840 GetTextTest(0, -1, L"012345", 6);
841 GetSelectionTest(6, 6);
842 SetInternalState(L"0123456", 3, 3, 3);
843
844 SetTextTest(6, 8, L"", TS_E_INVALIDPOS);
845
846 SetTextTest(7, 0, L"", TS_E_INVALIDPOS);
847 SetTextTest(7, 1, L"", TS_E_INVALIDPOS);
848 SetTextTest(7, 3, L"", TS_E_INVALIDPOS);
849 SetTextTest(7, 6, L"", TS_E_INVALIDPOS);
850
851 SetTextTest(7, 7, L"", S_OK);
852 GetTextTest(0, -1, L"0123456", 7);
853 GetSelectionTest(7, 7);
854 SetInternalState(L"0123456", 3, 3, 3);
855
856 SetTextTest(7, 8, L"", TS_E_INVALIDPOS);
857
858 SetInternalState(L"0123456", 3, 3, 3);
859 SetTextTest(3, 3, L"abc", S_OK);
860 GetTextTest(0, -1, L"012abc3456", 10);
861 GetSelectionTest(3, 6);
862
863 SetInternalState(L"0123456", 3, 3, 3);
864 SetTextTest(3, 6, L"abc", S_OK);
865 GetTextTest(0, -1, L"012abc6", 7);
866 GetSelectionTest(3, 6);
867
868 SetInternalState(L"0123456", 3, 3, 3);
869 SetTextTest(3, 7, L"abc", S_OK);
870 GetTextTest(0, -1, L"012abc", 6);
871 GetSelectionTest(3, 6);
872
873 SetInternalState(L"0123456", 3, 3, 3);
874 SetTextTest(6, 6, L"abc", S_OK);
875 GetTextTest(0, -1, L"012345abc6", 10);
876 GetSelectionTest(6, 9);
877
878 SetInternalState(L"0123456", 3, 3, 3);
879 SetTextTest(6, 7, L"abc", S_OK);
880 GetTextTest(0, -1, L"012345abc", 9);
881 GetSelectionTest(6, 9);
882
883 SetInternalState(L"0123456", 3, 3, 3);
884 SetTextTest(7, 7, L"abc", S_OK);
885 GetTextTest(0, -1, L"0123456abc", 10);
886 GetSelectionTest(7, 10);
887
888 return S_OK;
889 }
890
891 private:
892 DISALLOW_COPY_AND_ASSIGN(SetGetTextTestCallback);
893 };
894
895 TEST_F(TSFTextStoreTest, SetGetTextTest) {
896 SetGetTextTestCallback callback(text_store_);
897 EXPECT_CALL(*sink_, OnLockGranted(_))
898 .WillOnce(Invoke(&callback, &SetGetTextTestCallback::ReadLockGranted))
899 .WillOnce(Invoke(&callback,
900 &SetGetTextTestCallback::ReadWriteLockGranted));
901
902 wchar_t buffer[1024] = {};
903 ULONG text_buffer_copied = 0;
904 TS_RUNINFO run_info = {};
905 ULONG run_info_buffer_copied = 0;
906 LONG next_acp = 0;
907 EXPECT_EQ(TF_E_NOLOCK,
908 text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied,
909 &run_info, 1, &run_info_buffer_copied,
910 &next_acp));
911 TS_TEXTCHANGE change = {};
912 EXPECT_EQ(TF_E_NOLOCK, text_store_->SetText(0, 0, 0, L"abc", 3, &change));
913
914 HRESULT result = kInvalidResult;
915 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
916 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
917 }
918
919 class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback {
920 public:
921 explicit InsertTextAtSelectionTestCallback(TSFTextStore* text_store)
922 : TSFTextStoreTestCallback(text_store) {}
923
924 HRESULT ReadLockGranted(DWORD flags) {
925 const wchar_t kBuffer[] = L"0123456789";
926
927 SetInternalState(L"abcedfg", 0, 0, 0);
928 InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0);
929 GetSelectionTest(0, 0);
930 InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0);
931
932 SetInternalState(L"abcedfg", 0, 2, 5);
933 InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 2, 5);
934 GetSelectionTest(2, 5);
935 InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 2, 5);
936
937 LONG start = 0;
938 LONG end = 0;
939 TS_TEXTCHANGE change = {};
940 EXPECT_EQ(TS_E_NOLOCK,
941 text_store_->InsertTextAtSelection(0, kBuffer, 10,
942 &start, &end, &change));
943 return S_OK;
944 }
945
946 HRESULT ReadWriteLockGranted(DWORD flags) {
947 SetInternalState(L"abcedfg", 0, 0, 0);
948
949 const wchar_t kBuffer[] = L"0123456789";
950 InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0);
951 GetSelectionTest(0, 0);
952 InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0);
953
954 SetInternalState(L"", 0, 0, 0);
955 InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10);
956 GetSelectionTest(0, 10);
957 GetTextTest(0, -1, L"0123456789", 10);
958
959 SetInternalState(L"abcedfg", 0, 0, 0);
960 InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10);
961 GetSelectionTest(0, 10);
962 GetTextTest(0, -1, L"0123456789abcedfg", 17);
963
964 SetInternalState(L"abcedfg", 0, 0, 3);
965 InsertTextAtSelectionTest(kBuffer, 0, 0, 0, 0, 3, 0);
966 GetSelectionTest(0, 0);
967 GetTextTest(0, -1, L"edfg", 4);
968
969 SetInternalState(L"abcedfg", 0, 3, 7);
970 InsertTextAtSelectionTest(kBuffer, 10, 3, 13, 3, 7, 13);
971 GetSelectionTest(3, 13);
972 GetTextTest(0, -1, L"abc0123456789", 13);
973
974 SetInternalState(L"abcedfg", 0, 7, 7);
975 InsertTextAtSelectionTest(kBuffer, 10, 7, 17, 7, 7, 17);
976 GetSelectionTest(7, 17);
977 GetTextTest(0, -1, L"abcedfg0123456789", 17);
978
979 return S_OK;
980 }
981
982 private:
983 DISALLOW_COPY_AND_ASSIGN(InsertTextAtSelectionTestCallback);
984 };
985
986 TEST_F(TSFTextStoreTest, InsertTextAtSelectionTest) {
987 InsertTextAtSelectionTestCallback callback(text_store_);
988 EXPECT_CALL(*sink_, OnLockGranted(_))
989 .WillOnce(Invoke(&callback,
990 &InsertTextAtSelectionTestCallback::ReadLockGranted))
991 .WillOnce(
992 Invoke(&callback,
993 &InsertTextAtSelectionTestCallback::ReadWriteLockGranted));
994
995 HRESULT result = kInvalidResult;
996 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
997 EXPECT_EQ(S_OK, result);
998 result = kInvalidResult;
999 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1000 EXPECT_EQ(S_OK, result);
1001 }
1002
1003 class ScenarioTestCallback : public TSFTextStoreTestCallback {
1004 public:
1005 explicit ScenarioTestCallback(TSFTextStore* text_store)
1006 : TSFTextStoreTestCallback(text_store) {}
1007
1008 HRESULT LockGranted1(DWORD flags) {
1009 SetSelectionTest(0, 0, S_OK);
1010
1011 SetTextTest(0, 0, L"abc", S_OK);
1012 SetTextTest(1, 2, L"xyz", S_OK);
1013
1014 GetTextTest(0, -1, L"axyzc", 5);
1015
1016 composition_undelines()->clear();
1017 CompositionUnderline underline;
1018 underline.start_offset = 0;
1019 underline.end_offset = 5;
1020 underline.color = SK_ColorBLACK;
1021 underline.thick = false;
1022 composition_undelines()->push_back(underline);
1023 *edit_flag() = true;
1024 *committed_size() = 0;
1025 return S_OK;
1026 }
1027
1028 void SetCompositionText1(const ui::CompositionText& composition) {
1029 EXPECT_EQ(L"axyzc", composition.text);
1030 EXPECT_EQ(1, composition.selection.start());
1031 EXPECT_EQ(4, composition.selection.end());
1032 ASSERT_EQ(1, composition.underlines.size());
1033 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
1034 EXPECT_EQ(0, composition.underlines[0].start_offset);
1035 EXPECT_EQ(5, composition.underlines[0].end_offset);
1036 EXPECT_FALSE(composition.underlines[0].thick);
1037 }
1038
1039 HRESULT LockGranted2(DWORD flags) {
1040 SetTextTest(3, 4, L"ZCP", S_OK);
1041 GetTextTest(0, -1, L"axyZCPc", 7);
1042
1043 composition_undelines()->clear();
1044 CompositionUnderline underline;
1045 underline.start_offset = 3;
1046 underline.end_offset = 5;
1047 underline.color = SK_ColorBLACK;
1048 underline.thick = true;
1049 composition_undelines()->push_back(underline);
1050 underline.start_offset = 5;
1051 underline.end_offset = 7;
1052 underline.color = SK_ColorBLACK;
1053 underline.thick = false;
1054 composition_undelines()->push_back(underline);
1055
1056 *edit_flag() = true;
1057 *committed_size() = 3;
1058
1059 return S_OK;
1060 }
1061
1062 void InsertText2(const base::string16& text) {
1063 EXPECT_EQ(L"axy", text);
1064 }
1065
1066 void SetCompositionText2(const ui::CompositionText& composition) {
1067 EXPECT_EQ(L"ZCPc", composition.text);
1068 EXPECT_EQ(0, composition.selection.start());
1069 EXPECT_EQ(3, composition.selection.end());
1070 ASSERT_EQ(2, composition.underlines.size());
1071 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
1072 EXPECT_EQ(0, composition.underlines[0].start_offset);
1073 EXPECT_EQ(2, composition.underlines[0].end_offset);
1074 EXPECT_TRUE(composition.underlines[0].thick);
1075 EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color);
1076 EXPECT_EQ(2, composition.underlines[1].start_offset);
1077 EXPECT_EQ(4, composition.underlines[1].end_offset);
1078 EXPECT_FALSE(composition.underlines[1].thick);
1079 }
1080
1081 HRESULT LockGranted3(DWORD flags) {
1082 GetTextTest(0, -1, L"axyZCPc", 7);
1083
1084 composition_undelines()->clear();
1085 *edit_flag() = true;
1086 *committed_size() = 7;
1087
1088 return S_OK;
1089 }
1090
1091 void InsertText3(const base::string16& text) {
1092 EXPECT_EQ(L"ZCPc", text);
1093 }
1094
1095 void SetCompositionText3(const ui::CompositionText& composition) {
1096 EXPECT_EQ(L"", composition.text);
1097 EXPECT_EQ(0, composition.selection.start());
1098 EXPECT_EQ(0, composition.selection.end());
1099 EXPECT_EQ(0, composition.underlines.size());
1100 }
1101
1102 private:
1103 DISALLOW_COPY_AND_ASSIGN(ScenarioTestCallback);
1104 };
1105
1106 TEST_F(TSFTextStoreTest, ScenarioTest) {
1107 ScenarioTestCallback callback(text_store_);
1108 EXPECT_CALL(text_input_client_, SetCompositionText(_))
1109 .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText1))
1110 .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText2))
1111 .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText3));
1112
1113 EXPECT_CALL(text_input_client_, InsertText(_))
1114 .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText2))
1115 .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText3));
1116
1117 EXPECT_CALL(*sink_, OnLockGranted(_))
1118 .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted1))
1119 .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted2))
1120 .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted3));
1121
1122 // OnSelectionChange will be called once after LockGranted3().
1123 EXPECT_CALL(*sink_, OnSelectionChange())
1124 .WillOnce(Return(S_OK));
1125
1126 // OnLayoutChange will be called once after LockGranted3().
1127 EXPECT_CALL(*sink_, OnLayoutChange(_, _))
1128 .WillOnce(Return(S_OK));
1129
1130 // OnTextChange will be called once after LockGranted3().
1131 EXPECT_CALL(*sink_, OnTextChange(_, _))
1132 .WillOnce(Return(S_OK));
1133
1134 HRESULT result = kInvalidResult;
1135 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1136 EXPECT_EQ(S_OK, result);
1137 result = kInvalidResult;
1138 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1139 EXPECT_EQ(S_OK, result);
1140 result = kInvalidResult;
1141 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1142 EXPECT_EQ(S_OK, result);
1143 }
1144
1145 class GetTextExtTestCallback : public TSFTextStoreTestCallback {
1146 public:
1147 explicit GetTextExtTestCallback(TSFTextStore* text_store)
1148 : TSFTextStoreTestCallback(text_store),
1149 layout_prepared_character_num_(0) {}
1150
1151 HRESULT LockGranted(DWORD flags) {
1152 SetInternalState(L"0123456789012", 0, 0, 0);
1153 layout_prepared_character_num_ = 13;
1154
1155 TsViewCookie view_cookie = 0;
1156 EXPECT_EQ(S_OK, text_store_->GetActiveView(&view_cookie));
1157 GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
1158 GetTextExtTest(view_cookie, 0, 1, 11, 12, 20, 20);
1159 GetTextExtTest(view_cookie, 0, 2, 11, 12, 30, 20);
1160 GetTextExtTest(view_cookie, 9, 9, 100, 12, 100, 20);
1161 GetTextExtTest(view_cookie, 9, 10, 101, 12, 110, 20);
1162 GetTextExtTest(view_cookie, 10, 10, 110, 12, 110, 20);
1163 GetTextExtTest(view_cookie, 11, 11, 20, 112, 20, 120);
1164 GetTextExtTest(view_cookie, 11, 12, 21, 112, 30, 120);
1165 GetTextExtTest(view_cookie, 9, 12, 101, 12, 30, 120);
1166 GetTextExtTest(view_cookie, 9, 13, 101, 12, 40, 120);
1167 GetTextExtTest(view_cookie, 0, 13, 11, 12, 40, 120);
1168 GetTextExtTest(view_cookie, 13, 13, 40, 112, 40, 120);
1169
1170 layout_prepared_character_num_ = 12;
1171 GetTextExtNoLayoutTest(view_cookie, 13, 13);
1172
1173 layout_prepared_character_num_ = 0;
1174 GetTextExtNoLayoutTest(view_cookie, 0, 0);
1175
1176 SetInternalState(L"", 0, 0, 0);
1177 GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6);
1178
1179 // Last character is not availabe due to timing issue of async API.
1180 // In this case, we will get first character bounds instead of whole text
1181 // bounds.
1182 SetInternalState(L"abc", 0, 0, 3);
1183 layout_prepared_character_num_ = 2;
1184 GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
1185
1186 // TODO(nona, kinaba): Remove following test case after PPAPI supporting
1187 // GetCompositionCharacterBounds.
1188 SetInternalState(L"a", 0, 0, 1);
1189 layout_prepared_character_num_ = 0;
1190 GetTextExtTest(view_cookie, 0, 1, 1, 2, 4, 6);
1191 return S_OK;
1192 }
1193
1194 bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) {
1195 if (index >= layout_prepared_character_num_)
1196 return false;
1197 rect->set_x((index % 10) * 10 + 11);
1198 rect->set_y((index / 10) * 100 + 12);
1199 rect->set_width(9);
1200 rect->set_height(8);
1201 return true;
1202 }
1203
1204 gfx::Rect GetCaretBounds() {
1205 return gfx::Rect(1, 2, 3, 4);
1206 }
1207
1208 private:
1209 uint32 layout_prepared_character_num_;
1210
1211 DISALLOW_COPY_AND_ASSIGN(GetTextExtTestCallback);
1212 };
1213
1214 TEST_F(TSFTextStoreTest, GetTextExtTest) {
1215 GetTextExtTestCallback callback(text_store_);
1216 EXPECT_CALL(text_input_client_, GetCaretBounds())
1217 .WillRepeatedly(Invoke(&callback,
1218 &GetTextExtTestCallback::GetCaretBounds));
1219
1220 EXPECT_CALL(text_input_client_, GetCompositionCharacterBounds(_, _))
1221 .WillRepeatedly(
1222 Invoke(&callback,
1223 &GetTextExtTestCallback::GetCompositionCharacterBounds));
1224
1225 EXPECT_CALL(*sink_, OnLockGranted(_))
1226 .WillOnce(Invoke(&callback, &GetTextExtTestCallback::LockGranted));
1227
1228 HRESULT result = kInvalidResult;
1229 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
1230 EXPECT_EQ(S_OK, result);
1231 }
1232
1233 TEST_F(TSFTextStoreTest, RequestSupportedAttrs) {
1234 EXPECT_CALL(text_input_client_, GetTextInputType())
1235 .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT));
1236 EXPECT_CALL(text_input_client_, GetTextInputMode())
1237 .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT));
1238
1239 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 1, NULL));
1240
1241 const TS_ATTRID kUnknownAttributes[] = {GUID_NULL};
1242 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(
1243 0, arraysize(kUnknownAttributes), kUnknownAttributes))
1244 << "Must fail for unknown attributes";
1245
1246 const TS_ATTRID kAttributes[] = {GUID_NULL, GUID_PROP_INPUTSCOPE, GUID_NULL};
1247 EXPECT_EQ(S_OK, text_store_->RequestSupportedAttrs(
1248 0, arraysize(kAttributes), kAttributes))
1249 << "InputScope must be supported";
1250
1251 {
1252 SCOPED_TRACE("Check if RequestSupportedAttrs fails while focus is lost");
1253 // Emulate focus lost
1254 text_store_->SetFocusedTextInputClient(NULL, NULL);
1255 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 0, NULL));
1256 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(
1257 0, arraysize(kAttributes), kAttributes));
1258 }
1259 }
1260
1261 TEST_F(TSFTextStoreTest, RetrieveRequestedAttrs) {
1262 EXPECT_CALL(text_input_client_, GetTextInputType())
1263 .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT));
1264 EXPECT_CALL(text_input_client_, GetTextInputMode())
1265 .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT));
1266
1267 ULONG num_copied = 0xfffffff;
1268 EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs(
1269 1, NULL, &num_copied));
1270
1271 {
1272 SCOPED_TRACE("Make sure if InputScope is supported");
1273 TS_ATTRVAL buffer[2] = {};
1274 num_copied = 0xfffffff;
1275 ASSERT_EQ(S_OK, text_store_->RetrieveRequestedAttrs(
1276 arraysize(buffer), buffer, &num_copied));
1277 bool input_scope_found = false;
1278 for (size_t i = 0; i < num_copied; ++i) {
1279 base::win::ScopedVariant variant;
1280 // Move ownership from |buffer[i].varValue| to |variant|.
1281 std::swap(*variant.Receive(), buffer[i].varValue);
1282 if (IsEqualGUID(buffer[i].idAttr, GUID_PROP_INPUTSCOPE)) {
1283 EXPECT_EQ(VT_UNKNOWN, variant.type());
1284 base::win::ScopedComPtr<ITfInputScope> input_scope;
1285 EXPECT_HRESULT_SUCCEEDED(input_scope.QueryFrom((&variant)->punkVal));
1286 input_scope_found = true;
1287 // we do not break here to clean up all the retrieved VARIANTs.
1288 }
1289 }
1290 EXPECT_TRUE(input_scope_found);
1291 }
1292 {
1293 SCOPED_TRACE("Check if RetrieveRequestedAttrs fails while focus is lost");
1294 // Emulate focus lost
1295 text_store_->SetFocusedTextInputClient(NULL, NULL);
1296 num_copied = 0xfffffff;
1297 TS_ATTRVAL buffer[2] = {};
1298 EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs(
1299 arraysize(buffer), buffer, &num_copied));
1300 }
1301 }
1302
1303 } // namespace
1304 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/ime/win/tsf_text_store.cc ('k') | ui/views/widget/desktop_aura/desktop_root_window_host_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698