Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: ui/base/win/tsf_text_store_unittest.cc

Issue 10831403: TsfTextStore implementation. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Add unit tests. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/win/tsf_text_store.cc ('k') | ui/ui_unittests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/base/win/tsf_text_store.h"
6
7 #include "base/win/scoped_com_initializer.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "ui/base/ime/text_input_client.h"
11 #include "ui/gfx/rect.h"
12
13 using testing::_;
14 using testing::Invoke;
15 using testing::Return;
16
17 namespace ui {
18
19 namespace {
20 class MockTextInputClient : public TextInputClient {
21 public:
22 ~MockTextInputClient() {}
23 MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&));
24 MOCK_METHOD0(ConfirmCompositionText, void());
25 MOCK_METHOD0(ClearCompositionText, void());
26 MOCK_METHOD1(InsertText, void(const string16&));
27 MOCK_METHOD2(InsertChar, void(char16, int));
28 MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType());
29 MOCK_CONST_METHOD0(CanComposeInline, bool());
30 MOCK_METHOD0(GetCaretBounds, gfx::Rect());
31 MOCK_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*));
32 MOCK_METHOD0(HasCompositionText, bool());
33 MOCK_METHOD1(GetTextRange, bool(ui::Range*));
34 MOCK_METHOD1(GetCompositionTextRange, bool(ui::Range*));
35 MOCK_METHOD1(GetSelectionRange, bool(ui::Range*));
36 MOCK_METHOD1(SetSelectionRange, bool(const ui::Range&));
37 MOCK_METHOD1(DeleteRange, bool(const ui::Range&));
38 MOCK_METHOD2(GetTextFromRange, bool(const ui::Range&, string16*));
39 MOCK_METHOD0(OnInputMethodChanged, void());
40 MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment,
41 bool(base::i18n::TextDirection));
42 };
43
44 class MockStoreACPSink : public ITextStoreACPSink {
45 public:
46 MockStoreACPSink() : ref_count_(0) {
47 }
48
49 // IUnknown
50 virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
51 return InterlockedIncrement(&ref_count_);
52 }
53 virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
54 const LONG count = InterlockedDecrement(&ref_count_);
55 if (!count) {
56 delete this;
57 return 0;
58 }
59 return static_cast<ULONG>(count);
60 }
61 virtual HRESULT STDMETHODCALLTYPE QueryInterface(
62 REFIID iid, void** report) OVERRIDE {
63 if (iid == IID_IUnknown || iid == IID_ITextStoreACPSink) {
64 *report = static_cast<ITextStoreACPSink*>(this);
65 } else {
66 *report = NULL;
67 return E_NOINTERFACE;
68 }
69 AddRef();
70 return S_OK;
71 }
72
73 // ITextStoreACPSink
74 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnTextChange,
75 HRESULT(DWORD, const TS_TEXTCHANGE*));
76 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnSelectionChange,
77 HRESULT());
78 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLayoutChange,
79 HRESULT(TsLayoutCode, TsViewCookie));
80 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStatusChange,
81 HRESULT(DWORD));
82 MOCK_METHOD4_WITH_CALLTYPE(STDMETHODCALLTYPE, OnAttrsChange,
83 HRESULT(LONG, LONG, ULONG, const TS_ATTRID*));
84 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLockGranted,
85 HRESULT(DWORD));
86 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStartEditTransaction,
87 HRESULT());
88 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnEndEditTransaction,
89 HRESULT());
90
91 private:
92 ~MockStoreACPSink() {
93 }
94 volatile LONG ref_count_;
95 };
96
97 } // namespace
98
99 class TsfTextStoreTest : public testing::Test {
100 protected:
101 virtual void SetUp() OVERRIDE {
102 text_store_ = new TsfTextStore();
103 text_store_->AddRef();
104 sink_ = new MockStoreACPSink();
105 sink_->AddRef();
106 EXPECT_EQ(S_OK,
107 text_store_->AdviseSink(IID_ITextStoreACPSink,
Yohei Yukawa 2012/08/23 10:16:44 Indent?
horo 2012/08/23 10:36:18 Done.
108 sink_, TS_AS_ALL_SINKS));
109 text_store_->SetFocusedTextInputClient(0, &text_input_client_);
110 }
111
112 virtual void TearDown() OVERRIDE {
113 EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_));
114 sink_->Release();
115 text_store_->Release();
116 }
117
118 base::win::ScopedCOMInitializer com_initializer_;
119 MockTextInputClient text_input_client_;
120 TsfTextStore* text_store_;
121 MockStoreACPSink* sink_;
122 };
123
124 class TsfTextStoreTestCallback {
125 public:
126 explicit TsfTextStoreTestCallback(TsfTextStore* text_store)
127 : text_store_(text_store) {
128 CHECK(text_store_);
129 }
130 virtual ~TsfTextStoreTestCallback() {}
131
132 protected:
133 // Accessros to the internal state of TsfTextStore.
134 bool* edit_flag() { return &text_store_->edit_flag_; }
135 string16* string_buffer() { return &text_store_->string_buffer_; }
136 size_t* committed_size() { return &text_store_->committed_size_; }
137 Range* selection() { return &text_store_->selection_; }
138 CompositionUnderlines* composition_undelines() {
139 return &text_store_->composition_undelines_;
140 }
141
142 TsfTextStore* text_store_;
143 };
144
145 class SelectionTestCallback : public TsfTextStoreTestCallback {
146 public:
147 explicit SelectionTestCallback(TsfTextStore* text_store)
148 : TsfTextStoreTestCallback(text_store) {
149 }
150
151 HRESULT ReadLockGranted(DWORD flags) {
152 *string_buffer() = L"";
153 *committed_size() = 0;
154 selection()->set_start(0);
155 selection()->set_end(0);
156
157 GetSelectionTest(0, 0);
158 SetSelectionTest(0, 0, TF_E_NOLOCK);
159
160 *string_buffer() = L"012345";
161 *committed_size() = 0;
162 selection()->set_start(0);
163 selection()->set_end(3);
164
165 GetSelectionTest(0, 3);
166 SetSelectionTest(0, 0, TF_E_NOLOCK);
167
168 return S_OK;
169 }
170
171 HRESULT ReadWriteLockGranted(DWORD flags) {
172 *string_buffer() = L"";
173 *committed_size() = 0;
174 selection()->set_start(0);
175 selection()->set_end(0);
176
177 SetSelectionTest(0, 0, S_OK);
178 GetSelectionTest(0, 0);
179 SetSelectionTest(0, 1, TF_E_INVALIDPOS);
180 GetSelectionTest(0, 0);
181 SetSelectionTest(1, 0, TF_E_INVALIDPOS);
182 GetSelectionTest(0, 0);
183 SetSelectionTest(1, 1, TF_E_INVALIDPOS);
184 GetSelectionTest(0, 0);
185
186 *string_buffer() = L"012345";
187 *committed_size() = 0;
188 selection()->set_start(0);
189 selection()->set_end(0);
190
191 SetSelectionTest(0, 0, S_OK);
192 GetSelectionTest(0, 0);
193 SetSelectionTest(0, 3, S_OK);
194 GetSelectionTest(0, 3);
195 SetSelectionTest(0, 6, S_OK);
196 GetSelectionTest(0, 6);
197 SetSelectionTest(0, 7, TF_E_INVALIDPOS);
198 GetSelectionTest(0, 6);
199
200 SetSelectionTest(3, 0, TF_E_INVALIDPOS);
201 GetSelectionTest(0, 6);
202 SetSelectionTest(3, 3, S_OK);
203 GetSelectionTest(3, 3);
204 SetSelectionTest(3, 6, S_OK);
205 GetSelectionTest(3, 6);
206 SetSelectionTest(3, 7, TF_E_INVALIDPOS);
207 GetSelectionTest(3, 6);
208
209 SetSelectionTest(6, 0, TF_E_INVALIDPOS);
210 GetSelectionTest(3, 6);
211 SetSelectionTest(6, 3, TF_E_INVALIDPOS);
212 GetSelectionTest(3, 6);
213 SetSelectionTest(6, 6, S_OK);
214 GetSelectionTest(6, 6);
215 SetSelectionTest(6, 7, TF_E_INVALIDPOS);
216 GetSelectionTest(6, 6);
217
218 return S_OK;
219 }
220
221 private:
222 void SetSelectionTest(LONG acp_start, LONG acp_end, HRESULT expected_result) {
223 TS_SELECTION_ACP selection;
224 selection.acpStart = acp_start;
225 selection.acpEnd = acp_end;
226 selection.style.ase = TS_AE_NONE;
227 selection.style.fInterimChar = 0;
228 EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection));
229 }
230
231 void GetSelectionTest(LONG expected_acp_start, LONG expected_acp_end) {
232 TS_SELECTION_ACP selection;
233 ULONG fetched;
234 EXPECT_EQ(S_OK, text_store_->GetSelection(0, 1, &selection, &fetched));
235 EXPECT_EQ(1, fetched);
236 EXPECT_EQ(expected_acp_start, selection.acpStart);
237 EXPECT_EQ(expected_acp_end, selection.acpEnd);
238 }
239 };
240
241 TEST_F(TsfTextStoreTest, GetStatus) {
242 TS_STATUS status;
243 EXPECT_EQ(S_OK, text_store_->GetStatus(&status));
244 EXPECT_EQ(0, status.dwDynamicFlags);
245 EXPECT_EQ(TS_SS_NOHIDDENTEXT, status.dwStaticFlags);
246 }
247
248 TEST_F(TsfTextStoreTest, SetGetSelectionTest) {
249 SelectionTestCallback callback(text_store_);
250 EXPECT_CALL(*sink_, OnLockGranted(_))
251 .WillOnce(Invoke(&callback, &SelectionTestCallback::ReadLockGranted))
252 .WillOnce(Invoke(&callback,
253 &SelectionTestCallback::ReadWriteLockGranted));
254
255 TS_SELECTION_ACP selection_buffer;
256 ULONG fetched_count;
257 EXPECT_EQ(TS_E_NOLOCK,
258 text_store_->GetSelection(0, 1, &selection_buffer,
259 &fetched_count));
260
261 HRESULT result;
262 EXPECT_EQ(S_OK,
263 text_store_->RequestLock(TS_LF_READ, &result));
264 EXPECT_EQ(S_OK,
265 text_store_->RequestLock(TS_LF_READWRITE, &result));
266 }
267
268 class SenarioTestCallback : public TsfTextStoreTestCallback {
269 public:
270 explicit SenarioTestCallback(TsfTextStore* text_store)
271 : TsfTextStoreTestCallback(text_store) {
272 }
273
274 HRESULT LockGranted1(DWORD flags) {
275 TS_SELECTION_ACP selection;
276 selection.acpStart = 0;
277 selection.acpEnd = 0;
278 selection.style.ase = TS_AE_NONE;
279 selection.style.fInterimChar = 0;
280 EXPECT_EQ(S_OK,
281 text_store_->SetSelection(1, &selection));
282 TS_TEXTCHANGE change;
283 EXPECT_EQ(S_OK,
284 text_store_->SetText(0, 0, 0, L"abc", 3, &change));
285 EXPECT_EQ(0, change.acpStart);
286 EXPECT_EQ(0, change.acpOldEnd);
287 EXPECT_EQ(3, change.acpNewEnd);
288
289 EXPECT_EQ(S_OK,
290 text_store_->SetText(0, 1, 2, L"xyz", 3, &change));
291 EXPECT_EQ(1, change.acpStart);
292 EXPECT_EQ(2, change.acpOldEnd);
293 EXPECT_EQ(4, change.acpNewEnd);
294
295 wchar_t buffer[1024];
296 ULONG text_buffer_copied;
297 TS_RUNINFO run_info;
298 ULONG run_info_buffer_copied;
299 LONG next_acp;
300 EXPECT_EQ(S_OK,
301 text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied,
302 &run_info, 1, &run_info_buffer_copied,
303 &next_acp));
304 EXPECT_EQ(5, text_buffer_copied);
305 EXPECT_EQ(L"axyzc", string16(buffer, buffer + text_buffer_copied));
306 EXPECT_EQ(1, run_info_buffer_copied);
307 EXPECT_EQ(TS_RT_PLAIN, run_info.type);
308 EXPECT_EQ(5, run_info.uCount);
309 EXPECT_EQ(5, next_acp);
310
311 composition_undelines()->clear();
312 CompositionUnderline underline;
313 underline.start_offset = 0;
314 underline.end_offset = 5;
315 underline.color = SK_ColorBLACK;
316 underline.thick = false;
317 composition_undelines()->push_back(underline);
318 *edit_flag() = true;
319 *committed_size() = 0;
320 return S_OK;
321 }
322
323 void SetCompositionText1(const ui::CompositionText& composition) {
324 EXPECT_EQ(L"axyzc", composition.text);
325 EXPECT_EQ(1, composition.selection.start());
326 EXPECT_EQ(4, composition.selection.end());
327 ASSERT_EQ(1, composition.underlines.size());
328 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
329 EXPECT_EQ(0, composition.underlines[0].start_offset);
330 EXPECT_EQ(5, composition.underlines[0].end_offset);
331 EXPECT_FALSE(composition.underlines[0].thick);
332 }
333
334 HRESULT LockGranted2(DWORD flags) {
335 TS_TEXTCHANGE change;
336 EXPECT_EQ(S_OK,
337 text_store_->SetText(0, 3, 4, L"ZCP", 3, &change));
338 EXPECT_EQ(3, change.acpStart);
339 EXPECT_EQ(4, change.acpOldEnd);
340 EXPECT_EQ(6, change.acpNewEnd);
341
342 wchar_t buffer[1024];
343 ULONG text_buffer_copied;
344 TS_RUNINFO run_info;
345 ULONG run_info_buffer_copied;
346 LONG next_acp;
347 EXPECT_EQ(S_OK,
348 text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied,
349 &run_info, 1, &run_info_buffer_copied,
350 &next_acp));
351 EXPECT_EQ(7, text_buffer_copied);
352 EXPECT_EQ(L"axyZCPc", string16(buffer, buffer + text_buffer_copied));
353 EXPECT_EQ(1, run_info_buffer_copied);
354 EXPECT_EQ(TS_RT_PLAIN, run_info.type);
355 EXPECT_EQ(7, run_info.uCount);
356 EXPECT_EQ(7, next_acp);
357
358 composition_undelines()->clear();
359 CompositionUnderline underline;
360 underline.start_offset = 3;
361 underline.end_offset = 5;
362 underline.color = SK_ColorBLACK;
363 underline.thick = true;
364 composition_undelines()->push_back(underline);
365 underline.start_offset = 5;
366 underline.end_offset = 7;
367 underline.color = SK_ColorBLACK;
368 underline.thick = false;
369 composition_undelines()->push_back(underline);
370
371 *edit_flag() = true;
372 *committed_size() = 3;
373
374 return S_OK;
375 }
376
377 void InsertText2(const string16& text) {
378 EXPECT_EQ(L"axy", text);
379 }
380
381 void SetCompositionText2(const ui::CompositionText& composition) {
382 EXPECT_EQ(L"ZCPc", composition.text);
383 EXPECT_EQ(0, composition.selection.start());
384 EXPECT_EQ(3, composition.selection.end());
385 ASSERT_EQ(2, composition.underlines.size());
386 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color);
387 EXPECT_EQ(0, composition.underlines[0].start_offset);
388 EXPECT_EQ(2, composition.underlines[0].end_offset);
389 EXPECT_TRUE(composition.underlines[0].thick);
390 EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color);
391 EXPECT_EQ(2, composition.underlines[1].start_offset);
392 EXPECT_EQ(4, composition.underlines[1].end_offset);
393 EXPECT_FALSE(composition.underlines[1].thick);
394 }
395
396 HRESULT LockGranted3(DWORD flags) {
397 wchar_t buffer[1024];
398 ULONG text_buffer_copied;
399 TS_RUNINFO run_info;
400 ULONG run_info_buffer_copied;
401 LONG next_acp;
402 EXPECT_EQ(S_OK,
403 text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied,
404 &run_info, 1, &run_info_buffer_copied,
405 &next_acp));
406 EXPECT_EQ(7, text_buffer_copied);
407 EXPECT_EQ(L"axyZCPc", string16(buffer, buffer + text_buffer_copied));
408 EXPECT_EQ(1, run_info_buffer_copied);
409 EXPECT_EQ(TS_RT_PLAIN, run_info.type);
410 EXPECT_EQ(7, run_info.uCount);
411 EXPECT_EQ(7, next_acp);
412
413 composition_undelines()->clear();
414 *edit_flag() = true;
415 *committed_size() = 7;
416
417 return S_OK;
418 }
419
420 void InsertText3(const string16& text) {
421 EXPECT_EQ(L"ZCPc", text);
422 }
423
424 void SetCompositionText3(const ui::CompositionText& composition) {
425 EXPECT_EQ(L"", composition.text);
426 EXPECT_EQ(0, composition.selection.start());
427 EXPECT_EQ(0, composition.selection.end());
428 EXPECT_EQ(0, composition.underlines.size());
429 }
430 };
431
432 TEST_F(TsfTextStoreTest, SenarioTest) {
433 SenarioTestCallback callback(text_store_);
434 EXPECT_CALL(text_input_client_, SetCompositionText(_))
435 .WillOnce(Invoke(&callback, &SenarioTestCallback::SetCompositionText1))
436 .WillOnce(Invoke(&callback, &SenarioTestCallback::SetCompositionText2))
437 .WillOnce(Invoke(&callback, &SenarioTestCallback::SetCompositionText3));
438
439 EXPECT_CALL(text_input_client_, InsertText(_))
440 .WillOnce(Invoke(&callback, &SenarioTestCallback::InsertText2))
441 .WillOnce(Invoke(&callback, &SenarioTestCallback::InsertText3));
442
443 EXPECT_CALL(*sink_, OnLockGranted(_))
444 .WillOnce(Invoke(&callback, &SenarioTestCallback::LockGranted1))
445 .WillOnce(Invoke(&callback, &SenarioTestCallback::LockGranted2))
446 .WillOnce(Invoke(&callback, &SenarioTestCallback::LockGranted3));
447
448 // OnSelectionChange will be called once in LockGranted3().
449 EXPECT_CALL(*sink_, OnSelectionChange())
450 .WillOnce(Return(S_OK));
451
452 // OnLayoutChange will be called once in LockGranted3().
453 EXPECT_CALL(*sink_, OnLayoutChange(_, _))
454 .WillOnce(Return(S_OK));
455
456 // OnTextChange will be called once in LockGranted3().
457 EXPECT_CALL(*sink_, OnTextChange(_, _))
458 .WillOnce(Return(S_OK));
459
460 HRESULT result;
461 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
462 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
463 EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
464 }
465
466 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/win/tsf_text_store.cc ('k') | ui/ui_unittests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698