From 017d5d5c995d89c3de9e24a37d337547dc7c99ea Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 7 Mar 2022 14:14:29 +0100 Subject: [PATCH] UnitTests: Introduce Other than having a convenient framework to test our helpers, this allows CodeQL code analysis GitHub action. Signed-off-by: Simon Rozman --- .gitignore | 4 + README.md | 4 +- UnitTests/.gitignore | 4 + UnitTests/Shell.cpp | 30 +++++++ UnitTests/UnitTests.vcxproj | 125 ++++++++++++++++++++++++++++ UnitTests/UnitTests.vcxproj.filters | 33 ++++++++ UnitTests/Win.cpp | 41 +++++++++ UnitTests/pch.cpp | 6 ++ UnitTests/pch.h | 11 +++ WinStd.sln | 31 +++++++ include/WinStd/Shell.h | 5 -- 11 files changed, 287 insertions(+), 7 deletions(-) create mode 100644 UnitTests/.gitignore create mode 100644 UnitTests/Shell.cpp create mode 100644 UnitTests/UnitTests.vcxproj create mode 100644 UnitTests/UnitTests.vcxproj.filters create mode 100644 UnitTests/Win.cpp create mode 100644 UnitTests/pch.cpp create mode 100644 UnitTests/pch.h create mode 100644 WinStd.sln diff --git a/.gitignore b/.gitignore index 5df58667..daf2aa02 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ +/.vs +/Debug /doc +/Release +/x64 diff --git a/README.md b/README.md index 12932548..8c149ea8 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ WinStd provides a subset of Win32 API identically named functions (C++ polymorph ```C++ // Encode response as OEM. std::string response; -WideCharToMultiByte(CP_OEMCP, 0, L"Copyright \u00A9 2017", response, NULL, NULL); +WideCharToMultiByte(CP_OEMCP, 0, L"Copyright \u00A9 2017", -1, response, NULL, NULL); std::cout << response.c_str() << std::endl; ``` @@ -78,6 +78,6 @@ void main() An auto-generated documentation is [here](https://amebis.github.io/WinStd/). -More examples and use-cases can be found in [GÉANTLink](https://github.com/Amebis/GEANTLink) and [ZRCola](https://github.com/Amebis/ZRCola) projects source code. They make heavy use of WinStd. +More examples and use-cases can be found in [GÉANTLink](https://github.com/Amebis/GEANTLink) and [ZRCola](https://github.com/Amebis/ZRCola) projects source code. They make heavy use of WinStd. Examples can also be found in the `UnitTests` project. This is a one-man project for the time being, so the Win32 API support is far from complete. It is added as needed. Contributions are welcome. diff --git a/UnitTests/.gitignore b/UnitTests/.gitignore new file mode 100644 index 00000000..e9a4a85d --- /dev/null +++ b/UnitTests/.gitignore @@ -0,0 +1,4 @@ +/*.user +/Debug +/Release +/x64 diff --git a/UnitTests/Shell.cpp b/UnitTests/Shell.cpp new file mode 100644 index 00000000..63ee295c --- /dev/null +++ b/UnitTests/Shell.cpp @@ -0,0 +1,30 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2022 Amebis +*/ + +#include "pch.h" + +using namespace std; +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace UnitTests +{ + TEST_CLASS(Shell) + { + public: + TEST_METHOD(PathCanonicalizeA) + { + string path; + Assert::IsTrue(::PathCanonicalizeA(path, "C:\\Windows\\Temp\\test\\..")); + Assert::AreEqual("C:\\Windows\\Temp", path.c_str(), true); + } + + TEST_METHOD(PathCanonicalizeW) + { + wstring path; + Assert::IsTrue(::PathCanonicalizeW(path, L"C:\\Windows\\Temp\\test\\..")); + Assert::AreEqual(L"C:\\Windows\\Temp", path.c_str(), true); + } + }; +} diff --git a/UnitTests/UnitTests.vcxproj b/UnitTests/UnitTests.vcxproj new file mode 100644 index 00000000..be8c8280 --- /dev/null +++ b/UnitTests/UnitTests.vcxproj @@ -0,0 +1,125 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {9AFC377D-C32D-4D42-82C2-09FC818020A2} + Win32Proj + UnitTests + 10.0 + NativeUnitTestProject + + + + DynamicLibrary + true + v142 + Unicode + false + + + true + + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + true + + + false + + + + Use + Level4 + true + ..\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + true + pch.h + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + Shlwapi.lib;%(AdditionalDependencies) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + + + true + true + + + + + WIN32;%(PreprocessorDefinitions) + + + + + + + + + Create + + + + + + + + + + + \ No newline at end of file diff --git a/UnitTests/UnitTests.vcxproj.filters b/UnitTests/UnitTests.vcxproj.filters new file mode 100644 index 00000000..d64ef457 --- /dev/null +++ b/UnitTests/UnitTests.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/UnitTests/Win.cpp b/UnitTests/Win.cpp new file mode 100644 index 00000000..15e574de --- /dev/null +++ b/UnitTests/Win.cpp @@ -0,0 +1,41 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2022 Amebis +*/ + +#include "pch.h" + +using namespace std; +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace UnitTests +{ + TEST_CLASS(Win) + { + public: + TEST_METHOD(WideCharToMultiByte) + { + string response; + { + static const char expected[] = "Copyright \xA9 2017"; + Assert::IsTrue(sizeof(expected) <= WINSTD_STACK_BUFFER_BYTES); + Assert::AreEqual(_countof(expected), ::WideCharToMultiByte(1252, 0, L"Copyright \u00A9 2017", -1, response, NULL, NULL)); + Assert::AreEqual(expected, response.c_str(), true); + } + + { + static const char expected[] = "The WC_COMPOSITECHECK flag causes the WideCharToMultiByte function to test for decomposed Unicode characters and attempts to compose them before converting them to the requested code page. This flag is only available for conversion to single byte (SBCS) or double byte (DBCS) code pages (code pages < 50000, excluding code page 42). If your application needs to convert decomposed Unicode data to single byte or double byte code pages, this flag might be useful. However, not all characters can be converted this way and it is more reliable to save and store such data as Unicode.\r\n\r\nWhen an application is using WC_COMPOSITECHECK, some character combinations might remain incomplete or might have additional nonspacing characters left over.For example, A + \xc2\xa8 + \xc2\xa8 combines to \xc3\x84 + \xc2\xa8.Using the WC_DISCARDNS flag causes the function to discard additional nonspacing characters.Using the WC_DEFAULTCHAR flag causes the function to use the default replacement character(typically \" ? \") instead. Using the WC_SEPCHARS flag causes the function to attempt to convert each additional nonspacing character to the target code page. Usually this flag also causes the use of the replacement character (\" ? \"). However, for code page 1258 (Vietnamese) and 20269, nonspacing characters exist and can be used. The conversions for these code pages are not perfect. Some combinations do not convert correctly to code page 1258, and WC_COMPOSITECHECK corrupts data in code page 20269. As mentioned earlier, it is more reliable to design your application to save and store such data as Unicode."; + Assert::IsTrue(sizeof(expected) > WINSTD_STACK_BUFFER_BYTES); + Assert::AreEqual(_countof(expected), ::WideCharToMultiByte(CP_UTF8, 0, L"The WC_COMPOSITECHECK flag causes the WideCharToMultiByte function to test for decomposed Unicode characters and attempts to compose them before converting them to the requested code page. This flag is only available for conversion to single byte (SBCS) or double byte (DBCS) code pages (code pages < 50000, excluding code page 42). If your application needs to convert decomposed Unicode data to single byte or double byte code pages, this flag might be useful. However, not all characters can be converted this way and it is more reliable to save and store such data as Unicode.\r\n\r\nWhen an application is using WC_COMPOSITECHECK, some character combinations might remain incomplete or might have additional nonspacing characters left over.For example, A + \u00a8 + \u00a8 combines to \u00c4 + \u00a8.Using the WC_DISCARDNS flag causes the function to discard additional nonspacing characters.Using the WC_DEFAULTCHAR flag causes the function to use the default replacement character(typically \" ? \") instead. Using the WC_SEPCHARS flag causes the function to attempt to convert each additional nonspacing character to the target code page. Usually this flag also causes the use of the replacement character (\" ? \"). However, for code page 1258 (Vietnamese) and 20269, nonspacing characters exist and can be used. The conversions for these code pages are not perfect. Some combinations do not convert correctly to code page 1258, and WC_COMPOSITECHECK corrupts data in code page 20269. As mentioned earlier, it is more reliable to design your application to save and store such data as Unicode.", -1, response, NULL, NULL)); + Assert::AreEqual(expected, response.c_str(), true); + } + } + + TEST_METHOD(library) + { + winstd::library lib_shell32(LoadLibraryEx(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)); + if (!lib_shell32) + Assert::Fail(L"LoadLibraryEx failed"); + } + }; +} diff --git a/UnitTests/pch.cpp b/UnitTests/pch.cpp new file mode 100644 index 00000000..0d7800bc --- /dev/null +++ b/UnitTests/pch.cpp @@ -0,0 +1,6 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2022 Amebis +*/ + +#include "pch.h" diff --git a/UnitTests/pch.h b/UnitTests/pch.h new file mode 100644 index 00000000..3469cf88 --- /dev/null +++ b/UnitTests/pch.h @@ -0,0 +1,11 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2022 Amebis +*/ + +#pragma once + +#include +#include + +#include diff --git a/WinStd.sln b/WinStd.sln new file mode 100644 index 00000000..1f26b31f --- /dev/null +++ b/WinStd.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32126.315 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests", "UnitTests\UnitTests.vcxproj", "{9AFC377D-C32D-4D42-82C2-09FC818020A2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Debug|Win32.ActiveCfg = Debug|Win32 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Debug|Win32.Build.0 = Debug|Win32 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Debug|x64.ActiveCfg = Debug|x64 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Debug|x64.Build.0 = Debug|x64 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Release|Win32.ActiveCfg = Release|Win32 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Release|Win32.Build.0 = Release|Win32 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Release|x64.ActiveCfg = Release|x64 + {9AFC377D-C32D-4D42-82C2-09FC818020A2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BBDB843D-98C3-46EF-BDE8-0E80FD851852} + EndGlobalSection +EndGlobal diff --git a/include/WinStd/Shell.h b/include/WinStd/Shell.h index 61d9f223..f3a5ba04 100644 --- a/include/WinStd/Shell.h +++ b/include/WinStd/Shell.h @@ -19,9 +19,6 @@ template static BOOL PathCanonicalizeA(_Inout_ std::basic_string &sValue, _In_ LPCSTR pszPath) { - assert(0); // TODO: Test this code. - - // Allocate buffer on heap and read into it. char szBuffer[MAX_PATH + 1]; BOOL bResult = ::PathCanonicalizeA(szBuffer, pszPath); sValue.assign(szBuffer, bResult ? MAX_PATH : 0); @@ -36,8 +33,6 @@ static BOOL PathCanonicalizeA(_Inout_ std::basic_string &sVa template static BOOL PathCanonicalizeW(_Inout_ std::basic_string &sValue, _In_ LPCWSTR pszPath) { - assert(0); // TODO: Test this code. - wchar_t szBuffer[MAX_PATH + 1]; BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath); sValue.assign(szBuffer, bResult ? MAX_PATH : 0);