Skip to content

Commit

Permalink
common: do not accept invalid input in VersionHelper and add negative…
Browse files Browse the repository at this point in the history
… unit tests
  • Loading branch information
yuyoyuppe committed Aug 28, 2020
1 parent 870f109 commit fc4ac80
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 36 deletions.
93 changes: 81 additions & 12 deletions src/common/UnitTests-CommonLib/UnitTestsVersionHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
Expand All @@ -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)
{
Expand Down
34 changes: 18 additions & 16 deletions src/common/VersionHelper.cpp
Original file line number Diff line number Diff line change
@@ -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;

ss << str;
// Remove whitespaces chars and a leading 'v'
str = left_trim(trim(str), "v");
// Replace '.' with spaces
replace_chars(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 }
{
}

Expand Down
8 changes: 4 additions & 4 deletions src/common/VersionHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
1 change: 1 addition & 0 deletions src/common/common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
7 changes: 5 additions & 2 deletions src/common/common.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -223,4 +226,4 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>
</Project>
4 changes: 2 additions & 2 deletions src/common/d2d_svg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/common/pch.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define NOMINMAX
#include <winrt/base.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <Windows.h>
Expand Down
32 changes: 32 additions & 0 deletions src/common/string_utils.h
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit fc4ac80

Please sign in to comment.