1
0

refactor: rename testbench to test.

- rename testbench to test.
- add benchmark for future development.
This commit is contained in:
2025-09-29 13:34:02 +08:00
parent 82c3ed5b32
commit e7a05b3488
44 changed files with 55 additions and 19 deletions

65
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,65 @@
# Create executable test
add_executable(YYCCTest "")
# Setup test sources
target_sources(YYCCTest
PRIVATE
main.cpp
shared/literals.cpp
yycc/macro/version_cmp.cpp
yycc/macro/os_detector.cpp
yycc/macro/compiler_detector.cpp
yycc/macro/endian_detector.cpp
yycc/macro/ptr_size_detector.cpp
yycc/macro/stl_detector.cpp
yycc/flag_enum.cpp
yycc/constraint.cpp
yycc/constraint/builder.cpp
yycc/patch/ptr_pad.cpp
yycc/patch/fopen.cpp
yycc/patch/stream.cpp
yycc/patch/format.cpp
yycc/rust/env.cpp
yycc/string/reinterpret.cpp
yycc/string/op.cpp
yycc/num/parse.cpp
yycc/num/stringify.cpp
yycc/num/op.cpp
yycc/num/safe_cast.cpp
yycc/num/safe_op.cpp
yycc/encoding/stl.cpp
yycc/encoding/windows.cpp
yycc/encoding/iconv.cpp
yycc/windows/com.cpp
yycc/windows/dialog.cpp
yycc/windows/winfct.cpp
yycc/windows/console.cpp
yycc/carton/pycodec.cpp
yycc/carton/termcolor.cpp
yycc/carton/wcwidth.cpp
yycc/carton/tabulate.cpp
yycc/carton/clap.cpp
)
target_sources(YYCCTest
PRIVATE
FILE_SET HEADERS
FILES
shared/literals.hpp
)
# Setup headers
target_include_directories(YYCCTest
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}"
)
# Setup libraries
target_link_libraries(YYCCTest
PRIVATE
YYCCommonplace
GTest::gtest_main
)
# Discover all test
include(GoogleTest)
gtest_discover_tests(YYCCTest)

6
test/main.cpp Normal file
View File

@ -0,0 +1,6 @@
#include <gtest/gtest.h>
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

310
test/main_legacy.cpp Normal file
View File

@ -0,0 +1,310 @@
#include <YYCCommonplace.hpp>
#include <cstdio>
#include <set>
#include <map>
namespace Console = YYCC::ConsoleHelper;
namespace YYCCTestbench {
static void Assert(bool condition, const YYCC::yycc_char8_t* description) {
if (condition) {
Console::FormatLine(YYCC_U8(YYCC_COLOR_LIGHT_GREEN("OK: %s")), description);
} else {
Console::FormatLine(YYCC_U8(YYCC_COLOR_LIGHT_RED("Failed: %s\n")), description);
std::abort();
}
}
static void ConsoleTestbench() {
// UTF8 Output Test
Console::WriteLine(YYCC_U8("UTF8 Output Test:"));
for (const auto& strl : c_UTF8TestStrTable) {
Console::FormatLine(YYCC_U8("\t%s"), strl.c_str());
}
// UTF8 Input Test
Console::WriteLine(YYCC_U8("UTF8 Input Test:"));
for (const auto& strl : c_UTF8TestStrTable) {
Console::FormatLine(YYCC_U8("\tPlease type: %s"), strl.c_str());
Console::Write(YYCC_U8("\t> "));
YYCC::yycc_u8string gotten(Console::ReadLine());
if (gotten == strl) Console::FormatLine(YYCC_U8(YYCC_COLOR_LIGHT_GREEN("\tMatched! Got: %s")), gotten.c_str());
else Console::FormatLine(YYCC_U8(YYCC_COLOR_LIGHT_RED("\tNOT Matched! Got: %s")), gotten.c_str());
}
}
static void ExceptionTestbench() {
#if defined(YYCC_OS_WINDOWS)
YYCC::ExceptionHelper::Register([](const YYCC::yycc_u8string& log_path, const YYCC::yycc_u8string& coredump_path) -> void {
MessageBoxW(
NULL,
YYCC::EncodingHelper::UTF8ToWchar(
YYCC::StringHelper::Printf(YYCC_U8("Log generated:\nLog path: %s\nCore dump path: %s"), log_path.c_str(), coredump_path.c_str())
).c_str(),
L"Fatal Error", MB_OK + MB_ICONERROR
);
}
);
// Perform a div zero exception.
#if defined (YYCC_DEBUG_UE_FILTER)
// Reference: https://stackoverflow.com/questions/20981982/is-it-possible-to-debug-unhandledexceptionfilters-with-a-debugger
__try {
// all of code normally inside of main or WinMain here...
int i = 1, j = 0;
int k = i / j;
} __except (YYCC::ExceptionHelper::DebugCallUExceptionImpl(GetExceptionInformation())) {
OutputDebugStringW(L"executed filter function\n");
}
#else
int i = 1, j = 0;
int k = i / j;
#endif
YYCC::ExceptionHelper::Unregister();
#endif
}
enum class TestEnum : int8_t {
Test1, Test2, Test3
};
class TestConfigManager {
public:
TestConfigManager() :
m_IntSetting(YYCC_U8("int-setting"), INT32_C(0)),
m_FloatSetting(YYCC_U8("float-setting"), 0.0f),
m_StringSetting(YYCC_U8("string-setting"), YYCC_U8("")),
m_BoolSetting(YYCC_U8("bool-setting"), false),
m_ClampedFloatSetting(YYCC_U8("clamped-float-setting"), 0.0f, YYCC::Constraints::GetMinMaxRangeConstraint<float>(-1.0f, 1.0f)),
m_EnumSetting(YYCC_U8("enum-setting"), TestEnum::Test1),
m_CoreManager(YYCC_U8("test.cfg"), UINT64_C(0), {
&m_IntSetting, &m_FloatSetting, &m_StringSetting, &m_BoolSetting, &m_ClampedFloatSetting, &m_EnumSetting
}) {}
~TestConfigManager() {}
void PrintSettings() {
Console::WriteLine(YYCC_U8("Config Manager Settings:"));
Console::FormatLine(YYCC_U8("\tint-setting: %" PRIi32), m_IntSetting.Get());
Console::FormatLine(YYCC_U8("\tfloat-setting: %f"), m_FloatSetting.Get());
Console::FormatLine(YYCC_U8("\tstring-setting: %s"), m_StringSetting.Get().c_str());
Console::FormatLine(YYCC_U8("\tbool-setting: %s"), m_BoolSetting.Get() ? YYCC_U8("true") : YYCC_U8("false"));
Console::FormatLine(YYCC_U8("\tfloat-setting: %f"), m_ClampedFloatSetting.Get());
Console::FormatLine(YYCC_U8("\tenum-setting: %" PRIi8), static_cast<std::underlying_type_t<TestEnum>>(m_EnumSetting.Get()));
}
YYCC::ConfigManager::NumberSetting<int32_t> m_IntSetting;
YYCC::ConfigManager::NumberSetting<float> m_FloatSetting;
YYCC::ConfigManager::StringSetting m_StringSetting;
YYCC::ConfigManager::NumberSetting<bool> m_BoolSetting;
YYCC::ConfigManager::NumberSetting<float> m_ClampedFloatSetting;
YYCC::ConfigManager::NumberSetting<TestEnum> m_EnumSetting;
YYCC::ConfigManager::CoreManager m_CoreManager;
};
static void ConfigManagerTestbench() {
// init cfg manager
TestConfigManager test;
// test constraint works
Assert(!test.m_ClampedFloatSetting.Set(2.0f), YYCC_U8("YYCC::Constraints::Constraint"));
Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::Constraints::Constraint"));
// test modify settings
#define TEST_MACRO(member_name, set_val) { \
Assert(test.member_name.Set(set_val), YYCC_U8("YYCC::ConfigManager::AbstractSetting::Set")); \
Assert(test.member_name.Get() == set_val, YYCC_U8("YYCC::ConfigManager::AbstractSetting::Set")); \
}
TEST_MACRO(m_IntSetting, INT32_C(114));
TEST_MACRO(m_FloatSetting, 2.0f);
TEST_MACRO(m_StringSetting, YYCC_U8("fuck"));
TEST_MACRO(m_BoolSetting, true);
TEST_MACRO(m_ClampedFloatSetting, 0.5f);
TEST_MACRO(m_EnumSetting, TestEnum::Test2);
#undef TEST_MACRO
// test save
test.PrintSettings();
Assert(test.m_CoreManager.Save(), YYCC_U8("YYCC::ConfigManager::CoreManager::Save"));
// test reset
test.m_CoreManager.Reset();
test.PrintSettings();
Assert(test.m_IntSetting.Get() == INT32_C(0), YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_FloatSetting.Get() == 0.0f, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_StringSetting.Get() == YYCC_U8(""), YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_BoolSetting.Get() == false, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
Assert(test.m_EnumSetting.Get() == TestEnum::Test1, YYCC_U8("YYCC::ConfigManager::CoreManager::Reset"));
// test load
YYCC::ConfigManager::ConfigLoadResult wrong_result = YYCC::EnumHelper::Merge(
YYCC::ConfigManager::ConfigLoadResult::ItemError,
YYCC::ConfigManager::ConfigLoadResult::BrokenFile
);
Assert(!YYCC::EnumHelper::Has(test.m_CoreManager.Load(), wrong_result), YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
test.PrintSettings();
Assert(test.m_IntSetting.Get() == INT32_C(114), YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_FloatSetting.Get() == 2.0f, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_StringSetting.Get() == YYCC_U8("fuck"), YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_BoolSetting.Get() == true, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_ClampedFloatSetting.Get() == 0.5f, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
Assert(test.m_EnumSetting.Get() == TestEnum::Test2, YYCC_U8("YYCC::ConfigManager::CoreManager::Load"));
}
class TestArgParser {
public:
TestArgParser() :
m_IntArgument(YYCC_U8("int"), YYCC_U8_CHAR('i'), YYCC_U8("integral argument"), YYCC_U8("114514")),
m_FloatArgument(nullptr, YYCC_U8_CHAR('f'), nullptr, nullptr, true),
m_StringArgument(YYCC_U8("string"), YYCC::ArgParser::AbstractArgument::NO_SHORT_NAME, nullptr, nullptr, true),
m_BoolArgument(nullptr, YYCC_U8_CHAR('b'), nullptr),
m_ClampedFloatArgument(YYCC_U8("clamped-float"), YYCC::ArgParser::AbstractArgument::NO_SHORT_NAME, nullptr, nullptr, true, YYCC::Constraints::GetMinMaxRangeConstraint<float>(-1.0f, 1.0f)),
m_OptionContext(YYCC_U8("TestArgParser"), YYCC_U8("This is the testbench of argument parser."), {
&m_IntArgument, &m_FloatArgument, &m_StringArgument,
&m_BoolArgument, &m_ClampedFloatArgument
}) {}
~TestArgParser() {}
YYCC::ArgParser::NumberArgument<int32_t> m_IntArgument;
YYCC::ArgParser::NumberArgument<float> m_FloatArgument;
YYCC::ArgParser::StringArgument m_StringArgument;
YYCC::ArgParser::SwitchArgument m_BoolArgument;
YYCC::ArgParser::NumberArgument<float> m_ClampedFloatArgument;
YYCC::ArgParser::OptionContext m_OptionContext;
};
static void ArgParserTestbench(int argc, char* argv[]) {
// test command line getter
{
YYCC::ConsoleHelper::WriteLine(YYCC_U8("YYCC::ArgParser::ArgumentList::CreateFromStd"));
auto result = YYCC::ArgParser::ArgumentList::CreateFromStd(argc, argv);
for (result.Reset(); !result.IsEOF(); result.Next()) {
YYCC::ConsoleHelper::FormatLine(YYCC_U8("\t%s"), result.Argument().c_str());
}
}
#if defined(YYCC_OS_WINDOWS)
{
YYCC::ConsoleHelper::WriteLine(YYCC_U8("YYCC::ArgParser::ArgumentList::CreateFromWin32"));
auto result = YYCC::ArgParser::ArgumentList::CreateFromWin32();
for (result.Reset(); !result.IsEOF(); result.Next()) {
YYCC::ConsoleHelper::FormatLine(YYCC_U8("\t%s"), result.Argument().c_str());
}
}
#endif
// test option context
// init option context
TestArgParser test;
#define PREPARE_DATA(...) const char* test_argv[] = { __VA_ARGS__ }; \
auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(sizeof(test_argv) / sizeof(char*), const_cast<char**>(test_argv));
// normal test
{
PREPARE_DATA("exec", "-i", "114514");
Assert(test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(test.m_IntArgument.IsCaptured() && test.m_IntArgument.Get() == UINT32_C(114514), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(!test.m_BoolArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(!test.m_FloatArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(!test.m_StringArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(!test.m_BoolArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(!test.m_ClampedFloatArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// no argument
{
PREPARE_DATA("exec");
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// error argument
{
PREPARE_DATA("exec", "-?", "114514");
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// lost argument
{
PREPARE_DATA("exec", "-i");
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// dplicated assign
{
PREPARE_DATA("exec", "-i", "114514" "--int", "114514");
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// extra useless argument
{
PREPARE_DATA("exec", "-i", "114514" "1919810");
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// invalid clamp argument
{
PREPARE_DATA("exec", "-i", "114514", "--clamped-float", "114.0");
Assert(!test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// full argument
{
PREPARE_DATA("exec", "-i", "114514", "-f", "2.0", "--string", "fuck", "-b", "--clamped-float", "0.5");
Assert(test.m_OptionContext.Parse(al), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(test.m_IntArgument.IsCaptured() && test.m_IntArgument.Get() == UINT32_C(114514), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(test.m_FloatArgument.IsCaptured() && test.m_FloatArgument.Get() == 2.0f, YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(test.m_StringArgument.IsCaptured() && test.m_StringArgument.Get() == YYCC_U8("fuck"), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(test.m_BoolArgument.IsCaptured(), YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
Assert(test.m_ClampedFloatArgument.IsCaptured() && test.m_ClampedFloatArgument.Get() == 0.5f, YYCC_U8("YYCC::ArgParser::OptionContext::Parse"));
test.m_OptionContext.Reset();
}
// Help text
test.m_OptionContext.Help();
#undef PREPARE_DATA
}
}
int main(int argc, char* argv[]) {
#if YYCC_VERCMP_NE(YYCC_VER_MAJOR, YYCC_VER_MINOR, YYCC_VER_PATCH, 1, 3 ,0)
#error "The YYCC library used when compiling is not match code expected, this may cause build error."
#error "If you trust it, please annotate these preprocessor statement, otherwise please contact developer."
#endif
// common testbench
// normal
YYCCTestbench::EncodingTestbench();
YYCCTestbench::StringTestbench();
YYCCTestbench::ParserTestbench();
YYCCTestbench::WinFctTestbench();
YYCCTestbench::StdPatchTestbench();
YYCCTestbench::EnumHelperTestbench();
YYCCTestbench::VersionMacroTestbench();
// advanced
YYCCTestbench::ConfigManagerTestbench();
YYCCTestbench::ArgParserTestbench(argc, argv);
// testbench which may terminal app or ordering input
YYCCTestbench::ConsoleTestbench();
YYCCTestbench::DialogTestbench();
YYCCTestbench::ExceptionTestbench();
}

203
test/shared/literals.cpp Normal file
View File

@ -0,0 +1,203 @@
#include "literals.hpp"
#include <stdexcept>
namespace yyccshared::literals {
#define CONCAT(prefix, strl) prefix##strl
#define U8_LITERAL(strl) CONCAT(u8, strl)
#define U16_LITERAL(strl) CONCAT(u, strl)
#define U32_LITERAL(strl) CONCAT(U, strl)
#define WSTR_LITERAL(strl) CONCAT(L, strl)
#pragma region UtfLiterals Data
// UNICODE Test Strings
// Ref: https://stackoverflow.com/questions/478201/how-to-test-an-application-for-correct-encoding-e-g-utf-8
#define UNICODE_STR_JAPAN "\u30E6\u30FC\u30B6\u30FC\u5225\u30B5\u30A4\u30C8"
#define UNICODE_STR_CHINA "\u7B80\u4F53\u4E2D\u6587"
#define UNICODE_STR_KOREA "\uD06C\uB85C\uC2A4 \uD50C\uB7AB\uD3FC\uC73C\uB85C"
#define UNICODE_STR_ISRAEL "\u05DE\u05D3\u05D5\u05E8\u05D9\u05DD \u05DE\u05D1\u05D5\u05E7\u05E9\u05D9\u05DD"
#define UNICODE_STR_EGYPT "\u0623\u0641\u0636\u0644 \u0627\u0644\u0628\u062D\u0648\u062B"
#define UNICODE_STR_GREECE "\u03A3\u1F72 \u03B3\u03BD\u03C9\u03C1\u03AF\u03B6\u03C9 \u1F00\u03C0\u1F78"
#define UNICODE_STR_RUSSIA \
"\u0414\u0435\u0441\u044F\u0442\u0443\u044E \u041C\u0435\u0436\u0434\u0443\u043D\u0430\u0440\u043E\u0434\u043D\u0443\u044E"
#define UNICODE_STR_THAILAND \
"\u0E41\u0E1C\u0E48\u0E19\u0E14\u0E34\u0E19\u0E2E\u0E31\u0E48\u0E19\u0E40\u0E2A\u0E37\u0E48\u0E2D\u0E21\u0E42\u0E17\u0E23\u0E21\u0E41\u0E2A\u0E19\u0E2A\u0E31\u0E07\u0E40\u0E27\u0E0A"
#define UNICODE_STR_FRANCE "fran\u00E7ais langue \u00E9trang\u00E8re"
#define UNICODE_STR_SPAIN "ma\u00F1ana ol\u00E9"
#define UNICODE_STR_MATHMATICS "\u222E E\u22C5da = Q, n \u2192 \u221E, \u2211 f(i) = \u220F g(i)"
#define UNICODE_STR_EMOJI "\U0001F363 \u2716 \U0001F37A" // sushi x beer mug
static std::vector<std::u8string> UTFLIT_U8STR_VEC{
U8_LITERAL(UNICODE_STR_JAPAN),
U8_LITERAL(UNICODE_STR_CHINA),
U8_LITERAL(UNICODE_STR_KOREA),
U8_LITERAL(UNICODE_STR_ISRAEL),
U8_LITERAL(UNICODE_STR_EGYPT),
U8_LITERAL(UNICODE_STR_GREECE),
U8_LITERAL(UNICODE_STR_RUSSIA),
U8_LITERAL(UNICODE_STR_THAILAND),
U8_LITERAL(UNICODE_STR_FRANCE),
U8_LITERAL(UNICODE_STR_SPAIN),
U8_LITERAL(UNICODE_STR_MATHMATICS),
U8_LITERAL(UNICODE_STR_EMOJI),
};
static std::vector<std::wstring> UTFLIT_WSTR_VEC{
WSTR_LITERAL(UNICODE_STR_JAPAN),
WSTR_LITERAL(UNICODE_STR_CHINA),
WSTR_LITERAL(UNICODE_STR_KOREA),
WSTR_LITERAL(UNICODE_STR_ISRAEL),
WSTR_LITERAL(UNICODE_STR_EGYPT),
WSTR_LITERAL(UNICODE_STR_GREECE),
WSTR_LITERAL(UNICODE_STR_RUSSIA),
WSTR_LITERAL(UNICODE_STR_THAILAND),
WSTR_LITERAL(UNICODE_STR_FRANCE),
WSTR_LITERAL(UNICODE_STR_SPAIN),
WSTR_LITERAL(UNICODE_STR_MATHMATICS),
WSTR_LITERAL(UNICODE_STR_EMOJI),
};
static std::vector<std::u16string> UTFLIT_U16STR_VEC{
U16_LITERAL(UNICODE_STR_JAPAN),
U16_LITERAL(UNICODE_STR_CHINA),
U16_LITERAL(UNICODE_STR_KOREA),
U16_LITERAL(UNICODE_STR_ISRAEL),
U16_LITERAL(UNICODE_STR_EGYPT),
U16_LITERAL(UNICODE_STR_GREECE),
U16_LITERAL(UNICODE_STR_RUSSIA),
U16_LITERAL(UNICODE_STR_THAILAND),
U16_LITERAL(UNICODE_STR_FRANCE),
U16_LITERAL(UNICODE_STR_SPAIN),
U16_LITERAL(UNICODE_STR_MATHMATICS),
U16_LITERAL(UNICODE_STR_EMOJI),
};
static std::vector<std::u32string> UTFLIT_U32STR_VEC{
U32_LITERAL(UNICODE_STR_JAPAN),
U32_LITERAL(UNICODE_STR_CHINA),
U32_LITERAL(UNICODE_STR_KOREA),
U32_LITERAL(UNICODE_STR_ISRAEL),
U32_LITERAL(UNICODE_STR_EGYPT),
U32_LITERAL(UNICODE_STR_GREECE),
U32_LITERAL(UNICODE_STR_RUSSIA),
U32_LITERAL(UNICODE_STR_THAILAND),
U32_LITERAL(UNICODE_STR_FRANCE),
U32_LITERAL(UNICODE_STR_SPAIN),
U32_LITERAL(UNICODE_STR_MATHMATICS),
U32_LITERAL(UNICODE_STR_EMOJI),
};
#pragma endregion
#pragma region UtfLiterals
UtfLiterals::UtfLiterals() :
u8str_vec(UTFLIT_U8STR_VEC), u16str_vec(UTFLIT_U16STR_VEC), u32str_vec(UTFLIT_U32STR_VEC), wstr_vec(UTFLIT_WSTR_VEC) {
// Check whether each vector has same size.
bool okey = true;
size_t exp_size = this->u8str_vec.size();
if (this->u16str_vec.size() != exp_size) okey = false;
if (this->u32str_vec.size() != exp_size) okey = false;
if (this->wstr_vec.size() != exp_size) okey = false;
if (!okey) throw std::logic_error("utf literal vector have different size");
}
UtfLiterals::~UtfLiterals() {}
size_t UtfLiterals::get_size() const {
// We have checked the size of each vector in ctor.
// So we simply return the length of one of them.
return this->u8str_vec.size();
}
const std::vector<std::u8string> &UtfLiterals::get_u8str_vec() const {
return this->u8str_vec;
}
const std::vector<std::u16string> &UtfLiterals::get_u16str_vec() const {
return this->u16str_vec;
}
const std::vector<std::u32string> &UtfLiterals::get_u32str_vec() const {
return this->u32str_vec;
}
const std::vector<std::wstring> &UtfLiterals::get_wstr_vec() const {
return this->wstr_vec;
}
#pragma endregion
#pragma region OtherLiteral
OtherLiteral::OtherLiteral(std::string &&other_str, uint32_t windows_ident, std::string &&iconv_ident, std::u8string &&pycodec_ident) :
other_str(std::move(other_str)), windows_ident(windows_ident), iconv_ident(std::move(iconv_ident)),
pycodec_ident(std::move(pycodec_ident)) {}
OtherLiteral::~OtherLiteral() {}
const std::string &OtherLiteral::get_other_str() const {
return this->other_str;
}
uint32_t OtherLiteral::get_windows_ident() const {
return this->windows_ident;
}
const std::string &OtherLiteral::get_iconv_ident() const {
return this->iconv_ident;
}
const std::u8string &OtherLiteral::get_pycodec_ident() const {
return this->pycodec_ident;
}
#pragma endregion
#pragma region OtherLiterals Data
static std::vector<OtherLiteral> OTHERLIT_OTHERSTR_VEC{{"\xC4\xE3\xBA\xC3\xD6\xD0\xB9\xFA", UINT32_C(936), "GBK", u8"gbk"}};
#define OTHER_STR_GBK "\u4f60\u597d\u4e2d\u56fd"
static std::vector<std::u8string> OTHERLIT_U8STR_VEC{U8_LITERAL(OTHER_STR_GBK)};
static std::vector<std::wstring> OTHERLIT_WSTR_VEC{WSTR_LITERAL(OTHER_STR_GBK)};
#pragma endregion
#pragma region OtherLiterals
OtherLiterals::OtherLiterals() : other_str_vec(OTHERLIT_OTHERSTR_VEC), u8str_vec(OTHERLIT_U8STR_VEC), wstr_vec(OTHERLIT_WSTR_VEC) {
// Check whether each vector has same size.
bool okey = true;
size_t exp_size = this->other_str_vec.size();
if (this->u8str_vec.size() != exp_size) okey = false;
if (this->wstr_vec.size() != exp_size) okey = false;
if (!okey) throw std::logic_error("utf literal vector have different size");
}
OtherLiterals::~OtherLiterals() {}
size_t OtherLiterals::get_size() const {
// We have checked the size, return size directly.
return this->other_str_vec.size();
}
const std::vector<OtherLiteral> &OtherLiterals::get_other_str_vec() const {
return this->other_str_vec;
}
const std::vector<std::u8string> &OtherLiterals::get_u8str_vec() const {
return this->u8str_vec;
}
const std::vector<std::wstring> &OtherLiterals::get_wstr_vec() const {
return this->wstr_vec;
}
#pragma endregion
} // namespace yyccshared::literals

64
test/shared/literals.hpp Normal file
View File

@ -0,0 +1,64 @@
#pragma once
#include <yycc.hpp>
#include <yycc/macro/class_copy_move.hpp>
#include <cstdint>
#include <string>
#include <vector>
namespace yyccshared::literals {
class UtfLiterals {
public:
UtfLiterals();
~UtfLiterals();
YYCC_DELETE_COPY_MOVE(UtfLiterals)
size_t get_size() const;
const std::vector<std::u8string>& get_u8str_vec() const;
const std::vector<std::u16string>& get_u16str_vec() const;
const std::vector<std::u32string>& get_u32str_vec() const;
const std::vector<std::wstring>& get_wstr_vec() const;
private:
const std::vector<std::u8string>& u8str_vec;
const std::vector<std::u16string>& u16str_vec;
const std::vector<std::u32string>& u32str_vec;
const std::vector<std::wstring>& wstr_vec;
};
class OtherLiteral {
public:
OtherLiteral(std::string&& other_str, uint32_t windows_ident, std::string&& iconv_ident, std::u8string&& pycodec_ident);
~OtherLiteral();
YYCC_DEFAULT_COPY_MOVE(OtherLiteral)
const std::string& get_other_str() const;
uint32_t get_windows_ident() const;
const std::string& get_iconv_ident() const;
const std::u8string& get_pycodec_ident() const;
private:
std::string other_str;
uint32_t windows_ident;
std::string iconv_ident;
std::u8string pycodec_ident;
};
class OtherLiterals {
public:
OtherLiterals();
~OtherLiterals();
YYCC_DELETE_COPY_MOVE(OtherLiterals)
size_t get_size() const;
const std::vector<OtherLiteral>& get_other_str_vec() const;
const std::vector<std::u8string>& get_u8str_vec() const;
const std::vector<std::wstring>& get_wstr_vec() const;
private:
const std::vector<OtherLiteral>& other_str_vec;
const std::vector<std::u8string>& u8str_vec;
const std::vector<std::wstring>& wstr_vec;
};
} // namespace yyccshared::literals

View File

View File

@ -0,0 +1,121 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/carton/pycodec.hpp>
#include "../../shared/literals.hpp"
#define ENC ::yycc::carton::pycodec
namespace yycctest::carton::pycodec {
static auto UTF_LITERALS = ::yyccshared::literals::UtfLiterals();
static auto OTHER_LITERALS = ::yyccshared::literals::OtherLiterals();
TEST(CartonPycodec, ValidateName) {
EXPECT_TRUE(ENC::is_valid_encoding_name(u8"utf-8"));
EXPECT_TRUE(ENC::is_valid_encoding_name(u8"gb2312"));
EXPECT_TRUE(ENC::is_valid_encoding_name(u8"cp1252"));
EXPECT_FALSE(ENC::is_valid_encoding_name(u8"this must not be a valid encoding name"));
}
TEST(CartonPycodec, CharToUtf8) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& u8str_literals = OTHER_LITERALS.get_u8str_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
ENC::CharToUtf8 cv(other_str_literal.get_pycodec_ident());
auto rv = cv.to_utf8(other_str_literal.get_other_str());
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(CartonPycodec, Utf8ToChar) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& u8str_literals = OTHER_LITERALS.get_u8str_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
ENC::Utf8ToChar cv(other_str_literal.get_pycodec_ident());
auto rv = cv.to_char(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), other_str_literal.get_other_str());
}
}
TEST(CartonPycodec, Utf8ToWchar) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& wstr_literals = UTF_LITERALS.get_wstr_vec();
ENC::Utf8ToWchar cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_wchar(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), wstr_literals[i]);
}
}
TEST(CartonPycodec, WcharToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& wstr_literals = UTF_LITERALS.get_wstr_vec();
ENC::WcharToUtf8 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf8(wstr_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(CartonPycodec, Utf8ToUtf16) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
ENC::Utf8ToUtf16 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf16(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u16str_literals[i]);
}
}
TEST(CartonPycodec, Utf16ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
ENC::Utf16ToUtf8 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf8(u16str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(CartonPycodec, Utf8ToUtf32) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
ENC::Utf8ToUtf32 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf32(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u32str_literals[i]);
}
}
TEST(CartonPycodec, Utf32ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
ENC::Utf32ToUtf8 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf8(u32str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
}

View File

@ -0,0 +1,61 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/carton/tabulate.hpp>
#include <yycc/string/reinterpret.hpp>
#include <sstream>
#define TABULATE ::yycc::carton::tabulate
#define REINTERPRET ::yycc::string::reinterpret
namespace yycctest::carton::tabulate {
class CartonTabulate : public ::testing::Test {
protected:
CartonTabulate() : table(3u), ss() {
// setup basic data
table.set_prefix(u8"# ");
table.set_header({u8"中文1", u8"中文2", u8"中文3"});
table.set_bar(u8"===");
table.add_row({u8"a", u8"b", u8"c"});
}
~CartonTabulate() override = default;
void expected_print(const std::u8string_view& exp) {
ss.str("");
table.print(ss);
EXPECT_EQ(REINTERPRET::as_utf8_view(ss.view()), exp);
}
TABULATE::Tabulate table;
std::stringstream ss;
};
TEST_F(CartonTabulate, Full) {
table.show_header(true);
table.show_bar(true);
expected_print(u8"# 中文1 中文2 中文3 \n"
u8"# === === === \n"
u8"# a b c \n");
}
TEST_F(CartonTabulate, NoHeader) {
table.show_header(false);
table.show_bar(true);
expected_print(u8"# === === === \n"
u8"# a b c \n");
}
TEST_F(CartonTabulate, NoBar) {
table.show_header(true);
table.show_bar(false);
expected_print(u8"# 中文1 中文2 中文3 \n"
u8"# a b c \n");
}
TEST_F(CartonTabulate, OnlyData) {
table.show_header(false);
table.show_bar(false);
expected_print(u8"# a b c \n");
}
} // namespace yycctest::carton::tabulate

View File

@ -0,0 +1,44 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/carton/termcolor.hpp>
#include <yycc/flag_enum.hpp>
#define TERMCOLOR ::yycc::carton::termcolor
#define FLAG_ENUM ::yycc::flag_enum
using namespace std::literals::string_view_literals;
using Color = TERMCOLOR::Color;
using Attribute = TERMCOLOR::Attribute;
namespace yycctest::carton::termcolor {
TEST(CartonTermcolor, Lowlevel) {
EXPECT_EQ(TERMCOLOR::foreground(Color::Default), u8"");
EXPECT_EQ(TERMCOLOR::foreground(Color::Red), u8"\033[31m");
EXPECT_EQ(TERMCOLOR::foreground(Color::LightRed), u8"\033[91m");
EXPECT_EQ(TERMCOLOR::background(Color::Default), u8"");
EXPECT_EQ(TERMCOLOR::background(Color::Red), u8"\033[41m");
EXPECT_EQ(TERMCOLOR::background(Color::LightRed), u8"\033[101m");
EXPECT_EQ(TERMCOLOR::style(Attribute::Default), u8"");
EXPECT_EQ(TERMCOLOR::style(Attribute::Italic), u8"\033[3m");
EXPECT_EQ(TERMCOLOR::styles(FLAG_ENUM::merge(Attribute::Italic, Attribute::Bold)),
u8"\033[1m"
"\033[3m");
EXPECT_EQ(TERMCOLOR::reset(), u8"\033[0m"sv);
}
TEST(CartonTermcolor, Highlevel) {
EXPECT_EQ(TERMCOLOR::colored(u8"hello"sv), u8"hello\033[0m");
EXPECT_EQ(TERMCOLOR::colored(u8"hello"sv, Color::LightWhite, Color::Red, FLAG_ENUM::merge(Attribute::Italic, Attribute::Bold)),
u8"\033[97m"
"\033[41m"
"\033[1m"
"\033[3m"
"hello"
"\033[0m");
}
} // namespace yycctest::carton::termcolor

View File

@ -0,0 +1,54 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/carton/wcwidth.hpp>
#include <yycc/carton/termcolor.hpp>
#define WCWDITH ::yycc::carton::wcwidth
#define TERMCOLOR ::yycc::carton::termcolor
namespace yycctest::carton::wcwidth {
#define TEST_SUCCESS(strl, len) \
{ \
auto rv = WCWDITH::wcswidth(strl); \
ASSERT_TRUE(rv.has_value()); \
EXPECT_EQ(rv.value(), len); \
}
#define TEST_FAIL(strl) \
{ \
auto rv = WCWDITH::wcswidth(strl); \
EXPECT_FALSE(rv.has_value()); \
}
TEST(CartonWcwdith, BadAnsi) {
TEST_FAIL(u8"\033?");
}
TEST(CartonWcwdith, BadCsi) {
TEST_FAIL(u8"\033[\t");
}
TEST(CartonWcwdith, English) {
TEST_SUCCESS(u8"abc", 3);
}
TEST(CartonWcwdith, Chinese) {
TEST_SUCCESS(u8"中文", 4);
TEST_SUCCESS(u8"中a文", 5);
}
TEST(CartonWcwdith, Japanese) {
TEST_SUCCESS(u8"ありがとう", 10);
TEST_SUCCESS(u8"アリガトウ", 10);
TEST_SUCCESS(u8"アリガトウ", 6);
}
TEST(CartonWcwdith, Termcolor) {
using Color = TERMCOLOR::Color;
TEST_SUCCESS(TERMCOLOR::colored(u8"abc", Color::Red), 3);
TEST_SUCCESS(TERMCOLOR::colored(u8"中文", Color::Red), 4);
TEST_SUCCESS(TERMCOLOR::colored(u8"ありがとう", Color::Red), 10);
}
} // namespace yycctest::carton::wcwidth

50
test/yycc/constraint.cpp Normal file
View File

@ -0,0 +1,50 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/constraint.hpp>
#include <yycc/rust/prelude.hpp>
#define CONSTRAINT ::yycc::constraint::Constraint
namespace yycctest::constraint {
template<typename T>
bool check(const T& value) {
return false;
}
template<typename T>
T clamp(const T& value) {
return value;
}
TEST(Constraint, Normal) {
CONSTRAINT<u32> instance(check<u32>, clamp<u32>);
EXPECT_TRUE(instance.support_check());
EXPECT_TRUE(instance.support_clamp());
EXPECT_FALSE(instance.check(0));
EXPECT_EQ(instance.clamp(0), 0);
}
TEST(Constraint, SomeNone) {
{
CONSTRAINT<u32> instance(check<u32>, nullptr);
EXPECT_TRUE(instance.support_check());
EXPECT_FALSE(instance.support_clamp());
EXPECT_FALSE(instance.check(0));
}
{
CONSTRAINT<u32> instance(nullptr, clamp<u32>);
EXPECT_FALSE(instance.support_check());
EXPECT_TRUE(instance.support_clamp());
EXPECT_EQ(instance.clamp(0), 0);
}
}
TEST(Constraint, AllNone) {
CONSTRAINT<u32> instance(nullptr, nullptr);
EXPECT_FALSE(instance.support_check());
EXPECT_FALSE(instance.support_clamp());
}
}

View File

@ -0,0 +1,79 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/constraint/builder.hpp>
#include <yycc/rust/prelude.hpp>
#define BUILDER ::yycc::constraint::builder
using namespace std::literals::string_view_literals;
namespace yycctest::constraint::builder {
#define TEST_SUCCESS(constraint, value) \
EXPECT_TRUE(constraint.check(value)); \
EXPECT_EQ(constraint.clamp(value), value);
#define TEST_FAIL(constraint, value, clamped_value) \
EXPECT_FALSE(constraint.check(value)); \
EXPECT_EQ(constraint.clamp(value), clamped_value);
TEST(ConstraintBuilder, MinMaxConstraint) {
// Integral type
{
auto c = BUILDER::min_max_constraint<i32>(5, 61);
ASSERT_TRUE(c.support_check());
ASSERT_TRUE(c.support_clamp());
TEST_SUCCESS(c, 5);
TEST_SUCCESS(c, 6);
TEST_SUCCESS(c, 61);
TEST_FAIL(c, -2, 5);
TEST_FAIL(c, 0, 5);
TEST_FAIL(c, 66, 61);
}
// Unisgned integral type
{
auto c = BUILDER::min_max_constraint<u32>(5, 61);
ASSERT_TRUE(c.support_check());
ASSERT_TRUE(c.support_clamp());
TEST_SUCCESS(c, 5);
TEST_SUCCESS(c, 6);
TEST_SUCCESS(c, 61);
TEST_FAIL(c, 0, 5);
TEST_FAIL(c, 66, 61);
}
// Float point type
{
auto c = BUILDER::min_max_constraint<f32>(5.0f, 61.0f);
ASSERT_TRUE(c.support_check());
ASSERT_TRUE(c.support_clamp());
TEST_SUCCESS(c, 5.0f);
TEST_SUCCESS(c, 6.0f);
TEST_SUCCESS(c, 61.0f);
TEST_FAIL(c, 0.0f, 5.0f);
TEST_FAIL(c, 66.0f, 61.0f);
}
}
enum class TestEnum : u8 { Entry1 = 0, Entry2 = 1, Entry3 = 2 };
TEST(ConstraintBuilder, EnumConstraint) {
auto c = BUILDER::enum_constraint({TestEnum::Entry1, TestEnum::Entry2, TestEnum::Entry3}, 1u);
ASSERT_TRUE(c.support_check());
ASSERT_TRUE(c.support_clamp());
TEST_SUCCESS(c, TestEnum::Entry1);
TEST_SUCCESS(c, TestEnum::Entry2);
TEST_SUCCESS(c, TestEnum::Entry3);
TEST_FAIL(c, static_cast<TestEnum>(UINT8_C(61)), TestEnum::Entry2);
}
TEST(ConstraintBuilder, StrEnumConstraint) {
auto c = BUILDER::strenum_constraint({u8"first-entry"sv, u8"second-entry"sv, u8"third-entry"sv}, 1u);
ASSERT_TRUE(c.support_check());
ASSERT_TRUE(c.support_clamp());
TEST_SUCCESS(c, u8"first-entry");
TEST_SUCCESS(c, u8"second-entry");
TEST_SUCCESS(c, u8"third-entry");
TEST_FAIL(c, u8"wtf?", u8"second-entry");
}
} // namespace yycctest::constraint::builder

View File

@ -0,0 +1,115 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/encoding/iconv.hpp>
#include "../../shared/literals.hpp"
#define ENC ::yycc::encoding::iconv
namespace yycctest::encoding::iconv {
#if defined(YYCC_FEAT_ICONV)
static auto UTF_LITERALS = ::yyccshared::literals::UtfLiterals();
static auto OTHER_LITERALS = ::yyccshared::literals::OtherLiterals();
TEST(EncodingIconv, CharToUtf8) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& u8str_literals = OTHER_LITERALS.get_u8str_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
ENC::CharToUtf8 cv(other_str_literal.get_iconv_ident());
auto rv = cv.to_utf8(other_str_literal.get_other_str());
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(EncodingIconv, Utf8ToChar) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& u8str_literals = OTHER_LITERALS.get_u8str_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
ENC::Utf8ToChar cv(other_str_literal.get_iconv_ident());
auto rv = cv.to_char(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), other_str_literal.get_other_str());
}
}
TEST(EncodingIconv, Utf8ToWchar) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& wstr_literals = UTF_LITERALS.get_wstr_vec();
ENC::Utf8ToWchar cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_wchar(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), wstr_literals[i]);
}
}
TEST(EncodingIconv, WcharToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& wstr_literals = UTF_LITERALS.get_wstr_vec();
ENC::WcharToUtf8 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf8(wstr_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(EncodingIconv, Utf8ToUtf16) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
ENC::Utf8ToUtf16 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf16(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u16str_literals[i]);
}
}
TEST(EncodingIconv, Utf16ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
ENC::Utf16ToUtf8 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf8(u16str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(EncodingIconv, Utf8ToUtf32) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
ENC::Utf8ToUtf32 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf32(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u32str_literals[i]);
}
}
TEST(EncodingIconv, Utf32ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
ENC::Utf32ToUtf8 cv;
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = cv.to_utf8(u32str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
#endif
} // namespace yycctest::encoding::iconv

View File

@ -0,0 +1,56 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/encoding/stl.hpp>
#include "../../shared/literals.hpp"
#define ENC ::yycc::encoding::stl
namespace yycctest::encoding::stl {
static auto UTF_LITERALS = ::yyccshared::literals::UtfLiterals();
TEST(EncodingStl, Utf8ToUtf16) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf16(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u16str_literals[i]);
}
}
TEST(EncodingStl, Utf16ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf8(u16str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(EncodingStl, Utf8ToUtf32) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf32(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u32str_literals[i]);
}
}
TEST(EncodingStl, Utf32ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf8(u32str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
} // namespace yycctest::encoding::stl

View File

@ -0,0 +1,137 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/encoding/windows.hpp>
#include "../../shared/literals.hpp"
#define ENC ::yycc::encoding::windows
namespace yycctest::encoding::windows {
#if defined(YYCC_OS_WINDOWS)
static auto UTF_LITERALS = ::yyccshared::literals::UtfLiterals();
static auto OTHER_LITERALS = ::yyccshared::literals::OtherLiterals();
TEST(EncodingWindows, CharToWchar) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& wstr_literals = OTHER_LITERALS.get_wstr_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
auto rv = ENC::to_wchar(other_str_literal.get_other_str(), other_str_literal.get_windows_ident());
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), wstr_literals[i]);
}
}
TEST(EncodingWindows, WcharToChar) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& wstr_literals = OTHER_LITERALS.get_wstr_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
auto rv = ENC::to_char(wstr_literals[i], other_str_literal.get_windows_ident());
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), other_str_literal.get_other_str());
}
}
TEST(EncodingWindows, CharToUtf8) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& u8str_literals = OTHER_LITERALS.get_u8str_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
auto rv = ENC::to_utf8(other_str_literal.get_other_str(), other_str_literal.get_windows_ident());
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(EncodingWindows, Utf8ToChar) {
const auto& other_str_literals = OTHER_LITERALS.get_other_str_vec();
const auto& u8str_literals = OTHER_LITERALS.get_u8str_vec();
for (size_t i = 0; i < OTHER_LITERALS.get_size(); ++i) {
const auto& other_str_literal = other_str_literals[i];
auto rv = ENC::to_char(u8str_literals[i], other_str_literal.get_windows_ident());
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), other_str_literal.get_other_str());
}
}
TEST(EncodingWindows, Utf8ToWchar) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& wstr_literals = UTF_LITERALS.get_wstr_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_wchar(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), wstr_literals[i]);
}
}
TEST(EncodingWindows, WcharToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& wstr_literals = UTF_LITERALS.get_wstr_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf8(wstr_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
#if defined(YYCC_STL_MSSTL)
TEST(EncodingWindows, Utf8ToUtf16) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf16(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u16str_literals[i]);
}
}
TEST(EncodingWindows, Utf16ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u16str_literals = UTF_LITERALS.get_u16str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf8(u16str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
TEST(EncodingWindows, Utf8ToUtf32) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf32(u8str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u32str_literals[i]);
}
}
TEST(EncodingWindows, Utf32ToUtf8) {
const auto& u8str_literals = UTF_LITERALS.get_u8str_vec();
const auto& u32str_literals = UTF_LITERALS.get_u32str_vec();
for (size_t i = 0; i < UTF_LITERALS.get_size(); ++i) {
auto rv = ENC::to_utf8(u32str_literals[i]);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), u8str_literals[i]);
}
}
#endif
#endif
} // namespace yycctest::encoding::windows

83
test/yycc/flag_enum.cpp Normal file
View File

@ -0,0 +1,83 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/flag_enum.hpp>
#include <cinttypes>
#include <yycc/rust/prelude.hpp>
#define FLAG_ENUM ::yycc::flag_enum
namespace yycctest::flag_enum {
enum class TestEnum : u8 {
Bit1 = 0b00000001,
Bit2 = 0b00000010,
Bit3 = 0b00000100,
Bit4 = 0b00001000,
Bit5 = 0b00010000,
Bit6 = 0b00100000,
Bit7 = 0b01000000,
Bit8 = 0b10000000,
Empty = 0b00000000,
InvBit8 = 0b01111111,
MergedBit247 = Bit2 + Bit4 + Bit7,
};
TEST(FlagEnum, Merge) {
EXPECT_EQ(FLAG_ENUM::merge(TestEnum::Bit2, TestEnum::Bit4, TestEnum::Bit7), TestEnum::MergedBit247);
}
TEST(FlagEnum, Invert) {
EXPECT_EQ(FLAG_ENUM::invert(TestEnum::Bit8), TestEnum::InvBit8);
}
TEST(FlagEnum, Mask) {
TestEnum src = FLAG_ENUM::merge(TestEnum::Bit2, TestEnum::Bit4);
TestEnum val;
val = src;
FLAG_ENUM::mask(val, TestEnum::Bit2);
EXPECT_EQ(val, TestEnum::Bit2);
val = src;
FLAG_ENUM::mask(val, TestEnum::Bit4);
EXPECT_EQ(val, TestEnum::Bit4);
val = src;
FLAG_ENUM::mask(val, TestEnum::Bit3);
EXPECT_EQ(val, TestEnum::Empty);
}
TEST(FlagEnum, Add) {
TestEnum val = TestEnum::Bit2;
FLAG_ENUM::add(val, TestEnum::Bit4, TestEnum::Bit7);
EXPECT_EQ(val, TestEnum::MergedBit247);
}
TEST(FlagEnum, Remove) {
TestEnum val = TestEnum::MergedBit247;
FLAG_ENUM::remove(val, TestEnum::Bit2, TestEnum::Bit7);
EXPECT_EQ(val, TestEnum::Bit4);
}
TEST(FlagEnum, Has) {
TestEnum val = TestEnum::MergedBit247;
EXPECT_TRUE(FLAG_ENUM::has(val, TestEnum::Bit2));
EXPECT_FALSE(FLAG_ENUM::has(val, TestEnum::Bit3));
EXPECT_TRUE(FLAG_ENUM::has(val, TestEnum::Bit4));
EXPECT_TRUE(FLAG_ENUM::has(val, TestEnum::Bit7));
}
TEST(FlagEnum, Boolean) {
EXPECT_FALSE(FLAG_ENUM::boolean(TestEnum::Empty));
EXPECT_TRUE(FLAG_ENUM::boolean(TestEnum::Bit1));
EXPECT_TRUE(FLAG_ENUM::boolean(TestEnum::InvBit8));
EXPECT_TRUE(FLAG_ENUM::boolean(TestEnum::MergedBit247));
}
TEST(FlagEnum, Integer) {
EXPECT_EQ(FLAG_ENUM::integer(TestEnum::Empty), UINT8_C(0));
EXPECT_EQ(FLAG_ENUM::integer(TestEnum::Bit1), UINT8_C(1));
}
}

View File

@ -0,0 +1,20 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/macro/compiler_detector.hpp>
#define COMPILER ::yycc::macro::compiler
namespace yycctest::macro::compiler {
TEST(MacroCompiler, Main) {
auto rv = COMPILER::get_compiler();
#if defined(YYCC_CC_MSVC)
EXPECT_EQ(rv, COMPILER::CompilerKind::Msvc);
#elif defined(YYCC_CC_GCC)
EXPECT_EQ(rv, COMPILER::CompilerKind::Gcc);
#else
EXPECT_EQ(rv, COMPILER::CompilerKind::Clang);
#endif
}
} // namespace yycctest::macro::compiler

View File

@ -0,0 +1,18 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/macro/endian_detector.hpp>
#define ENDIAN ::yycc::macro::endian
namespace yycctest::macro::endian {
TEST(MacroEndian, Main) {
auto rv = ENDIAN::get_endian();
#if defined(YYCC_ENDIAN_LITTLE)
EXPECT_EQ(rv, ENDIAN::EndianKind::Little);
#else
EXPECT_EQ(rv, ENDIAN::EndianKind::Big);
#endif
}
} // namespace yycctest::macro::endian

View File

@ -0,0 +1,20 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/macro/os_detector.hpp>
#define OS ::yycc::macro::os
namespace yycctest::macro::os {
TEST(MacroOs, Main) {
auto rv = OS::get_os();
#if defined(YYCC_OS_WINDOWS)
EXPECT_EQ(rv, OS::OsKind::Windows);
#elif defined(YYCC_OS_LINUX)
EXPECT_EQ(rv, OS::OsKind::Linux);
#else
EXPECT_EQ(rv, OS::OsKind::MacOs);
#endif
}
} // namespace yycctest::macro::os

View File

@ -0,0 +1,18 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/macro/ptr_size_detector.hpp>
#define PTR_SIZE ::yycc::macro::ptr_size
namespace yycctest::macro::ptr_size {
TEST(MacroPtrSize, Main) {
auto rv = PTR_SIZE::get_ptr_size();
#if defined(YYCC_PTRSIZE_32)
EXPECT_EQ(rv, PTR_SIZE::PtrSizeKind::Bits32);
#else
EXPECT_EQ(rv, PTR_SIZE::PtrSizeKind::Bits64);
#endif
}
} // namespace yycctest::macro::ptr_size

View File

@ -0,0 +1,20 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/macro/stl_detector.hpp>
#define STL ::yycc::macro::stl
namespace yycctest::macro::stl {
TEST(MacroStl, Main) {
auto rv = STL::get_stl();
#if defined(YYCC_STL_MSSTL)
EXPECT_EQ(rv, STL::StlKind::MsStl);
#elif defined(YYCC_STL_GNUSTL)
EXPECT_EQ(rv, STL::StlKind::GnuStl);
#else
EXPECT_EQ(rv, STL::StlKind::ClangStl);
#endif
}
} // namespace yycctest::macro::stl

View File

@ -0,0 +1,31 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/macro/version_cmp.hpp>
namespace yycctest::macro::version_cmp {
TEST(MacroVersionCmp, Same) {
// Test for same version.
EXPECT_TRUE(YYCC_VERCMP_E(1, 2, 3, 1, 2, 3));
EXPECT_FALSE(YYCC_VERCMP_NE(1, 2, 3, 1, 2, 3));
EXPECT_FALSE(YYCC_VERCMP_G(1, 2, 3, 1, 2, 3));
EXPECT_TRUE(YYCC_VERCMP_GE(1, 2, 3, 1, 2, 3));
EXPECT_TRUE(YYCC_VERCMP_NL(1, 2, 3, 1, 2, 3));
EXPECT_FALSE(YYCC_VERCMP_L(1, 2, 3, 1, 2, 3));
EXPECT_TRUE(YYCC_VERCMP_LE(1, 2, 3, 1, 2, 3));
EXPECT_TRUE(YYCC_VERCMP_NG(1, 2, 3, 1, 2, 3));
}
TEST(MacroVersionCmp, Math) {
// In version number, 1.2.10 is greater than 1.2.9
EXPECT_FALSE(YYCC_VERCMP_E(1, 2, 10, 1, 2, 9));
EXPECT_TRUE(YYCC_VERCMP_NE(1, 2, 10, 1, 2, 9));
EXPECT_TRUE(YYCC_VERCMP_G(1, 2, 10, 1, 2, 9));
EXPECT_TRUE(YYCC_VERCMP_GE(1, 2, 10, 1, 2, 9));
EXPECT_TRUE(YYCC_VERCMP_NL(1, 2, 10, 1, 2, 9));
EXPECT_FALSE(YYCC_VERCMP_L(1, 2, 10, 1, 2, 9));
EXPECT_FALSE(YYCC_VERCMP_LE(1, 2, 10, 1, 2, 9));
EXPECT_FALSE(YYCC_VERCMP_NG(1, 2, 10, 1, 2, 9));
}
}

19
test/yycc/num/op.cpp Normal file
View File

@ -0,0 +1,19 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/num/op.hpp>
#include <yycc/rust/prelude.hpp>
#define OP ::yycc::num::op
namespace yycctest::num::op {
TEST(NumOp, DivCeil) {
// Normal case
EXPECT_EQ(OP::div_ceil<u32>(8, 4), UINT32_C(2));
EXPECT_EQ(OP::div_ceil<u32>(7, 4), UINT32_C(2));
// Limit case
EXPECT_EQ(OP::div_ceil<u8>(255, 2), UINT8_C(128));
}
}

81
test/yycc/num/parse.cpp Normal file
View File

@ -0,0 +1,81 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/num/parse.hpp>
#include <yycc/rust/prelude.hpp>
#define PARSE ::yycc::num::parse
namespace yycctest::num::parse {
// These 2 test macros build string container via given string.
// Check `try_parse` first, and then check `parse`.
#define TEST_SUCCESS(type_t, expected_value, string_value, ...) \
{ \
std::u8string cache_string(string_value); \
auto rv = PARSE::parse<type_t>(cache_string __VA_OPT__(,) __VA_ARGS__); \
ASSERT_TRUE(rv.has_value()); \
EXPECT_EQ(rv.value(), expected_value); \
}
#define TEST_FAIL(type_t, string_value, ...) \
{ \
std::u8string cache_string(string_value); \
auto rv = PARSE::parse<type_t>(cache_string __VA_OPT__(,) __VA_ARGS__); \
EXPECT_FALSE(rv.has_value()); \
}
TEST(NumParse, Common) {
TEST_SUCCESS(i8, INT8_C(-61), u8"-61");
TEST_SUCCESS(u8, UINT8_C(200), u8"200");
TEST_SUCCESS(i16, INT16_C(6161), u8"6161");
TEST_SUCCESS(u16, UINT16_C(32800), u8"32800");
TEST_SUCCESS(i32, INT32_C(61616161), u8"61616161");
TEST_SUCCESS(u32, UINT32_C(4294967293), u8"4294967293");
TEST_SUCCESS(i64, INT64_C(616161616161), u8"616161616161");
TEST_SUCCESS(u64, UINT64_C(9223372036854775807), u8"9223372036854775807");
TEST_SUCCESS(float, 1.0f, u8"1.0");
TEST_SUCCESS(double, 1.0, u8"1.0");
TEST_SUCCESS(bool, true, u8"true");
TEST_SUCCESS(bool, false, u8"false");
}
TEST(NumParse, Radix) {
TEST_SUCCESS(u32, UINT32_C(0xffff), u8"ffff", 16);
TEST_SUCCESS(u32, UINT32_C(032), u8"032", 8);
TEST_SUCCESS(u32, UINT32_C(0B1011), u8"1011", 2);
}
TEST(NumParse, CaseInsensitive) {
TEST_SUCCESS(bool, true, u8"tRUE");
}
TEST(NumParse, Overflow) {
TEST_FAIL(i8, u8"6161");
TEST_FAIL(u8, u8"32800");
TEST_FAIL(i16, u8"61616161");
TEST_FAIL(u16, u8"4294967293");
TEST_FAIL(i32, u8"616161616161");
TEST_FAIL(u32, u8"9223372036854775807");
TEST_FAIL(i64, u8"616161616161616161616161");
TEST_FAIL(u64, u8"92233720368547758079223372036854775807");
TEST_FAIL(float, u8"1e40");
TEST_FAIL(double, u8"1e114514");
}
TEST(NumParse, BadRadix) {
TEST_FAIL(u32, u8"fghj", 16);
TEST_FAIL(u32, u8"099", 8);
TEST_FAIL(u32, u8"12345", 2);
}
TEST(NumParse, InvalidWords) {
TEST_FAIL(u32, u8"hello, world!");
TEST_FAIL(bool, u8"hello, world!");
}
} // namespace yycctest::num::parse

View File

@ -0,0 +1,51 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/num/safe_cast.hpp>
#include <yycc/macro/ptr_size_detector.hpp>
#include <yycc/rust/prelude.hpp>
#define CAST ::yycc::num::safe_cast
namespace yycctest::num::safe_cast {
TEST(NumSafeCast, To) {
// Definitely okey
auto rv = CAST::to<u32, u8>(UINT8_C(1));
EXPECT_EQ(rv, UINT32_C(1));
}
TEST(NumSafeCast, TryTo) {
// Okey
{
auto rv = CAST::try_to<u8, u32>(UINT32_C(1));
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), UINT8_C(1));
}
// Bad cast
{
auto rv = CAST::try_to<u8, u32>(UINT32_C(6161));
EXPECT_FALSE(rv.has_value());
}
}
TEST(NumSafeCast, VariableLength) {
// Both 32-bit and 64-bit pointer size are okey.
{
auto rv = CAST::try_to<usize, u64>(UINT64_C(0x00000000ffffffff));
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), 0xffffffffu);
}
// Only 64-bit pointer size is okey.
{
auto rv = CAST::try_to<usize, u64>(UINT64_C(0xffffffffffffffff));
#if defined(YYCC_PTRSIZE_64)
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), 0xffffffffffffffffu);
#else
EXPECT_FALSE(rv.has_value());
#endif
}
}
}

300
test/yycc/num/safe_op.cpp Normal file
View File

@ -0,0 +1,300 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/num/safe_op.hpp>
#include <cstdint>
#include <limits>
#include <yycc/rust/prelude.hpp>
#define OP ::yycc::num::safe_op
namespace yycctest::num::safe_op {
template<typename T>
constexpr T MAX = std::numeric_limits<T>::max();
template<typename T>
constexpr T MIN = std::numeric_limits<T>::min();
#pragma region Wrapping operations
TEST(NumSafeOp, WrappingAdd) {
// Unsigned
EXPECT_EQ(OP::wrapping_add<u32>(200, 55), UINT32_C(255));
EXPECT_EQ(OP::wrapping_add<u32>(200, MAX<u32>), UINT32_C(199));
// Signed
EXPECT_EQ(OP::wrapping_add<i32>(100, 27), INT32_C(127));
EXPECT_EQ(OP::wrapping_add<i32>(MAX<i32>, 2), MIN<i32> + 1);
}
TEST(NumSafeOp, WrappingSub) {
// Unsigned
EXPECT_EQ(OP::wrapping_sub<u32>(100, 100), 0);
EXPECT_EQ(OP::wrapping_sub<u32>(100, MAX<u32>), UINT32_C(101));
// Signed
EXPECT_EQ(OP::wrapping_sub<i32>(0, 127), INT32_C(-127));
EXPECT_EQ(OP::wrapping_sub<i32>(-2, MAX<i32>), MAX<i32>);
}
TEST(NumSafeOp, WrappingMul) {
// Unsigned
EXPECT_EQ(OP::wrapping_mul<u8>(10, 12), UINT8_C(120));
EXPECT_EQ(OP::wrapping_mul<u8>(25, 12), UINT8_C(44));
// Signed
EXPECT_EQ(OP::wrapping_mul<i32>(10, 12), INT32_C(120));
EXPECT_EQ(OP::wrapping_mul<i8>(11, 12), INT32_C(-124));
}
TEST(NumSafeOp, WrappingDiv) {
// Unsigned
EXPECT_EQ(OP::wrapping_div<u32>(100, 10), UINT32_C(10));
// Signed
EXPECT_EQ(OP::wrapping_div<i32>(100, 10), INT32_C(10));
EXPECT_EQ(OP::wrapping_div<i8>(-128, -1), INT32_C(-128));
}
#pragma endregion
#pragma region Checked operations
TEST(NumSafeOp, CheckedAdd) {
// Unsigned
{
auto rv = OP::checked_add<u32>(MAX<u32> - 2, 1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), MAX<u32> - 1);
}
{
auto rv = OP::checked_add<u32>(MAX<u32> - 2, 3);
EXPECT_FALSE(rv.has_value());
}
// Signed
{
auto rv = OP::checked_add<i32>(MAX<i32> - 2, 1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), MAX<i32> - 1);
}
{
auto rv = OP::checked_add<i32>(MAX<i32> - 2, 3);
EXPECT_FALSE(rv.has_value());
}
}
TEST(NumSafeOp, CheckedSub) {
// Unsigned
{
auto rv = OP::checked_sub<u32>(1, 1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), 0);
}
{
auto rv = OP::checked_sub<u32>(0, 1);
EXPECT_FALSE(rv.has_value());
}
// Signed
{
auto rv = OP::checked_sub<i32>(MIN<i32> + 2, 1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), MIN<i32> + 1);
}
{
auto rv = OP::checked_sub<i32>(MIN<i32> + 2, 3);
EXPECT_FALSE(rv.has_value());
}
}
TEST(NumSafeOp, CheckedMul) {
// Unsigned
{
auto rv = OP::checked_mul<u32>(5, 1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), 5);
}
{
auto rv = OP::checked_mul<u32>(MAX<u32>, 2);
EXPECT_FALSE(rv.has_value());
}
// Signed
{
auto rv = OP::checked_mul<i32>(MAX<i32>, 1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), MAX<i32>);
}
{
auto rv = OP::checked_mul<i32>(MAX<i32>, 2);
EXPECT_FALSE(rv.has_value());
}
}
TEST(NumSafeOp, CheckedDiv) {
// Unsigned
{
auto rv = OP::checked_div<u32>(128, 2);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), 64);
}
{
auto rv = OP::checked_div<u32>(1, 0);
EXPECT_FALSE(rv.has_value());
}
// Signed
{
auto rv = OP::checked_div<i32>(MIN<i32> + 1, -1);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), INT32_C(2147483647));
}
{
auto rv = OP::checked_div<i32>(MIN<i32>, -1);
EXPECT_FALSE(rv.has_value());
}
{
auto rv = OP::checked_div<i32>(1, 0);
EXPECT_FALSE(rv.has_value());
}
}
#pragma endregion
#pragma region Overflowing operations
TEST(NumSafeOp, OverflowingAdd) {
// Unsigned
{
auto rv = OP::overflowing_add<u32>(5, 2);
EXPECT_EQ(rv.first, 7);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_add<u32>(MAX<u32>, 1);
EXPECT_EQ(rv.first, 0);
EXPECT_EQ(rv.second, true);
}
// Signed
{
auto rv = OP::overflowing_add<i32>(5, 2);
EXPECT_EQ(rv.first, 7);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_add<i32>(MAX<i32>, 1);
EXPECT_EQ(rv.first, MIN<i32>);
EXPECT_EQ(rv.second, true);
}
}
TEST(NumSafeOp, OverflowingSub) {
// Unsigned
{
auto rv = OP::overflowing_sub<u32>(5, 2);
EXPECT_EQ(rv.first, 3);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_sub<u32>(0, 1);
EXPECT_EQ(rv.first, MAX<u32>);
EXPECT_EQ(rv.second, true);
}
// Signed
{
auto rv = OP::overflowing_sub<i32>(5, 2);
EXPECT_EQ(rv.first, 3);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_sub<i32>(MIN<i32>, 1);
EXPECT_EQ(rv.first, MAX<i32>);
EXPECT_EQ(rv.second, true);
}
}
TEST(NumSafeOp, OverflowingMul) {
// Unsigned
{
auto rv = OP::overflowing_mul<u32>(5, 2);
EXPECT_EQ(rv.first, 10);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_mul<u32>(UINT32_C(1000000000), 10);
EXPECT_EQ(rv.first, UINT32_C(1410065408));
EXPECT_EQ(rv.second, true);
}
// Signed
{
auto rv = OP::overflowing_mul<i32>(5, 2);
EXPECT_EQ(rv.first, 10);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_mul<i32>(INT32_C(1000000000), 10);
EXPECT_EQ(rv.first, INT32_C(1410065408));
EXPECT_EQ(rv.second, true);
}
}
TEST(NumSafeOp, OverflowingDiv) {
// Unsigned
{
auto rv = OP::overflowing_div<u32>(5, 2);
EXPECT_EQ(rv.first, 2);
EXPECT_EQ(rv.second, false);
}
// Signed
{
auto rv = OP::overflowing_div<i32>(5, 2);
EXPECT_EQ(rv.first, 2);
EXPECT_EQ(rv.second, false);
}
{
auto rv = OP::overflowing_div<i32>(MIN<i32>, -1);
EXPECT_EQ(rv.first, MIN<i32>);
EXPECT_EQ(rv.second, true);
}
}
#pragma endregion
#pragma region Saturating operations
TEST(NumSafeOp, SaturatingAdd) {
// Unsigned
EXPECT_EQ(OP::saturating_add<u32>(100, 1), UINT32_C(101));
EXPECT_EQ(OP::saturating_add<u32>(MAX<u32>, 127), MAX<u32>);
// Signed
EXPECT_EQ(OP::saturating_add<i32>(100, 1), INT32_C(101));
EXPECT_EQ(OP::saturating_add<i32>(MAX<i32>, 100), MAX<i32>);
EXPECT_EQ(OP::saturating_add<i32>(MIN<i32>, -1), MIN<i32>);
}
TEST(NumSafeOp, SaturatingSub) {
// Unsigned
EXPECT_EQ(OP::saturating_sub<u32>(100, 27), UINT32_C(73));
EXPECT_EQ(OP::saturating_sub<u32>(13, 127), 0);
// Signed
EXPECT_EQ(OP::saturating_sub<i32>(100, 127), -27);
EXPECT_EQ(OP::saturating_sub<i32>(MIN<i32>, 100), MIN<i32>);
EXPECT_EQ(OP::saturating_sub<i32>(MAX<i32>, -1), MAX<i32>);
}
TEST(NumSafeOp, SaturatingMul) {
// Unsigned
EXPECT_EQ(OP::saturating_mul<u32>(2, 10), UINT32_C(20));
EXPECT_EQ(OP::saturating_mul<u32>(MAX<u32>, 10), MAX<u32>);
// Signed
EXPECT_EQ(OP::saturating_mul<i32>(10, 12), 120);
EXPECT_EQ(OP::saturating_mul<i32>(MAX<i32>, 10), MAX<i32>);
EXPECT_EQ(OP::saturating_mul<i32>(MIN<i32>, 10), MIN<i32>);
}
TEST(NumSafeOp, SaturatingDiv) {
// Unsigned
EXPECT_EQ(OP::saturating_div<u32>(5, 2), UINT32_C(2));
// Signed
EXPECT_EQ(OP::saturating_div<i32>(5, 2), 2);
EXPECT_EQ(OP::saturating_div<i32>(MAX<i32>, -1), MIN<i32> + 1);
EXPECT_EQ(OP::saturating_div<i32>(MIN<i32>, -1), MAX<i32>);
}
#pragma endregion
} // namespace yycctest::num::safe_op

View File

@ -0,0 +1,41 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/num/stringify.hpp>
#include <yycc/rust/prelude.hpp>
#define STRINGIFY ::yycc::num::stringify
namespace yycctest::num::stringify {
#define TEST_SUCCESS(type_t, value, string_value, ...) \
{ \
type_t cache = value; \
std::u8string ret = STRINGIFY::stringify<type_t>(cache __VA_OPT__(,) __VA_ARGS__); \
EXPECT_EQ(ret, string_value); \
}
TEST(NumStringify, Common) {
TEST_SUCCESS(i8, INT8_C(-61), u8"-61");
TEST_SUCCESS(u8, UINT8_C(200), u8"200");
TEST_SUCCESS(i16, INT16_C(6161), u8"6161");
TEST_SUCCESS(u16, UINT16_C(32800), u8"32800");
TEST_SUCCESS(i32, INT32_C(61616161), u8"61616161");
TEST_SUCCESS(u32, UINT32_C(4294967293), u8"4294967293");
TEST_SUCCESS(i64, INT64_C(616161616161), u8"616161616161");
TEST_SUCCESS(u64, UINT64_C(9223372036854775807), u8"9223372036854775807");
TEST_SUCCESS(float, 1.0f, u8"1.0", std::chars_format::fixed, 1);
TEST_SUCCESS(double, 1.0, u8"1.0", std::chars_format::fixed, 1);
TEST_SUCCESS(bool, true, u8"true");
TEST_SUCCESS(bool, false, u8"false");
}
TEST(NumStringify, Radix) {
TEST_SUCCESS(u32, UINT32_C(0xffff), u8"ffff", 16);
TEST_SUCCESS(u32, UINT32_C(032), u8"32", 8);
TEST_SUCCESS(u32, UINT32_C(0B1011), u8"1011", 2);
}
} // namespace yycctest::num::stringify

24
test/yycc/patch/fopen.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/patch/fopen.hpp>
#define FOPEN ::yycc::patch::fopen
namespace yycctest::patch::fopen {
TEST(PatchFopen, Normal) {
FILE* handle;
#if defined(YYCC_OS_WINDOWS)
// In Windows, we can always visit NUL device.
handle = FOPEN::fopen(u8"NUL", u8"wb");
#else
// In other system following UNIX design, we can visit /dev/null device.
handle = FOPEN::fopen(u8"/dev/null", u8"wb");
#endif
ASSERT_TRUE(handle != nullptr);
std::fclose(handle);
}
} // namespace yycctest::patch::fopen

View File

@ -0,0 +1,35 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/patch/format.hpp>
#define FORMAT ::yycc::patch::format
namespace yycctest::patch::format {
static constexpr char8_t PROBE[] = u8"hello";
static std::u8string PROBE_STRING(PROBE);
static constexpr std::u8string_view PROBE_STRING_VIEW(PROBE);
TEST(PatchFormat, OrdinaryFormat) {
auto rv = FORMAT::format("{:c}{}{}{}{}{} world!",
PROBE[0],
PROBE_STRING.data(),
PROBE_STRING.c_str(),
PROBE,
PROBE_STRING,
PROBE_STRING_VIEW);
EXPECT_EQ(rv, "hhellohellohellohellohello world!");
}
TEST(PatchFormat, Utf8Format) {
auto rv = FORMAT::format(u8"{:c}{}{}{}{}{} world!",
PROBE[0],
PROBE_STRING.data(),
PROBE_STRING.c_str(),
PROBE,
PROBE_STRING,
PROBE_STRING_VIEW);
EXPECT_EQ(rv, u8"hhellohellohellohellohello world!");
}
}

View File

@ -0,0 +1,21 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/string/op.hpp>
#include <yycc/patch/ptr_pad.hpp>
#include <cinttypes>
#define OP ::yycc::string::op
namespace yycctest::patch::ptr_pad {
TEST(PatchPtrPad, Normal) {
auto rv = OP::printf(u8"0x%" PRIXPTR_LPAD PRIXPTR, nullptr);
#if defined(YYCC_PTRSIZE_32)
EXPECT_EQ(rv, u8"0x00000000");
#else
EXPECT_EQ(rv, u8"0x0000000000000000");
#endif
}
}

View File

@ -0,0 +1,31 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/patch/stream.hpp>
#include <yycc/string/reinterpret.hpp>
#include <sstream>
#define REINTERPRET ::yycc::string::reinterpret
using namespace std::literals::string_view_literals;
using namespace ::yycc::patch::stream;
namespace yycctest::patch::stream {
TEST(PatchStream, StringView) {
std::stringstream ss;
ss << u8"hello"sv;
EXPECT_EQ(REINTERPRET::as_utf8_view(ss.view()), u8"hello"sv);
}
TEST(PatchStream, CStrPtr) {
std::stringstream ss;
ss << u8"hello";
EXPECT_EQ(REINTERPRET::as_utf8_view(ss.view()), u8"hello");
}
TEST(PatchStream, Character) {
std::stringstream ss;
ss << u8'y';
EXPECT_EQ(REINTERPRET::as_utf8_view(ss.view()), u8"y");
}
}

45
test/yycc/rust/env.cpp Normal file
View File

@ -0,0 +1,45 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/rust/env.hpp>
#define ENV ::yycc::rust::env
namespace yycctest::rust::env {
constexpr char8_t VAR_NAME[] = u8"HOMER";
constexpr char8_t VAR_VALUE[] = u8"doh";
TEST(RustEnv, All) {
// Write a new variable should okey
{
auto rv = ENV::set_var(VAR_NAME, VAR_VALUE);
ASSERT_TRUE(rv.has_value());
}
// After writing, we can fetch it and check its value.
{
auto rv = ENV::get_var(VAR_NAME);
ASSERT_TRUE(rv.has_value());
EXPECT_EQ(rv.value(), VAR_VALUE);
}
// The we can delete it.
{
auto rv = ENV::del_var(VAR_NAME);
ASSERT_TRUE(rv.has_value());
}
// Delete inexisting variable also should be okey
{
auto rv = ENV::del_var(VAR_NAME);
ASSERT_TRUE(rv.has_value());
}
// After deleting, we can not fetch it anymore.
{
auto rv = ENV::get_var(VAR_NAME);
ASSERT_FALSE(rv.has_value());
}
}
}

143
test/yycc/string/op.cpp Normal file
View File

@ -0,0 +1,143 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/string/op.hpp>
#include <yycc/rust/prelude.hpp>
#define OP ::yycc::string::op
using namespace std::literals::string_view_literals;
namespace yycctest::string::op {
TEST(StringOp, Printf) {
// UTF8 string
{
auto rv = OP::printf(u8"%s == %s", u8"Hello World", u8"Hello, world");
EXPECT_EQ(rv, u8"Hello World == Hello, world");
}
// Ordinary string
{
auto rv = OP::printf("%s == %s", "Hello World", "Hello, world");
EXPECT_EQ(rv, "Hello World == Hello, world");
}
}
TEST(StringOp, Replace) {
// Normal case
{
auto rv = OP::replace(u8"aabbcc", u8"bb", u8"dd");
EXPECT_EQ(rv, u8"aaddcc");
}
// No matched expected string
{
auto rv = OP::replace(u8"aabbcc", u8"zz", u8"yy");
EXPECT_EQ(rv, u8"aabbcc");
}
// Empty expected string
{
auto rv = OP::replace(u8"aabbcc", std::u8string_view(), u8"zz");
EXPECT_EQ(rv, u8"aabbcc");
}
// Empty replace string
{
auto rv = OP::replace(u8"aaaabbaa", u8"aa", u8"");
EXPECT_EQ(rv, u8"bb");
}
// Nested replacing
{
auto rv = OP::replace(u8"aaxcc", u8"x", u8"yx");
EXPECT_EQ(rv, u8"aayxcc");
}
// Empty source string
{
auto rv = OP::replace(std::u8string_view(), u8"", u8"xy");
EXPECT_EQ(rv, u8"");
}
}
TEST(StringOp, Lower) {
auto rv = OP::to_lower(u8"LOWER");
EXPECT_EQ(rv, u8"lower");
}
TEST(StringOp, Upper) {
auto rv = OP::to_upper(u8"upper");
EXPECT_EQ(rv, u8"UPPER");
}
TEST(StringOp, Join) {
std::vector<std::u8string_view> datas{u8""sv, u8"1"sv, u8"2"sv, u8""sv};
auto rv = OP::join(datas.begin(), datas.end(), u8", ");
EXPECT_EQ(rv, u8", 1, 2, ");
}
TEST(StringOp, Strip) {
// Normal strip
{
auto rv = OP::strip(u8" \taaa\n", u8" \t\r\n");
EXPECT_EQ(rv, u8"aaa");
}
{
auto rv = OP::lstrip(u8" \taaa\n", u8" \t\r\n");
EXPECT_EQ(rv, u8"aaa\n");
}
{
auto rv = OP::rstrip(u8" \taaa\n", u8" \t\r\n");
EXPECT_EQ(rv, u8" \taaa");
}
// Special strip
{
auto rv = OP::strip(u8"啊啊啊aaaあああ", u8"啊あ");
EXPECT_EQ(rv, u8"aaa");
}
{
auto rv = OP::strip(u8"啊啊啊aaaあああ", u8"");
EXPECT_EQ(rv, u8"aaaあああ");
}
{
auto rv = OP::strip(u8"啊啊啊aaaあああ", u8"");
EXPECT_EQ(rv, u8"啊啊啊aaa");
}
// Possible buggy strip.
// We use 2 UTF8 code points introduced following:
// U+00AA (UTF-8: C2 AA)
// U+1002A (UTF-8 : F0 90 80 AA)
{
auto rv = OP::rstrip(u8"aaa\u00AA", u8"\u00AA\U0001002A");
EXPECT_EQ(rv, u8"aaa");
}
}
TEST(StringOp, Split) {
// Normal
{
auto rv = OP::split(u8", 1, 2, ", u8", ");
ASSERT_EQ(rv.size(), 4u);
EXPECT_EQ(rv[0], u8"");
EXPECT_EQ(rv[1], u8"1");
EXPECT_EQ(rv[2], u8"2");
EXPECT_EQ(rv[3], u8"");
}
// No matched delimiter
{
auto rv = OP::split(u8"test", u8"-");
ASSERT_EQ(rv.size(), 1u);
EXPECT_EQ(rv[0], u8"test");
}
// Empty delimiter
{
auto rv = OP::split(u8"test", std::u8string_view());
ASSERT_EQ(rv.size(), 1u);
EXPECT_EQ(rv[0], u8"test");
}
// Empty source string
{
auto rv = OP::split(std::u8string_view(), u8"");
ASSERT_EQ(rv.size(), 1u);
EXPECT_TRUE(rv[0].empty());
}
}
} // namespace yycctest::string::op

View File

@ -0,0 +1,71 @@
#include <cstring>
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/string/reinterpret.hpp>
#include <yycc/rust/prelude.hpp>
#define REINTERPRET ::yycc::string::reinterpret
#define AS_UINT8(p) static_cast<u8>(p)
#define CONST_VOID_PTR(p) reinterpret_cast<const void*>(p)
#define VOID_PTR(p) reinterpret_cast<void*>(p)
namespace yycctest::string::reinterpret {
static std::u8string PROBE(u8"Test");
TEST(StringReinterpret, Character) {
const auto& src = PROBE[0];
const auto dst = REINTERPRET::as_ordinary(src);
const auto new_src = REINTERPRET::as_utf8(dst);
// Value should be the same after casting.
EXPECT_EQ(AS_UINT8(src), AS_UINT8(dst));
EXPECT_EQ(AS_UINT8(src), AS_UINT8(new_src));
}
TEST(StringReinterpret, ConstPointer) {
const auto* src = PROBE.data();
const auto* dst = REINTERPRET::as_ordinary(src);
const auto* new_src = REINTERPRET::as_utf8(dst);
// Pointer should point to the same address after casting.
EXPECT_EQ(CONST_VOID_PTR(src), CONST_VOID_PTR(dst));
EXPECT_EQ(CONST_VOID_PTR(src), CONST_VOID_PTR(new_src));
}
TEST(StringReinterpret, Pointer) {
auto* src = PROBE.data();
auto* dst = REINTERPRET::as_ordinary(src);
auto* new_src = REINTERPRET::as_utf8(dst);
// Pointer should point to the same address after casting.
EXPECT_EQ(VOID_PTR(src), VOID_PTR(dst));
EXPECT_EQ(VOID_PTR(src), VOID_PTR(new_src));
}
TEST(StringReinterpret, StlString) {
auto src = std::u8string(PROBE);
auto dst = REINTERPRET::as_ordinary(src);
auto new_src = REINTERPRET::as_utf8(dst);
// Check memory length and data.
ASSERT_EQ(src.length(), dst.length());
EXPECT_TRUE(std::memcmp(src.data(), dst.data(), src.length()) == 0);
ASSERT_EQ(src.length(), new_src.length());
EXPECT_TRUE(std::memcmp(src.data(), new_src.data(), src.length()) == 0);
}
TEST(StringReinterpret, StlStringView) {
auto src = std::u8string_view(PROBE);
auto dst = REINTERPRET::as_ordinary_view(src);
auto new_src = REINTERPRET::as_utf8_view(dst);
// Check memory length and data.
ASSERT_EQ(src.length(), dst.length());
EXPECT_TRUE(std::memcmp(src.data(), dst.data(), src.length()) == 0);
ASSERT_EQ(src.length(), new_src.length());
EXPECT_TRUE(std::memcmp(src.data(), new_src.data(), src.length()) == 0);
}
} // namespace yycctest::string::reinterpret

16
test/yycc/windows/com.cpp Normal file
View File

@ -0,0 +1,16 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/windows/com.hpp>
#define COM ::yycc::windows::com
namespace yycctest::windows::com {
#if defined(YYCC_OS_WINDOWS) && defined(YYCC_STL_MSSTL)
TEST(WindowsCom, IsInitialized) {
// COM environment should always be ready.
EXPECT_TRUE(COM::is_initialized());
}
#endif
}

View File

@ -0,0 +1,17 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/windows/console.hpp>
#define CONSOLE ::yycc::windows::console
namespace yycctest::windows::console {
#if defined(YYCC_OS_WINDOWS) && defined(YYCC_STL_MSSTL)
TEST(WindowsConsole, ColorfulConsole) {
// Set colorful console should always be success.
auto rv = CONSOLE::colorful_console();
EXPECT_TRUE(rv.has_value());
}
#endif
}

View File

@ -0,0 +1,55 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/windows/dialog.hpp>
#define DIALOG ::yycc::windows::dialog
namespace yycctest::windows::dialog {
#if defined(YYCC_OS_WINDOWS) && defined(YYCC_STL_MSSTL)
TEST(WindowsDialog, Normal) {
// TODO:
// I temporaryly disable all dialog open functions in this function after testing them.
// Because they need human to operate them to finish the test.
// Once I find a better way to do automatic test (maybe send message to these dialogs to close them?)
// I will add them back.
// Prepare parameters
DIALOG::FileDialog params;
auto& filters = params.configre_file_types();
filters.add_filter(u8"Microsoft Word (*.docx; *.doc)", {u8"*.docx", u8"*.doc"});
filters.add_filter(u8"Microsoft Excel (*.xlsx; *.xls)", {u8"*.xlsx", u8"*.xls"});
filters.add_filter(u8"Microsoft PowerPoint (*.pptx; *.ppt)", {u8"*.pptx", u8"*.ppt"});
filters.add_filter(u8"Text File (*.txt)", {u8"*.txt"});
filters.add_filter(u8"All Files (*.*)", {u8"*.*"});
params.set_default_file_type_index(1u);
//// Open file
//{
// auto rv = DIALOG::open_file(params);
// EXPECT_TRUE(rv.has_value());
//}
//// Open files
//{
// auto rv = DIALOG::open_files(params);
// EXPECT_TRUE(rv.has_value());
//}
//// Save file
//{
// auto rv = DIALOG::save_file(params);
// EXPECT_TRUE(rv.has_value());
//}
// Clear file filters for following operations
params.clear();
params.set_default_file_type_index(0u);
//// Open folder
//{
// auto rv = DIALOG::open_folder(params);
// EXPECT_TRUE(rv.has_value());
//}
}
#endif
}

View File

@ -0,0 +1,49 @@
#include <gtest/gtest.h>
#include <yycc.hpp>
#include <yycc/windows/winfct.hpp>
#define WINFCT ::yycc::windows::winfct
namespace yycctest::windows::winfct {
#if defined(YYCC_OS_WINDOWS)
TEST(WindowsWinFct, GetCurrentModule) {
auto rv = WINFCT::get_current_module();
EXPECT_TRUE(rv.has_value());
}
TEST(WindowsWinFct, GetTempDirectory) {
auto rv = WINFCT::get_temp_directory();
EXPECT_TRUE(rv.has_value());
}
TEST(WindowsWinFct, GetModuleFileName) {
auto handle = WINFCT::get_current_module();
ASSERT_TRUE(handle.has_value());
auto rv = WINFCT::get_module_file_name(handle.value());
EXPECT_TRUE(rv.has_value());
}
TEST(WindowsWinFct, IsValidCodePage) {
// Test valid code page
EXPECT_TRUE(WINFCT::is_valid_code_page(437));
EXPECT_TRUE(WINFCT::is_valid_code_page(65001));
// This code page must be invalid
EXPECT_FALSE(WINFCT::is_valid_code_page(6161));
}
#if defined(YYCC_STL_MSSTL)
TEST(WindowsWinFct, GetKnownPath) {
auto rv = WINFCT::get_known_path(WINFCT::KnownDirectory::LocalAppData);
EXPECT_TRUE(rv.has_value());
}
#endif
// YYC MARK:
// I can't test CopyFile, MoveFile and DeleteFile.
#endif
} // namespace yycctest::windows::winfct