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

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