diff --git a/sakura_core/_os/CClipboard.cpp b/sakura_core/_os/CClipboard.cpp index 8a3bea8f27..fa0d6806a0 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) const { + return ::SetClipboardData(uFormat, hMem); +} + +HANDLE CClipboard::GetClipboardData(UINT uFormat) const { + return ::GetClipboardData(uFormat); +} + +BOOL CClipboard::EmptyClipboard() const { + return ::EmptyClipboard(); +} + +BOOL CClipboard::IsClipboardFormatAvailable(UINT format) const { + return ::IsClipboardFormatAvailable(format); +} diff --git a/sakura_core/_os/CClipboard.h b/sakura_core/_os/CClipboard.h index 7dfa2f7c0a..f398c56796 100644 --- a/sakura_core/_os/CClipboard.h +++ b/sakura_core/_os/CClipboard.h @@ -66,5 +66,16 @@ class CClipboard{ static bool HasValidData(); //!< クリップボード内に、サクラエディタで扱えるデータがあればtrue static CLIPFORMAT GetSakuraFormat(); //!< サクラエディタ独自のクリップボードデータ形式 static int GetDataType(); //!< クリップボードデータ形式(CF_UNICODETEXT等)の取得 + +protected: + // 単体テスト用コンストラクタ + explicit CClipboard(bool openStatus) : m_bOpenResult(openStatus) {} + + // 同名の 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/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 ) { diff --git a/tests/unittests/test-cclipboard.cpp b/tests/unittests/test-cclipboard.cpp index c4330bc81b..4db5b13f66 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_CONST_METHOD2(SetClipboardData, HANDLE (UINT, HANDLE)); + MOCK_CONST_METHOD1(GetClipboardData, HANDLE (UINT)); + MOCK_CONST_METHOD0(EmptyClipboard, BOOL ()); + MOCK_CONST_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) { + // 適切なダミーデータを用意するのが難しいため未実装 +}