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