mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-13 04:42:43 -06:00
271 lines
11 KiB
C++
271 lines
11 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
|
|
using namespace WEX::Common;
|
|
using namespace WEX::Logging;
|
|
using namespace WEX::TestExecution;
|
|
|
|
template<>
|
|
class WEX::TestExecution::VerifyOutputTraits<std::vector<std::wstring>>
|
|
{
|
|
public:
|
|
static WEX::Common::NoThrowString ToString(const std::vector<std::wstring>& vec)
|
|
{
|
|
WEX::Common::NoThrowString str;
|
|
str.Append(L"{ ");
|
|
for (size_t i = 0; i < vec.size(); ++i)
|
|
{
|
|
str.Append(i == 0 ? L"\"" : L", \"");
|
|
str.Append(vec[i].c_str());
|
|
str.Append(L"\"");
|
|
}
|
|
str.Append(L" }");
|
|
return str;
|
|
}
|
|
};
|
|
|
|
class StringTests
|
|
{
|
|
TEST_CLASS(StringTests);
|
|
|
|
TEST_METHOD(VisualizeControlCodes)
|
|
{
|
|
const std::wstring_view input{ L"\u001b[A \u001b[B\x7f" };
|
|
const std::wstring_view expected{ L"\u241b[A\u2423\u241b[B\x2421" };
|
|
const auto actual = til::visualize_control_codes(input);
|
|
VERIFY_ARE_EQUAL(expected, actual);
|
|
}
|
|
|
|
TEST_METHOD(starts_with)
|
|
{
|
|
VERIFY_IS_TRUE(til::starts_with("", ""));
|
|
|
|
VERIFY_IS_TRUE(til::starts_with("abc", ""));
|
|
VERIFY_IS_TRUE(til::starts_with("abc", "a"));
|
|
VERIFY_IS_TRUE(til::starts_with("abc", "ab"));
|
|
VERIFY_IS_TRUE(til::starts_with("abc", "abc"));
|
|
VERIFY_IS_FALSE(til::starts_with("abc", "abcd"));
|
|
|
|
VERIFY_IS_FALSE(til::starts_with("", "abc"));
|
|
VERIFY_IS_FALSE(til::starts_with("a", "abc"));
|
|
VERIFY_IS_FALSE(til::starts_with("ab", "abc"));
|
|
VERIFY_IS_TRUE(til::starts_with("abc", "abc"));
|
|
VERIFY_IS_TRUE(til::starts_with("abcd", "abc"));
|
|
}
|
|
|
|
TEST_METHOD(ends_with)
|
|
{
|
|
VERIFY_IS_TRUE(til::ends_with("", ""));
|
|
|
|
VERIFY_IS_TRUE(til::ends_with("abc", ""));
|
|
VERIFY_IS_TRUE(til::ends_with("abc", "c"));
|
|
VERIFY_IS_TRUE(til::ends_with("abc", "bc"));
|
|
VERIFY_IS_TRUE(til::ends_with("abc", "abc"));
|
|
VERIFY_IS_FALSE(til::ends_with("abc", "0abc"));
|
|
|
|
VERIFY_IS_FALSE(til::ends_with("", "abc"));
|
|
VERIFY_IS_FALSE(til::ends_with("c", "abc"));
|
|
VERIFY_IS_FALSE(til::ends_with("bc", "abc"));
|
|
VERIFY_IS_TRUE(til::ends_with("abc", "abc"));
|
|
VERIFY_IS_TRUE(til::ends_with("0abc", "abc"));
|
|
}
|
|
|
|
// Normally this would be the spot where you'd find a TEST_METHOD(parse_u64).
|
|
// I didn't quite trust my coding skills and thus opted to use fuzz-testing.
|
|
// The below function was used to test parse_u64 for unsafety and conformance with clang's strtoul.
|
|
// The test was run as:
|
|
// clang++ -fsanitize=address,undefined,fuzzer -std=c++17 file.cpp
|
|
// and was run for 20min across 16 jobs in parallel.
|
|
#if 0
|
|
template<typename T, typename Traits>
|
|
std::optional<uint64_t> parse_u64(const std::basic_string_view<T, Traits>& str, int base = 0) noexcept
|
|
{
|
|
// ... implementation ...
|
|
}
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|
{
|
|
while (size > 0 && (isspace(*data) || *data == '+' || *data == '-'))
|
|
{
|
|
--size;
|
|
++data;
|
|
}
|
|
|
|
if (size == 0 || size > 127)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
char narrow_buffer[128];
|
|
memcpy(narrow_buffer, data, size);
|
|
// strtoul requires a null terminator
|
|
narrow_buffer[size] = 0;
|
|
|
|
char* end;
|
|
const auto val = strtoull(narrow_buffer, &end, 0);
|
|
const auto bad = end != narrow_buffer + size || val == ULLONG_MAX;
|
|
const auto expected = bad ? std::nullopt : std::optional{ val };
|
|
|
|
const auto actual = parse_u64(std::string_view{ narrow_buffer, size });
|
|
if (expected != actual && actual.value_or(0) != ULLONG_MAX)
|
|
{
|
|
__builtin_trap();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
TEST_METHOD(parse_u64_overflow)
|
|
{
|
|
VERIFY_ARE_EQUAL(UINT64_C(18446744073709551614), til::details::parse_u64(std::string_view{ "18446744073709551614" }));
|
|
VERIFY_ARE_EQUAL(UINT64_C(18446744073709551615), til::details::parse_u64(std::string_view{ "18446744073709551615" }));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::details::parse_u64(std::string_view{ "18446744073709551616" }));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::details::parse_u64(std::string_view{ "18446744073709551617" }));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::details::parse_u64(std::string_view{ "88888888888888888888" }));
|
|
}
|
|
|
|
TEST_METHOD(parse_unsigned)
|
|
{
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>(""));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("0x"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("Z"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("0xZ"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("0Z"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("123abc"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("0123abc"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_unsigned<uint32_t>("0x100000000"));
|
|
VERIFY_ARE_EQUAL(0u, til::parse_unsigned<uint32_t>("0"));
|
|
VERIFY_ARE_EQUAL(0u, til::parse_unsigned<uint32_t>("0x0"));
|
|
VERIFY_ARE_EQUAL(0123u, til::parse_unsigned<uint32_t>("0123"));
|
|
VERIFY_ARE_EQUAL(123u, til::parse_unsigned<uint32_t>("123"));
|
|
VERIFY_ARE_EQUAL(0x123u, til::parse_unsigned<uint32_t>("0x123"));
|
|
VERIFY_ARE_EQUAL(0x123abcu, til::parse_unsigned<uint32_t>("0x123abc"));
|
|
VERIFY_ARE_EQUAL(0X123ABCu, til::parse_unsigned<uint32_t>("0X123ABC"));
|
|
VERIFY_ARE_EQUAL(UINT32_MAX, til::parse_unsigned<uint32_t>("0xffffffff"));
|
|
VERIFY_ARE_EQUAL(UINT32_MAX, til::parse_unsigned<uint32_t>("4294967295"));
|
|
}
|
|
|
|
TEST_METHOD(parse_signed)
|
|
{
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>(""));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("-"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("--"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("--0"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("-0Z"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("-123abc"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("-0123abc"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("0x80000000"));
|
|
VERIFY_ARE_EQUAL(std::nullopt, til::parse_signed<int32_t>("-0x80000001"));
|
|
VERIFY_ARE_EQUAL(0, til::parse_signed<int32_t>("0"));
|
|
VERIFY_ARE_EQUAL(0, til::parse_signed<int32_t>("-0"));
|
|
VERIFY_ARE_EQUAL(0, til::parse_signed<int32_t>("-0x0"));
|
|
VERIFY_ARE_EQUAL(0123, til::parse_signed<int32_t>("0123"));
|
|
VERIFY_ARE_EQUAL(123, til::parse_signed<int32_t>("123"));
|
|
VERIFY_ARE_EQUAL(0x123, til::parse_signed<int32_t>("0x123"));
|
|
VERIFY_ARE_EQUAL(-0123, til::parse_signed<int32_t>("-0123"));
|
|
VERIFY_ARE_EQUAL(-123, til::parse_signed<int32_t>("-123"));
|
|
VERIFY_ARE_EQUAL(-0x123, til::parse_signed<int32_t>("-0x123"));
|
|
VERIFY_ARE_EQUAL(-0x123abc, til::parse_signed<int32_t>("-0x123abc"));
|
|
VERIFY_ARE_EQUAL(-0X123ABC, til::parse_signed<int32_t>("-0X123ABC"));
|
|
VERIFY_ARE_EQUAL(INT32_MIN, til::parse_signed<int32_t>("-0x80000000"));
|
|
VERIFY_ARE_EQUAL(INT32_MIN, til::parse_signed<int32_t>("-2147483648"));
|
|
VERIFY_ARE_EQUAL(INT32_MAX, til::parse_signed<int32_t>("0x7fffffff"));
|
|
VERIFY_ARE_EQUAL(INT32_MAX, til::parse_signed<int32_t>("2147483647"));
|
|
}
|
|
|
|
TEST_METHOD(tolower_ascii)
|
|
{
|
|
for (wchar_t ch = 0; ch < 128; ++ch)
|
|
{
|
|
VERIFY_ARE_EQUAL(std::towlower(ch), til::tolower_ascii(ch));
|
|
}
|
|
}
|
|
|
|
TEST_METHOD(toupper_ascii)
|
|
{
|
|
for (wchar_t ch = 0; ch < 128; ++ch)
|
|
{
|
|
VERIFY_ARE_EQUAL(std::towupper(ch), til::toupper_ascii(ch));
|
|
}
|
|
}
|
|
|
|
TEST_METHOD(equals_insensitive_ascii)
|
|
{
|
|
VERIFY_IS_TRUE(til::equals_insensitive_ascii("", ""));
|
|
VERIFY_IS_FALSE(til::equals_insensitive_ascii("", "foo"));
|
|
VERIFY_IS_FALSE(til::equals_insensitive_ascii("foo", "fo"));
|
|
VERIFY_IS_FALSE(til::equals_insensitive_ascii("fooo", "foo"));
|
|
VERIFY_IS_TRUE(til::equals_insensitive_ascii("cOUnterStriKE", "COuntERStRike"));
|
|
}
|
|
|
|
TEST_METHOD(split_iterator)
|
|
{
|
|
static constexpr auto split = [](const std::string_view& str, const char needle) {
|
|
std::vector<std::string_view> substrings;
|
|
for (auto&& s : til::split_iterator{ str, needle })
|
|
{
|
|
substrings.emplace_back(s);
|
|
}
|
|
return substrings;
|
|
};
|
|
|
|
std::vector<std::string_view> expected;
|
|
std::vector<std::string_view> actual;
|
|
|
|
expected = { "foo" };
|
|
actual = split("foo", ' ');
|
|
VERIFY_ARE_EQUAL(expected, actual);
|
|
|
|
expected = { "", "foo" };
|
|
actual = split(" foo", ' ');
|
|
VERIFY_ARE_EQUAL(expected, actual);
|
|
|
|
expected = { "foo", "" };
|
|
actual = split("foo ", ' ');
|
|
VERIFY_ARE_EQUAL(expected, actual);
|
|
|
|
expected = { "foo", "bar", "baz" };
|
|
actual = split("foo bar baz", ' ');
|
|
VERIFY_ARE_EQUAL(expected, actual);
|
|
|
|
expected = { "", "", "foo", "", "bar", "", "" };
|
|
actual = split(";;foo;;bar;;", ';');
|
|
VERIFY_ARE_EQUAL(expected, actual);
|
|
}
|
|
|
|
TEST_METHOD(CleanPathAndFilename)
|
|
{
|
|
VERIFY_ARE_EQUAL(LR"(CUsersGeddyMusicAnalog Man)", til::clean_filename(LR"(C:\Users\Geddy\Music\"Analog Man")"));
|
|
VERIFY_ARE_EQUAL(LR"(C:\Users\Geddy\Music\Analog Man)", til::clean_path(LR"(C:\Users\Geddy\Music\"Analog Man")"));
|
|
}
|
|
|
|
TEST_METHOD(LegalPath)
|
|
{
|
|
VERIFY_IS_TRUE(til::is_legal_path(LR"(C:\Users\Documents and Settings\Users\;\Why not)"));
|
|
VERIFY_IS_FALSE(til::is_legal_path(LR"(C:\Users\Documents and Settings\"Quote-un-quote users")"));
|
|
}
|
|
|
|
TEST_METHOD(IterateFontFamilies)
|
|
{
|
|
static constexpr auto expected = [](auto&&... args) {
|
|
return std::vector<std::wstring>{ std::forward<decltype(args)>(args)... };
|
|
};
|
|
static constexpr auto actual = [](std::wstring_view families) {
|
|
std::vector<std::wstring> split;
|
|
til::iterate_font_families(families, [&](std::wstring&& str) {
|
|
split.emplace_back(std::move(str));
|
|
});
|
|
return split;
|
|
};
|
|
|
|
VERIFY_ARE_EQUAL(expected(L"foo", L" b a r ", LR"(b"az)"), actual(LR"( foo ," b a r ",b\"az)"));
|
|
VERIFY_ARE_EQUAL(expected(LR"(foo, bar)"), actual(LR"("foo, bar")"));
|
|
VERIFY_ARE_EQUAL(expected(LR"("foo")", LR"('bar')"), actual(LR"('"foo"', "'bar'")"));
|
|
VERIFY_ARE_EQUAL(expected(LR"("foo")", LR"('bar')"), actual(LR"("\"foo\"", '\'bar\'')"));
|
|
VERIFY_ARE_EQUAL(expected(L"foo"), actual(LR"(,,,,foo,,,,)"));
|
|
}
|
|
};
|