#include "stdafx.h" #include #include #include #include namespace fs = boost::filesystem; namespace abres = ActiveBasic::Resource; using boost::implicit_cast; struct HModuleDeleter { typedef HMODULE pointer; void operator ()(pointer hmod) const { ::FreeLibrary(hmod); } }; typedef std::unique_ptr UniqueHModule; template struct ScopeExitHolder { ScopeExitHolder(F f) : f(f) {} ~ScopeExitHolder() { f(); } private: F f; ScopeExitHolder(ScopeExitHolder const&); ScopeExitHolder& operator =(ScopeExitHolder const&); }; #define AB_SCOPE_EXIT_2(f) auto BOOST_PP_CAT(AB_SCOPE_EXIT_FUNCTION_TEMP_, __LINE__) = (f); \ ScopeExitHolder BOOST_PP_CAT(AB_SCOPE_EXIT_FUNCTION_HOLDER_, __LINE__)_ (BOOST_PP_CAT(AB_SCOPE_EXIT_FUNCTION_TEMP_, __LINE__)); #define AB_SCOPE_EXIT(f) AB_SCOPE_EXIT_2([&]() f) template ScopeExitHolder ScopeExit(F fn) { return fn; } #define GET_AT(bd, y, x) (*reinterpret_cast(static_cast((bd).Scan0) + (y) * bdL.Stride + (x) * sizeof (DWORD))) bool IconEquals(HICON hiconL, HICON hiconR) { Gdiplus::Bitmap bmpL(hiconL), bmpR(hiconR); if (bmpL.GetWidth() == bmpR.GetWidth() && bmpR.GetHeight() == bmpR.GetHeight()) { Gdiplus::Rect rc(0, 0, bmpL.GetWidth(), bmpL.GetHeight()); Gdiplus::BitmapData bdL = {}, bdR = {}; BOOST_CHECK_EQUAL(bmpL.LockBits(&rc, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bdL), Gdiplus::Ok); BOOST_CHECK_EQUAL(bmpR.LockBits(&rc, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bdR), Gdiplus::Ok); AB_SCOPE_EXIT({bmpL.UnlockBits(&bdL);}); AB_SCOPE_EXIT({bmpR.UnlockBits(&bdR);}); if (bdL.Width == bdR.Width && bdL.Height == bdR.Height) { for (UINT i = 0; i < bdL.Height; ++i) { if (std::memcmp( static_cast(bdL.Scan0) + i * bdL.Stride, static_cast(bdR.Scan0) + i * bdR.Stride, bdL.Width * sizeof (std::uint32_t)) != 0) { return false; } } return true; } } return false; } UniqueHModule LoadABModule(LPCWSTR name) { TCHAR moduleName[MAX_PATH]; ::GetModuleFileName(nullptr, moduleName, MAX_PATH); auto systemDir = fs::path(moduleName).parent_path().parent_path().parent_path() / L"build/release/system"; UniqueHModule hmodRes(::LoadLibraryExW((systemDir / name).wstring().c_str(), nullptr, LOAD_LIBRARY_AS_DATAFILE)); BOOST_REQUIRE_NE(hmodRes.get(), implicit_cast(nullptr)); return hmodRes; } BOOST_AUTO_TEST_CASE( IconResourceLoading ) { Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); AB_SCOPE_EXIT_2(std::bind(Gdiplus::GdiplusShutdown, gdiplusToken)); UniqueHModule hmodRes = LoadABModule(L"res.dll"); auto hBasicProgramIconL = (HICON)::LoadImage(hmodRes.get(), MAKEINTRESOURCE(IDI_BASICPROGRAM), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); auto hBasicProgramIconR = abres::LoadIconAlt(hmodRes.get(), IDI_BASICPROGRAM, 16, 16, LR_DEFAULTCOLOR); BOOST_CHECK(hBasicProgramIconL != nullptr); BOOST_CHECK(hBasicProgramIconR != nullptr); BOOST_CHECK(IconEquals(hBasicProgramIconL, hBasicProgramIconR)); auto hcurL = ::LoadCursor(hmodRes.get(), MAKEINTRESOURCE(IDC_CURSOR_PEN)); auto hcurR = abres::LoadCursorAlt(hmodRes.get(), IDC_CURSOR_PEN); BOOST_CHECK(hcurL != nullptr); BOOST_CHECK(hcurR != nullptr); //BOOST_CHECK(IconEquals(hcurL, hcurR)); } BOOST_AUTO_TEST_CASE( StringResourceLoading ) { UniqueHModule hmodRes = LoadABModule(L"res.dll"); WCHAR strL[1024]; ::LoadStringW(hmodRes.get(), IDS_DEV_GROUP, strL, ARRAYSIZE(strL)); boost::optional strR = abres::LoadStringAlt(hmodRes.get(), IDS_DEV_GROUP); BOOST_CHECK(!!strR); BOOST_CHECK(strL == *strR); }