From efa1266f10e90c0c46f47cc06645422142cb2d9f Mon Sep 17 00:00:00 2001 From: Yuqian Yang Date: Wed, 3 Sep 2025 12:42:10 +0800 Subject: common -> base in test dir. --- test/CMakeLists.txt | 2 +- test/base/CMakeLists.txt | 40 ++++++ test/base/Event2Test.cpp | 54 ++++++++ test/base/HandlerRegistryTest.cpp | 37 +++++ test/base/PropertyTreeTest.cpp | 26 ++++ test/base/SelfResolvableTest.cpp | 110 +++++++++++++++ test/base/StringTest.cpp | 112 +++++++++++++++ test/base/StringToNumberConverterTest.cpp | 166 +++++++++++++++++++++++ test/base/StringUtilTest.cpp | 118 ++++++++++++++++ test/base/SubProcessHelper/CruEcho.cpp | 9 ++ test/base/SubProcessHelper/CruTee.cpp | 10 ++ test/base/SubProcessTest.cpp | 30 ++++ test/base/platform/unix/UnixFileStreamTest.cpp | 30 ++++ test/base/platform/unix/UnixFileTest.cpp | 38 ++++++ test/base/platform/win/StreamConvertTest.cpp | 39 ++++++ test/base/platform/win/Win32FileStreamTest.cpp | 37 +++++ test/common/CMakeLists.txt | 40 ------ test/common/Event2Test.cpp | 54 -------- test/common/HandlerRegistryTest.cpp | 37 ----- test/common/PropertyTreeTest.cpp | 26 ---- test/common/SelfResolvableTest.cpp | 110 --------------- test/common/StringTest.cpp | 112 --------------- test/common/StringToNumberConverterTest.cpp | 166 ----------------------- test/common/StringUtilTest.cpp | 118 ---------------- test/common/SubProcessHelper/CruEcho.cpp | 9 -- test/common/SubProcessHelper/CruTee.cpp | 10 -- test/common/SubProcessTest.cpp | 30 ---- test/common/platform/unix/UnixFileStreamTest.cpp | 30 ---- test/common/platform/unix/UnixFileTest.cpp | 38 ------ test/common/platform/win/StreamConvertTest.cpp | 39 ------ test/common/platform/win/Win32FileStreamTest.cpp | 37 ----- 31 files changed, 857 insertions(+), 857 deletions(-) create mode 100644 test/base/CMakeLists.txt create mode 100644 test/base/Event2Test.cpp create mode 100644 test/base/HandlerRegistryTest.cpp create mode 100644 test/base/PropertyTreeTest.cpp create mode 100644 test/base/SelfResolvableTest.cpp create mode 100644 test/base/StringTest.cpp create mode 100644 test/base/StringToNumberConverterTest.cpp create mode 100644 test/base/StringUtilTest.cpp create mode 100644 test/base/SubProcessHelper/CruEcho.cpp create mode 100644 test/base/SubProcessHelper/CruTee.cpp create mode 100644 test/base/SubProcessTest.cpp create mode 100644 test/base/platform/unix/UnixFileStreamTest.cpp create mode 100644 test/base/platform/unix/UnixFileTest.cpp create mode 100644 test/base/platform/win/StreamConvertTest.cpp create mode 100644 test/base/platform/win/Win32FileStreamTest.cpp delete mode 100644 test/common/CMakeLists.txt delete mode 100644 test/common/Event2Test.cpp delete mode 100644 test/common/HandlerRegistryTest.cpp delete mode 100644 test/common/PropertyTreeTest.cpp delete mode 100644 test/common/SelfResolvableTest.cpp delete mode 100644 test/common/StringTest.cpp delete mode 100644 test/common/StringToNumberConverterTest.cpp delete mode 100644 test/common/StringUtilTest.cpp delete mode 100644 test/common/SubProcessHelper/CruEcho.cpp delete mode 100644 test/common/SubProcessHelper/CruTee.cpp delete mode 100644 test/common/SubProcessTest.cpp delete mode 100644 test/common/platform/unix/UnixFileStreamTest.cpp delete mode 100644 test/common/platform/unix/UnixFileTest.cpp delete mode 100644 test/common/platform/win/StreamConvertTest.cpp delete mode 100644 test/common/platform/win/Win32FileStreamTest.cpp (limited to 'test') diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 524b3dd0..cd51b2f3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,7 +15,7 @@ function(cru_catch_discover_tests target) endif() endfunction() -add_subdirectory(common) +add_subdirectory(base) add_subdirectory(platform) add_subdirectory(xml) add_subdirectory(toml) diff --git a/test/base/CMakeLists.txt b/test/base/CMakeLists.txt new file mode 100644 index 00000000..683c8295 --- /dev/null +++ b/test/base/CMakeLists.txt @@ -0,0 +1,40 @@ +add_executable(CruBaseTest + Event2Test.cpp + HandlerRegistryTest.cpp + PropertyTreeTest.cpp + SelfResolvableTest.cpp + StringTest.cpp + StringToNumberConverterTest.cpp + StringUtilTest.cpp + SubProcessTest.cpp +) +target_link_libraries(CruBaseTest PRIVATE CruBase CruTestBase) + +add_executable(CruTestHelperEcho + SubProcessHelper/CruEcho.cpp +) + +add_executable(CruTestHelperTee + SubProcessHelper/CruTee.cpp +) + +target_compile_definitions(CruBaseTest PRIVATE + CRU_TEST_HELPER_ECHO_LOCATION="$" + CRU_TEST_HELPER_TEE_LOCATION="$" +) + +if (UNIX AND NOT EMSCRIPTEN) + target_sources(CruBaseTest PRIVATE + platform/unix/UnixFileTest.cpp + platform/unix/UnixFileStreamTest.cpp + ) +endif() + +if (WIN32) + target_sources(CruBaseTest PRIVATE + platform/win/StreamConvertTest.cpp + platform/win/Win32FileStreamTest.cpp + ) +endif() + +cru_catch_discover_tests(CruBaseTest) diff --git a/test/base/Event2Test.cpp b/test/base/Event2Test.cpp new file mode 100644 index 00000000..0c67f28e --- /dev/null +++ b/test/base/Event2Test.cpp @@ -0,0 +1,54 @@ +#include "cru/base/Event2.h" + +#include + +using cru::Event2; + +TEST_CASE("Event2", "[event2]") { + Event2 event; + + int counter = 0; + + auto handler = [&counter] { counter++; }; + auto token = event.AddHandler(handler); + + auto handler2 = [&counter](decltype(event)::Context* context) { counter++; }; + + SECTION("two handlers should work.") { + event.Raise(); + REQUIRE(counter == 1); + event.Raise(); + REQUIRE(counter == 2); + + event.AddHandler(handler2); + event.Raise(); + REQUIRE(counter == 4); + } + + SECTION("handler revoker should work.") { + token.RevokeHandler(); + event.Raise(); + REQUIRE(counter == 0); + + token = event.AddHandler(handler); + event.AddHandler(handler2); + event.Raise(); + REQUIRE(counter == 2); + + token.RevokeHandler(); + event.Raise(); + REQUIRE(counter == 3); + } + + SECTION("stop handling should work.") { + auto short_circuit_handler = [&counter](decltype(event)::Context* context) { + context->SetStopHandling(); + }; + + event.AddHandler(short_circuit_handler); + event.AddHandler(handler2); + + event.Raise(); + REQUIRE(counter == 1); + } +} diff --git a/test/base/HandlerRegistryTest.cpp b/test/base/HandlerRegistryTest.cpp new file mode 100644 index 00000000..aacef70f --- /dev/null +++ b/test/base/HandlerRegistryTest.cpp @@ -0,0 +1,37 @@ +#include "cru/base/HandlerRegistry.h" + +#include + +#include + +TEST_CASE("HandlerRegistry", "[handler_registry]") { + using namespace cru; + HandlerRegistry registry; + + int counter = 1; + + auto tag1 = registry.AddHandler([&counter] { counter++; }); + auto tag2 = registry.AddHandler([&counter] { counter++; }); + + for (const auto& handler : registry) { + handler(); + } + + REQUIRE(counter == 3); + + registry.RemoveHandler(tag1); + + for (const auto& handler : registry) { + handler(); + } + + REQUIRE(counter == 4); + + registry.RemoveHandler(tag2); + + for (const auto& handler : registry) { + handler(); + } + + REQUIRE(counter == 4); +} diff --git a/test/base/PropertyTreeTest.cpp b/test/base/PropertyTreeTest.cpp new file mode 100644 index 00000000..24d7ca9e --- /dev/null +++ b/test/base/PropertyTreeTest.cpp @@ -0,0 +1,26 @@ +#include "cru/base/PropertyTree.h" + +#include + +TEST_CASE("PropertyTree", "[property_tree]") { + using cru::PropertySubTreeRef; + using cru::PropertyTree; + + PropertyTree tree({ + {u"k1", u"v1"}, + {u"k2", u"v2"}, + {u"k3.sub", u"v3"}, + }); + + REQUIRE(tree.GetValue(u"k1") == u"v1"); + REQUIRE(tree.GetValue(u"k2") == u"v2"); + REQUIRE(tree.GetValue(u"k3.sub") == u"v3"); + + PropertySubTreeRef sub_tree = tree.GetSubTreeRef(u"k3"); + REQUIRE(sub_tree.GetValue(u"sub") == u"v3"); + + PropertySubTreeRef root_tree = sub_tree.GetParent(); + REQUIRE(root_tree.GetValue(u"k1") == u"v1"); + REQUIRE(root_tree.GetValue(u"k2") == u"v2"); + REQUIRE(root_tree.GetValue(u"k3.sub") == u"v3"); +} diff --git a/test/base/SelfResolvableTest.cpp b/test/base/SelfResolvableTest.cpp new file mode 100644 index 00000000..c214bd77 --- /dev/null +++ b/test/base/SelfResolvableTest.cpp @@ -0,0 +1,110 @@ +#include "cru/base/Base.h" +#include "cru/base/SelfResolvable.h" + +#include + +#include + +namespace { +class SelfResolvableTestClassBase { + public: + SelfResolvableTestClassBase() = default; + CRU_DELETE_COPY(SelfResolvableTestClassBase) + CRU_DEFAULT_MOVE(SelfResolvableTestClassBase) + virtual ~SelfResolvableTestClassBase() = default; +}; + +class SelfResolvableTestClass + : public SelfResolvableTestClassBase, + public cru::SelfResolvable { + public: + SelfResolvableTestClass() : ptr_(new int(123)) {} + CRU_DELETE_COPY(SelfResolvableTestClass) + CRU_DEFAULT_MOVE(SelfResolvableTestClass) + ~SelfResolvableTestClass() override = default; + + private: + std::shared_ptr ptr_; +}; +} // namespace + +TEST_CASE("SelfResolvable resolver should work.", "[self-resolvable]") { + SelfResolvableTestClass test_object; + + auto resolver = test_object.CreateResolver(); + REQUIRE(resolver.Resolve() == &test_object); + + auto resolver_copy = resolver; + REQUIRE(resolver.Resolve() == &test_object); + REQUIRE(resolver.Resolve() == &test_object); + + auto resolver_move = std::move(resolver_copy); + REQUIRE(resolver.Resolve() == &test_object); + REQUIRE(resolver_copy.IsValid() == false); + REQUIRE(resolver_move.Resolve() == &test_object); +} + +TEST_CASE("SelfResolvable object destructed should work.", + "[self-resolvable]") { + SelfResolvableTestClass* test_object = new SelfResolvableTestClass(); + + auto resolver = test_object->CreateResolver(); + auto resolver_copy = resolver; + + delete test_object; + + REQUIRE(resolver.Resolve() == nullptr); + REQUIRE(resolver_copy.Resolve() == nullptr); + + auto resolver_copy2 = resolver_copy; + REQUIRE(resolver_copy2.Resolve() == nullptr); + + auto resolver_move = std::move(resolver_copy); + REQUIRE(resolver_copy.IsValid() == false); + REQUIRE(resolver_move.Resolve() == nullptr); +} + +TEST_CASE("SelfResolvable object moved should work.", "[self-resolvable]") { + SelfResolvableTestClass test_object; + + auto resolver = test_object.CreateResolver(); + auto resolver_copy = resolver; + + SelfResolvableTestClass moved_object = std::move(test_object); + + REQUIRE(resolver.Resolve() == &moved_object); + REQUIRE(resolver_copy.Resolve() == &moved_object); + + auto resolver_copy2 = resolver_copy; + REQUIRE(resolver_copy2.Resolve() == &moved_object); + + auto resolver_move = std::move(resolver_copy); + REQUIRE(resolver_copy.IsValid() == false); + REQUIRE(resolver_move.Resolve() == &moved_object); +} + +TEST_CASE("SelfResolvable should work for casted type.", "[self-resolvable]") { + auto test_object = new SelfResolvableTestClass(); + + cru::ObjectResolver base_resolver = + test_object->CreateResolver(); + + REQUIRE(base_resolver.Resolve() == test_object); + + auto base_resolver2 = base_resolver; + REQUIRE(base_resolver2.Resolve() == test_object); + + auto base_resolver3 = std::move(base_resolver2); + REQUIRE(base_resolver3.Resolve() == test_object); + + auto moved_object = new SelfResolvableTestClass(std::move(*test_object)); + delete test_object; + + REQUIRE(base_resolver.Resolve() == moved_object); + REQUIRE(base_resolver3.Resolve() == moved_object); + + delete moved_object; + + REQUIRE(base_resolver.Resolve() == nullptr); + REQUIRE(base_resolver3.Resolve() == nullptr); +} diff --git a/test/base/StringTest.cpp b/test/base/StringTest.cpp new file mode 100644 index 00000000..9ed351e5 --- /dev/null +++ b/test/base/StringTest.cpp @@ -0,0 +1,112 @@ +#include "cru/base/Format.h" +#include "cru/base/String.h" + +#include + +TEST_CASE("String Append", "[string]") { + using cru::String; + + String s; + s.append(u"ha"); + s.append(s); + REQUIRE(s == String(u"haha")); +} + +TEST_CASE("String IndexConvert", "[string]") { + using cru::String; + + String s(u"123"); + REQUIRE(s.IndexFromCodePointToCodeUnit(1) == 1); + REQUIRE(s.IndexFromCodeUnitToCodePoint(1) == 1); + REQUIRE(s.IndexFromCodeUnitToCodePoint(3) == 3); + REQUIRE(s.IndexFromCodeUnitToCodePoint(3) == 3); +} + +TEST_CASE("String Format", "[string]") { + using cru::Format; + using cru::String; + + REQUIRE(Format(u"{} + {} = {}", 123, 321, 444) == String(u"123 + 321 = 444")); +} + +TEST_CASE("String Trim", "[string]") { + using cru::String; + REQUIRE(String(u" abc ").Trim() == u"abc"); +} + +TEST_CASE("String SplitToLines", "[string]") { + using cru::String; + + String s(u"abc\ndef\nghi"); + auto lines = s.SplitToLines(); + REQUIRE(lines.size() == 3); + REQUIRE(lines[0] == String(u"abc")); + REQUIRE(lines[1] == String(u"def")); + REQUIRE(lines[2] == String(u"ghi")); +} + +TEST_CASE("String SplitToLinesWithEmptyLine", "[string]") { + using cru::String; + + String s(u"abc\n \ndef\n\nghi\n"); + auto lines = s.SplitToLines(); + REQUIRE(lines.size() == 6); + REQUIRE(lines[0] == String(u"abc")); + REQUIRE(lines[1] == String(u" ")); + REQUIRE(lines[2] == String(u"def")); + REQUIRE(lines[3] == String(u"")); + REQUIRE(lines[4] == String(u"ghi")); + REQUIRE(lines[5] == String(u"")); +} + +TEST_CASE("String SplitToLinesRemoveSpaceLine", "[string]") { + using cru::String; + + String s(u"abc\n \ndef\n\nghi\n"); + auto lines = s.SplitToLines(true); + REQUIRE(lines.size() == 3); + REQUIRE(lines[0] == String(u"abc")); + REQUIRE(lines[1] == String(u"def")); + REQUIRE(lines[2] == String(u"ghi")); +} + +TEST_CASE("StringView ToUtf8", "[string]") { + using cru::StringView; + StringView utf16_text = u"aπ你🤣!"; + std::string_view utf8_text = "aπ你🤣!"; + + REQUIRE(utf16_text.ToUtf8() == utf8_text); +} + +TEST_CASE("String FromUtf8", "[string]") { + std::u16string_view utf16_text = u"aπ你🤣!"; + std::string_view utf8_text = "aπ你🤣!"; + + REQUIRE(cru::String::FromUtf8(utf8_text) == utf16_text); +} + +TEST_CASE("StringView ParseToDouble", "[string]") { + using cru::StringToNumberFlags; + using cru::StringView; + REQUIRE(StringView(u"3.14159").ParseToDouble() == 3.14159); + REQUIRE( + StringView(u" 3.14159") + .ParseToDouble(nullptr, StringToNumberFlags::kAllowLeadingSpaces) == + 3.14159); + REQUIRE(StringView(u" 3.14159 ") + .ParseToDouble(nullptr, + StringToNumberFlags::kAllowLeadingSpaces | + StringToNumberFlags::kAllowTrailingSpaces) == + 3.14159); +} + +TEST_CASE("String ParseToDoubleList", "[string]") { + using cru::StringView; + + auto list = StringView(u" 1.23 2.34 3.45 ").ParseToDoubleList(); + + REQUIRE(list.size() == 3); + REQUIRE(list[0] == 1.23); + REQUIRE(list[1] == 2.34); + REQUIRE(list[2] == 3.45); +} diff --git a/test/base/StringToNumberConverterTest.cpp b/test/base/StringToNumberConverterTest.cpp new file mode 100644 index 00000000..82062bdb --- /dev/null +++ b/test/base/StringToNumberConverterTest.cpp @@ -0,0 +1,166 @@ +#include "cru/base/Exception.h" +#include "cru/base/StringToNumberConverter.h" + +#include + +TEST_CASE("StringToIntegerConverterImpl Base0", "[string]") { + using namespace cru; + StringToIntegerConverter converter({}, 0); + Index processed_characters_count; + + REQUIRE(converter.Parse("12345678", &processed_characters_count) == + StringToIntegerResult(false, 12345678)); + REQUIRE(processed_characters_count == 8); + + REQUIRE(converter.Parse("0", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 1); + + REQUIRE(converter.Parse("012", &processed_characters_count) == + StringToIntegerResult(false, 012)); + REQUIRE(processed_characters_count == 3); + + REQUIRE(converter.Parse("0x12", &processed_characters_count) == + StringToIntegerResult(false, 0x12)); + REQUIRE(processed_characters_count == 4); + + REQUIRE(converter.Parse("0X12", &processed_characters_count) == + StringToIntegerResult(false, 0x12)); + REQUIRE(processed_characters_count == 4); + + REQUIRE(converter.Parse("0b101", &processed_characters_count) == + StringToIntegerResult(false, 0b101)); + REQUIRE(processed_characters_count == 5); + + REQUIRE(converter.Parse("0B101", &processed_characters_count) == + StringToIntegerResult(false, 0b101)); + REQUIRE(processed_characters_count == 5); + + REQUIRE(converter.Parse("-123", &processed_characters_count) == + StringToIntegerResult(true, 123)); + REQUIRE(processed_characters_count == 4); + + REQUIRE(converter.Parse("-0x10", &processed_characters_count) == + StringToIntegerResult(true, 0x10)); + REQUIRE(processed_characters_count == 5); +} + +TEST_CASE("StringToIntegerConverterImpl Base0ForError", "[string]") { + using namespace cru; + StringToIntegerConverter converter({}, 0); + Index processed_characters_count; + + REQUIRE(converter.Parse("a", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 0); + + REQUIRE(converter.Parse("0a", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 0); + + REQUIRE(converter.Parse("0x", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 0); + + REQUIRE(converter.Parse("0xx", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 0); + + REQUIRE(converter.Parse(" 0", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 0); + + REQUIRE(converter.Parse("0 ", &processed_characters_count) == + StringToIntegerResult(false, 0)); + REQUIRE(processed_characters_count == 0); +} + +TEST_CASE("StringToIntegerConverterImpl ThrowOnErrorFlag", "[string]") { + using namespace cru; + StringToIntegerConverter converter(StringToNumberFlags::kThrowOnError, 0); + Index processed_characters_count; + REQUIRE_THROWS_AS(converter.Parse("?", &processed_characters_count), + Exception); +} + +TEST_CASE("StringToIntegerConverterImpl AllowLeadingZeroFlag", "[string]") { + using namespace cru; + StringToIntegerConverter converter( + StringToNumberFlags::kAllowLeadingSpaces, 0); + Index processed_characters_count; + REQUIRE(converter.Parse(" 123", &processed_characters_count) == + StringToIntegerResult(false, 123)); + REQUIRE(processed_characters_count == 6); +} + +TEST_CASE("StringToIntegerConverterImpl AllowTrailingZeroFlag", "[string]") { + using namespace cru; + StringToIntegerConverter converter( + StringToNumberFlags::kAllowTrailingSpaces, 0); + Index processed_characters_count; + REQUIRE(converter.Parse("123 ", &processed_characters_count) == + StringToIntegerResult(false, 123)); + REQUIRE(processed_characters_count == 6); +} + +TEST_CASE("StringToIntegerConverterImpl AllowTrailingJunk", "[string]") { + using namespace cru; + StringToIntegerConverter converter( + StringToNumberFlags::kAllowTrailingJunk, 0); + Index processed_characters_count; + REQUIRE(converter.Parse("123 12", &processed_characters_count) == + StringToIntegerResult(false, 123)); + REQUIRE(processed_characters_count == 3); +} + +TEST_CASE("StringToIntegerConverterImpl AllowLeadingZeroForInteger", + "[string]") { + using namespace cru; + StringToIntegerConverter converter( + StringToNumberFlags::kAllowLeadingZeroForInteger, 0); + Index processed_characters_count; + REQUIRE(converter.Parse("0x0012", &processed_characters_count) == + StringToIntegerResult(false, 0x12)); + REQUIRE(processed_characters_count == 6); + + REQUIRE(converter.Parse("000011", &processed_characters_count) == + StringToIntegerResult(false, 000011)); + REQUIRE(processed_characters_count == 6); + + REQUIRE(converter.Parse("0b0011", &processed_characters_count) == + StringToIntegerResult(false, 0b0011)); + REQUIRE(processed_characters_count == 6); +} + +TEST_CASE("StringToIntegerConverterImpl CompositeFlags", "[string]") { + using namespace cru; + StringToIntegerConverter converter( + StringToNumberFlags::kAllowLeadingSpaces | + StringToNumberFlags::kAllowTrailingJunk | + StringToNumberFlags::kAllowLeadingZeroForInteger, + 0); + Index processed_characters_count; + + REQUIRE(converter.Parse(" 0x00123!!!", &processed_characters_count) == + StringToIntegerResult(false, 0x00123)); + REQUIRE(processed_characters_count == 10); +} + +TEST_CASE("StringToIntegerConverterImpl OtherBase", "[string]") { + using namespace cru; + StringToIntegerConverter converter({}, 7); + Index processed_characters_count; + + REQUIRE(converter.Parse("12", &processed_characters_count) == + StringToIntegerResult(false, 9)); + REQUIRE(processed_characters_count == 2); + + REQUIRE(converter.Parse("-12", &processed_characters_count) == + StringToIntegerResult(true, 9)); + REQUIRE(processed_characters_count == 3); + + converter.base = 11; + REQUIRE(converter.Parse("1a", &processed_characters_count) == + StringToIntegerResult(false, 21)); + REQUIRE(processed_characters_count == 2); +} diff --git a/test/base/StringUtilTest.cpp b/test/base/StringUtilTest.cpp new file mode 100644 index 00000000..1da6e963 --- /dev/null +++ b/test/base/StringUtilTest.cpp @@ -0,0 +1,118 @@ +#include "cru/base/String.h" +#include "cru/base/StringUtil.h" + +#include + +using cru::Index; +using cru::k_invalid_code_point; + +TEST_CASE("StringUtil Utf8NextCodePoint", "[string]") { + using cru::Utf8NextCodePoint; + std::string_view text = "aπ你🤣!"; + Index current = 0; + REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x0061); + REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x03C0); + REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x4F60); + REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x1F923); + REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x0021); + REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == + k_invalid_code_point); + REQUIRE(current == static_cast(text.size())); +} + +TEST_CASE("StringUtil Utf16NextCodePoint", "[string]") { + using cru::Utf16NextCodePoint; + std::u16string_view text = u"aπ你🤣!"; + Index current = 0; + REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x0061); + REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x03C0); + REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x4F60); + REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x1F923); + REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == + 0x0021); + REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == + k_invalid_code_point); + REQUIRE(current == static_cast(text.size())); +} + +TEST_CASE("StringUtil Utf16PreviousCodePoint", "[string]") { + using cru::Utf16PreviousCodePoint; + std::u16string_view text = u"aπ你🤣!"; + Index current = text.size(); + REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == + 0x0021); + REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == + 0x1F923); + REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == + 0x4F60); + REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == + 0x03C0); + REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == + 0x0061); + REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == + k_invalid_code_point); + REQUIRE(current == 0); +} + +TEST_CASE("StringUtil Utf8CodePointIterator", "[string]") { + using cru::Utf8CodePointIterator; + std::string_view text = "aπ你🤣!"; + std::vector code_points; + + for (auto cp : Utf8CodePointIterator(text.data(), text.size())) { + code_points.push_back(cp); + } + + std::vector expected_code_points{0x0061, 0x03C0, 0x4F60, + 0x1F923, 0x0021}; + + REQUIRE(code_points == expected_code_points); +} + +TEST_CASE("StringUtil Utf16CodePointIterator", "[string]") { + using cru::Utf16CodePointIterator; + std::u16string_view text = u"aπ你🤣!"; + std::vector code_points; + + for (auto cp : Utf16CodePointIterator(text.data(), text.size())) { + code_points.push_back(cp); + } + + std::vector expected_code_points{0x0061, 0x03C0, 0x4F60, + 0x1F923, 0x0021}; + + REQUIRE(code_points == expected_code_points); +} + +// TEST(WinString, IndexUtf8ToUtf16) { +// using cru::platform::win::IndexUtf8ToUtf16; +// std::string_view utf8_string = "aπ你🤣!"; +// std::wstring_view utf16_string = L"aπ你🤣!"; +// REQUIRE(IndexUtf8ToUtf16(utf8_string, 0, utf16_string), 0); +// REQUIRE(IndexUtf8ToUtf16(utf8_string, 1, utf16_string), 1); +// REQUIRE(IndexUtf8ToUtf16(utf8_string, 3, utf16_string), 2); +// REQUIRE(IndexUtf8ToUtf16(utf8_string, 6, utf16_string), 3); +// REQUIRE(IndexUtf8ToUtf16(utf8_string, 10, utf16_string), 5); +// REQUIRE(IndexUtf8ToUtf16(utf8_string, 11, utf16_string), 6); +// } + +// TEST(WinString, IndexUtf16ToUtf8) { +// using cru::platform::win::IndexUtf16ToUtf8; +// std::string_view utf8_string = "aπ你🤣!"; +// std::wstring_view utf16_string = L"aπ你🤣!"; +// REQUIRE(IndexUtf16ToUtf8(utf16_string, 0, utf8_string), 0); +// REQUIRE(IndexUtf16ToUtf8(utf16_string, 1, utf8_string), 1); +// REQUIRE(IndexUtf16ToUtf8(utf16_string, 2, utf8_string), 3); +// REQUIRE(IndexUtf16ToUtf8(utf16_string, 3, utf8_string), 6); +// REQUIRE(IndexUtf16ToUtf8(utf16_string, 5, utf8_string), 10); +// REQUIRE(IndexUtf16ToUtf8(utf16_string, 6, utf8_string), 11); +// } diff --git a/test/base/SubProcessHelper/CruEcho.cpp b/test/base/SubProcessHelper/CruEcho.cpp new file mode 100644 index 00000000..5f23c027 --- /dev/null +++ b/test/base/SubProcessHelper/CruEcho.cpp @@ -0,0 +1,9 @@ +#include + +int main(int argc, char* argv[]) { + for (int i = 1; i < argc - 1; ++i) { + std::cout << argv[i] << " "; + } + std::cout << argv[argc - 1]; + return 0; +} diff --git a/test/base/SubProcessHelper/CruTee.cpp b/test/base/SubProcessHelper/CruTee.cpp new file mode 100644 index 00000000..4470d2a8 --- /dev/null +++ b/test/base/SubProcessHelper/CruTee.cpp @@ -0,0 +1,10 @@ +#include +#include + +int main() { + std::string s; + while (std::cin >> s) { + std::cout << s; + } + return 0; +} diff --git a/test/base/SubProcessTest.cpp b/test/base/SubProcessTest.cpp new file mode 100644 index 00000000..d353dec0 --- /dev/null +++ b/test/base/SubProcessTest.cpp @@ -0,0 +1,30 @@ +#include "cru/base/String.h" +#include "cru/base/SubProcess.h" + +#include + +using cru::String; +using cru::SubProcess; + +TEST_CASE("SubProcess", "[subprocess]") { + SECTION("echo should work.") { + SubProcess process = SubProcess::Create( + String::FromUtf8(CRU_TEST_HELPER_ECHO_LOCATION), {u"abc"}); + process.Wait(); + REQUIRE(process.GetExitResult().IsSuccess()); + auto output = process.GetStdoutStream()->ReadToEndAsUtf8String(); + REQUIRE(output == u"abc"); + } + + SECTION("tee should work.") { + constexpr auto str = "abc"; + SubProcess process = + SubProcess::Create(String::FromUtf8(CRU_TEST_HELPER_TEE_LOCATION)); + process.GetStdinStream()->Write(str, 3); + process.GetStdinStream()->Close(); + process.Wait(); + REQUIRE(process.GetExitResult().IsSuccess()); + auto output = process.GetStdoutStream()->ReadToEndAsUtf8String(); + REQUIRE(output == u"abc"); + } +} diff --git a/test/base/platform/unix/UnixFileStreamTest.cpp b/test/base/platform/unix/UnixFileStreamTest.cpp new file mode 100644 index 00000000..417fccc2 --- /dev/null +++ b/test/base/platform/unix/UnixFileStreamTest.cpp @@ -0,0 +1,30 @@ +#include "cru/base/platform/unix/UnixFileStream.h" + +#include + +#include +#include + +TEST_CASE("UnixFileStream Work", "[stream]") { + using namespace cru; + using namespace cru::io; + using namespace cru::platform::unix; + + auto temp_file_path = + (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") + .generic_string(); + mkstemp(temp_file_path.data()); + + UnixFileStream file(temp_file_path.c_str(), O_WRONLY | O_CREAT); + file.Write("abc", 3); + file.Close(); + + UnixFileStream file2(temp_file_path.c_str(), O_RDONLY); + auto buffer = std::make_unique(3); + file2.Read(buffer.get(), 3); + REQUIRE(std::string_view(reinterpret_cast(buffer.get()), 3) == + "abc"); + file2.Close(); + + std::filesystem::remove(temp_file_path); +} diff --git a/test/base/platform/unix/UnixFileTest.cpp b/test/base/platform/unix/UnixFileTest.cpp new file mode 100644 index 00000000..d5bba0db --- /dev/null +++ b/test/base/platform/unix/UnixFileTest.cpp @@ -0,0 +1,38 @@ + +#include "cru/base/platform/unix/UnixFileStream.h" + +#include + +#include +#include + +TEST_CASE("UnixFile Work", "[unix]") { + using namespace cru; + using namespace cru::platform::unix; + + auto calledTimes = 0; + auto mockClose = [&calledTimes](int _) { + calledTimes += 1; + return 0; + }; + + auto temp_file_path = + (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") + .generic_string(); + mkstemp(temp_file_path.data()); + + auto fdNumber = ::open(temp_file_path.c_str(), O_WRONLY | O_CREAT); + + { + UnixFileDescriptor fd(fdNumber, true, std::move(mockClose)); + REQUIRE(calledTimes == 0); + UnixFileDescriptor fd2(std::move(fd)); + REQUIRE(calledTimes == 0); + UnixFileDescriptor fd3; + fd3 = std::move(fd2); + REQUIRE(calledTimes == 0); + } + REQUIRE(calledTimes == 1); + + std::filesystem::remove(temp_file_path); +} diff --git a/test/base/platform/win/StreamConvertTest.cpp b/test/base/platform/win/StreamConvertTest.cpp new file mode 100644 index 00000000..90ebb568 --- /dev/null +++ b/test/base/platform/win/StreamConvertTest.cpp @@ -0,0 +1,39 @@ +#include "cru/base/io/OpenFileFlag.h" +#include "cru/base/platform/win/Exception.h" +#include "cru/base/platform/win/StreamConvert.h" +#include "cru/base/platform/win/Win32FileStream.h" + +#include + +#include +#include + +TEST_CASE("StreamConvert FileStreamWork", "[stream]") { + using namespace cru; + using namespace cru::io; + using namespace cru::platform::win; + + auto temp_file_path = + (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") + .native(); + _wmktemp(temp_file_path.data()); + + String path = temp_file_path; + + Win32FileStream file(path, OpenFileFlags::Write | OpenFileFlags::Create); + file.Write("abc", 3); + file.Close(); + + Win32FileStream file2(path, OpenFileFlags::Read); + IStream* com_stream = ConvertStreamToComStream(&file2); + LARGE_INTEGER position; + position.QuadPart = 0; + ThrowIfFailed(com_stream->Seek(position, SEEK_SET, nullptr)); + auto buffer = std::make_unique(3); + ThrowIfFailed(com_stream->Read(buffer.get(), 3, nullptr)); + REQUIRE(std::string_view(buffer.get(), 3) == "abc"); + com_stream->Release(); + file2.Close(); + + std::filesystem::remove(temp_file_path); +} diff --git a/test/base/platform/win/Win32FileStreamTest.cpp b/test/base/platform/win/Win32FileStreamTest.cpp new file mode 100644 index 00000000..dc2f49d4 --- /dev/null +++ b/test/base/platform/win/Win32FileStreamTest.cpp @@ -0,0 +1,37 @@ +#include "cru/base/io/OpenFileFlag.h" +#include "cru/base/platform/win/Win32FileStream.h" + +#include + +#include +#include + +TEST_CASE("Win32FileStream Work", "[stream]") { + using namespace cru; + using namespace cru::io; + using namespace cru::platform::win; + + auto temp_file_path = + (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") + .native(); + _wmktemp(temp_file_path.data()); + + String path = temp_file_path; + + Win32FileStream file(path, OpenFileFlags::Write | OpenFileFlags::Create); + auto write_count = file.Write("abc", 3); + REQUIRE(write_count == 3); + file.Close(); + + REQUIRE(std::filesystem::file_size(path.ToUtf8()) == 3); + + Win32FileStream file2(path, OpenFileFlags::Read); + auto buffer = std::make_unique(3); + auto read_count = file2.Read(buffer.get(), 3); + REQUIRE(read_count == 3); + REQUIRE(std::string_view(reinterpret_cast(buffer.get()), 3) == + "abc"); + file2.Close(); + + std::filesystem::remove(temp_file_path); +} diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt deleted file mode 100644 index 683c8295..00000000 --- a/test/common/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -add_executable(CruBaseTest - Event2Test.cpp - HandlerRegistryTest.cpp - PropertyTreeTest.cpp - SelfResolvableTest.cpp - StringTest.cpp - StringToNumberConverterTest.cpp - StringUtilTest.cpp - SubProcessTest.cpp -) -target_link_libraries(CruBaseTest PRIVATE CruBase CruTestBase) - -add_executable(CruTestHelperEcho - SubProcessHelper/CruEcho.cpp -) - -add_executable(CruTestHelperTee - SubProcessHelper/CruTee.cpp -) - -target_compile_definitions(CruBaseTest PRIVATE - CRU_TEST_HELPER_ECHO_LOCATION="$" - CRU_TEST_HELPER_TEE_LOCATION="$" -) - -if (UNIX AND NOT EMSCRIPTEN) - target_sources(CruBaseTest PRIVATE - platform/unix/UnixFileTest.cpp - platform/unix/UnixFileStreamTest.cpp - ) -endif() - -if (WIN32) - target_sources(CruBaseTest PRIVATE - platform/win/StreamConvertTest.cpp - platform/win/Win32FileStreamTest.cpp - ) -endif() - -cru_catch_discover_tests(CruBaseTest) diff --git a/test/common/Event2Test.cpp b/test/common/Event2Test.cpp deleted file mode 100644 index 0c67f28e..00000000 --- a/test/common/Event2Test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "cru/base/Event2.h" - -#include - -using cru::Event2; - -TEST_CASE("Event2", "[event2]") { - Event2 event; - - int counter = 0; - - auto handler = [&counter] { counter++; }; - auto token = event.AddHandler(handler); - - auto handler2 = [&counter](decltype(event)::Context* context) { counter++; }; - - SECTION("two handlers should work.") { - event.Raise(); - REQUIRE(counter == 1); - event.Raise(); - REQUIRE(counter == 2); - - event.AddHandler(handler2); - event.Raise(); - REQUIRE(counter == 4); - } - - SECTION("handler revoker should work.") { - token.RevokeHandler(); - event.Raise(); - REQUIRE(counter == 0); - - token = event.AddHandler(handler); - event.AddHandler(handler2); - event.Raise(); - REQUIRE(counter == 2); - - token.RevokeHandler(); - event.Raise(); - REQUIRE(counter == 3); - } - - SECTION("stop handling should work.") { - auto short_circuit_handler = [&counter](decltype(event)::Context* context) { - context->SetStopHandling(); - }; - - event.AddHandler(short_circuit_handler); - event.AddHandler(handler2); - - event.Raise(); - REQUIRE(counter == 1); - } -} diff --git a/test/common/HandlerRegistryTest.cpp b/test/common/HandlerRegistryTest.cpp deleted file mode 100644 index aacef70f..00000000 --- a/test/common/HandlerRegistryTest.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "cru/base/HandlerRegistry.h" - -#include - -#include - -TEST_CASE("HandlerRegistry", "[handler_registry]") { - using namespace cru; - HandlerRegistry registry; - - int counter = 1; - - auto tag1 = registry.AddHandler([&counter] { counter++; }); - auto tag2 = registry.AddHandler([&counter] { counter++; }); - - for (const auto& handler : registry) { - handler(); - } - - REQUIRE(counter == 3); - - registry.RemoveHandler(tag1); - - for (const auto& handler : registry) { - handler(); - } - - REQUIRE(counter == 4); - - registry.RemoveHandler(tag2); - - for (const auto& handler : registry) { - handler(); - } - - REQUIRE(counter == 4); -} diff --git a/test/common/PropertyTreeTest.cpp b/test/common/PropertyTreeTest.cpp deleted file mode 100644 index 24d7ca9e..00000000 --- a/test/common/PropertyTreeTest.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "cru/base/PropertyTree.h" - -#include - -TEST_CASE("PropertyTree", "[property_tree]") { - using cru::PropertySubTreeRef; - using cru::PropertyTree; - - PropertyTree tree({ - {u"k1", u"v1"}, - {u"k2", u"v2"}, - {u"k3.sub", u"v3"}, - }); - - REQUIRE(tree.GetValue(u"k1") == u"v1"); - REQUIRE(tree.GetValue(u"k2") == u"v2"); - REQUIRE(tree.GetValue(u"k3.sub") == u"v3"); - - PropertySubTreeRef sub_tree = tree.GetSubTreeRef(u"k3"); - REQUIRE(sub_tree.GetValue(u"sub") == u"v3"); - - PropertySubTreeRef root_tree = sub_tree.GetParent(); - REQUIRE(root_tree.GetValue(u"k1") == u"v1"); - REQUIRE(root_tree.GetValue(u"k2") == u"v2"); - REQUIRE(root_tree.GetValue(u"k3.sub") == u"v3"); -} diff --git a/test/common/SelfResolvableTest.cpp b/test/common/SelfResolvableTest.cpp deleted file mode 100644 index c214bd77..00000000 --- a/test/common/SelfResolvableTest.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "cru/base/Base.h" -#include "cru/base/SelfResolvable.h" - -#include - -#include - -namespace { -class SelfResolvableTestClassBase { - public: - SelfResolvableTestClassBase() = default; - CRU_DELETE_COPY(SelfResolvableTestClassBase) - CRU_DEFAULT_MOVE(SelfResolvableTestClassBase) - virtual ~SelfResolvableTestClassBase() = default; -}; - -class SelfResolvableTestClass - : public SelfResolvableTestClassBase, - public cru::SelfResolvable { - public: - SelfResolvableTestClass() : ptr_(new int(123)) {} - CRU_DELETE_COPY(SelfResolvableTestClass) - CRU_DEFAULT_MOVE(SelfResolvableTestClass) - ~SelfResolvableTestClass() override = default; - - private: - std::shared_ptr ptr_; -}; -} // namespace - -TEST_CASE("SelfResolvable resolver should work.", "[self-resolvable]") { - SelfResolvableTestClass test_object; - - auto resolver = test_object.CreateResolver(); - REQUIRE(resolver.Resolve() == &test_object); - - auto resolver_copy = resolver; - REQUIRE(resolver.Resolve() == &test_object); - REQUIRE(resolver.Resolve() == &test_object); - - auto resolver_move = std::move(resolver_copy); - REQUIRE(resolver.Resolve() == &test_object); - REQUIRE(resolver_copy.IsValid() == false); - REQUIRE(resolver_move.Resolve() == &test_object); -} - -TEST_CASE("SelfResolvable object destructed should work.", - "[self-resolvable]") { - SelfResolvableTestClass* test_object = new SelfResolvableTestClass(); - - auto resolver = test_object->CreateResolver(); - auto resolver_copy = resolver; - - delete test_object; - - REQUIRE(resolver.Resolve() == nullptr); - REQUIRE(resolver_copy.Resolve() == nullptr); - - auto resolver_copy2 = resolver_copy; - REQUIRE(resolver_copy2.Resolve() == nullptr); - - auto resolver_move = std::move(resolver_copy); - REQUIRE(resolver_copy.IsValid() == false); - REQUIRE(resolver_move.Resolve() == nullptr); -} - -TEST_CASE("SelfResolvable object moved should work.", "[self-resolvable]") { - SelfResolvableTestClass test_object; - - auto resolver = test_object.CreateResolver(); - auto resolver_copy = resolver; - - SelfResolvableTestClass moved_object = std::move(test_object); - - REQUIRE(resolver.Resolve() == &moved_object); - REQUIRE(resolver_copy.Resolve() == &moved_object); - - auto resolver_copy2 = resolver_copy; - REQUIRE(resolver_copy2.Resolve() == &moved_object); - - auto resolver_move = std::move(resolver_copy); - REQUIRE(resolver_copy.IsValid() == false); - REQUIRE(resolver_move.Resolve() == &moved_object); -} - -TEST_CASE("SelfResolvable should work for casted type.", "[self-resolvable]") { - auto test_object = new SelfResolvableTestClass(); - - cru::ObjectResolver base_resolver = - test_object->CreateResolver(); - - REQUIRE(base_resolver.Resolve() == test_object); - - auto base_resolver2 = base_resolver; - REQUIRE(base_resolver2.Resolve() == test_object); - - auto base_resolver3 = std::move(base_resolver2); - REQUIRE(base_resolver3.Resolve() == test_object); - - auto moved_object = new SelfResolvableTestClass(std::move(*test_object)); - delete test_object; - - REQUIRE(base_resolver.Resolve() == moved_object); - REQUIRE(base_resolver3.Resolve() == moved_object); - - delete moved_object; - - REQUIRE(base_resolver.Resolve() == nullptr); - REQUIRE(base_resolver3.Resolve() == nullptr); -} diff --git a/test/common/StringTest.cpp b/test/common/StringTest.cpp deleted file mode 100644 index 9ed351e5..00000000 --- a/test/common/StringTest.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "cru/base/Format.h" -#include "cru/base/String.h" - -#include - -TEST_CASE("String Append", "[string]") { - using cru::String; - - String s; - s.append(u"ha"); - s.append(s); - REQUIRE(s == String(u"haha")); -} - -TEST_CASE("String IndexConvert", "[string]") { - using cru::String; - - String s(u"123"); - REQUIRE(s.IndexFromCodePointToCodeUnit(1) == 1); - REQUIRE(s.IndexFromCodeUnitToCodePoint(1) == 1); - REQUIRE(s.IndexFromCodeUnitToCodePoint(3) == 3); - REQUIRE(s.IndexFromCodeUnitToCodePoint(3) == 3); -} - -TEST_CASE("String Format", "[string]") { - using cru::Format; - using cru::String; - - REQUIRE(Format(u"{} + {} = {}", 123, 321, 444) == String(u"123 + 321 = 444")); -} - -TEST_CASE("String Trim", "[string]") { - using cru::String; - REQUIRE(String(u" abc ").Trim() == u"abc"); -} - -TEST_CASE("String SplitToLines", "[string]") { - using cru::String; - - String s(u"abc\ndef\nghi"); - auto lines = s.SplitToLines(); - REQUIRE(lines.size() == 3); - REQUIRE(lines[0] == String(u"abc")); - REQUIRE(lines[1] == String(u"def")); - REQUIRE(lines[2] == String(u"ghi")); -} - -TEST_CASE("String SplitToLinesWithEmptyLine", "[string]") { - using cru::String; - - String s(u"abc\n \ndef\n\nghi\n"); - auto lines = s.SplitToLines(); - REQUIRE(lines.size() == 6); - REQUIRE(lines[0] == String(u"abc")); - REQUIRE(lines[1] == String(u" ")); - REQUIRE(lines[2] == String(u"def")); - REQUIRE(lines[3] == String(u"")); - REQUIRE(lines[4] == String(u"ghi")); - REQUIRE(lines[5] == String(u"")); -} - -TEST_CASE("String SplitToLinesRemoveSpaceLine", "[string]") { - using cru::String; - - String s(u"abc\n \ndef\n\nghi\n"); - auto lines = s.SplitToLines(true); - REQUIRE(lines.size() == 3); - REQUIRE(lines[0] == String(u"abc")); - REQUIRE(lines[1] == String(u"def")); - REQUIRE(lines[2] == String(u"ghi")); -} - -TEST_CASE("StringView ToUtf8", "[string]") { - using cru::StringView; - StringView utf16_text = u"aπ你🤣!"; - std::string_view utf8_text = "aπ你🤣!"; - - REQUIRE(utf16_text.ToUtf8() == utf8_text); -} - -TEST_CASE("String FromUtf8", "[string]") { - std::u16string_view utf16_text = u"aπ你🤣!"; - std::string_view utf8_text = "aπ你🤣!"; - - REQUIRE(cru::String::FromUtf8(utf8_text) == utf16_text); -} - -TEST_CASE("StringView ParseToDouble", "[string]") { - using cru::StringToNumberFlags; - using cru::StringView; - REQUIRE(StringView(u"3.14159").ParseToDouble() == 3.14159); - REQUIRE( - StringView(u" 3.14159") - .ParseToDouble(nullptr, StringToNumberFlags::kAllowLeadingSpaces) == - 3.14159); - REQUIRE(StringView(u" 3.14159 ") - .ParseToDouble(nullptr, - StringToNumberFlags::kAllowLeadingSpaces | - StringToNumberFlags::kAllowTrailingSpaces) == - 3.14159); -} - -TEST_CASE("String ParseToDoubleList", "[string]") { - using cru::StringView; - - auto list = StringView(u" 1.23 2.34 3.45 ").ParseToDoubleList(); - - REQUIRE(list.size() == 3); - REQUIRE(list[0] == 1.23); - REQUIRE(list[1] == 2.34); - REQUIRE(list[2] == 3.45); -} diff --git a/test/common/StringToNumberConverterTest.cpp b/test/common/StringToNumberConverterTest.cpp deleted file mode 100644 index 82062bdb..00000000 --- a/test/common/StringToNumberConverterTest.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "cru/base/Exception.h" -#include "cru/base/StringToNumberConverter.h" - -#include - -TEST_CASE("StringToIntegerConverterImpl Base0", "[string]") { - using namespace cru; - StringToIntegerConverter converter({}, 0); - Index processed_characters_count; - - REQUIRE(converter.Parse("12345678", &processed_characters_count) == - StringToIntegerResult(false, 12345678)); - REQUIRE(processed_characters_count == 8); - - REQUIRE(converter.Parse("0", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 1); - - REQUIRE(converter.Parse("012", &processed_characters_count) == - StringToIntegerResult(false, 012)); - REQUIRE(processed_characters_count == 3); - - REQUIRE(converter.Parse("0x12", &processed_characters_count) == - StringToIntegerResult(false, 0x12)); - REQUIRE(processed_characters_count == 4); - - REQUIRE(converter.Parse("0X12", &processed_characters_count) == - StringToIntegerResult(false, 0x12)); - REQUIRE(processed_characters_count == 4); - - REQUIRE(converter.Parse("0b101", &processed_characters_count) == - StringToIntegerResult(false, 0b101)); - REQUIRE(processed_characters_count == 5); - - REQUIRE(converter.Parse("0B101", &processed_characters_count) == - StringToIntegerResult(false, 0b101)); - REQUIRE(processed_characters_count == 5); - - REQUIRE(converter.Parse("-123", &processed_characters_count) == - StringToIntegerResult(true, 123)); - REQUIRE(processed_characters_count == 4); - - REQUIRE(converter.Parse("-0x10", &processed_characters_count) == - StringToIntegerResult(true, 0x10)); - REQUIRE(processed_characters_count == 5); -} - -TEST_CASE("StringToIntegerConverterImpl Base0ForError", "[string]") { - using namespace cru; - StringToIntegerConverter converter({}, 0); - Index processed_characters_count; - - REQUIRE(converter.Parse("a", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 0); - - REQUIRE(converter.Parse("0a", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 0); - - REQUIRE(converter.Parse("0x", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 0); - - REQUIRE(converter.Parse("0xx", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 0); - - REQUIRE(converter.Parse(" 0", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 0); - - REQUIRE(converter.Parse("0 ", &processed_characters_count) == - StringToIntegerResult(false, 0)); - REQUIRE(processed_characters_count == 0); -} - -TEST_CASE("StringToIntegerConverterImpl ThrowOnErrorFlag", "[string]") { - using namespace cru; - StringToIntegerConverter converter(StringToNumberFlags::kThrowOnError, 0); - Index processed_characters_count; - REQUIRE_THROWS_AS(converter.Parse("?", &processed_characters_count), - Exception); -} - -TEST_CASE("StringToIntegerConverterImpl AllowLeadingZeroFlag", "[string]") { - using namespace cru; - StringToIntegerConverter converter( - StringToNumberFlags::kAllowLeadingSpaces, 0); - Index processed_characters_count; - REQUIRE(converter.Parse(" 123", &processed_characters_count) == - StringToIntegerResult(false, 123)); - REQUIRE(processed_characters_count == 6); -} - -TEST_CASE("StringToIntegerConverterImpl AllowTrailingZeroFlag", "[string]") { - using namespace cru; - StringToIntegerConverter converter( - StringToNumberFlags::kAllowTrailingSpaces, 0); - Index processed_characters_count; - REQUIRE(converter.Parse("123 ", &processed_characters_count) == - StringToIntegerResult(false, 123)); - REQUIRE(processed_characters_count == 6); -} - -TEST_CASE("StringToIntegerConverterImpl AllowTrailingJunk", "[string]") { - using namespace cru; - StringToIntegerConverter converter( - StringToNumberFlags::kAllowTrailingJunk, 0); - Index processed_characters_count; - REQUIRE(converter.Parse("123 12", &processed_characters_count) == - StringToIntegerResult(false, 123)); - REQUIRE(processed_characters_count == 3); -} - -TEST_CASE("StringToIntegerConverterImpl AllowLeadingZeroForInteger", - "[string]") { - using namespace cru; - StringToIntegerConverter converter( - StringToNumberFlags::kAllowLeadingZeroForInteger, 0); - Index processed_characters_count; - REQUIRE(converter.Parse("0x0012", &processed_characters_count) == - StringToIntegerResult(false, 0x12)); - REQUIRE(processed_characters_count == 6); - - REQUIRE(converter.Parse("000011", &processed_characters_count) == - StringToIntegerResult(false, 000011)); - REQUIRE(processed_characters_count == 6); - - REQUIRE(converter.Parse("0b0011", &processed_characters_count) == - StringToIntegerResult(false, 0b0011)); - REQUIRE(processed_characters_count == 6); -} - -TEST_CASE("StringToIntegerConverterImpl CompositeFlags", "[string]") { - using namespace cru; - StringToIntegerConverter converter( - StringToNumberFlags::kAllowLeadingSpaces | - StringToNumberFlags::kAllowTrailingJunk | - StringToNumberFlags::kAllowLeadingZeroForInteger, - 0); - Index processed_characters_count; - - REQUIRE(converter.Parse(" 0x00123!!!", &processed_characters_count) == - StringToIntegerResult(false, 0x00123)); - REQUIRE(processed_characters_count == 10); -} - -TEST_CASE("StringToIntegerConverterImpl OtherBase", "[string]") { - using namespace cru; - StringToIntegerConverter converter({}, 7); - Index processed_characters_count; - - REQUIRE(converter.Parse("12", &processed_characters_count) == - StringToIntegerResult(false, 9)); - REQUIRE(processed_characters_count == 2); - - REQUIRE(converter.Parse("-12", &processed_characters_count) == - StringToIntegerResult(true, 9)); - REQUIRE(processed_characters_count == 3); - - converter.base = 11; - REQUIRE(converter.Parse("1a", &processed_characters_count) == - StringToIntegerResult(false, 21)); - REQUIRE(processed_characters_count == 2); -} diff --git a/test/common/StringUtilTest.cpp b/test/common/StringUtilTest.cpp deleted file mode 100644 index 1da6e963..00000000 --- a/test/common/StringUtilTest.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "cru/base/String.h" -#include "cru/base/StringUtil.h" - -#include - -using cru::Index; -using cru::k_invalid_code_point; - -TEST_CASE("StringUtil Utf8NextCodePoint", "[string]") { - using cru::Utf8NextCodePoint; - std::string_view text = "aπ你🤣!"; - Index current = 0; - REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x0061); - REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x03C0); - REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x4F60); - REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x1F923); - REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x0021); - REQUIRE(Utf8NextCodePoint(text.data(), text.size(), current, ¤t) == - k_invalid_code_point); - REQUIRE(current == static_cast(text.size())); -} - -TEST_CASE("StringUtil Utf16NextCodePoint", "[string]") { - using cru::Utf16NextCodePoint; - std::u16string_view text = u"aπ你🤣!"; - Index current = 0; - REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x0061); - REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x03C0); - REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x4F60); - REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x1F923); - REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == - 0x0021); - REQUIRE(Utf16NextCodePoint(text.data(), text.size(), current, ¤t) == - k_invalid_code_point); - REQUIRE(current == static_cast(text.size())); -} - -TEST_CASE("StringUtil Utf16PreviousCodePoint", "[string]") { - using cru::Utf16PreviousCodePoint; - std::u16string_view text = u"aπ你🤣!"; - Index current = text.size(); - REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == - 0x0021); - REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == - 0x1F923); - REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == - 0x4F60); - REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == - 0x03C0); - REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == - 0x0061); - REQUIRE(Utf16PreviousCodePoint(text.data(), text.size(), current, ¤t) == - k_invalid_code_point); - REQUIRE(current == 0); -} - -TEST_CASE("StringUtil Utf8CodePointIterator", "[string]") { - using cru::Utf8CodePointIterator; - std::string_view text = "aπ你🤣!"; - std::vector code_points; - - for (auto cp : Utf8CodePointIterator(text.data(), text.size())) { - code_points.push_back(cp); - } - - std::vector expected_code_points{0x0061, 0x03C0, 0x4F60, - 0x1F923, 0x0021}; - - REQUIRE(code_points == expected_code_points); -} - -TEST_CASE("StringUtil Utf16CodePointIterator", "[string]") { - using cru::Utf16CodePointIterator; - std::u16string_view text = u"aπ你🤣!"; - std::vector code_points; - - for (auto cp : Utf16CodePointIterator(text.data(), text.size())) { - code_points.push_back(cp); - } - - std::vector expected_code_points{0x0061, 0x03C0, 0x4F60, - 0x1F923, 0x0021}; - - REQUIRE(code_points == expected_code_points); -} - -// TEST(WinString, IndexUtf8ToUtf16) { -// using cru::platform::win::IndexUtf8ToUtf16; -// std::string_view utf8_string = "aπ你🤣!"; -// std::wstring_view utf16_string = L"aπ你🤣!"; -// REQUIRE(IndexUtf8ToUtf16(utf8_string, 0, utf16_string), 0); -// REQUIRE(IndexUtf8ToUtf16(utf8_string, 1, utf16_string), 1); -// REQUIRE(IndexUtf8ToUtf16(utf8_string, 3, utf16_string), 2); -// REQUIRE(IndexUtf8ToUtf16(utf8_string, 6, utf16_string), 3); -// REQUIRE(IndexUtf8ToUtf16(utf8_string, 10, utf16_string), 5); -// REQUIRE(IndexUtf8ToUtf16(utf8_string, 11, utf16_string), 6); -// } - -// TEST(WinString, IndexUtf16ToUtf8) { -// using cru::platform::win::IndexUtf16ToUtf8; -// std::string_view utf8_string = "aπ你🤣!"; -// std::wstring_view utf16_string = L"aπ你🤣!"; -// REQUIRE(IndexUtf16ToUtf8(utf16_string, 0, utf8_string), 0); -// REQUIRE(IndexUtf16ToUtf8(utf16_string, 1, utf8_string), 1); -// REQUIRE(IndexUtf16ToUtf8(utf16_string, 2, utf8_string), 3); -// REQUIRE(IndexUtf16ToUtf8(utf16_string, 3, utf8_string), 6); -// REQUIRE(IndexUtf16ToUtf8(utf16_string, 5, utf8_string), 10); -// REQUIRE(IndexUtf16ToUtf8(utf16_string, 6, utf8_string), 11); -// } diff --git a/test/common/SubProcessHelper/CruEcho.cpp b/test/common/SubProcessHelper/CruEcho.cpp deleted file mode 100644 index 5f23c027..00000000 --- a/test/common/SubProcessHelper/CruEcho.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include - -int main(int argc, char* argv[]) { - for (int i = 1; i < argc - 1; ++i) { - std::cout << argv[i] << " "; - } - std::cout << argv[argc - 1]; - return 0; -} diff --git a/test/common/SubProcessHelper/CruTee.cpp b/test/common/SubProcessHelper/CruTee.cpp deleted file mode 100644 index 4470d2a8..00000000 --- a/test/common/SubProcessHelper/CruTee.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -int main() { - std::string s; - while (std::cin >> s) { - std::cout << s; - } - return 0; -} diff --git a/test/common/SubProcessTest.cpp b/test/common/SubProcessTest.cpp deleted file mode 100644 index d353dec0..00000000 --- a/test/common/SubProcessTest.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "cru/base/String.h" -#include "cru/base/SubProcess.h" - -#include - -using cru::String; -using cru::SubProcess; - -TEST_CASE("SubProcess", "[subprocess]") { - SECTION("echo should work.") { - SubProcess process = SubProcess::Create( - String::FromUtf8(CRU_TEST_HELPER_ECHO_LOCATION), {u"abc"}); - process.Wait(); - REQUIRE(process.GetExitResult().IsSuccess()); - auto output = process.GetStdoutStream()->ReadToEndAsUtf8String(); - REQUIRE(output == u"abc"); - } - - SECTION("tee should work.") { - constexpr auto str = "abc"; - SubProcess process = - SubProcess::Create(String::FromUtf8(CRU_TEST_HELPER_TEE_LOCATION)); - process.GetStdinStream()->Write(str, 3); - process.GetStdinStream()->Close(); - process.Wait(); - REQUIRE(process.GetExitResult().IsSuccess()); - auto output = process.GetStdoutStream()->ReadToEndAsUtf8String(); - REQUIRE(output == u"abc"); - } -} diff --git a/test/common/platform/unix/UnixFileStreamTest.cpp b/test/common/platform/unix/UnixFileStreamTest.cpp deleted file mode 100644 index 417fccc2..00000000 --- a/test/common/platform/unix/UnixFileStreamTest.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "cru/base/platform/unix/UnixFileStream.h" - -#include - -#include -#include - -TEST_CASE("UnixFileStream Work", "[stream]") { - using namespace cru; - using namespace cru::io; - using namespace cru::platform::unix; - - auto temp_file_path = - (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") - .generic_string(); - mkstemp(temp_file_path.data()); - - UnixFileStream file(temp_file_path.c_str(), O_WRONLY | O_CREAT); - file.Write("abc", 3); - file.Close(); - - UnixFileStream file2(temp_file_path.c_str(), O_RDONLY); - auto buffer = std::make_unique(3); - file2.Read(buffer.get(), 3); - REQUIRE(std::string_view(reinterpret_cast(buffer.get()), 3) == - "abc"); - file2.Close(); - - std::filesystem::remove(temp_file_path); -} diff --git a/test/common/platform/unix/UnixFileTest.cpp b/test/common/platform/unix/UnixFileTest.cpp deleted file mode 100644 index d5bba0db..00000000 --- a/test/common/platform/unix/UnixFileTest.cpp +++ /dev/null @@ -1,38 +0,0 @@ - -#include "cru/base/platform/unix/UnixFileStream.h" - -#include - -#include -#include - -TEST_CASE("UnixFile Work", "[unix]") { - using namespace cru; - using namespace cru::platform::unix; - - auto calledTimes = 0; - auto mockClose = [&calledTimes](int _) { - calledTimes += 1; - return 0; - }; - - auto temp_file_path = - (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") - .generic_string(); - mkstemp(temp_file_path.data()); - - auto fdNumber = ::open(temp_file_path.c_str(), O_WRONLY | O_CREAT); - - { - UnixFileDescriptor fd(fdNumber, true, std::move(mockClose)); - REQUIRE(calledTimes == 0); - UnixFileDescriptor fd2(std::move(fd)); - REQUIRE(calledTimes == 0); - UnixFileDescriptor fd3; - fd3 = std::move(fd2); - REQUIRE(calledTimes == 0); - } - REQUIRE(calledTimes == 1); - - std::filesystem::remove(temp_file_path); -} diff --git a/test/common/platform/win/StreamConvertTest.cpp b/test/common/platform/win/StreamConvertTest.cpp deleted file mode 100644 index 90ebb568..00000000 --- a/test/common/platform/win/StreamConvertTest.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "cru/base/io/OpenFileFlag.h" -#include "cru/base/platform/win/Exception.h" -#include "cru/base/platform/win/StreamConvert.h" -#include "cru/base/platform/win/Win32FileStream.h" - -#include - -#include -#include - -TEST_CASE("StreamConvert FileStreamWork", "[stream]") { - using namespace cru; - using namespace cru::io; - using namespace cru::platform::win; - - auto temp_file_path = - (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") - .native(); - _wmktemp(temp_file_path.data()); - - String path = temp_file_path; - - Win32FileStream file(path, OpenFileFlags::Write | OpenFileFlags::Create); - file.Write("abc", 3); - file.Close(); - - Win32FileStream file2(path, OpenFileFlags::Read); - IStream* com_stream = ConvertStreamToComStream(&file2); - LARGE_INTEGER position; - position.QuadPart = 0; - ThrowIfFailed(com_stream->Seek(position, SEEK_SET, nullptr)); - auto buffer = std::make_unique(3); - ThrowIfFailed(com_stream->Read(buffer.get(), 3, nullptr)); - REQUIRE(std::string_view(buffer.get(), 3) == "abc"); - com_stream->Release(); - file2.Close(); - - std::filesystem::remove(temp_file_path); -} diff --git a/test/common/platform/win/Win32FileStreamTest.cpp b/test/common/platform/win/Win32FileStreamTest.cpp deleted file mode 100644 index dc2f49d4..00000000 --- a/test/common/platform/win/Win32FileStreamTest.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "cru/base/io/OpenFileFlag.h" -#include "cru/base/platform/win/Win32FileStream.h" - -#include - -#include -#include - -TEST_CASE("Win32FileStream Work", "[stream]") { - using namespace cru; - using namespace cru::io; - using namespace cru::platform::win; - - auto temp_file_path = - (std::filesystem::temp_directory_path() / "cru_test_temp.XXXXXX") - .native(); - _wmktemp(temp_file_path.data()); - - String path = temp_file_path; - - Win32FileStream file(path, OpenFileFlags::Write | OpenFileFlags::Create); - auto write_count = file.Write("abc", 3); - REQUIRE(write_count == 3); - file.Close(); - - REQUIRE(std::filesystem::file_size(path.ToUtf8()) == 3); - - Win32FileStream file2(path, OpenFileFlags::Read); - auto buffer = std::make_unique(3); - auto read_count = file2.Read(buffer.get(), 3); - REQUIRE(read_count == 3); - REQUIRE(std::string_view(reinterpret_cast(buffer.get()), 3) == - "abc"); - file2.Close(); - - std::filesystem::remove(temp_file_path); -} -- cgit v1.2.3