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