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