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

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