Home | History | Annotate | Download | only in win
      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