UnitTests: Introduce

Other than having a convenient framework to test our helpers, this
allows CodeQL code analysis GitHub action.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2022-03-07 14:14:29 +01:00
parent 3b110f7dc5
commit 017d5d5c99
11 changed files with 287 additions and 7 deletions

4
.gitignore vendored
View File

@ -1 +1,5 @@
/.vs
/Debug
/doc
/Release
/x64

View File

@ -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.

4
UnitTests/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/*.user
/Debug
/Release
/x64

30
UnitTests/Shell.cpp Normal file
View File

@ -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);
}
};
}

125
UnitTests/UnitTests.vcxproj Normal file
View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{9AFC377D-C32D-4D42-82C2-09FC818020A2}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>UnitTests</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Shell.cpp" />
<ClCompile Include="Win.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Shell.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Win.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

41
UnitTests/Win.cpp Normal file
View File

@ -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<int>(_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<int>(_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");
}
};
}

6
UnitTests/pch.cpp Normal file
View File

@ -0,0 +1,6 @@
/*
SPDX-License-Identifier: MIT
Copyright © 2022 Amebis
*/
#include "pch.h"

11
UnitTests/pch.h Normal file
View File

@ -0,0 +1,11 @@
/*
SPDX-License-Identifier: MIT
Copyright © 2022 Amebis
*/
#pragma once
#include <WinStd/Shell.h>
#include <WinStd/Win.h>
#include <CppUnitTest.h>

31
WinStd.sln Normal file
View File

@ -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

View File

@ -19,9 +19,6 @@
template<class _Traits, class _Ax>
static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &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<char, _Traits, _Ax> &sVa
template<class _Traits, class _Ax>
static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &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);