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 #include "ui/base/ime/win/tsf_text_store.h"
7 #include <initguid.h> // for GUID_NULL and GUID_PROP_INPUTSCOPE
8 #include <InputScope.h>
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"
20 using testing::Invoke;
21 using testing::Return;
26 class MockTextInputClient : public TextInputClient {
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 string16&));
33 MOCK_METHOD2(InsertChar, void(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&, string16*));
47 MOCK_METHOD0(OnInputMethodChanged, void());
48 MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment,
49 bool(base::i18n::TextDirection));
50 MOCK_METHOD2(ExtendSelectionAndDelete, void(size_t, size_t));
51 MOCK_METHOD1(EnsureCaretInRect, void(const gfx::Rect&));
54 class MockStoreACPSink : public ITextStoreACPSink {
56 MockStoreACPSink() : ref_count_(0) {}
59 virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
60 return InterlockedIncrement(&ref_count_);
62 virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
63 const LONG count = InterlockedDecrement(&ref_count_);
68 return static_cast<ULONG>(count);
70 virtual HRESULT STDMETHODCALLTYPE QueryInterface(
71 REFIID iid, void** report) OVERRIDE {
72 if (iid == IID_IUnknown || iid == IID_ITextStoreACPSink) {
73 *report = static_cast<ITextStoreACPSink*>(this);
83 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnTextChange,
84 HRESULT(DWORD, const TS_TEXTCHANGE*));
85 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnSelectionChange,
87 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLayoutChange,
88 HRESULT(TsLayoutCode, TsViewCookie));
89 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStatusChange,
91 MOCK_METHOD4_WITH_CALLTYPE(STDMETHODCALLTYPE, OnAttrsChange,
92 HRESULT(LONG, LONG, ULONG, const TS_ATTRID*));
93 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLockGranted,
95 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStartEditTransaction,
97 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnEndEditTransaction,
101 virtual ~MockStoreACPSink() {}
103 volatile LONG ref_count_;
106 const HWND kWindowHandle = reinterpret_cast<HWND>(1);
110 class TSFTextStoreTest : public testing::Test {
112 virtual void SetUp() OVERRIDE {
113 text_store_ = new TSFTextStore();
114 sink_ = new MockStoreACPSink();
115 EXPECT_EQ(S_OK, text_store_->AdviseSink(IID_ITextStoreACPSink,
116 sink_, TS_AS_ALL_SINKS));
117 text_store_->SetFocusedTextInputClient(kWindowHandle,
118 &text_input_client_);
121 virtual void TearDown() OVERRIDE {
122 EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_));
127 // Accessors to the internal state of TSFTextStore.
128 string16* string_buffer() { return &text_store_->string_buffer_; }
129 size_t* committed_size() { return &text_store_->committed_size_; }
131 base::win::ScopedCOMInitializer com_initializer_;
132 MockTextInputClient text_input_client_;
133 scoped_refptr<TSFTextStore> text_store_;
134 scoped_refptr<MockStoreACPSink> sink_;
137 class TSFTextStoreTestCallback {
139 explicit TSFTextStoreTestCallback(TSFTextStore* text_store)
140 : text_store_(text_store) {
143 virtual ~TSFTextStoreTestCallback() {}
146 // Accessors to the internal state of TSFTextStore.
147 bool* edit_flag() { return &text_store_->edit_flag_; }
148 string16* string_buffer() { return &text_store_->string_buffer_; }
149 size_t* committed_size() { return &text_store_->committed_size_; }
150 gfx::Range* selection() { return &text_store_->selection_; }
151 CompositionUnderlines* composition_undelines() {
152 return &text_store_->composition_undelines_;
155 void SetInternalState(const string16& new_string_buffer,
156 LONG new_committed_size, LONG new_selection_start,
157 LONG new_selection_end) {
158 ASSERT_LE(0, new_committed_size);
159 ASSERT_LE(new_committed_size, new_selection_start);
160 ASSERT_LE(new_selection_start, new_selection_end);
161 ASSERT_LE(new_selection_end, static_cast<LONG>(new_string_buffer.size()));
162 *string_buffer() = new_string_buffer;
163 *committed_size() = new_committed_size;
164 selection()->set_start(new_selection_start);
165 selection()->set_end(new_selection_end);
168 bool HasReadLock() const { return text_store_->HasReadLock(); }
169 bool HasReadWriteLock() const { return text_store_->HasReadWriteLock(); }
171 void GetSelectionTest(LONG expected_acp_start, LONG expected_acp_end) {
172 TS_SELECTION_ACP selection = {};
174 EXPECT_EQ(S_OK, text_store_->GetSelection(0, 1, &selection, &fetched));
175 EXPECT_EQ(1, fetched);
176 EXPECT_EQ(expected_acp_start, selection.acpStart);
177 EXPECT_EQ(expected_acp_end, selection.acpEnd);
180 void SetSelectionTest(LONG acp_start, LONG acp_end, HRESULT expected_result) {
181 TS_SELECTION_ACP selection = {};
182 selection.acpStart = acp_start;
183 selection.acpEnd = acp_end;
184 selection.style.ase = TS_AE_NONE;
185 selection.style.fInterimChar = 0;
186 EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection));
187 if (expected_result == S_OK) {
188 GetSelectionTest(acp_start, acp_end);
192 void SetTextTest(LONG acp_start, LONG acp_end,
193 const string16& text, HRESULT error_code) {
194 TS_TEXTCHANGE change = {};
195 ASSERT_EQ(error_code,
196 text_store_->SetText(0, acp_start, acp_end,
197 text.c_str(), text.size(), &change));
198 if (error_code == S_OK) {
199 EXPECT_EQ(acp_start, change.acpStart);
200 EXPECT_EQ(acp_end, change.acpOldEnd);
201 EXPECT_EQ(acp_start + text.size(), change.acpNewEnd);
205 void GetTextTest(LONG acp_start, LONG acp_end,
206 const string16& expected_string,
207 LONG expected_next_acp) {
208 wchar_t buffer[1024] = {};
209 ULONG text_buffer_copied = 0;
210 TS_RUNINFO run_info = {};
211 ULONG run_info_buffer_copied = 0;
214 text_store_->GetText(acp_start, acp_end, buffer, 1024,
216 &run_info, 1, &run_info_buffer_copied,
218 ASSERT_EQ(expected_string.size(), text_buffer_copied);
219 EXPECT_EQ(expected_string, string16(buffer, buffer + text_buffer_copied));
220 EXPECT_EQ(1, run_info_buffer_copied);
221 EXPECT_EQ(expected_string.size(), run_info.uCount);
222 EXPECT_EQ(TS_RT_PLAIN, run_info.type);
223 EXPECT_EQ(expected_next_acp, next_acp);
226 void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) {
227 wchar_t buffer[1024] = {};
228 ULONG text_buffer_copied = 0;
229 TS_RUNINFO run_info = {};
230 ULONG run_info_buffer_copied = 0;
232 EXPECT_EQ(error_code,
233 text_store_->GetText(acp_start, acp_end, buffer, 1024,
235 &run_info, 1, &run_info_buffer_copied,
239 void InsertTextAtSelectionTest(const wchar_t* buffer, ULONG buffer_size,
240 LONG expected_start, LONG expected_end,
241 LONG expected_change_start,
242 LONG expected_change_old_end,
243 LONG expected_change_new_end) {
246 TS_TEXTCHANGE change = {};
248 text_store_->InsertTextAtSelection(0, buffer, buffer_size,
249 &start, &end, &change));
250 EXPECT_EQ(expected_start, start);
251 EXPECT_EQ(expected_end, end);
252 EXPECT_EQ(expected_change_start, change.acpStart);
253 EXPECT_EQ(expected_change_old_end, change.acpOldEnd);
254 EXPECT_EQ(expected_change_new_end, change.acpNewEnd);
257 void InsertTextAtSelectionQueryOnlyTest(const wchar_t* buffer,
264 text_store_->InsertTextAtSelection(TS_IAS_QUERYONLY, buffer,
265 buffer_size, &start, &end,
267 EXPECT_EQ(expected_start, start);
268 EXPECT_EQ(expected_end, end);
271 void GetTextExtTest(TsViewCookie view_cookie, LONG acp_start, LONG acp_end,
272 LONG expected_left, LONG expected_top,
273 LONG expected_right, LONG expected_bottom) {
275 BOOL clipped = FALSE;
276 EXPECT_EQ(S_OK, text_store_->GetTextExt(view_cookie, acp_start, acp_end,
278 EXPECT_EQ(expected_left, rect.left);
279 EXPECT_EQ(expected_top, rect.top);
280 EXPECT_EQ(expected_right, rect.right);
281 EXPECT_EQ(expected_bottom, rect.bottom);
282 EXPECT_EQ(FALSE, clipped);
285 void GetTextExtNoLayoutTest(TsViewCookie view_cookie, LONG acp_start,
288 BOOL clipped = FALSE;
289 EXPECT_EQ(TS_E_NOLAYOUT,
290 text_store_->GetTextExt(view_cookie, acp_start, acp_end,
294 scoped_refptr<TSFTextStore> text_store_;
297 DISALLOW_COPY_AND_ASSIGN(TSFTextStoreTestCallback);
302 const HRESULT kInvalidResult = 0x12345678;
304 TEST_F(TSFTextStoreTest, GetStatusTest) {
305 TS_STATUS status = {};
306 EXPECT_EQ(S_OK, text_store_->GetStatus(&status));
307 EXPECT_EQ(0, status.dwDynamicFlags);
308 EXPECT_EQ(TS_SS_TRANSITORY | TS_SS_NOHIDDENTEXT, status.dwStaticFlags);
311 TEST_F(TSFTextStoreTest, QueryInsertTest) {
312 LONG result_start = 0;
314 *string_buffer() = L"";
315 *committed_size() = 0;
316 EXPECT_EQ(E_INVALIDARG,
317 text_store_->QueryInsert(0, 0, 0, NULL, &result_end));
318 EXPECT_EQ(E_INVALIDARG,
319 text_store_->QueryInsert(0, 0, 0, &result_start, NULL));
321 text_store_->QueryInsert(0, 0, 0, &result_start, &result_end));
322 EXPECT_EQ(0, result_start);
323 EXPECT_EQ(0, result_end);
324 *string_buffer() = L"1234";
325 *committed_size() = 1;
326 EXPECT_EQ(E_INVALIDARG,
327 text_store_->QueryInsert(0, 1, 0, &result_start, &result_end));
328 EXPECT_EQ(E_INVALIDARG,
329 text_store_->QueryInsert(1, 0, 0, &result_start, &result_end));
331 text_store_->QueryInsert(2, 2, 0, &result_start, &result_end));
332 EXPECT_EQ(2, result_start);
333 EXPECT_EQ(2, result_end);
335 text_store_->QueryInsert(2, 3, 0, &result_start, &result_end));
336 EXPECT_EQ(2, result_start);
337 EXPECT_EQ(3, result_end);
338 EXPECT_EQ(E_INVALIDARG,
339 text_store_->QueryInsert(3, 2, 0, &result_start, &result_end));
341 text_store_->QueryInsert(3, 4, 0, &result_start, &result_end));
342 EXPECT_EQ(3, result_start);
343 EXPECT_EQ(4, result_end);
344 EXPECT_EQ(E_INVALIDARG,
345 text_store_->QueryInsert(3, 5, 0, &result_start, &result_end));
348 class SyncRequestLockTestCallback : public TSFTextStoreTestCallback {
350 explicit SyncRequestLockTestCallback(TSFTextStore* text_store)
351 : TSFTextStoreTestCallback(text_store) {}
353 HRESULT LockGranted1(DWORD flags) {
354 EXPECT_TRUE(HasReadLock());
355 EXPECT_FALSE(HasReadWriteLock());
359 HRESULT LockGranted2(DWORD flags) {
360 EXPECT_TRUE(HasReadLock());
361 EXPECT_TRUE(HasReadWriteLock());
365 HRESULT LockGranted3(DWORD flags) {
366 EXPECT_TRUE(HasReadLock());
367 EXPECT_FALSE(HasReadWriteLock());
368 HRESULT result = kInvalidResult;
369 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
370 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
374 HRESULT LockGranted4(DWORD flags) {
375 EXPECT_TRUE(HasReadLock());
376 EXPECT_FALSE(HasReadWriteLock());
377 HRESULT result = kInvalidResult;
379 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
380 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
384 HRESULT LockGranted5(DWORD flags) {
385 EXPECT_TRUE(HasReadLock());
386 EXPECT_TRUE(HasReadWriteLock());
387 HRESULT result = kInvalidResult;
388 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
389 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
393 HRESULT LockGranted6(DWORD flags) {
394 EXPECT_TRUE(HasReadLock());
395 EXPECT_TRUE(HasReadWriteLock());
396 HRESULT result = kInvalidResult;
398 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
399 EXPECT_EQ(TS_E_SYNCHRONOUS, result);
404 DISALLOW_COPY_AND_ASSIGN(SyncRequestLockTestCallback);
407 TEST_F(TSFTextStoreTest, SynchronousRequestLockTest) {
408 SyncRequestLockTestCallback callback(text_store_);
409 EXPECT_CALL(*sink_, OnLockGranted(_))
410 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted1))
411 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted2))
412 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted3))
413 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted4))
414 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted5))
415 .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted6));
417 HRESULT result = kInvalidResult;
418 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
419 EXPECT_EQ(S_OK, result);
420 result = kInvalidResult;
422 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
423 EXPECT_EQ(S_OK, result);
425 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
426 EXPECT_EQ(S_OK, result);
427 result = kInvalidResult;
428 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result));
429 EXPECT_EQ(S_OK, result);
431 result = kInvalidResult;
433 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
434 EXPECT_EQ(S_OK, result);
435 result = kInvalidResult;
437 text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result));
438 EXPECT_EQ(S_OK, result);
441 class AsyncRequestLockTestCallback : public TSFTextStoreTestCallback {
443 explicit AsyncRequestLockTestCallback(TSFTextStore* text_store)
444 : TSFTextStoreTestCallback(text_store),
447 HRESULT LockGranted1(DWORD flags) {
448 EXPECT_EQ(0, state_);
450 EXPECT_TRUE(HasReadLock());
451 EXPECT_FALSE(HasReadWriteLock());
452 HRESULT result = kInvalidResult;
453 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
454 EXPECT_EQ(TS_S_ASYNC, result);
455 EXPECT_EQ(1, state_);
460 HRESULT LockGranted2(DWORD flags) {
461 EXPECT_EQ(2, state_);
462 EXPECT_TRUE(HasReadLock());
463 EXPECT_FALSE(HasReadWriteLock());
464 HRESULT result = kInvalidResult;
465 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
466 EXPECT_EQ(TS_S_ASYNC, result);
467 EXPECT_EQ(2, state_);
472 HRESULT LockGranted3(DWORD flags) {
473 EXPECT_EQ(3, state_);
474 EXPECT_TRUE(HasReadLock());
475 EXPECT_TRUE(HasReadWriteLock());
476 HRESULT result = kInvalidResult;
477 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
478 EXPECT_EQ(TS_S_ASYNC, result);
479 EXPECT_EQ(3, state_);
484 HRESULT LockGranted4(DWORD flags) {
485 EXPECT_EQ(4, state_);
486 EXPECT_TRUE(HasReadLock());
487 EXPECT_TRUE(HasReadWriteLock());
488 HRESULT result = kInvalidResult;
489 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
490 EXPECT_EQ(TS_S_ASYNC, result);
491 EXPECT_EQ(4, state_);
496 HRESULT LockGranted5(DWORD flags) {
497 EXPECT_EQ(5, state_);
498 EXPECT_TRUE(HasReadLock());
499 EXPECT_FALSE(HasReadWriteLock());
507 DISALLOW_COPY_AND_ASSIGN(AsyncRequestLockTestCallback);
510 TEST_F(TSFTextStoreTest, AsynchronousRequestLockTest) {
511 AsyncRequestLockTestCallback callback(text_store_);
512 EXPECT_CALL(*sink_, OnLockGranted(_))
513 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted1))
514 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted2))
515 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted3))
516 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted4))
517 .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted5));
519 HRESULT result = kInvalidResult;
520 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
521 EXPECT_EQ(S_OK, result);
524 class RequestLockTextChangeTestCallback : public TSFTextStoreTestCallback {
526 explicit RequestLockTextChangeTestCallback(TSFTextStore* text_store)
527 : TSFTextStoreTestCallback(text_store),
530 HRESULT LockGranted1(DWORD flags) {
531 EXPECT_EQ(0, state_);
533 EXPECT_TRUE(HasReadLock());
534 EXPECT_TRUE(HasReadWriteLock());
537 SetInternalState(L"012345", 6, 6, 6);
538 composition_undelines()->clear();
544 void InsertText(const string16& text) {
545 EXPECT_EQ(2, state_);
546 EXPECT_EQ(L"012345", text);
550 void SetCompositionText(const ui::CompositionText& composition) {
551 EXPECT_EQ(3, state_);
552 EXPECT_EQ(L"", composition.text);
553 EXPECT_EQ(0, composition.selection.start());
554 EXPECT_EQ(0, composition.selection.end());
555 EXPECT_EQ(0, composition.underlines.size());
559 HRESULT OnTextChange(DWORD flags, const TS_TEXTCHANGE* change) {
560 EXPECT_EQ(4, state_);
561 HRESULT result = kInvalidResult;
563 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
564 EXPECT_EQ(S_OK, result);
565 EXPECT_EQ(6, state_);
570 HRESULT LockGranted2(DWORD flags) {
571 EXPECT_EQ(5, state_);
572 EXPECT_TRUE(HasReadLock());
573 EXPECT_TRUE(HasReadWriteLock());
581 DISALLOW_COPY_AND_ASSIGN(RequestLockTextChangeTestCallback);
584 TEST_F(TSFTextStoreTest, RequestLockOnTextChangeTest) {
585 RequestLockTextChangeTestCallback callback(text_store_);
586 EXPECT_CALL(*sink_, OnLockGranted(_))
587 .WillOnce(Invoke(&callback,
588 &RequestLockTextChangeTestCallback::LockGranted1))
589 .WillOnce(Invoke(&callback,
590 &RequestLockTextChangeTestCallback::LockGranted2));
592 EXPECT_CALL(*sink_, OnSelectionChange())
593 .WillOnce(Return(S_OK));
594 EXPECT_CALL(*sink_, OnLayoutChange(_, _))
595 .WillOnce(Return(S_OK));
596 EXPECT_CALL(*sink_, OnTextChange(_, _))
597 .WillOnce(Invoke(&callback,
598 &RequestLockTextChangeTestCallback::OnTextChange));
599 EXPECT_CALL(text_input_client_, InsertText(_))
600 .WillOnce(Invoke(&callback,
601 &RequestLockTextChangeTestCallback::InsertText));
602 EXPECT_CALL(text_input_client_, SetCompositionText(_))
603 .WillOnce(Invoke(&callback,
604 &RequestLockTextChangeTestCallback::SetCompositionText));
606 HRESULT result = kInvalidResult;
607 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
608 EXPECT_EQ(S_OK, result);
611 class SelectionTestCallback : public TSFTextStoreTestCallback {
613 explicit SelectionTestCallback(TSFTextStore* text_store)
614 : TSFTextStoreTestCallback(text_store) {}
616 HRESULT ReadLockGranted(DWORD flags) {
617 SetInternalState(L"", 0, 0, 0);
619 GetSelectionTest(0, 0);
620 SetSelectionTest(0, 0, TF_E_NOLOCK);
622 SetInternalState(L"012345", 0, 0, 3);
624 GetSelectionTest(0, 3);
625 SetSelectionTest(0, 0, TF_E_NOLOCK);
630 HRESULT ReadWriteLockGranted(DWORD flags) {
631 SetInternalState(L"", 0, 0, 0);
633 SetSelectionTest(0, 0, S_OK);
634 GetSelectionTest(0, 0);
635 SetSelectionTest(0, 1, TF_E_INVALIDPOS);
636 SetSelectionTest(1, 0, TF_E_INVALIDPOS);
637 SetSelectionTest(1, 1, TF_E_INVALIDPOS);
639 SetInternalState(L"0123456", 3, 3, 3);
641 SetSelectionTest(0, 0, TF_E_INVALIDPOS);
642 SetSelectionTest(0, 1, TF_E_INVALIDPOS);
643 SetSelectionTest(0, 3, TF_E_INVALIDPOS);
644 SetSelectionTest(0, 6, TF_E_INVALIDPOS);
645 SetSelectionTest(0, 7, TF_E_INVALIDPOS);
646 SetSelectionTest(0, 8, TF_E_INVALIDPOS);
648 SetSelectionTest(1, 0, TF_E_INVALIDPOS);
649 SetSelectionTest(1, 1, TF_E_INVALIDPOS);
650 SetSelectionTest(1, 3, TF_E_INVALIDPOS);
651 SetSelectionTest(1, 6, TF_E_INVALIDPOS);
652 SetSelectionTest(1, 7, TF_E_INVALIDPOS);
653 SetSelectionTest(1, 8, TF_E_INVALIDPOS);
655 SetSelectionTest(3, 0, TF_E_INVALIDPOS);
656 SetSelectionTest(3, 1, TF_E_INVALIDPOS);
657 SetSelectionTest(3, 3, S_OK);
658 SetSelectionTest(3, 6, S_OK);
659 SetSelectionTest(3, 7, S_OK);
660 SetSelectionTest(3, 8, TF_E_INVALIDPOS);
662 SetSelectionTest(6, 0, TF_E_INVALIDPOS);
663 SetSelectionTest(6, 1, TF_E_INVALIDPOS);
664 SetSelectionTest(6, 3, TF_E_INVALIDPOS);
665 SetSelectionTest(6, 6, S_OK);
666 SetSelectionTest(6, 7, S_OK);
667 SetSelectionTest(6, 8, TF_E_INVALIDPOS);
669 SetSelectionTest(7, 0, TF_E_INVALIDPOS);
670 SetSelectionTest(7, 1, TF_E_INVALIDPOS);
671 SetSelectionTest(7, 3, TF_E_INVALIDPOS);
672 SetSelectionTest(7, 6, TF_E_INVALIDPOS);
673 SetSelectionTest(7, 7, S_OK);
674 SetSelectionTest(7, 8, TF_E_INVALIDPOS);
676 SetSelectionTest(8, 0, TF_E_INVALIDPOS);
677 SetSelectionTest(8, 1, TF_E_INVALIDPOS);
678 SetSelectionTest(8, 3, TF_E_INVALIDPOS);
679 SetSelectionTest(8, 6, TF_E_INVALIDPOS);
680 SetSelectionTest(8, 7, TF_E_INVALIDPOS);
681 SetSelectionTest(8, 8, TF_E_INVALIDPOS);
687 TEST_F(TSFTextStoreTest, SetGetSelectionTest) {
688 SelectionTestCallback callback(text_store_);
689 EXPECT_CALL(*sink_, OnLockGranted(_))
690 .WillOnce(Invoke(&callback, &SelectionTestCallback::ReadLockGranted))
691 .WillOnce(Invoke(&callback,
692 &SelectionTestCallback::ReadWriteLockGranted));
694 TS_SELECTION_ACP selection_buffer = {};
695 ULONG fetched_count = 0;
696 EXPECT_EQ(TS_E_NOLOCK,
697 text_store_->GetSelection(0, 1, &selection_buffer,
700 HRESULT result = kInvalidResult;
701 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
702 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
705 class SetGetTextTestCallback : public TSFTextStoreTestCallback {
707 explicit SetGetTextTestCallback(TSFTextStore* text_store)
708 : TSFTextStoreTestCallback(text_store) {}
710 HRESULT ReadLockGranted(DWORD flags) {
711 SetTextTest(0, 0, L"", TF_E_NOLOCK);
713 GetTextTest(0, -1, L"", 0);
714 GetTextTest(0, 0, L"", 0);
715 GetTextErrorTest(0, 1, TF_E_INVALIDPOS);
717 SetInternalState(L"0123456", 3, 3, 3);
719 GetTextErrorTest(-1, -1, TF_E_INVALIDPOS);
720 GetTextErrorTest(-1, 0, TF_E_INVALIDPOS);
721 GetTextErrorTest(-1, 1, TF_E_INVALIDPOS);
722 GetTextErrorTest(-1, 3, TF_E_INVALIDPOS);
723 GetTextErrorTest(-1, 6, TF_E_INVALIDPOS);
724 GetTextErrorTest(-1, 7, TF_E_INVALIDPOS);
725 GetTextErrorTest(-1, 8, TF_E_INVALIDPOS);
727 GetTextTest(0, -1, L"0123456", 7);
728 GetTextTest(0, 0, L"", 0);
729 GetTextTest(0, 1, L"0", 1);
730 GetTextTest(0, 3, L"012", 3);
731 GetTextTest(0, 6, L"012345", 6);
732 GetTextTest(0, 7, L"0123456", 7);
733 GetTextErrorTest(0, 8, TF_E_INVALIDPOS);
735 GetTextTest(1, -1, L"123456", 7);
736 GetTextErrorTest(1, 0, TF_E_INVALIDPOS);
737 GetTextTest(1, 1, L"", 1);
738 GetTextTest(1, 3, L"12", 3);
739 GetTextTest(1, 6, L"12345", 6);
740 GetTextTest(1, 7, L"123456", 7);
741 GetTextErrorTest(1, 8, TF_E_INVALIDPOS);
743 GetTextTest(3, -1, L"3456", 7);
744 GetTextErrorTest(3, 0, TF_E_INVALIDPOS);
745 GetTextErrorTest(3, 1, TF_E_INVALIDPOS);
746 GetTextTest(3, 3, L"", 3);
747 GetTextTest(3, 6, L"345", 6);
748 GetTextTest(3, 7, L"3456", 7);
749 GetTextErrorTest(3, 8, TF_E_INVALIDPOS);
751 GetTextTest(6, -1, L"6", 7);
752 GetTextErrorTest(6, 0, TF_E_INVALIDPOS);
753 GetTextErrorTest(6, 1, TF_E_INVALIDPOS);
754 GetTextErrorTest(6, 3, TF_E_INVALIDPOS);
755 GetTextTest(6, 6, L"", 6);
756 GetTextTest(6, 7, L"6", 7);
757 GetTextErrorTest(6, 8, TF_E_INVALIDPOS);
759 GetTextTest(7, -1, L"", 7);
760 GetTextErrorTest(7, 0, TF_E_INVALIDPOS);
761 GetTextErrorTest(7, 1, TF_E_INVALIDPOS);
762 GetTextErrorTest(7, 3, TF_E_INVALIDPOS);
763 GetTextErrorTest(7, 6, TF_E_INVALIDPOS);
764 GetTextTest(7, 7, L"", 7);
765 GetTextErrorTest(7, 8, TF_E_INVALIDPOS);
767 GetTextErrorTest(8, -1, TF_E_INVALIDPOS);
768 GetTextErrorTest(8, 0, TF_E_INVALIDPOS);
769 GetTextErrorTest(8, 1, TF_E_INVALIDPOS);
770 GetTextErrorTest(8, 3, TF_E_INVALIDPOS);
771 GetTextErrorTest(8, 6, TF_E_INVALIDPOS);
772 GetTextErrorTest(8, 7, TF_E_INVALIDPOS);
773 GetTextErrorTest(8, 8, TF_E_INVALIDPOS);
778 HRESULT ReadWriteLockGranted(DWORD flags) {
779 SetInternalState(L"", 0, 0, 0);
780 SetTextTest(0, 0, L"", S_OK);
782 SetInternalState(L"", 0, 0, 0);
783 SetTextTest(0, 1, L"", TS_E_INVALIDPOS);
785 SetInternalState(L"0123456", 3, 3, 3);
787 SetTextTest(0, 0, L"", TS_E_INVALIDPOS);
788 SetTextTest(0, 1, L"", TS_E_INVALIDPOS);
789 SetTextTest(0, 3, L"", TS_E_INVALIDPOS);
790 SetTextTest(0, 6, L"", TS_E_INVALIDPOS);
791 SetTextTest(0, 7, L"", TS_E_INVALIDPOS);
792 SetTextTest(0, 8, L"", TS_E_INVALIDPOS);
794 SetTextTest(1, 0, L"", TS_E_INVALIDPOS);
795 SetTextTest(1, 1, L"", TS_E_INVALIDPOS);
796 SetTextTest(1, 3, L"", TS_E_INVALIDPOS);
797 SetTextTest(1, 6, L"", TS_E_INVALIDPOS);
798 SetTextTest(1, 7, L"", TS_E_INVALIDPOS);
799 SetTextTest(1, 8, L"", TS_E_INVALIDPOS);
801 SetTextTest(3, 0, L"", TS_E_INVALIDPOS);
802 SetTextTest(3, 1, L"", TS_E_INVALIDPOS);
804 SetTextTest(3, 3, L"", S_OK);
805 GetTextTest(0, -1, L"0123456", 7);
806 GetSelectionTest(3, 3);
807 SetInternalState(L"0123456", 3, 3, 3);
809 SetTextTest(3, 6, L"", S_OK);
810 GetTextTest(0, -1, L"0126", 4);
811 GetSelectionTest(3, 3);
812 SetInternalState(L"0123456", 3, 3, 3);
814 SetTextTest(3, 7, L"", S_OK);
815 GetTextTest(0, -1, L"012", 3);
816 GetSelectionTest(3, 3);
817 SetInternalState(L"0123456", 3, 3, 3);
819 SetTextTest(3, 8, L"", TS_E_INVALIDPOS);
821 SetTextTest(6, 0, L"", TS_E_INVALIDPOS);
822 SetTextTest(6, 1, L"", TS_E_INVALIDPOS);
823 SetTextTest(6, 3, L"", TS_E_INVALIDPOS);
825 SetTextTest(6, 6, L"", S_OK);
826 GetTextTest(0, -1, L"0123456", 7);
827 GetSelectionTest(6, 6);
828 SetInternalState(L"0123456", 3, 3, 3);
830 SetTextTest(6, 7, L"", S_OK);
831 GetTextTest(0, -1, L"012345", 6);
832 GetSelectionTest(6, 6);
833 SetInternalState(L"0123456", 3, 3, 3);
835 SetTextTest(6, 8, L"", TS_E_INVALIDPOS);
837 SetTextTest(7, 0, L"", TS_E_INVALIDPOS);
838 SetTextTest(7, 1, L"", TS_E_INVALIDPOS);
839 SetTextTest(7, 3, L"", TS_E_INVALIDPOS);
840 SetTextTest(7, 6, L"", TS_E_INVALIDPOS);
842 SetTextTest(7, 7, L"", S_OK);
843 GetTextTest(0, -1, L"0123456", 7);
844 GetSelectionTest(7, 7);
845 SetInternalState(L"0123456", 3, 3, 3);
847 SetTextTest(7, 8, L"", TS_E_INVALIDPOS);
849 SetInternalState(L"0123456", 3, 3, 3);
850 SetTextTest(3, 3, L"abc", S_OK);
851 GetTextTest(0, -1, L"012abc3456", 10);
852 GetSelectionTest(3, 6);
854 SetInternalState(L"0123456", 3, 3, 3);
855 SetTextTest(3, 6, L"abc", S_OK);
856 GetTextTest(0, -1, L"012abc6", 7);
857 GetSelectionTest(3, 6);
859 SetInternalState(L"0123456", 3, 3, 3);
860 SetTextTest(3, 7, L"abc", S_OK);
861 GetTextTest(0, -1, L"012abc", 6);
862 GetSelectionTest(3, 6);
864 SetInternalState(L"0123456", 3, 3, 3);
865 SetTextTest(6, 6, L"abc", S_OK);
866 GetTextTest(0, -1, L"012345abc6", 10);
867 GetSelectionTest(6, 9);
869 SetInternalState(L"0123456", 3, 3, 3);
870 SetTextTest(6, 7, L"abc", S_OK);
871 GetTextTest(0, -1, L"012345abc", 9);
872 GetSelectionTest(6, 9);
874 SetInternalState(L"0123456", 3, 3, 3);
875 SetTextTest(7, 7, L"abc", S_OK);
876 GetTextTest(0, -1, L"0123456abc", 10);
877 GetSelectionTest(7, 10);
883 DISALLOW_COPY_AND_ASSIGN(SetGetTextTestCallback);
886 TEST_F(TSFTextStoreTest, SetGetTextTest) {
887 SetGetTextTestCallback callback(text_store_);
888 EXPECT_CALL(*sink_, OnLockGranted(_))
889 .WillOnce(Invoke(&callback, &SetGetTextTestCallback::ReadLockGranted))
890 .WillOnce(Invoke(&callback,
891 &SetGetTextTestCallback::ReadWriteLockGranted));
893 wchar_t buffer[1024] = {};
894 ULONG text_buffer_copied = 0;
895 TS_RUNINFO run_info = {};
896 ULONG run_info_buffer_copied = 0;
898 EXPECT_EQ(TF_E_NOLOCK,
899 text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied,
900 &run_info, 1, &run_info_buffer_copied,
902 TS_TEXTCHANGE change = {};
903 EXPECT_EQ(TF_E_NOLOCK, text_store_->SetText(0, 0, 0, L"abc", 3, &change));
905 HRESULT result = kInvalidResult;
906 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
907 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
910 class InsertTextAtSelectionTestCallback : public TSFTextStoreTestCallback {
912 explicit InsertTextAtSelectionTestCallback(TSFTextStore* text_store)
913 : TSFTextStoreTestCallback(text_store) {}
915 HRESULT ReadLockGranted(DWORD flags) {
916 const wchar_t kBuffer[] = L"0123456789";
918 SetInternalState(L"abcedfg", 0, 0, 0);
919 InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0);
920 GetSelectionTest(0, 0);
921 InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0);
923 SetInternalState(L"abcedfg", 0, 2, 5);
924 InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 2, 5);
925 GetSelectionTest(2, 5);
926 InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 2, 5);
930 TS_TEXTCHANGE change = {};
931 EXPECT_EQ(TS_E_NOLOCK,
932 text_store_->InsertTextAtSelection(0, kBuffer, 10,
933 &start, &end, &change));
937 HRESULT ReadWriteLockGranted(DWORD flags) {
938 SetInternalState(L"abcedfg", 0, 0, 0);
940 const wchar_t kBuffer[] = L"0123456789";
941 InsertTextAtSelectionQueryOnlyTest(kBuffer, 10, 0, 0);
942 GetSelectionTest(0, 0);
943 InsertTextAtSelectionQueryOnlyTest(kBuffer, 0, 0, 0);
945 SetInternalState(L"", 0, 0, 0);
946 InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10);
947 GetSelectionTest(0, 10);
948 GetTextTest(0, -1, L"0123456789", 10);
950 SetInternalState(L"abcedfg", 0, 0, 0);
951 InsertTextAtSelectionTest(kBuffer, 10, 0, 10, 0, 0, 10);
952 GetSelectionTest(0, 10);
953 GetTextTest(0, -1, L"0123456789abcedfg", 17);
955 SetInternalState(L"abcedfg", 0, 0, 3);
956 InsertTextAtSelectionTest(kBuffer, 0, 0, 0, 0, 3, 0);
957 GetSelectionTest(0, 0);
958 GetTextTest(0, -1, L"edfg", 4);
960 SetInternalState(L"abcedfg", 0, 3, 7);
961 InsertTextAtSelectionTest(kBuffer, 10, 3, 13, 3, 7, 13);
962 GetSelectionTest(3, 13);
963 GetTextTest(0, -1, L"abc0123456789", 13);
965 SetInternalState(L"abcedfg", 0, 7, 7);
966 InsertTextAtSelectionTest(kBuffer, 10, 7, 17, 7, 7, 17);
967 GetSelectionTest(7, 17);
968 GetTextTest(0, -1, L"abcedfg0123456789", 17);
974 DISALLOW_COPY_AND_ASSIGN(InsertTextAtSelectionTestCallback);
977 TEST_F(TSFTextStoreTest, InsertTextAtSelectionTest) {
978 InsertTextAtSelectionTestCallback callback(text_store_);
979 EXPECT_CALL(*sink_, OnLockGranted(_))
980 .WillOnce(Invoke(&callback,
981 &InsertTextAtSelectionTestCallback::ReadLockGranted))
984 &InsertTextAtSelectionTestCallback::ReadWriteLockGranted));
986 HRESULT result = kInvalidResult;
987 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
988 EXPECT_EQ(S_OK, result);
989 result = kInvalidResult;
990 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
991 EXPECT_EQ(S_OK, result);
994 class ScenarioTestCallback : public TSFTextStoreTestCallback {
996 explicit ScenarioTestCallback(TSFTextStore* text_store)
997 : TSFTextStoreTestCallback(text_store) {}
999 HRESULT LockGranted1(DWORD flags) {
1000 SetSelectionTest(0, 0, S_OK);
1002 SetTextTest(0, 0, L"abc", S_OK);
1003 SetTextTest(1, 2, L"xyz", S_OK);
1005 GetTextTest(0, -1, L"axyzc", 5);
1007 composition_undelines()->clear();
1008 CompositionUnderline underline;
1009 underline.start_offset = 0;
1010 underline.end_offset = 5;
1011 underline.color = SK_ColorBLACK;
1012 underline.thick = false;
1013 composition_undelines()->push_back(underline);
1014 *edit_flag() = true;
1015 *committed_size() = 0;
1019 void SetCompositionText1(const ui::CompositionText& composition) {
1020 EXPECT_EQ(L"axyzc", composition.text);
1021 EXPECT_EQ(1, composition.selection.start());
1022 EXPECT_EQ(4, composition.selection.end());
1023 ASSERT_EQ(1, composition.underlines.size());
1024 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
1025 EXPECT_EQ(0, composition.underlines[0].start_offset);
1026 EXPECT_EQ(5, composition.underlines[0].end_offset);
1027 EXPECT_FALSE(composition.underlines[0].thick);
1030 HRESULT LockGranted2(DWORD flags) {
1031 SetTextTest(3, 4, L"ZCP", S_OK);
1032 GetTextTest(0, -1, L"axyZCPc", 7);
1034 composition_undelines()->clear();
1035 CompositionUnderline underline;
1036 underline.start_offset = 3;
1037 underline.end_offset = 5;
1038 underline.color = SK_ColorBLACK;
1039 underline.thick = true;
1040 composition_undelines()->push_back(underline);
1041 underline.start_offset = 5;
1042 underline.end_offset = 7;
1043 underline.color = SK_ColorBLACK;
1044 underline.thick = false;
1045 composition_undelines()->push_back(underline);
1047 *edit_flag() = true;
1048 *committed_size() = 3;
1053 void InsertText2(const string16& text) {
1054 EXPECT_EQ(L"axy", text);
1057 void SetCompositionText2(const ui::CompositionText& composition) {
1058 EXPECT_EQ(L"ZCPc", composition.text);
1059 EXPECT_EQ(0, composition.selection.start());
1060 EXPECT_EQ(3, composition.selection.end());
1061 ASSERT_EQ(2, composition.underlines.size());
1062 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
1063 EXPECT_EQ(0, composition.underlines[0].start_offset);
1064 EXPECT_EQ(2, composition.underlines[0].end_offset);
1065 EXPECT_TRUE(composition.underlines[0].thick);
1066 EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color);
1067 EXPECT_EQ(2, composition.underlines[1].start_offset);
1068 EXPECT_EQ(4, composition.underlines[1].end_offset);
1069 EXPECT_FALSE(composition.underlines[1].thick);
1072 HRESULT LockGranted3(DWORD flags) {
1073 GetTextTest(0, -1, L"axyZCPc", 7);
1075 composition_undelines()->clear();
1076 *edit_flag() = true;
1077 *committed_size() = 7;
1082 void InsertText3(const string16& text) {
1083 EXPECT_EQ(L"ZCPc", text);
1086 void SetCompositionText3(const ui::CompositionText& composition) {
1087 EXPECT_EQ(L"", composition.text);
1088 EXPECT_EQ(0, composition.selection.start());
1089 EXPECT_EQ(0, composition.selection.end());
1090 EXPECT_EQ(0, composition.underlines.size());
1094 DISALLOW_COPY_AND_ASSIGN(ScenarioTestCallback);
1097 TEST_F(TSFTextStoreTest, ScenarioTest) {
1098 ScenarioTestCallback callback(text_store_);
1099 EXPECT_CALL(text_input_client_, SetCompositionText(_))
1100 .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText1))
1101 .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText2))
1102 .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText3));
1104 EXPECT_CALL(text_input_client_, InsertText(_))
1105 .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText2))
1106 .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText3));
1108 EXPECT_CALL(*sink_, OnLockGranted(_))
1109 .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted1))
1110 .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted2))
1111 .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted3));
1113 // OnSelectionChange will be called once after LockGranted3().
1114 EXPECT_CALL(*sink_, OnSelectionChange())
1115 .WillOnce(Return(S_OK));
1117 // OnLayoutChange will be called once after LockGranted3().
1118 EXPECT_CALL(*sink_, OnLayoutChange(_, _))
1119 .WillOnce(Return(S_OK));
1121 // OnTextChange will be called once after LockGranted3().
1122 EXPECT_CALL(*sink_, OnTextChange(_, _))
1123 .WillOnce(Return(S_OK));
1125 HRESULT result = kInvalidResult;
1126 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1127 EXPECT_EQ(S_OK, result);
1128 result = kInvalidResult;
1129 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1130 EXPECT_EQ(S_OK, result);
1131 result = kInvalidResult;
1132 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
1133 EXPECT_EQ(S_OK, result);
1136 class GetTextExtTestCallback : public TSFTextStoreTestCallback {
1138 explicit GetTextExtTestCallback(TSFTextStore* text_store)
1139 : TSFTextStoreTestCallback(text_store),
1140 layout_prepared_character_num_(0) {}
1142 HRESULT LockGranted(DWORD flags) {
1143 SetInternalState(L"0123456789012", 0, 0, 0);
1144 layout_prepared_character_num_ = 13;
1146 TsViewCookie view_cookie = 0;
1147 EXPECT_EQ(S_OK, text_store_->GetActiveView(&view_cookie));
1148 GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
1149 GetTextExtTest(view_cookie, 0, 1, 11, 12, 20, 20);
1150 GetTextExtTest(view_cookie, 0, 2, 11, 12, 30, 20);
1151 GetTextExtTest(view_cookie, 9, 9, 100, 12, 100, 20);
1152 GetTextExtTest(view_cookie, 9, 10, 101, 12, 110, 20);
1153 GetTextExtTest(view_cookie, 10, 10, 110, 12, 110, 20);
1154 GetTextExtTest(view_cookie, 11, 11, 20, 112, 20, 120);
1155 GetTextExtTest(view_cookie, 11, 12, 21, 112, 30, 120);
1156 GetTextExtTest(view_cookie, 9, 12, 101, 12, 30, 120);
1157 GetTextExtTest(view_cookie, 9, 13, 101, 12, 40, 120);
1158 GetTextExtTest(view_cookie, 0, 13, 11, 12, 40, 120);
1159 GetTextExtTest(view_cookie, 13, 13, 40, 112, 40, 120);
1161 layout_prepared_character_num_ = 12;
1162 GetTextExtNoLayoutTest(view_cookie, 13, 13);
1164 layout_prepared_character_num_ = 0;
1165 GetTextExtNoLayoutTest(view_cookie, 0, 0);
1167 SetInternalState(L"", 0, 0, 0);
1168 GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6);
1170 // Last character is not availabe due to timing issue of async API.
1171 // In this case, we will get first character bounds instead of whole text
1173 SetInternalState(L"abc", 0, 0, 3);
1174 layout_prepared_character_num_ = 2;
1175 GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
1177 // TODO(nona, kinaba): Remove following test case after PPAPI supporting
1178 // GetCompositionCharacterBounds.
1179 SetInternalState(L"a", 0, 0, 1);
1180 layout_prepared_character_num_ = 0;
1181 GetTextExtTest(view_cookie, 0, 1, 1, 2, 4, 6);
1185 bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) {
1186 if (index >= layout_prepared_character_num_)
1188 rect->set_x((index % 10) * 10 + 11);
1189 rect->set_y((index / 10) * 100 + 12);
1191 rect->set_height(8);
1195 gfx::Rect GetCaretBounds() {
1196 return gfx::Rect(1, 2, 3, 4);
1200 uint32 layout_prepared_character_num_;
1202 DISALLOW_COPY_AND_ASSIGN(GetTextExtTestCallback);
1205 TEST_F(TSFTextStoreTest, GetTextExtTest) {
1206 GetTextExtTestCallback callback(text_store_);
1207 EXPECT_CALL(text_input_client_, GetCaretBounds())
1208 .WillRepeatedly(Invoke(&callback,
1209 &GetTextExtTestCallback::GetCaretBounds));
1211 EXPECT_CALL(text_input_client_, GetCompositionCharacterBounds(_, _))
1214 &GetTextExtTestCallback::GetCompositionCharacterBounds));
1216 EXPECT_CALL(*sink_, OnLockGranted(_))
1217 .WillOnce(Invoke(&callback, &GetTextExtTestCallback::LockGranted));
1219 HRESULT result = kInvalidResult;
1220 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result));
1221 EXPECT_EQ(S_OK, result);
1224 TEST_F(TSFTextStoreTest, RequestSupportedAttrs) {
1225 EXPECT_CALL(text_input_client_, GetTextInputType())
1226 .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT));
1227 EXPECT_CALL(text_input_client_, GetTextInputMode())
1228 .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT));
1230 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 1, NULL));
1232 const TS_ATTRID kUnknownAttributes[] = {GUID_NULL};
1233 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(
1234 0, arraysize(kUnknownAttributes), kUnknownAttributes))
1235 << "Must fail for unknown attributes";
1237 const TS_ATTRID kAttributes[] = {GUID_NULL, GUID_PROP_INPUTSCOPE, GUID_NULL};
1238 EXPECT_EQ(S_OK, text_store_->RequestSupportedAttrs(
1239 0, arraysize(kAttributes), kAttributes))
1240 << "InputScope must be supported";
1243 SCOPED_TRACE("Check if RequestSupportedAttrs fails while focus is lost");
1244 // Emulate focus lost
1245 text_store_->SetFocusedTextInputClient(NULL, NULL);
1246 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(0, 0, NULL));
1247 EXPECT_HRESULT_FAILED(text_store_->RequestSupportedAttrs(
1248 0, arraysize(kAttributes), kAttributes));
1252 TEST_F(TSFTextStoreTest, RetrieveRequestedAttrs) {
1253 EXPECT_CALL(text_input_client_, GetTextInputType())
1254 .WillRepeatedly(Return(TEXT_INPUT_TYPE_TEXT));
1255 EXPECT_CALL(text_input_client_, GetTextInputMode())
1256 .WillRepeatedly(Return(TEXT_INPUT_MODE_DEFAULT));
1258 ULONG num_copied = 0xfffffff;
1259 EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs(
1260 1, NULL, &num_copied));
1263 SCOPED_TRACE("Make sure if InputScope is supported");
1264 TS_ATTRVAL buffer[2] = {};
1265 num_copied = 0xfffffff;
1266 ASSERT_EQ(S_OK, text_store_->RetrieveRequestedAttrs(
1267 arraysize(buffer), buffer, &num_copied));
1268 bool input_scope_found = false;
1269 for (size_t i = 0; i < num_copied; ++i) {
1270 base::win::ScopedVariant variant;
1271 // Move ownership from |buffer[i].varValue| to |variant|.
1272 std::swap(*variant.Receive(), buffer[i].varValue);
1273 if (IsEqualGUID(buffer[i].idAttr, GUID_PROP_INPUTSCOPE)) {
1274 EXPECT_EQ(VT_UNKNOWN, variant.type());
1275 base::win::ScopedComPtr<ITfInputScope> input_scope;
1276 EXPECT_HRESULT_SUCCEEDED(input_scope.QueryFrom((&variant)->punkVal));
1277 input_scope_found = true;
1278 // we do not break here to clean up all the retrieved VARIANTs.
1281 EXPECT_TRUE(input_scope_found);
1284 SCOPED_TRACE("Check if RetrieveRequestedAttrs fails while focus is lost");
1285 // Emulate focus lost
1286 text_store_->SetFocusedTextInputClient(NULL, NULL);
1287 num_copied = 0xfffffff;
1288 TS_ATTRVAL buffer[2] = {};
1289 EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs(
1290 arraysize(buffer), buffer, &num_copied));