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