From 733f16e5fe670677fbdc2e97072f6d0dbd6386fa Mon Sep 17 00:00:00 2001 From: Kengo Ide Date: Sat, 12 Feb 2022 11:05:37 +0900 Subject: [PATCH 1/5] =?UTF-8?q?CClipboard.h=20=E7=B7=A8=E9=9B=86=E6=99=82?= =?UTF-8?q?=E3=81=AE=E5=86=8D=E3=82=B3=E3=83=B3=E3=83=91=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E7=AF=84=E5=9B=B2=E3=82=92=E7=B8=AE=E5=B0=8F=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * CDocEditor.h に実装されていた CClipboard の呼び出しコードを CDocEditor.cpp に移動。 * CDocEditor.h から #include "_os/CClipboard.h" を除去。 * 不足していた #include を追加。 --- sakura_core/cmd/CViewCommander_Clipboard.cpp | 1 + sakura_core/doc/CDocEditor.cpp | 6 ++++++ sakura_core/doc/CDocEditor.h | 6 +----- sakura_core/macro/CMacro.cpp | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/sakura_core/cmd/CViewCommander_Clipboard.cpp b/sakura_core/cmd/CViewCommander_Clipboard.cpp index 207dc4c04b..031f1b52c0 100644 --- a/sakura_core/cmd/CViewCommander_Clipboard.cpp +++ b/sakura_core/cmd/CViewCommander_Clipboard.cpp @@ -26,6 +26,7 @@ #include "uiparts/CWaitCursor.h" #include "util/os.h" #include "apiwrap/CommonControl.h" +#include "_os/CClipboard.h" /** 切り取り(選択範囲をクリップボードにコピーして削除) diff --git a/sakura_core/doc/CDocEditor.cpp b/sakura_core/doc/CDocEditor.cpp index 29c3ca3fc9..d61c13e2ab 100644 --- a/sakura_core/doc/CDocEditor.cpp +++ b/sakura_core/doc/CDocEditor.cpp @@ -34,6 +34,7 @@ #include "CEol.h" #include "window/CEditWnd.h" #include "debug/CRunningTimer.h" +#include "_os/CClipboard.h" CDocEditor::CDocEditor(CEditDoc* pcDoc) : m_pcDocRef(pcDoc) @@ -166,6 +167,11 @@ void CDocEditor::SetImeMode( int mode ) } // To Here Nov. 20, 2000 genta +bool CDocEditor::IsEnablePaste() const +{ + return CClipboard::HasValidData(); +} + /*! 末尾に行を追加 diff --git a/sakura_core/doc/CDocEditor.h b/sakura_core/doc/CDocEditor.h index 56f2694ae0..1b2c4c33c3 100644 --- a/sakura_core/doc/CDocEditor.h +++ b/sakura_core/doc/CDocEditor.h @@ -28,7 +28,6 @@ #pragma once #include "doc/CDocListener.h" -#include "_os/CClipboard.h" #include "COpeBuf.h" class CEditDoc; @@ -84,10 +83,7 @@ class CDocEditor : public CDocListenerEx{ } //! クリップボードから貼り付け可能か? - bool IsEnablePaste( void ) const - { - return CClipboard::HasValidData(); - } + bool IsEnablePaste( void ) const; public: CEditDoc* m_pcDocRef; diff --git a/sakura_core/macro/CMacro.cpp b/sakura_core/macro/CMacro.cpp index e8e0e2af43..c9301eb0ca 100644 --- a/sakura_core/macro/CMacro.cpp +++ b/sakura_core/macro/CMacro.cpp @@ -61,6 +61,7 @@ #include "CSelectLang.h" #include "config/app_constants.h" #include "String_define.h" +#include "_os/CClipboard.h" CMacro::CMacro( EFunctionCode nFuncID ) { From e7a0b5c80320f51263a6b9530664841a940ae526 Mon Sep 17 00:00:00 2001 From: Kengo Ide Date: Sun, 13 Feb 2022 15:09:01 +0900 Subject: [PATCH 2/5] =?UTF-8?q?CClipboard=20=E5=86=85=E3=81=AE=20API=20?= =?UTF-8?q?=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97=E3=82=92=E3=82=AA=E3=83=BC?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=83=A9=E3=82=A4=E3=83=89=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * モックしたい関数を呼び出しているコードから名前空間指定を除去。 * モックしたい関数と同名の仮想メンバ関数をクラスに追加し、元の API へリダイレクトするように実装。 --- sakura_core/_os/CClipboard.cpp | 42 +++++++++++++++++++++++----------- sakura_core/_os/CClipboard.h | 8 +++++++ 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/sakura_core/_os/CClipboard.cpp b/sakura_core/_os/CClipboard.cpp index 8a3bea8f27..b77bc6adbf 100644 --- a/sakura_core/_os/CClipboard.cpp +++ b/sakura_core/_os/CClipboard.cpp @@ -56,7 +56,7 @@ CClipboard::~CClipboard() void CClipboard::Empty() { - ::EmptyClipboard(); + EmptyClipboard(); } void CClipboard::Close() @@ -112,7 +112,7 @@ bool CClipboard::SetText( ::GlobalUnlock( hgClipText ); //クリップボードに設定 - ::SetClipboardData( CF_UNICODETEXT, hgClipText ); + SetClipboardData( CF_UNICODETEXT, hgClipText ); bUnicodeText = false; } // 1回しか通らない. breakでここまで飛ぶ @@ -142,7 +142,7 @@ bool CClipboard::SetText( ::GlobalUnlock( hgClipSakura ); //クリップボードに設定 - ::SetClipboardData( uFormatSakuraClip, hgClipSakura ); + SetClipboardData( uFormatSakuraClip, hgClipSakura ); bSakuraText = false; } // 1回しか通らない. breakでここまで飛ぶ @@ -160,7 +160,7 @@ bool CClipboard::SetText( BYTE* pClip = GlobalLockBYTE( hgClipMSDEVColumn ); pClip[0] = 0; ::GlobalUnlock( hgClipMSDEVColumn ); - ::SetClipboardData( uFormat, hgClipMSDEVColumn ); + SetClipboardData( uFormat, hgClipMSDEVColumn ); } } } @@ -178,7 +178,7 @@ bool CClipboard::SetText( BYTE* pClip = (BYTE*)::GlobalLock( hgClipMSDEVLine ); pClip[0] = 0x01; ::GlobalUnlock( hgClipMSDEVLine ); - ::SetClipboardData( uFormat, hgClipMSDEVLine ); + SetClipboardData( uFormat, hgClipMSDEVLine ); } } } @@ -194,7 +194,7 @@ bool CClipboard::SetText( BYTE* pClip = (BYTE*)::GlobalLock( hgClipMSDEVLine2 ); pClip[0] = 0x01; // ※ ClipSpy で調べるとデータはこれとは違うが内容には無関係に動くっぽい ::GlobalUnlock( hgClipMSDEVLine2 ); - ::SetClipboardData( uFormat, hgClipMSDEVLine2 ); + SetClipboardData( uFormat, hgClipMSDEVLine2 ); } } } @@ -250,7 +250,7 @@ bool CClipboard::SetHtmlText(const CNativeW& cmemBUf) //クリップボードに設定 UINT uFormat = ::RegisterClipboardFormat( L"HTML Format" ); - ::SetClipboardData( uFormat, hgClipText ); + SetClipboardData( uFormat, hgClipText ); return true; } @@ -299,8 +299,8 @@ bool CClipboard::GetText(CNativeW* cmemBuf, bool* pbColumnSelect, bool* pbLineSe //サクラ形式のデータがあれば取得 CLIPFORMAT uFormatSakuraClip = CClipboard::GetSakuraFormat(); if( (uGetFormat == -1 || uGetFormat == uFormatSakuraClip) - && ::IsClipboardFormatAvailable( uFormatSakuraClip ) ){ - HGLOBAL hSakura = ::GetClipboardData( uFormatSakuraClip ); + && IsClipboardFormatAvailable( uFormatSakuraClip ) ){ + HGLOBAL hSakura = GetClipboardData( uFormatSakuraClip ); if (hSakura != NULL) { BYTE* pData = (BYTE*)::GlobalLock(hSakura); size_t nLength = *((int*)pData); @@ -315,7 +315,7 @@ bool CClipboard::GetText(CNativeW* cmemBuf, bool* pbColumnSelect, bool* pbLineSe // From Here 2005/05/29 novice UNICODE TEXT 対応処理を追加 HGLOBAL hUnicode = NULL; if( uGetFormat == -1 || uGetFormat == CF_UNICODETEXT ){ - hUnicode = ::GetClipboardData( CF_UNICODETEXT ); + hUnicode = GetClipboardData( CF_UNICODETEXT ); } if( hUnicode != NULL ){ //DWORD nLen = GlobalSize(hUnicode); @@ -329,7 +329,7 @@ bool CClipboard::GetText(CNativeW* cmemBuf, bool* pbColumnSelect, bool* pbLineSe //OEMTEXT形式のデータがあれば取得 HGLOBAL hText = NULL; if( uGetFormat == -1 || uGetFormat == CF_OEMTEXT ){ - hText = ::GetClipboardData( CF_OEMTEXT ); + hText = GetClipboardData( CF_OEMTEXT ); } if( hText != NULL ){ char* szData = GlobalLockChar(hText); @@ -348,8 +348,8 @@ bool CClipboard::GetText(CNativeW* cmemBuf, bool* pbColumnSelect, bool* pbLineSe /* 2008.09.10 bosagami パス貼り付け対応 */ //HDROP形式のデータがあれば取得 if( (uGetFormat == -1 || uGetFormat == CF_HDROP) - && ::IsClipboardFormatAvailable(CF_HDROP) ){ - HDROP hDrop = (HDROP)::GetClipboardData(CF_HDROP); + && IsClipboardFormatAvailable(CF_HDROP) ){ + HDROP hDrop = (HDROP)GetClipboardData(CF_HDROP); if(hDrop != NULL){ WCHAR sTmpPath[_MAX_PATH + 1] = {0}; const int nMaxCnt = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); @@ -673,3 +673,19 @@ int CClipboard::GetDataType() if(::IsClipboardFormatAvailable(CF_HDROP))return CF_HDROP; return -1; } + +HANDLE CClipboard::SetClipboardData(UINT uFormat, HANDLE hMem) { + return ::SetClipboardData(uFormat, hMem); +} + +HANDLE CClipboard::GetClipboardData(UINT uFormat) { + return ::GetClipboardData(uFormat); +} + +BOOL CClipboard::EmptyClipboard() { + return ::EmptyClipboard(); +} + +BOOL CClipboard::IsClipboardFormatAvailable(UINT format) { + return ::IsClipboardFormatAvailable(format); +} diff --git a/sakura_core/_os/CClipboard.h b/sakura_core/_os/CClipboard.h index 7dfa2f7c0a..81916fd794 100644 --- a/sakura_core/_os/CClipboard.h +++ b/sakura_core/_os/CClipboard.h @@ -66,5 +66,13 @@ class CClipboard{ static bool HasValidData(); //!< クリップボード内に、サクラエディタで扱えるデータがあればtrue static CLIPFORMAT GetSakuraFormat(); //!< サクラエディタ独自のクリップボードデータ形式 static int GetDataType(); //!< クリップボードデータ形式(CF_UNICODETEXT等)の取得 + +protected: + // 単体テスト用 + CClipboard(bool openStatus) : m_bOpenResult(openStatus) {} + virtual HANDLE SetClipboardData(UINT uFormat, HANDLE hMem); + virtual HANDLE GetClipboardData(UINT uFormat); + virtual BOOL EmptyClipboard(); + virtual BOOL IsClipboardFormatAvailable(UINT format); }; #endif /* SAKURA_CCLIPBOARD_4E783022_214C_4E51_A2E0_54EC343500F6_H_ */ From a5a85a8edb5e040321dec23593631adaf1313f0b Mon Sep 17 00:00:00 2001 From: Kengo Ide Date: Sun, 13 Feb 2022 16:21:27 +0900 Subject: [PATCH 3/5] =?UTF-8?q?CClipboard=20=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=81=A7=20Google=20Mock=20=E3=82=92=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E3=81=99=E3=82=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unittests/test-cclipboard.cpp | 272 ++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) diff --git a/tests/unittests/test-cclipboard.cpp b/tests/unittests/test-cclipboard.cpp index c4330bc81b..d723639ba7 100644 --- a/tests/unittests/test-cclipboard.cpp +++ b/tests/unittests/test-cclipboard.cpp @@ -23,11 +23,14 @@ distribution. */ #include +#include #ifndef NOMINMAX #define NOMINMAX #endif /* #ifndef NOMINMAX */ +#include +#include #include #include #include @@ -40,6 +43,9 @@ #include "mem/CNativeW.h" #include "_os/CClipboard.h" +using ::testing::_; +using ::testing::Return; + /*! * HWND型のスマートポインタを実現するためのdeleterクラス */ @@ -159,3 +165,269 @@ TEST_F(CClipboardTestFixture, SetTextAndGetText) EXPECT_STREQ(buffer.GetStringPtr(), text.data()); EXPECT_TRUE(line); } + +// グローバルメモリに書き込まれた特定の Unicode 文字列にマッチする述語関数 +MATCHER_P(WideStringInGlobalMemory, expected_string, "") { + const wchar_t* s = (const wchar_t*)::GlobalLock(arg); + if (!s) return false; + std::wstring_view actual(s); + bool match = actual == expected_string; + ::GlobalUnlock(arg); + return match; +} + +// グローバルメモリに書き込まれた特定の ANSI 文字列にマッチする述語関数 +MATCHER_P(AnsiStringInGlobalMemory, expected_string, "") { + const char* s = (const char*)::GlobalLock(arg); + if (!s) return false; + std::string_view actual(s); + bool match = actual == expected_string; + ::GlobalUnlock(arg); + return match; +} + +// グローバルメモリに書き込まれたサクラ独自形式データにマッチする述語関数 +MATCHER_P(SakuraFormatInGlobalMemory, expected_string, "") { + char* p = (char*)::GlobalLock(arg); + if (!p) return false; + int length = *(int*)p; + p += sizeof(int); + std::wstring_view actual((const wchar_t*)p); + bool match = actual.size() == length && actual == expected_string; + ::GlobalUnlock(arg); + return match; +} + +// グローバルメモリに書き込まれた特定のバイト値にマッチする述語関数 +MATCHER_P(ByteValueInGlobalMemory, value, "") { + unsigned char* p = (unsigned char*)::GlobalLock(arg); + if (!p) return false; + bool match = *p == value; + ::GlobalUnlock(arg); + return match; +} + +class MockCClipboard : public CClipboard { +public: + MockCClipboard(bool openStatus = true) : CClipboard(openStatus) {} + ~MockCClipboard() override {} + MOCK_METHOD2(SetClipboardData, HANDLE (UINT, HANDLE)); + MOCK_METHOD1(GetClipboardData, HANDLE (UINT)); + MOCK_METHOD0(EmptyClipboard, BOOL ()); + MOCK_METHOD1(IsClipboardFormatAvailable, BOOL (UINT)); +}; + +// Empty のテスト。 +// EmptyClipboard が呼ばれることを確認する。 +TEST(CClipboard, Empty) { + MockCClipboard clipboard; + EXPECT_CALL(clipboard, EmptyClipboard()).WillOnce(Return(TRUE)); + clipboard.Empty(); +} + +// SetHtmlTextのテスト。 +// SetClipboardData に渡された引数が期待される結果と一致することを確認する。 +TEST(CClipboard, SetHtmlText1) +{ + constexpr const wchar_t inputData[] = L"test 109"; + constexpr const char expected[] = + "Version:0.9\r\n" + "StartHTML:00000097\r\n" + "EndHTML:00000178\r\n" + "StartFragment:00000134\r\n" + "EndFragment:00000142\r\n" + "\r\n" + "\r\n" + "test 109\r\n" + "\r\n" + "\r\n"; + const UINT uHtmlFormat = ::RegisterClipboardFormat(L"HTML Format"); + + MockCClipboard clipboard; + EXPECT_CALL(clipboard, SetClipboardData(uHtmlFormat, AnsiStringInGlobalMemory(expected))); + EXPECT_TRUE(clipboard.SetHtmlText(inputData)); +} + +// クリップボードのオープンに失敗していた場合、SetHtmlText は何もせずに失敗する。 +TEST(CClipboard, SetHtmlText2) { + MockCClipboard clipboard(false); + EXPECT_CALL(clipboard, SetClipboardData(_, _)).Times(0); + EXPECT_FALSE(clipboard.SetHtmlText(L"test")); +} + +// SetText のテスト(フォーマット指定なし・矩形選択なし・行選択なし) +TEST(CClipboard, SetText1) { + constexpr std::wstring_view text = L"てすと"; + const CLIPFORMAT sakuraFormat = CClipboard::GetSakuraFormat(); + MockCClipboard clipboard; + EXPECT_CALL(clipboard, SetClipboardData(CF_UNICODETEXT, WideStringInGlobalMemory(text))); + EXPECT_CALL(clipboard, SetClipboardData(sakuraFormat, SakuraFormatInGlobalMemory(text))); + EXPECT_TRUE(clipboard.SetText(text.data(), text.length(), false, false, -1)); +} + +// SetText のテスト(CF_UNICODETEXTのみ・矩形選択あり・行選択なし) +TEST(CClipboard, SetText2) { + constexpr std::wstring_view text = L"てすと"; + MockCClipboard clipboard; + EXPECT_CALL(clipboard, SetClipboardData(CF_UNICODETEXT, WideStringInGlobalMemory(text))); + EXPECT_CALL(clipboard, SetClipboardData(::RegisterClipboardFormat(L"MSDEVColumnSelect"), ByteValueInGlobalMemory(0))); + EXPECT_FALSE(clipboard.SetText(text.data(), text.length(), true, false, CF_UNICODETEXT)); +} + +// SetText のテスト(サクラ独自形式のみ・矩形選択なし・行選択あり) +TEST(CClipboard, SetText3) { + constexpr std::wstring_view text = L"てすと"; + const CLIPFORMAT sakuraFormat = CClipboard::GetSakuraFormat(); + MockCClipboard clipboard; + EXPECT_CALL(clipboard, SetClipboardData(sakuraFormat, SakuraFormatInGlobalMemory(text))); + EXPECT_CALL(clipboard, SetClipboardData(::RegisterClipboardFormat(L"MSDEVLineSelect"), ByteValueInGlobalMemory(1))); + EXPECT_CALL(clipboard, SetClipboardData(::RegisterClipboardFormat(L"VisualStudioEditorOperationsLineCutCopyClipboardTag"), ByteValueInGlobalMemory(1))); + EXPECT_FALSE(clipboard.SetText(text.data(), text.length(), false, true, sakuraFormat)); +} + +// SetText のテスト。 +// クリップボードのオープンに失敗していた場合、SetText は何もせずに失敗する。 +TEST(CClipboard, SetText4) { + constexpr std::wstring_view text = L"てすと"; + MockCClipboard clipboard(false); + EXPECT_CALL(clipboard, SetClipboardData(_, _)).Times(0); + EXPECT_FALSE(clipboard.SetText(text.data(), text.length(), false, false, -1)); +} + +// グローバルメモリを RAII で管理する簡易ヘルパークラス +class GlobalMemory { +public: + GlobalMemory(UINT flags, SIZE_T bytes) : handle_(::GlobalAlloc(flags, bytes)) {} + GlobalMemory(const GlobalMemory&) = delete; + GlobalMemory& operator=(const GlobalMemory&) = delete; + ~GlobalMemory() { + if (handle_) + ::GlobalFree(handle_); + } + HGLOBAL Get() { return handle_; } + template void Lock(std::function f) { + f(reinterpret_cast(::GlobalLock(handle_))); + ::GlobalUnlock(handle_); + } +private: + HGLOBAL handle_; +}; + +// GetText のテストで使用するダミーデータを準備するためのフィクスチャクラス +class CClipboardGetText : public testing::Test { +protected: + MockCClipboard clipboard; + CNativeW buffer; + const CLIPFORMAT sakuraFormat = CClipboard::GetSakuraFormat(); + const CEol eol{ EEolType::cr_and_lf }; + static constexpr std::wstring_view unicodeText = L"CF_UNICODE"; + static constexpr std::wstring_view sakuraText = L"SAKURAClipW"; + static constexpr std::string_view oemText = "CF_OEMTEXT"; + GlobalMemory unicodeMemory{ GMEM_MOVEABLE, (unicodeText.size() + 1) * sizeof(wchar_t) }; + GlobalMemory sakuraMemory{ GMEM_MOVEABLE, sizeof(int) + (sakuraText.size() + 1) * sizeof(wchar_t) }; + GlobalMemory oemMemory{ GMEM_MOVEABLE, oemText.size() + 1 }; + + CClipboardGetText() { + unicodeMemory.Lock([=](wchar_t* p) { + std::wcscpy(p, unicodeText.data()); + }); + sakuraMemory.Lock([=](unsigned char* p) { + *(int*)p = sakuraText.size(); + std::wcscpy((wchar_t*)(p + sizeof(int)), sakuraText.data()); + }); + oemMemory.Lock([=](char* p) { + std::strcpy(p, oemText.data()); + }); + } +}; + +// CClipboard::GetText のテスト群。 +// +// GetText で取得したいデータ形式が特に指定されていない場合、 +// サクラ形式 -> CF_UNICODETEXT -> CF_OEMTEXT -> CF_HDROP の順で取得を試みる。 + +// サクラ形式を正常に取得するパス。 +TEST_F(CClipboardGetText, NoSpecifiedFormat1) { + ON_CALL(clipboard, IsClipboardFormatAvailable(sakuraFormat)).WillByDefault(Return(TRUE)); + ON_CALL(clipboard, GetClipboardData(sakuraFormat)).WillByDefault(Return(sakuraMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, -1)); + EXPECT_STREQ(buffer.GetStringPtr(), sakuraText.data()); +} + +// クリップボードにサクラ形式がなかった場合、CF_UNICODETEXTを取得する。 +TEST_F(CClipboardGetText, NoSpecifiedFormat2) { + ON_CALL(clipboard, IsClipboardFormatAvailable(sakuraFormat)).WillByDefault(Return(FALSE)); + ON_CALL(clipboard, GetClipboardData(CF_UNICODETEXT)).WillByDefault(Return(unicodeMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, -1)); + EXPECT_STREQ(buffer.GetStringPtr(), unicodeText.data()); +} + +// クリップボードにはサクラ形式があるはずだが、GetClipboardDataが失敗した場合、CF_UNICODETEXTを取得する。 +TEST_F(CClipboardGetText, NoSpecifiedFormat3) { + ON_CALL(clipboard, IsClipboardFormatAvailable(sakuraFormat)).WillByDefault(Return(TRUE)); + ON_CALL(clipboard, GetClipboardData(sakuraFormat)).WillByDefault(Return(nullptr)); + ON_CALL(clipboard, GetClipboardData(CF_UNICODETEXT)).WillByDefault(Return(unicodeMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, -1)); + EXPECT_STREQ(buffer.GetStringPtr(), unicodeText.data()); +} + +// サクラ形式とCF_UNICODETEXTの取得に失敗した場合、CF_OEMTEXTを取得する。 +TEST_F(CClipboardGetText, NoSpecifiedFormat4) { + ON_CALL(clipboard, IsClipboardFormatAvailable(sakuraFormat)).WillByDefault(Return(FALSE)); + ON_CALL(clipboard, GetClipboardData(CF_UNICODETEXT)).WillByDefault(Return(nullptr)); + ON_CALL(clipboard, GetClipboardData(CF_OEMTEXT)).WillByDefault(Return(oemMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, -1)); + EXPECT_STREQ(buffer.GetStringPtr(), L"CF_OEMTEXT"); +} + +// サクラ形式とCF_UNICODETEXTとCF_OEMTEXTが失敗した場合、CF_HDROPを取得する。 +TEST_F(CClipboardGetText, DISABLED_NoSpecifiedFormat5) { + // 適切なダミーデータを用意するのが難しいため未実装 +} + +// GetText で取得したいデータ形式が指定されている場合、他のデータ形式は無視する。 + +// サクラ形式を指定して取得する。 +TEST_F(CClipboardGetText, SakuraFormatSuccess) { + ON_CALL(clipboard, IsClipboardFormatAvailable(sakuraFormat)).WillByDefault(Return(TRUE)); + ON_CALL(clipboard, GetClipboardData(sakuraFormat)).WillByDefault(Return(sakuraMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, sakuraFormat)); + EXPECT_STREQ(buffer.GetStringPtr(), sakuraText.data()); +} + +// サクラ形式が指定されているが取得に失敗した場合。 +TEST_F(CClipboardGetText, SakuraFormatFailure) { + ON_CALL(clipboard, IsClipboardFormatAvailable(sakuraFormat)).WillByDefault(Return(FALSE)); + EXPECT_FALSE(clipboard.GetText(&buffer, nullptr, nullptr, eol, sakuraFormat)); +} + +// CF_UNICODETEXTを指定して取得する。 +TEST_F(CClipboardGetText, UnicodeTextSucces) { + ON_CALL(clipboard, GetClipboardData(CF_UNICODETEXT)).WillByDefault(Return(unicodeMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, CF_UNICODETEXT)); + EXPECT_STREQ(buffer.GetStringPtr(), unicodeText.data()); +} + +// CF_UNICODETEXTが指定されているが取得に失敗した場合。 +TEST_F(CClipboardGetText, UnicodeTextFailure) { + ON_CALL(clipboard, GetClipboardData(CF_UNICODETEXT)).WillByDefault(Return(nullptr)); + EXPECT_FALSE(clipboard.GetText(&buffer, nullptr, nullptr, eol, CF_UNICODETEXT)); +} + +// CF_OEMTEXTを指定して取得する。 +TEST_F(CClipboardGetText, OemTextSuccess) { + ON_CALL(clipboard, GetClipboardData(CF_OEMTEXT)).WillByDefault(Return(oemMemory.Get())); + EXPECT_TRUE(clipboard.GetText(&buffer, nullptr, nullptr, eol, CF_OEMTEXT)); + EXPECT_STREQ(buffer.GetStringPtr(), L"CF_OEMTEXT"); +} + +// CF_OEMTEXTが指定されているが取得に失敗した場合。 +TEST_F(CClipboardGetText, OemTextFailure) { + ON_CALL(clipboard, GetClipboardData(CF_OEMTEXT)).WillByDefault(Return(nullptr)); + EXPECT_FALSE(clipboard.GetText(&buffer, nullptr, nullptr, eol, CF_OEMTEXT)); +} + +// CF_HDROP を指定して取得する。 +TEST_F(CClipboardGetText, DISABLED_HDropSuccess) { + // 適切なダミーデータを用意するのが難しいため未実装 +} From eca61cc5567364899dddc91e6a815923844cbee2 Mon Sep 17 00:00:00 2001 From: Kengo Ide Date: Sun, 13 Feb 2022 18:15:42 +0900 Subject: [PATCH 4/5] =?UTF-8?q?protected=20=E3=82=B3=E3=83=B3=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=83=A9=E3=82=AF=E3=82=BF=E3=83=BC=E3=82=92=20explic?= =?UTF-8?q?it=20=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sakura_core/_os/CClipboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sakura_core/_os/CClipboard.h b/sakura_core/_os/CClipboard.h index 81916fd794..dedc6a138a 100644 --- a/sakura_core/_os/CClipboard.h +++ b/sakura_core/_os/CClipboard.h @@ -69,7 +69,7 @@ class CClipboard{ protected: // 単体テスト用 - CClipboard(bool openStatus) : m_bOpenResult(openStatus) {} + explicit CClipboard(bool openStatus) : m_bOpenResult(openStatus) {} virtual HANDLE SetClipboardData(UINT uFormat, HANDLE hMem); virtual HANDLE GetClipboardData(UINT uFormat); virtual BOOL EmptyClipboard(); From d2a0f7225772015bd177f3f672a927cd742fc440 Mon Sep 17 00:00:00 2001 From: Kengo Ide Date: Mon, 14 Feb 2022 14:32:55 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E5=8F=8D=E6=98=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 仮想メンバ関数を const にした。 * 仮想メンバ関数の宣言部に目的を説明するコメントを追加した。 --- sakura_core/_os/CClipboard.cpp | 8 ++++---- sakura_core/_os/CClipboard.h | 13 ++++++++----- tests/unittests/test-cclipboard.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/sakura_core/_os/CClipboard.cpp b/sakura_core/_os/CClipboard.cpp index b77bc6adbf..fa0d6806a0 100644 --- a/sakura_core/_os/CClipboard.cpp +++ b/sakura_core/_os/CClipboard.cpp @@ -674,18 +674,18 @@ int CClipboard::GetDataType() return -1; } -HANDLE CClipboard::SetClipboardData(UINT uFormat, HANDLE hMem) { +HANDLE CClipboard::SetClipboardData(UINT uFormat, HANDLE hMem) const { return ::SetClipboardData(uFormat, hMem); } -HANDLE CClipboard::GetClipboardData(UINT uFormat) { +HANDLE CClipboard::GetClipboardData(UINT uFormat) const { return ::GetClipboardData(uFormat); } -BOOL CClipboard::EmptyClipboard() { +BOOL CClipboard::EmptyClipboard() const { return ::EmptyClipboard(); } -BOOL CClipboard::IsClipboardFormatAvailable(UINT format) { +BOOL CClipboard::IsClipboardFormatAvailable(UINT format) const { return ::IsClipboardFormatAvailable(format); } diff --git a/sakura_core/_os/CClipboard.h b/sakura_core/_os/CClipboard.h index dedc6a138a..f398c56796 100644 --- a/sakura_core/_os/CClipboard.h +++ b/sakura_core/_os/CClipboard.h @@ -68,11 +68,14 @@ class CClipboard{ static int GetDataType(); //!< クリップボードデータ形式(CF_UNICODETEXT等)の取得 protected: - // 単体テスト用 + // 単体テスト用コンストラクタ explicit CClipboard(bool openStatus) : m_bOpenResult(openStatus) {} - virtual HANDLE SetClipboardData(UINT uFormat, HANDLE hMem); - virtual HANDLE GetClipboardData(UINT uFormat); - virtual BOOL EmptyClipboard(); - virtual BOOL IsClipboardFormatAvailable(UINT format); + + // 同名の Windows API に引数を転送する仮想メンバ関数。 + // 単体テスト内でオーバーライドすることで副作用のないテストを実施するのが目的。 + virtual HANDLE SetClipboardData(UINT uFormat, HANDLE hMem) const; + virtual HANDLE GetClipboardData(UINT uFormat) const; + virtual BOOL EmptyClipboard() const; + virtual BOOL IsClipboardFormatAvailable(UINT format) const; }; #endif /* SAKURA_CCLIPBOARD_4E783022_214C_4E51_A2E0_54EC343500F6_H_ */ diff --git a/tests/unittests/test-cclipboard.cpp b/tests/unittests/test-cclipboard.cpp index d723639ba7..4db5b13f66 100644 --- a/tests/unittests/test-cclipboard.cpp +++ b/tests/unittests/test-cclipboard.cpp @@ -211,10 +211,10 @@ class MockCClipboard : public CClipboard { public: MockCClipboard(bool openStatus = true) : CClipboard(openStatus) {} ~MockCClipboard() override {} - MOCK_METHOD2(SetClipboardData, HANDLE (UINT, HANDLE)); - MOCK_METHOD1(GetClipboardData, HANDLE (UINT)); - MOCK_METHOD0(EmptyClipboard, BOOL ()); - MOCK_METHOD1(IsClipboardFormatAvailable, BOOL (UINT)); + MOCK_CONST_METHOD2(SetClipboardData, HANDLE (UINT, HANDLE)); + MOCK_CONST_METHOD1(GetClipboardData, HANDLE (UINT)); + MOCK_CONST_METHOD0(EmptyClipboard, BOOL ()); + MOCK_CONST_METHOD1(IsClipboardFormatAvailable, BOOL (UINT)); }; // Empty のテスト。