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