Index: ui/base/win/tsf_text_store_unittest.cc |
diff --git a/ui/base/win/tsf_text_store_unittest.cc b/ui/base/win/tsf_text_store_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aa1e297d10542dc1db0ea4cc681495423e6498dd |
--- /dev/null |
+++ b/ui/base/win/tsf_text_store_unittest.cc |
@@ -0,0 +1,1123 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/base/win/tsf_text_store.h" |
+ |
+#include "base/win/scoped_com_initializer.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "ui/base/ime/text_input_client.h" |
+#include "ui/gfx/rect.h" |
+ |
+using testing::_; |
+using testing::Invoke; |
+using testing::Return; |
+ |
+namespace ui { |
+ |
+namespace { |
+ |
+class MockTextInputClient : public TextInputClient { |
+ public: |
+ ~MockTextInputClient() {} |
+ MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&)); |
+ MOCK_METHOD0(ConfirmCompositionText, void()); |
+ MOCK_METHOD0(ClearCompositionText, void()); |
+ MOCK_METHOD1(InsertText, void(const string16&)); |
+ MOCK_METHOD2(InsertChar, void(char16, int)); |
+ MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType()); |
+ MOCK_CONST_METHOD0(CanComposeInline, bool()); |
+ MOCK_METHOD0(GetCaretBounds, gfx::Rect()); |
+ MOCK_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*)); |
+ MOCK_METHOD0(HasCompositionText, bool()); |
+ MOCK_METHOD1(GetTextRange, bool(ui::Range*)); |
+ MOCK_METHOD1(GetCompositionTextRange, bool(ui::Range*)); |
+ MOCK_METHOD1(GetSelectionRange, bool(ui::Range*)); |
+ MOCK_METHOD1(SetSelectionRange, bool(const ui::Range&)); |
+ MOCK_METHOD1(DeleteRange, bool(const ui::Range&)); |
+ MOCK_METHOD2(GetTextFromRange, bool(const ui::Range&, string16*)); |
+ MOCK_METHOD0(OnInputMethodChanged, void()); |
+ MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment, |
+ bool(base::i18n::TextDirection)); |
+}; |
+ |
+class MockStoreACPSink : public ITextStoreACPSink { |
+ public: |
+ MockStoreACPSink() : ref_count_(0) { |
+ } |
+ |
+ // IUnknown |
+ virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE { |
+ return InterlockedIncrement(&ref_count_); |
+ } |
+ virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE { |
+ const LONG count = InterlockedDecrement(&ref_count_); |
+ if (!count) { |
+ delete this; |
+ return 0; |
+ } |
+ return static_cast<ULONG>(count); |
+ } |
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface( |
+ REFIID iid, void** report) OVERRIDE { |
+ if (iid == IID_IUnknown || iid == IID_ITextStoreACPSink) { |
+ *report = static_cast<ITextStoreACPSink*>(this); |
+ } else { |
+ *report = NULL; |
+ return E_NOINTERFACE; |
+ } |
+ AddRef(); |
+ return S_OK; |
+ } |
+ |
+ // ITextStoreACPSink |
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnTextChange, |
+ HRESULT(DWORD, const TS_TEXTCHANGE*)); |
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnSelectionChange, |
+ HRESULT()); |
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLayoutChange, |
+ HRESULT(TsLayoutCode, TsViewCookie)); |
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStatusChange, |
+ HRESULT(DWORD)); |
+ MOCK_METHOD4_WITH_CALLTYPE(STDMETHODCALLTYPE, OnAttrsChange, |
+ HRESULT(LONG, LONG, ULONG, const TS_ATTRID*)); |
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, OnLockGranted, |
+ HRESULT(DWORD)); |
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnStartEditTransaction, |
+ HRESULT()); |
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, OnEndEditTransaction, |
+ HRESULT()); |
+ |
+ private: |
+ ~MockStoreACPSink() { |
+ } |
+ |
+ volatile LONG ref_count_; |
+}; |
+ |
+} // namespace |
+ |
+class TsfTextStoreTest : public testing::Test { |
+ protected: |
+ virtual void SetUp() OVERRIDE { |
+ text_store_ = new TsfTextStore(); |
+ text_store_->AddRef(); |
+ sink_ = new MockStoreACPSink(); |
+ sink_->AddRef(); |
+ EXPECT_EQ(S_OK, text_store_->AdviseSink(IID_ITextStoreACPSink, |
+ sink_, TS_AS_ALL_SINKS)); |
+ text_store_->SetFocusedTextInputClient(0, &text_input_client_); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { |
+ EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_)); |
+ sink_->Release(); |
+ text_store_->Release(); |
+ } |
+ |
+ base::win::ScopedCOMInitializer com_initializer_; |
+ MockTextInputClient text_input_client_; |
+ TsfTextStore* text_store_; |
+ MockStoreACPSink* sink_; |
+}; |
+ |
+class TsfTextStoreTestCallback { |
+ public: |
+ explicit TsfTextStoreTestCallback(TsfTextStore* text_store) |
+ : text_store_(text_store) { |
+ CHECK(text_store_); |
+ } |
+ virtual ~TsfTextStoreTestCallback() {} |
+ |
+ protected: |
+ // Accessors to the internal state of TsfTextStore. |
+ bool* edit_flag() { return &text_store_->edit_flag_; } |
+ string16* string_buffer() { return &text_store_->string_buffer_; } |
+ size_t* committed_size() { return &text_store_->committed_size_; } |
+ Range* selection() { return &text_store_->selection_; } |
+ CompositionUnderlines* composition_undelines() { |
+ return &text_store_->composition_undelines_; |
+ } |
+ |
+ void SetInternalState(const string16& new_string_buffer, |
+ LONG new_committed_size, LONG new_selection_start, |
+ LONG new_selection_end) { |
+ ASSERT_LE(0, new_committed_size); |
+ ASSERT_LE(new_committed_size, new_selection_start); |
+ ASSERT_LE(new_selection_start, new_selection_end); |
+ ASSERT_LE(new_selection_end, static_cast<LONG>(new_string_buffer.size())); |
+ *string_buffer() = new_string_buffer; |
+ *committed_size() = new_committed_size; |
+ selection()->set_start(new_selection_start); |
+ selection()->set_end(new_selection_end); |
+ } |
+ |
+ bool HasReadLock() const { return text_store_->HasReadLock(); } |
+ bool HasReadWriteLock() const { return text_store_->HasReadWriteLock(); } |
+ |
+ void GetSelectionTest(LONG expected_acp_start, LONG expected_acp_end) { |
+ TS_SELECTION_ACP selection; |
+ ULONG fetched; |
+ EXPECT_EQ(S_OK, text_store_->GetSelection(0, 1, &selection, &fetched)); |
+ EXPECT_EQ(1, fetched); |
+ EXPECT_EQ(expected_acp_start, selection.acpStart); |
+ EXPECT_EQ(expected_acp_end, selection.acpEnd); |
+ } |
+ |
+ void SetSelectionTest(LONG acp_start, LONG acp_end, HRESULT expected_result) { |
+ TS_SELECTION_ACP selection; |
+ selection.acpStart = acp_start; |
+ selection.acpEnd = acp_end; |
+ selection.style.ase = TS_AE_NONE; |
+ selection.style.fInterimChar = 0; |
+ EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection)); |
+ if (expected_result == S_OK) { |
+ GetSelectionTest(acp_start, acp_end); |
+ } |
+ } |
+ |
+ void SetTextTest(LONG acp_start, LONG acp_end, |
+ const string16& text, HRESULT error_code) { |
+ TS_TEXTCHANGE change; |
+ ASSERT_EQ(error_code, |
+ text_store_->SetText(0, acp_start, acp_end, |
+ text.c_str(), text.size(), &change)); |
+ if (error_code == S_OK) { |
+ EXPECT_EQ(acp_start, change.acpStart); |
+ EXPECT_EQ(acp_end, change.acpOldEnd); |
+ EXPECT_EQ(acp_start + text.size(), change.acpNewEnd); |
+ } |
+ } |
+ |
+ void GetTextTest(LONG acp_start, LONG acp_end, |
+ const string16& expected_string, |
+ LONG expected_next_acp) { |
+ wchar_t buffer[1024]; |
+ ULONG text_buffer_copied; |
+ TS_RUNINFO run_info; |
+ ULONG run_info_buffer_copied; |
+ LONG next_acp; |
+ ASSERT_EQ(S_OK, |
+ text_store_->GetText(acp_start, acp_end, buffer, 1024, |
+ &text_buffer_copied, |
+ &run_info, 1, &run_info_buffer_copied, |
+ &next_acp)); |
+ ASSERT_EQ(expected_string.size(), text_buffer_copied); |
+ EXPECT_EQ(expected_string, string16(buffer, buffer + text_buffer_copied)); |
+ EXPECT_EQ(1, run_info_buffer_copied); |
+ EXPECT_EQ(expected_string.size(), run_info.uCount); |
+ EXPECT_EQ(TS_RT_PLAIN, run_info.type); |
+ EXPECT_EQ(expected_next_acp, next_acp); |
+ } |
+ |
+ void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) { |
+ wchar_t buffer[1024]; |
+ ULONG text_buffer_copied; |
+ TS_RUNINFO run_info; |
+ ULONG run_info_buffer_copied; |
+ LONG next_acp; |
+ EXPECT_EQ(error_code, |
+ text_store_->GetText(acp_start, acp_end, buffer, 1024, |
+ &text_buffer_copied, |
+ &run_info, 1, &run_info_buffer_copied, |
+ &next_acp)); |
+ } |
+ |
+ void InsertTextAtSelectionTest(const wchar_t* buffer, ULONG buffer_size, |
+ LONG expected_start, LONG expected_end, |
+ LONG expected_change_start, |
+ LONG expected_change_old_end, |
+ LONG expected_change_new_end) { |
+ LONG start, end; |
+ TS_TEXTCHANGE change; |
+ EXPECT_EQ(S_OK, |
+ text_store_->InsertTextAtSelection(0, buffer, buffer_size, |
+ &start, &end, &change)); |
+ EXPECT_EQ(expected_start, start); |
+ EXPECT_EQ(expected_end, end); |
+ EXPECT_EQ(expected_change_start, change.acpStart); |
+ EXPECT_EQ(expected_change_old_end, change.acpOldEnd); |
+ EXPECT_EQ(expected_change_new_end, change.acpNewEnd); |
+ } |
+ |
+ void InsertTextAtSelectionQueryOnlyTest(const wchar_t* buffer, |
+ ULONG buffer_size, |
+ LONG expected_start, |
+ LONG expected_end) { |
+ LONG start, end; |
+ EXPECT_EQ(S_OK, |
+ text_store_->InsertTextAtSelection(TS_IAS_QUERYONLY, buffer, |
+ buffer_size, &start, &end, |
+ NULL)); |
+ EXPECT_EQ(expected_start, start); |
+ EXPECT_EQ(expected_end, end); |
+ } |
+ |
+ void GetTextExtTest(TsViewCookie view_cookie, LONG acp_start, LONG acp_end, |
+ LONG expected_left, LONG expected_top, |
+ LONG expected_right, LONG expected_bottom) { |
+ RECT rect; |
+ BOOL clipped; |
+ EXPECT_EQ(S_OK, text_store_->GetTextExt(view_cookie, acp_start, acp_end, |
+ &rect, &clipped)); |
+ EXPECT_EQ(expected_left, rect.left); |
+ EXPECT_EQ(expected_top, rect.top); |
+ EXPECT_EQ(expected_right, rect.right); |
+ EXPECT_EQ(expected_bottom, rect.bottom); |
+ EXPECT_EQ(FALSE, clipped); |
+ } |
+ |
+ void GetTextExtNoLayoutTest(TsViewCookie view_cookie, LONG acp_start, |
+ LONG acp_end) { |
+ RECT rect; |
+ BOOL clipped; |
+ EXPECT_EQ(TS_E_NOLAYOUT, |
+ text_store_->GetTextExt(view_cookie, acp_start, acp_end, |
+ &rect, &clipped)); |
+ } |
+ |
+ TsfTextStore* text_store_; |
+}; |
+ |
+TEST_F(TsfTextStoreTest, GetStatusTest) { |
+ TS_STATUS status; |
+ EXPECT_EQ(S_OK, text_store_->GetStatus(&status)); |
+ EXPECT_EQ(0, status.dwDynamicFlags); |
+ EXPECT_EQ(TS_SS_NOHIDDENTEXT, status.dwStaticFlags); |
+} |
+ |
+ |
+class SyncRequestLockTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit SyncRequestLockTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store) { |
+ } |
+ |
+ HRESULT LockGranted1(DWORD flags) { |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_FALSE(HasReadWriteLock()); |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted2(DWORD flags) { |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted3(DWORD flags) { |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_FALSE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(TS_E_SYNCHRONOUS, result); |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted4(DWORD flags) { |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_FALSE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, |
+ text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(TS_E_SYNCHRONOUS, result); |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted5(DWORD flags) { |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(TS_E_SYNCHRONOUS, result); |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted6(DWORD flags) { |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, |
+ text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(TS_E_SYNCHRONOUS, result); |
+ return S_OK; |
+ } |
+}; |
+ |
+TEST_F(TsfTextStoreTest, SynchronousRequestLockTest) { |
+ SyncRequestLockTestCallback callback(text_store_); |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted1)) |
+ .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted2)) |
+ .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted3)) |
+ .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted4)) |
+ .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted5)) |
+ .WillOnce(Invoke(&callback, &SyncRequestLockTestCallback::LockGranted6)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(S_OK, result); |
+ EXPECT_EQ(S_OK, |
+ text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(S_OK, result); |
+ |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(S_OK, result); |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(S_OK, result); |
+ |
+ EXPECT_EQ(S_OK, |
+ text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(S_OK, result); |
+ EXPECT_EQ(S_OK, |
+ text_store_->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &result)); |
+ EXPECT_EQ(S_OK, result); |
+} |
+ |
+class AsyncRequestLockTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit AsyncRequestLockTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store), |
+ state_(0) { |
+ } |
+ |
+ HRESULT LockGranted1(DWORD flags) { |
+ EXPECT_EQ(0, state_); |
+ state_ = 1; |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_FALSE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+ EXPECT_EQ(TS_S_ASYNC, result); |
+ EXPECT_EQ(1, state_); |
+ state_ = 2; |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted2(DWORD flags) { |
+ EXPECT_EQ(2, state_); |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_FALSE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+ EXPECT_EQ(TS_S_ASYNC, result); |
+ EXPECT_EQ(2, state_); |
+ state_ = 3; |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted3(DWORD flags) { |
+ EXPECT_EQ(3, state_); |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+ EXPECT_EQ(TS_S_ASYNC, result); |
+ EXPECT_EQ(3, state_); |
+ state_ = 4; |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted4(DWORD flags) { |
+ EXPECT_EQ(4, state_); |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+ EXPECT_EQ(TS_S_ASYNC, result); |
+ EXPECT_EQ(4, state_); |
+ state_ = 5; |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted5(DWORD flags) { |
+ EXPECT_EQ(5, state_); |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_FALSE(HasReadWriteLock()); |
+ state_ = 6; |
+ return S_OK; |
+ } |
+ |
+ private: |
+ int state_; |
+}; |
+ |
+TEST_F(TsfTextStoreTest, AsynchronousRequestLockTest) { |
+ AsyncRequestLockTestCallback callback(text_store_); |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted1)) |
+ .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted2)) |
+ .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted3)) |
+ .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted4)) |
+ .WillOnce(Invoke(&callback, &AsyncRequestLockTestCallback::LockGranted5)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+ EXPECT_EQ(S_OK, result); |
+} |
+ |
+class RequestLockTextChangeTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit RequestLockTextChangeTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store), |
+ state_(0) { |
+ } |
+ |
+ HRESULT LockGranted1(DWORD flags) { |
+ EXPECT_EQ(0, state_); |
+ state_ = 1; |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ |
+ *edit_flag() = true; |
+ SetInternalState(L"012345", 6, 6, 6); |
+ composition_undelines()->clear(); |
+ |
+ state_ = 2; |
+ return S_OK; |
+ } |
+ |
+ void InsertText(const string16& text) { |
+ EXPECT_EQ(2, state_); |
+ EXPECT_EQ(L"012345", text); |
+ state_ = 3; |
+ } |
+ |
+ void SetCompositionText(const ui::CompositionText& composition) { |
+ EXPECT_EQ(3, state_); |
+ EXPECT_EQ(L"", composition.text); |
+ EXPECT_EQ(0, composition.selection.start()); |
+ EXPECT_EQ(0, composition.selection.end()); |
+ EXPECT_EQ(0, composition.underlines.size()); |
+ state_ = 4; |
+ } |
+ |
+ HRESULT OnTextChange(DWORD flags, const TS_TEXTCHANGE* change) { |
+ EXPECT_EQ(4, state_); |
+ HRESULT result; |
+ state_ = 5; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+ EXPECT_EQ(S_OK, result); |
+ EXPECT_EQ(6, state_); |
+ state_ = 7; |
+ return S_OK; |
+ } |
+ |
+ HRESULT LockGranted2(DWORD flags) { |
+ EXPECT_EQ(5, state_); |
+ EXPECT_TRUE(HasReadLock()); |
+ EXPECT_TRUE(HasReadWriteLock()); |
+ state_ = 6; |
+ return S_OK; |
+ } |
+ |
+ private: |
+ int state_; |
+}; |
+ |
+TEST_F(TsfTextStoreTest, RequestLockOnTextChangeTest) { |
+ RequestLockTextChangeTestCallback callback(text_store_); |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, |
+ &RequestLockTextChangeTestCallback::LockGranted1)) |
+ .WillOnce(Invoke(&callback, |
+ &RequestLockTextChangeTestCallback::LockGranted2)); |
+ |
+ EXPECT_CALL(*sink_, OnSelectionChange()) |
+ .WillOnce(Return(S_OK)); |
+ EXPECT_CALL(*sink_, OnLayoutChange(_, _)) |
+ .WillOnce(Return(S_OK)); |
+ EXPECT_CALL(*sink_, OnTextChange(_, _)) |
+ .WillOnce(Invoke(&callback, |
+ &RequestLockTextChangeTestCallback::OnTextChange)); |
+ EXPECT_CALL(text_input_client_, InsertText(_)) |
+ .WillOnce(Invoke(&callback, |
+ &RequestLockTextChangeTestCallback::InsertText)); |
+ EXPECT_CALL(text_input_client_, SetCompositionText(_)) |
+ .WillOnce(Invoke(&callback, |
+ &RequestLockTextChangeTestCallback::SetCompositionText)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+ EXPECT_EQ(S_OK, result); |
+} |
+ |
+class SelectionTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit SelectionTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store) { |
+ } |
+ |
+ HRESULT ReadLockGranted(DWORD flags) { |
+ SetInternalState(L"", 0, 0, 0); |
+ |
+ GetSelectionTest(0, 0); |
+ SetSelectionTest(0, 0, TF_E_NOLOCK); |
+ |
+ SetInternalState(L"012345", 0, 0, 3); |
+ |
+ GetSelectionTest(0, 3); |
+ SetSelectionTest(0, 0, TF_E_NOLOCK); |
+ |
+ return S_OK; |
+ } |
+ |
+ HRESULT ReadWriteLockGranted(DWORD flags) { |
+ SetInternalState(L"", 0, 0, 0); |
+ |
+ SetSelectionTest(0, 0, S_OK); |
+ GetSelectionTest(0, 0); |
+ SetSelectionTest(0, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 1, TF_E_INVALIDPOS); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetSelectionTest(0, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(0, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(0, 3, TF_E_INVALIDPOS); |
+ SetSelectionTest(0, 6, TF_E_INVALIDPOS); |
+ SetSelectionTest(0, 7, TF_E_INVALIDPOS); |
+ SetSelectionTest(0, 8, TF_E_INVALIDPOS); |
+ |
+ SetSelectionTest(1, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 3, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 6, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 7, TF_E_INVALIDPOS); |
+ SetSelectionTest(1, 8, TF_E_INVALIDPOS); |
+ |
+ SetSelectionTest(3, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(3, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(3, 3, S_OK); |
+ SetSelectionTest(3, 6, S_OK); |
+ SetSelectionTest(3, 7, S_OK); |
+ SetSelectionTest(3, 8, TF_E_INVALIDPOS); |
+ |
+ SetSelectionTest(6, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(6, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(6, 3, TF_E_INVALIDPOS); |
+ SetSelectionTest(6, 6, S_OK); |
+ SetSelectionTest(6, 7, S_OK); |
+ SetSelectionTest(6, 8, TF_E_INVALIDPOS); |
+ |
+ SetSelectionTest(7, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(7, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(7, 3, TF_E_INVALIDPOS); |
+ SetSelectionTest(7, 6, TF_E_INVALIDPOS); |
+ SetSelectionTest(7, 7, S_OK); |
+ SetSelectionTest(7, 8, TF_E_INVALIDPOS); |
+ |
+ SetSelectionTest(8, 0, TF_E_INVALIDPOS); |
+ SetSelectionTest(8, 1, TF_E_INVALIDPOS); |
+ SetSelectionTest(8, 3, TF_E_INVALIDPOS); |
+ SetSelectionTest(8, 6, TF_E_INVALIDPOS); |
+ SetSelectionTest(8, 7, TF_E_INVALIDPOS); |
+ SetSelectionTest(8, 8, TF_E_INVALIDPOS); |
+ |
+ return S_OK; |
+ } |
+}; |
+ |
+TEST_F(TsfTextStoreTest, SetGetSelectionTest) { |
+ SelectionTestCallback callback(text_store_); |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, &SelectionTestCallback::ReadLockGranted)) |
+ .WillOnce(Invoke(&callback, |
+ &SelectionTestCallback::ReadWriteLockGranted)); |
+ |
+ TS_SELECTION_ACP selection_buffer; |
+ ULONG fetched_count; |
+ EXPECT_EQ(TS_E_NOLOCK, |
+ text_store_->GetSelection(0, 1, &selection_buffer, |
+ &fetched_count)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+} |
+ |
+ |
+class SetGetTextTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit SetGetTextTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store) { |
+ } |
+ |
+ HRESULT ReadLockGranted(DWORD flags) { |
+ SetTextTest(0, 0, L"", TF_E_NOLOCK); |
+ |
+ GetTextTest(0, -1, L"", 0); |
+ GetTextTest(0, 0, L"", 0); |
+ GetTextErrorTest(0, 1, TF_E_INVALIDPOS); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ GetTextErrorTest(-1, -1, TF_E_INVALIDPOS); |
+ GetTextErrorTest(-1, 0, TF_E_INVALIDPOS); |
+ GetTextErrorTest(-1, 1, TF_E_INVALIDPOS); |
+ GetTextErrorTest(-1, 3, TF_E_INVALIDPOS); |
+ GetTextErrorTest(-1, 6, TF_E_INVALIDPOS); |
+ GetTextErrorTest(-1, 7, TF_E_INVALIDPOS); |
+ GetTextErrorTest(-1, 8, TF_E_INVALIDPOS); |
+ |
+ GetTextTest(0, -1, L"0123456", 7); |
+ GetTextTest(0, 0, L"", 0); |
+ GetTextTest(0, 1, L"0", 1); |
+ GetTextTest(0, 3, L"012", 3); |
+ GetTextTest(0, 6, L"012345", 6); |
+ GetTextTest(0, 7, L"0123456", 7); |
+ GetTextErrorTest(0, 8, TF_E_INVALIDPOS); |
+ |
+ GetTextTest(1, -1, L"123456", 7); |
+ GetTextErrorTest(1, 0, TF_E_INVALIDPOS); |
+ GetTextTest(1, 1, L"", 1); |
+ GetTextTest(1, 3, L"12", 3); |
+ GetTextTest(1, 6, L"12345", 6); |
+ GetTextTest(1, 7, L"123456", 7); |
+ GetTextErrorTest(1, 8, TF_E_INVALIDPOS); |
+ |
+ GetTextTest(3, -1, L"3456", 7); |
+ GetTextErrorTest(3, 0, TF_E_INVALIDPOS); |
+ GetTextErrorTest(3, 1, TF_E_INVALIDPOS); |
+ GetTextTest(3, 3, L"", 3); |
+ GetTextTest(3, 6, L"345", 6); |
+ GetTextTest(3, 7, L"3456", 7); |
+ GetTextErrorTest(3, 8, TF_E_INVALIDPOS); |
+ |
+ GetTextTest(6, -1, L"6", 7); |
+ GetTextErrorTest(6, 0, TF_E_INVALIDPOS); |
+ GetTextErrorTest(6, 1, TF_E_INVALIDPOS); |
+ GetTextErrorTest(6, 3, TF_E_INVALIDPOS); |
+ GetTextTest(6, 6, L"", 6); |
+ GetTextTest(6, 7, L"6", 7); |
+ GetTextErrorTest(6, 8, TF_E_INVALIDPOS); |
+ |
+ GetTextTest(7, -1, L"", 7); |
+ GetTextErrorTest(7, 0, TF_E_INVALIDPOS); |
+ GetTextErrorTest(7, 1, TF_E_INVALIDPOS); |
+ GetTextErrorTest(7, 3, TF_E_INVALIDPOS); |
+ GetTextErrorTest(7, 6, TF_E_INVALIDPOS); |
+ GetTextTest(7, 7, L"", 7); |
+ GetTextErrorTest(7, 8, TF_E_INVALIDPOS); |
+ |
+ GetTextErrorTest(8, -1, TF_E_INVALIDPOS); |
+ GetTextErrorTest(8, 0, TF_E_INVALIDPOS); |
+ GetTextErrorTest(8, 1, TF_E_INVALIDPOS); |
+ GetTextErrorTest(8, 3, TF_E_INVALIDPOS); |
+ GetTextErrorTest(8, 6, TF_E_INVALIDPOS); |
+ GetTextErrorTest(8, 7, TF_E_INVALIDPOS); |
+ GetTextErrorTest(8, 8, TF_E_INVALIDPOS); |
+ |
+ return S_OK; |
+ } |
+ |
+ HRESULT ReadWriteLockGranted(DWORD flags) { |
+ SetInternalState(L"", 0, 0, 0); |
+ SetTextTest(0, 0, L"", S_OK); |
+ |
+ SetInternalState(L"", 0, 0, 0); |
+ SetTextTest(0, 1, L"", TS_E_INVALIDPOS); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(0, 0, L"", TS_E_INVALIDPOS); |
+ SetTextTest(0, 1, L"", TS_E_INVALIDPOS); |
+ SetTextTest(0, 3, L"", TS_E_INVALIDPOS); |
+ SetTextTest(0, 6, L"", TS_E_INVALIDPOS); |
+ SetTextTest(0, 7, L"", TS_E_INVALIDPOS); |
+ SetTextTest(0, 8, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(1, 0, L"", TS_E_INVALIDPOS); |
+ SetTextTest(1, 1, L"", TS_E_INVALIDPOS); |
+ SetTextTest(1, 3, L"", TS_E_INVALIDPOS); |
+ SetTextTest(1, 6, L"", TS_E_INVALIDPOS); |
+ SetTextTest(1, 7, L"", TS_E_INVALIDPOS); |
+ SetTextTest(1, 8, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(3, 0, L"", TS_E_INVALIDPOS); |
+ SetTextTest(3, 1, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(3, 3, L"", S_OK); |
+ GetTextTest(0, -1, L"0123456", 7); |
+ GetSelectionTest(3, 3); |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(3, 6, L"", S_OK); |
+ GetTextTest(0, -1, L"0126", 4); |
+ GetSelectionTest(3, 3); |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(3, 7, L"", S_OK); |
+ GetTextTest(0, -1, L"012", 3); |
+ GetSelectionTest(3, 3); |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(3, 8, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(6, 0, L"", TS_E_INVALIDPOS); |
+ SetTextTest(6, 1, L"", TS_E_INVALIDPOS); |
+ SetTextTest(6, 3, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(6, 6, L"", S_OK); |
+ GetTextTest(0, -1, L"0123456", 7); |
+ GetSelectionTest(6, 6); |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(6, 7, L"", S_OK); |
+ GetTextTest(0, -1, L"012345", 6); |
+ GetSelectionTest(6, 6); |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(6, 8, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(7, 0, L"", TS_E_INVALIDPOS); |
+ SetTextTest(7, 1, L"", TS_E_INVALIDPOS); |
+ SetTextTest(7, 3, L"", TS_E_INVALIDPOS); |
+ SetTextTest(7, 6, L"", TS_E_INVALIDPOS); |
+ |
+ SetTextTest(7, 7, L"", S_OK); |
+ GetTextTest(0, -1, L"0123456", 7); |
+ GetSelectionTest(7, 7); |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ |
+ SetTextTest(7, 8, L"", TS_E_INVALIDPOS); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ SetTextTest(3, 3, L"abc", S_OK); |
+ GetTextTest(0, -1, L"012abc3456", 10); |
+ GetSelectionTest(3, 6); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ SetTextTest(3, 6, L"abc", S_OK); |
+ GetTextTest(0, -1, L"012abc6", 7); |
+ GetSelectionTest(3, 6); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ SetTextTest(3, 7, L"abc", S_OK); |
+ GetTextTest(0, -1, L"012abc", 6); |
+ GetSelectionTest(3, 6); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ SetTextTest(6, 6, L"abc", S_OK); |
+ GetTextTest(0, -1, L"012345abc6", 10); |
+ GetSelectionTest(6, 9); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ SetTextTest(6, 7, L"abc", S_OK); |
+ GetTextTest(0, -1, L"012345abc", 9); |
+ GetSelectionTest(6, 9); |
+ |
+ SetInternalState(L"0123456", 3, 3, 3); |
+ SetTextTest(7, 7, L"abc", S_OK); |
+ GetTextTest(0, -1, L"0123456abc", 10); |
+ GetSelectionTest(7, 10); |
+ |
+ return S_OK; |
+ } |
+}; |
+ |
+TEST_F(TsfTextStoreTest, SetGetTextTest) { |
+ SetGetTextTestCallback callback(text_store_); |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, &SetGetTextTestCallback::ReadLockGranted)) |
+ .WillOnce(Invoke(&callback, |
+ &SetGetTextTestCallback::ReadWriteLockGranted)); |
+ |
+ wchar_t buffer[1024]; |
+ ULONG text_buffer_copied; |
+ TS_RUNINFO run_info; |
+ ULONG run_info_buffer_copied; |
+ LONG next_acp; |
+ EXPECT_EQ(TF_E_NOLOCK, |
+ text_store_->GetText(0, -1, buffer, 1024, &text_buffer_copied, |
+ &run_info, 1, &run_info_buffer_copied, |
+ &next_acp)); |
+ TS_TEXTCHANGE change; |
+ EXPECT_EQ(TF_E_NOLOCK, text_store_->SetText(0, 0, 0, L"abc", 3, &change)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+} |
+ |
+class InsertTextAtSelectionTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit InsertTextAtSelectionTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store) { |
+ } |
+ |
+ HRESULT ReadLockGranted(DWORD flags) { |
+ SetInternalState(L"abcedfg", 0, 0, 0); |
+ |
+ wchar_t buffer[] = L"0123456789"; |
+ InsertTextAtSelectionQueryOnlyTest(buffer, 10, 0, 10); |
+ GetSelectionTest(0, 0); |
+ InsertTextAtSelectionQueryOnlyTest(buffer, 0, 0, 0); |
+ |
+ LONG start, end; |
+ TS_TEXTCHANGE change; |
+ EXPECT_EQ(TS_E_NOLOCK, |
+ text_store_->InsertTextAtSelection(0, buffer, 10, |
+ &start, &end, &change)); |
+ return S_OK; |
+ } |
+ |
+ HRESULT ReadWriteLockGranted(DWORD flags) { |
+ SetInternalState(L"abcedfg", 0, 0, 0); |
+ |
+ const wchar_t buffer[] = L"0123456789"; |
+ InsertTextAtSelectionQueryOnlyTest(buffer, 10, 0, 10); |
+ GetSelectionTest(0, 0); |
+ InsertTextAtSelectionQueryOnlyTest(buffer, 0, 0, 0); |
+ |
+ SetInternalState(L"", 0, 0, 0); |
+ InsertTextAtSelectionTest(buffer, 10, 0, 10, 0, 0, 10); |
+ GetSelectionTest(0, 10); |
+ GetTextTest(0, -1, L"0123456789", 10); |
+ |
+ SetInternalState(L"abcedfg", 0, 0, 0); |
+ InsertTextAtSelectionTest(buffer, 10, 0, 10, 0, 0, 10); |
+ GetSelectionTest(0, 10); |
+ GetTextTest(0, -1, L"0123456789abcedfg", 17); |
+ |
+ SetInternalState(L"abcedfg", 0, 0, 3); |
+ InsertTextAtSelectionTest(buffer, 0, 0, 0, 0, 3, 0); |
+ GetSelectionTest(0, 0); |
+ GetTextTest(0, -1, L"edfg", 4); |
+ |
+ SetInternalState(L"abcedfg", 0, 3, 7); |
+ InsertTextAtSelectionTest(buffer, 10, 3, 13, 3, 7, 13); |
+ GetSelectionTest(3, 13); |
+ GetTextTest(0, -1, L"abc0123456789", 13); |
+ |
+ SetInternalState(L"abcedfg", 0, 7, 7); |
+ InsertTextAtSelectionTest(buffer, 10, 7, 17, 7, 7, 17); |
+ GetSelectionTest(7, 17); |
+ GetTextTest(0, -1, L"abcedfg0123456789", 17); |
+ |
+ return S_OK; |
+ } |
+}; |
+ |
+TEST_F(TsfTextStoreTest, InsertTextAtSelectionTest) { |
+ InsertTextAtSelectionTestCallback callback(text_store_); |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, |
+ &InsertTextAtSelectionTestCallback::ReadLockGranted)) |
+ .WillOnce( |
+ Invoke(&callback, |
+ &InsertTextAtSelectionTestCallback::ReadWriteLockGranted)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+} |
+ |
+class ScenarioTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit ScenarioTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store) { |
+ } |
+ |
+ HRESULT LockGranted1(DWORD flags) { |
+ SetSelectionTest(0, 0, S_OK); |
+ |
+ SetTextTest(0, 0, L"abc", S_OK); |
+ SetTextTest(1, 2, L"xyz", S_OK); |
+ |
+ GetTextTest(0, -1, L"axyzc", 5); |
+ |
+ composition_undelines()->clear(); |
+ CompositionUnderline underline; |
+ underline.start_offset = 0; |
+ underline.end_offset = 5; |
+ underline.color = SK_ColorBLACK; |
+ underline.thick = false; |
+ composition_undelines()->push_back(underline); |
+ *edit_flag() = true; |
+ *committed_size() = 0; |
+ return S_OK; |
+ } |
+ |
+ void SetCompositionText1(const ui::CompositionText& composition) { |
+ EXPECT_EQ(L"axyzc", composition.text); |
+ EXPECT_EQ(1, composition.selection.start()); |
+ EXPECT_EQ(4, composition.selection.end()); |
+ ASSERT_EQ(1, composition.underlines.size()); |
+ EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color); |
+ EXPECT_EQ(0, composition.underlines[0].start_offset); |
+ EXPECT_EQ(5, composition.underlines[0].end_offset); |
+ EXPECT_FALSE(composition.underlines[0].thick); |
+ } |
+ |
+ HRESULT LockGranted2(DWORD flags) { |
+ SetTextTest(3, 4, L"ZCP", S_OK); |
+ GetTextTest(0, -1, L"axyZCPc", 7); |
+ |
+ composition_undelines()->clear(); |
+ CompositionUnderline underline; |
+ underline.start_offset = 3; |
+ underline.end_offset = 5; |
+ underline.color = SK_ColorBLACK; |
+ underline.thick = true; |
+ composition_undelines()->push_back(underline); |
+ underline.start_offset = 5; |
+ underline.end_offset = 7; |
+ underline.color = SK_ColorBLACK; |
+ underline.thick = false; |
+ composition_undelines()->push_back(underline); |
+ |
+ *edit_flag() = true; |
+ *committed_size() = 3; |
+ |
+ return S_OK; |
+ } |
+ |
+ void InsertText2(const string16& text) { |
+ EXPECT_EQ(L"axy", text); |
+ } |
+ |
+ void SetCompositionText2(const ui::CompositionText& composition) { |
+ EXPECT_EQ(L"ZCPc", composition.text); |
+ EXPECT_EQ(0, composition.selection.start()); |
+ EXPECT_EQ(3, composition.selection.end()); |
+ ASSERT_EQ(2, composition.underlines.size()); |
+ EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color); |
+ EXPECT_EQ(0, composition.underlines[0].start_offset); |
+ EXPECT_EQ(2, composition.underlines[0].end_offset); |
+ EXPECT_TRUE(composition.underlines[0].thick); |
+ EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color); |
+ EXPECT_EQ(2, composition.underlines[1].start_offset); |
+ EXPECT_EQ(4, composition.underlines[1].end_offset); |
+ EXPECT_FALSE(composition.underlines[1].thick); |
+ } |
+ |
+ HRESULT LockGranted3(DWORD flags) { |
+ GetTextTest(0, -1, L"axyZCPc", 7); |
+ |
+ composition_undelines()->clear(); |
+ *edit_flag() = true; |
+ *committed_size() = 7; |
+ |
+ return S_OK; |
+ } |
+ |
+ void InsertText3(const string16& text) { |
+ EXPECT_EQ(L"ZCPc", text); |
+ } |
+ |
+ void SetCompositionText3(const ui::CompositionText& composition) { |
+ EXPECT_EQ(L"", composition.text); |
+ EXPECT_EQ(0, composition.selection.start()); |
+ EXPECT_EQ(0, composition.selection.end()); |
+ EXPECT_EQ(0, composition.underlines.size()); |
+ } |
+}; |
+ |
+TEST_F(TsfTextStoreTest, ScenarioTest) { |
+ ScenarioTestCallback callback(text_store_); |
+ EXPECT_CALL(text_input_client_, SetCompositionText(_)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText1)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText2)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::SetCompositionText3)); |
+ |
+ EXPECT_CALL(text_input_client_, InsertText(_)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText2)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::InsertText3)); |
+ |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted1)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted2)) |
+ .WillOnce(Invoke(&callback, &ScenarioTestCallback::LockGranted3)); |
+ |
+ // OnSelectionChange will be called once after LockGranted3(). |
+ EXPECT_CALL(*sink_, OnSelectionChange()) |
+ .WillOnce(Return(S_OK)); |
+ |
+ // OnLayoutChange will be called once after LockGranted3(). |
+ EXPECT_CALL(*sink_, OnLayoutChange(_, _)) |
+ .WillOnce(Return(S_OK)); |
+ |
+ // OnTextChange will be called once after LockGranted3(). |
+ EXPECT_CALL(*sink_, OnTextChange(_, _)) |
+ .WillOnce(Return(S_OK)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); |
+} |
+ |
+class GetTextExtTestCallback : public TsfTextStoreTestCallback { |
+ public: |
+ explicit GetTextExtTestCallback(TsfTextStore* text_store) |
+ : TsfTextStoreTestCallback(text_store), |
+ charactor_bounds_error_flag_(false) { |
+ } |
+ |
+ HRESULT LockGranted(DWORD flags) { |
+ SetInternalState(L"0123456789012345", 0, 0, 0); |
+ |
+ TsViewCookie view_cookie; |
+ EXPECT_EQ(S_OK, text_store_->GetActiveView(&view_cookie)); |
+ GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20); |
+ GetTextExtTest(view_cookie, 0, 1, 11, 12, 20, 20); |
+ GetTextExtTest(view_cookie, 0, 2, 11, 12, 30, 20); |
+ GetTextExtTest(view_cookie, 9, 9, 100, 12, 100, 20); |
+ GetTextExtTest(view_cookie, 9, 10, 101, 12, 110, 20); |
+ GetTextExtTest(view_cookie, 10, 10, 110, 12, 110, 20); |
+ GetTextExtTest(view_cookie, 11, 11, 20, 112, 20, 120); |
+ GetTextExtTest(view_cookie, 11, 12, 21, 112, 30, 120); |
+ GetTextExtTest(view_cookie, 9, 12, 11, 12, 110, 120); |
+ GetTextExtTest(view_cookie, 9, 13, 11, 12, 110, 120); |
+ GetTextExtNoLayoutTest(view_cookie, 9, 14); |
+ |
+ charactor_bounds_error_flag_ = true; |
+ GetTextExtNoLayoutTest(view_cookie, 0, 0); |
+ |
+ SetInternalState(L"", 0, 0, 0); |
+ GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6); |
+ return S_OK; |
+ } |
+ |
+ bool GetCompositionCharacterBounds(uint32 index, gfx::Rect* rect) { |
+ if (charactor_bounds_error_flag_) |
+ return false; |
+ if (index >= 13) |
+ return false; |
+ rect->set_x((index % 10) * 10 + 11); |
+ rect->set_y((index / 10) * 100 + 12); |
+ rect->set_width(9); |
+ rect->set_height(8); |
+ return true; |
+ } |
+ |
+ gfx::Rect GetCaretBounds() { |
+ return gfx::Rect(1, 2, 3, 4); |
+ } |
+ |
+ private: |
+ bool charactor_bounds_error_flag_; |
+}; |
+ |
+TEST_F(TsfTextStoreTest, GetTextExtTest) { |
+ GetTextExtTestCallback callback(text_store_); |
+ EXPECT_CALL(text_input_client_, GetCaretBounds()) |
+ .WillRepeatedly(Invoke(&callback, |
+ &GetTextExtTestCallback::GetCaretBounds)); |
+ |
+ EXPECT_CALL(text_input_client_, GetCompositionCharacterBounds(_, _)) |
+ .WillRepeatedly( |
+ Invoke(&callback, |
+ &GetTextExtTestCallback::GetCompositionCharacterBounds)); |
+ |
+ EXPECT_CALL(*sink_, OnLockGranted(_)) |
+ .WillOnce(Invoke(&callback, &GetTextExtTestCallback::LockGranted)); |
+ |
+ HRESULT result; |
+ EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READ, &result)); |
+} |
+ |
+} // namespace ui |