mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 11:17:53 +01:00
common: do not accept invalid input in VersionHelper and add negative unit tests
This commit is contained in:
committed by
Andrey Nekrasov
parent
870f1095cd
commit
fc4ac803aa
@@ -4,11 +4,20 @@
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace Microsoft::VisualStudio::CppUnitTestFramework
|
||||
{
|
||||
template<>
|
||||
inline std::wstring ToString<VersionHelper>(const VersionHelper& v)
|
||||
{
|
||||
return v.toWstring();
|
||||
}
|
||||
}
|
||||
|
||||
namespace UnitTestsVersionHelper
|
||||
{
|
||||
const int MAJOR_VERSION_0 = 0;
|
||||
const int MINOR_VERSION_12 = 12;
|
||||
const int REVISION_VERSION_0 = 0;
|
||||
const size_t MAJOR_VERSION_0 = 0;
|
||||
const size_t MINOR_VERSION_12 = 12;
|
||||
const size_t REVISION_VERSION_0 = 0;
|
||||
|
||||
TEST_CLASS (UnitTestsVersionHelper)
|
||||
{
|
||||
@@ -23,9 +32,9 @@ namespace UnitTestsVersionHelper
|
||||
}
|
||||
TEST_METHOD (integerConstructorShouldProperlyInitializationWithDifferentVersionNumbers)
|
||||
{
|
||||
const int testcaseMajor = 2;
|
||||
const int testcaseMinor = 25;
|
||||
const int testcaseRevision = 1;
|
||||
const size_t testcaseMajor = 2;
|
||||
const size_t testcaseMinor = 25;
|
||||
const size_t testcaseRevision = 1;
|
||||
VersionHelper sut(testcaseMajor, testcaseMinor, testcaseRevision);
|
||||
|
||||
Assert::AreEqual(testcaseMajor, sut.major);
|
||||
@@ -36,17 +45,77 @@ namespace UnitTestsVersionHelper
|
||||
{
|
||||
VersionHelper sut("v0.12.3");
|
||||
|
||||
Assert::AreEqual(0, sut.major);
|
||||
Assert::AreEqual(12, sut.minor);
|
||||
Assert::AreEqual(3, sut.revision);
|
||||
Assert::AreEqual(0ull, sut.major);
|
||||
Assert::AreEqual(12ull, sut.minor);
|
||||
Assert::AreEqual(3ull, sut.revision);
|
||||
}
|
||||
TEST_METHOD (stringConstructorShouldProperlyInitializationWithDifferentVersionNumbers)
|
||||
{
|
||||
VersionHelper sut("v2.25.1");
|
||||
|
||||
Assert::AreEqual(2, sut.major);
|
||||
Assert::AreEqual(25, sut.minor);
|
||||
Assert::AreEqual(1, sut.revision);
|
||||
Assert::AreEqual(2ull, sut.major);
|
||||
Assert::AreEqual(25ull, sut.minor);
|
||||
Assert::AreEqual(1ull, sut.revision);
|
||||
}
|
||||
TEST_METHOD (emptyStringNotAccepted)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (invalidStringNotAccepted1)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("v2a.");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (invalidStringNotAccepted2)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("12abc2vv.0");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (invalidStringNotAccepted3)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("123");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (invalidStringNotAccepted4)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("v1v2v3");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (invalidStringNotAccepted5)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("v.1.2.3v");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (partialVersionStringNotAccepted1)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("v1.");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (partialVersionStringNotAccepted2)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("v1.2");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (partialVersionStringNotAccepted3)
|
||||
{
|
||||
Assert::ExpectException<std::logic_error>([] {
|
||||
VersionHelper sut("v1.2.");
|
||||
});
|
||||
}
|
||||
TEST_METHOD (parsedWithoutLeadingV)
|
||||
{
|
||||
VersionHelper expected{ 12ull, 13ull, 111ull };
|
||||
VersionHelper actual("12.13.111");
|
||||
Assert::AreEqual(actual, expected);
|
||||
}
|
||||
TEST_METHOD (whenMajorVersionIsGreaterComparisonOperatorShouldReturnProperValue)
|
||||
{
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#include "pch.h"
|
||||
#include "VersionHelper.h"
|
||||
|
||||
#include "string_utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
VersionHelper::VersionHelper(std::string str)
|
||||
{
|
||||
std::replace(str.begin(), str.end(), '.', ' ');
|
||||
std::replace(str.begin(), str.end(), 'v', ' ');
|
||||
std::stringstream ss;
|
||||
// Remove whitespaces chars and a leading 'v'
|
||||
str = left_trim(trim(str), "v");
|
||||
// Replace '.' with spaces
|
||||
replace_chars(str, ".", ' ');
|
||||
|
||||
ss << str;
|
||||
|
||||
std::string temp;
|
||||
ss >> temp;
|
||||
std::stringstream(temp) >> major;
|
||||
ss >> temp;
|
||||
std::stringstream(temp) >> minor;
|
||||
ss >> temp;
|
||||
std::stringstream(temp) >> revision;
|
||||
std::istringstream ss{ str };
|
||||
ss >> major;
|
||||
ss >> minor;
|
||||
ss >> revision;
|
||||
if (ss.fail() || !ss.eof())
|
||||
{
|
||||
throw std::logic_error("VersionHelper: couldn't parse the supplied version string");
|
||||
}
|
||||
}
|
||||
|
||||
VersionHelper::VersionHelper(int major, int minor, int revision) :
|
||||
major(major),
|
||||
minor(minor),
|
||||
revision(revision)
|
||||
VersionHelper::VersionHelper(const size_t major, const size_t minor, const size_t revision) :
|
||||
major{ major },
|
||||
minor{ minor },
|
||||
revision{ revision }
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
struct VersionHelper
|
||||
{
|
||||
VersionHelper(std::string str);
|
||||
VersionHelper(int major, int minor, int revision);
|
||||
VersionHelper(const size_t major, const size_t minor, const size_t revision);
|
||||
|
||||
auto operator<=>(const VersionHelper&) const = default;
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int revision;
|
||||
size_t major;
|
||||
size_t minor;
|
||||
size_t revision;
|
||||
|
||||
std::wstring toWstring() const;
|
||||
};
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
<ClInclude Include="os-detect.h" />
|
||||
<ClInclude Include="RestartManagement.h" />
|
||||
<ClInclude Include="shared_constants.h" />
|
||||
<ClInclude Include="string_utils.h" />
|
||||
<ClInclude Include="timeutil.h" />
|
||||
<ClInclude Include="two_way_pipe_message_ipc.h" />
|
||||
<ClInclude Include="VersionHelper.h" />
|
||||
|
||||
@@ -131,13 +131,16 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="comUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LowlevelKeyboardEvent.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WinHookEvent.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="string_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="d2d_svg.cpp">
|
||||
@@ -223,4 +226,4 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -34,10 +34,10 @@ D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float ma
|
||||
transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f);
|
||||
float h_scale = fill * height / svg_height;
|
||||
float v_scale = fill * width / svg_width;
|
||||
used_scale = min(h_scale, v_scale);
|
||||
used_scale = std::min(h_scale, v_scale);
|
||||
if (max_scale > 0)
|
||||
{
|
||||
used_scale = min(used_scale, max_scale);
|
||||
used_scale = std::min(used_scale, max_scale);
|
||||
}
|
||||
transform = transform * D2D1::Matrix3x2F::Scale(used_scale, used_scale, D2D1::Point2F(width / 2.0f, height / 2.0f));
|
||||
transform = transform * D2D1::Matrix3x2F::Translation((float)x, (float)y);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#define NOMINMAX
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <Windows.h>
|
||||
|
||||
32
src/common/string_utils.h
Normal file
32
src/common/string_utils.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
constexpr inline std::string_view default_trim_arg = " \t\r\n";
|
||||
|
||||
inline std::string_view left_trim(std::string_view s, const std::string_view chars_to_trim = default_trim_arg)
|
||||
{
|
||||
s.remove_prefix(std::min(s.find_first_not_of(chars_to_trim), size(s)));
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string_view right_trim(std::string_view s, const std::string_view chars_to_trim = default_trim_arg)
|
||||
{
|
||||
s.remove_suffix(std::min(size(s) - s.find_last_not_of(chars_to_trim) - 1, size(s)));
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::string_view trim(std::string_view s, const std::string_view chars_to_trim = default_trim_arg)
|
||||
{
|
||||
return left_trim(right_trim(s, chars_to_trim), chars_to_trim);
|
||||
}
|
||||
|
||||
inline void replace_chars(std::string& s, const std::string_view chars_to_replace, const char replacement_char)
|
||||
{
|
||||
for (const char c : chars_to_replace)
|
||||
{
|
||||
std::replace(begin(s), end(s), c, replacement_char);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user