feat replace gtest by doctest
This commit is contained in:
parent
c7fe469c1b
commit
7c1582769e
@ -17,6 +17,7 @@ set(BUILD_STATIC ON)
|
|||||||
set(BUILD_RTTR_DYNAMIC OFF)
|
set(BUILD_RTTR_DYNAMIC OFF)
|
||||||
set(BUILD_UNIT_TESTS OFF)
|
set(BUILD_UNIT_TESTS OFF)
|
||||||
set(BUILD_EXAMPLES OFF)
|
set(BUILD_EXAMPLES OFF)
|
||||||
|
add_library(test_main STATIC src/sled/testing/test_main.cc)
|
||||||
add_library(sled STATIC "")
|
add_library(sled STATIC "")
|
||||||
|
|
||||||
add_subdirectory(3party/gperftools EXCLUDE_FROM_ALL)
|
add_subdirectory(3party/gperftools EXCLUDE_FROM_ALL)
|
||||||
@ -42,6 +43,7 @@ endif()
|
|||||||
# add_subdirectory(3party/eigen EXCLUDE_FROM_ALL)
|
# add_subdirectory(3party/eigen EXCLUDE_FROM_ALL)
|
||||||
target_include_directories(sled PUBLIC src/ 3party/eigen 3party/inja
|
target_include_directories(sled PUBLIC src/ 3party/eigen 3party/inja
|
||||||
3party/rxcpp)
|
3party/rxcpp)
|
||||||
|
target_include_directories(test_main PUBLIC src/)
|
||||||
target_sources(
|
target_sources(
|
||||||
sled
|
sled
|
||||||
PRIVATE src/sled/async/async.cc
|
PRIVATE src/sled/async/async.cc
|
||||||
@ -68,6 +70,7 @@ target_sources(
|
|||||||
src/sled/system/thread_pool.cc
|
src/sled/system/thread_pool.cc
|
||||||
src/sled/task_queue/pending_task_safety_flag.cc
|
src/sled/task_queue/pending_task_safety_flag.cc
|
||||||
src/sled/task_queue/task_queue_base.cc
|
src/sled/task_queue/task_queue_base.cc
|
||||||
|
src/sled/testing/test.cc
|
||||||
src/sled/timer/task_queue_timeout.cc
|
src/sled/timer/task_queue_timeout.cc
|
||||||
src/sled/timer/timer.cc
|
src/sled/timer/timer.cc
|
||||||
src/sled/units/time_delta.cc
|
src/sled/units/time_delta.cc
|
||||||
@ -122,9 +125,6 @@ function(sled_add_test)
|
|||||||
cmake_parse_arguments("${prefix}" "${options}" "${one_value_keywords}"
|
cmake_parse_arguments("${prefix}" "${options}" "${one_value_keywords}"
|
||||||
"${multi_value_keywords}" ${ARGN})
|
"${multi_value_keywords}" ${ARGN})
|
||||||
|
|
||||||
message(WARNING "SLED_TEST_NAME: ${SLED_TEST_NAME}")
|
|
||||||
message(WARNING "SLED_TEST_SRCS: ${SLED_TEST_SRCS}")
|
|
||||||
message(WARNING "SLED_TEST_LIBS: ${SLED_TEST_LIBS}")
|
|
||||||
add_executable(${SLED_TEST_NAME} ${SLED_TEST_SRCS})
|
add_executable(${SLED_TEST_NAME} ${SLED_TEST_SRCS})
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
@ -134,28 +134,30 @@ function(sled_add_test)
|
|||||||
|
|
||||||
target_link_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
|
target_link_options(${SLED_TEST_NAME} PRIVATE ${EXTRA_FLAGS})
|
||||||
endif()
|
endif()
|
||||||
|
if(MSVC)
|
||||||
|
target_compile_options(${SLED_TEST_NAME} PRIVATE /FI"sled/testing/test.h")
|
||||||
|
else()
|
||||||
|
target_compile_options(${SLED_TEST_NAME} PRIVATE -include
|
||||||
|
sled/testing/test.h)
|
||||||
|
endif()
|
||||||
target_include_directories(${SLED_TEST_NAME} PRIVATE ${SLED_TEST_INC_DIRS})
|
target_include_directories(${SLED_TEST_NAME} PRIVATE ${SLED_TEST_INC_DIRS})
|
||||||
target_link_libraries(${SLED_TEST_NAME} PRIVATE ${SLED_TEST_LIBS}
|
target_link_libraries(${SLED_TEST_NAME} PRIVATE ${SLED_TEST_LIBS})
|
||||||
GTest::gtest)
|
|
||||||
add_test(NAME ${SLED_TEST_NAME} COMMAND ${SLED_TEST_NAME})
|
add_test(NAME ${SLED_TEST_NAME} COMMAND ${SLED_TEST_NAME})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
if(SLED_BUILD_TESTS)
|
if(SLED_BUILD_TESTS)
|
||||||
include(FetchContent)
|
# include(FetchContent) FetchContent_Declare( googletest URL
|
||||||
FetchContent_Declare(
|
# https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||||
googletest
|
# ) FetchContent_MakeAvailable(googletest)
|
||||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(googletest)
|
|
||||||
|
|
||||||
sled_add_test(
|
sled_add_test(
|
||||||
NAME
|
NAME
|
||||||
sled_all_tests
|
sled_all_tests
|
||||||
SRCS
|
SRCS
|
||||||
|
src/sled/debugging/demangle_test.cc
|
||||||
src/sled/async/async_test.cc
|
src/sled/async/async_test.cc
|
||||||
src/sled/any_test.cc
|
src/sled/any_test.cc
|
||||||
src/sled/filesystem/path_test.cc
|
src/sled/filesystem/path_test.cc
|
||||||
src/sled/futures/detail/just_test.cc
|
|
||||||
src/sled/log/fmt_test.cc
|
src/sled/log/fmt_test.cc
|
||||||
src/sled/synchronization/sequence_checker_test.cc
|
src/sled/synchronization/sequence_checker_test.cc
|
||||||
src/sled/cleanup_test.cc
|
src/sled/cleanup_test.cc
|
||||||
@ -169,7 +171,7 @@ if(SLED_BUILD_TESTS)
|
|||||||
src/sled/uri_test.cc
|
src/sled/uri_test.cc
|
||||||
LIBS
|
LIBS
|
||||||
sled
|
sled
|
||||||
GTest::gtest_main)
|
test_main)
|
||||||
|
|
||||||
sled_add_test(NAME sled_symbolize_test SRCS
|
sled_add_test(NAME sled_symbolize_test SRCS
|
||||||
src/sled/debugging/symbolize_test.cc LIBS sled)
|
src/sled/debugging/symbolize_test.cc LIBS sled)
|
||||||
|
@ -1,48 +1,50 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/any.h>
|
#include <sled/any.h>
|
||||||
#include <sled/log/log.h>
|
#include <sled/log/log.h>
|
||||||
|
|
||||||
TEST(Any, Assign)
|
TEST_SUITE("Any")
|
||||||
{
|
{
|
||||||
sled::Any any1;
|
TEST_CASE("Assign")
|
||||||
sled::Any any2(any1);
|
{
|
||||||
sled::Any any3(1);
|
sled::Any any1;
|
||||||
sled::Any any4(any3);
|
sled::Any any2(any1);
|
||||||
sled::Any any5 = 1;
|
sled::Any any3(1);
|
||||||
EXPECT_FALSE(any1.HasValue());
|
sled::Any any4(any3);
|
||||||
EXPECT_FALSE(any2.HasValue());
|
sled::Any any5 = 1;
|
||||||
EXPECT_TRUE(any3.HasValue());
|
CHECK_FALSE(any1.HasValue());
|
||||||
EXPECT_TRUE(any4.HasValue());
|
CHECK_FALSE(any2.HasValue());
|
||||||
EXPECT_TRUE(any5.HasValue());
|
CHECK(any3.HasValue());
|
||||||
EXPECT_EQ(any3.Cast<int>(), 1);
|
CHECK(any4.HasValue());
|
||||||
EXPECT_EQ(any4.Cast<int>(), 1);
|
CHECK(any5.HasValue());
|
||||||
EXPECT_EQ(any5.Cast<int>(), 1);
|
CHECK_EQ(any3.Cast<int>(), 1);
|
||||||
EXPECT_EQ(any3.CastOr<std::string>("def"), "def");
|
CHECK_EQ(any4.Cast<int>(), 1);
|
||||||
EXPECT_EQ(any4.CastOr<std::string>("def"), "def");
|
CHECK_EQ(any5.Cast<int>(), 1);
|
||||||
EXPECT_EQ(any5.CastOr<std::string>("def"), "def");
|
CHECK_EQ(any3.CastOr<std::string>("def"), "def");
|
||||||
EXPECT_EQ(any3.CastOr<int>(11), 1);
|
CHECK_EQ(any4.CastOr<std::string>("def"), "def");
|
||||||
}
|
CHECK_EQ(any5.CastOr<std::string>("def"), "def");
|
||||||
|
CHECK_EQ(any3.CastOr<int>(11), 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Any, std_swap)
|
TEST_CASE("std_swap")
|
||||||
{
|
{
|
||||||
sled::Any a;
|
sled::Any a;
|
||||||
sled::Any b = 2;
|
sled::Any b = 2;
|
||||||
EXPECT_FALSE(a.HasValue());
|
CHECK_FALSE(a.HasValue());
|
||||||
EXPECT_TRUE(b.HasValue());
|
CHECK(b.HasValue());
|
||||||
std::swap(a, b);
|
std::swap(a, b);
|
||||||
EXPECT_TRUE(a.HasValue());
|
CHECK(a.HasValue());
|
||||||
EXPECT_FALSE(b.HasValue());
|
CHECK_FALSE(b.HasValue());
|
||||||
EXPECT_EQ(a.Cast<int>(), 2);
|
CHECK_EQ(a.Cast<int>(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Any, custom_swap)
|
TEST_CASE("custom_swap")
|
||||||
{
|
{
|
||||||
sled::Any a;
|
sled::Any a;
|
||||||
sled::Any b = 2;
|
sled::Any b = 2;
|
||||||
EXPECT_FALSE(a.HasValue());
|
CHECK_FALSE(a.HasValue());
|
||||||
EXPECT_TRUE(b.HasValue());
|
CHECK(b.HasValue());
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
EXPECT_TRUE(a.HasValue());
|
CHECK(a.HasValue());
|
||||||
EXPECT_FALSE(b.HasValue());
|
CHECK_FALSE(b.HasValue());
|
||||||
EXPECT_EQ(a.Cast<int>(), 2);
|
CHECK_EQ(a.Cast<int>(), 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/async/async.h>
|
#include <sled/async/async.h>
|
||||||
#include <sled/log/log.h>
|
#include <sled/log/log.h>
|
||||||
#include <sled/system/fiber/wait_group.h>
|
#include <sled/system/fiber/wait_group.h>
|
||||||
#include <sled/system/thread.h>
|
#include <sled/system/thread.h>
|
||||||
|
|
||||||
TEST(Async, task)
|
TEST_SUITE("Async")
|
||||||
{
|
{
|
||||||
auto task1 = async::spawn([] { return 42; }).then([](int value) { return value * 3; }).then([](int value) {
|
TEST_CASE("task")
|
||||||
EXPECT_EQ(value, 126);
|
{
|
||||||
return value;
|
auto task1 = async::spawn([] { return 42; }).then([](int value) { return value * 3; }).then([](int value) {
|
||||||
});
|
CHECK_EQ(value, 126);
|
||||||
task1.wait();
|
return value;
|
||||||
EXPECT_EQ(126, task1.get());
|
});
|
||||||
}
|
task1.wait();
|
||||||
|
CHECK_EQ(126, task1.get());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Async, parallel_for)
|
TEST_CASE("parallel_for")
|
||||||
{
|
{
|
||||||
const int count = 1000;
|
const int count = 1000;
|
||||||
std::vector<int> values(count);
|
std::vector<int> values(count);
|
||||||
async::parallel_for(async::irange(0, count), [&values](int x) {
|
async::parallel_for(async::irange(0, count), [&values](int x) {
|
||||||
EXPECT_FALSE(values[x]);
|
CHECK_FALSE(values[x]);
|
||||||
values[x] = true;
|
values[x] = true;
|
||||||
});
|
});
|
||||||
for (int i = 0; i < count; i++) { EXPECT_TRUE(values[i]) << i; }
|
for (int i = 0; i < count; i++) { CHECK(values[i]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Async, parallel_reduce)
|
TEST_CASE("parallel_reduce")
|
||||||
{
|
{
|
||||||
auto r = async::parallel_reduce(async::irange(1, 5), 0, [](int x, int y) { return x + y; });
|
auto r = async::parallel_reduce(async::irange(1, 5), 0, [](int x, int y) { return x + y; });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/cleanup.h>
|
#include <sled/cleanup.h>
|
||||||
#include <sled/random.h>
|
#include <sled/random.h>
|
||||||
|
|
||||||
TEST(Cleanup, TestCleanup)
|
TEST_SUITE("Cleanup")
|
||||||
{
|
{
|
||||||
sled::Random rand(1314);
|
TEST_CASE("assign")
|
||||||
for (int i = 0; i < 100; ++i) {
|
{
|
||||||
int a = rand.Rand(10000);
|
sled::Random rand(1314);
|
||||||
int b = rand.Rand(10000, 20000);
|
for (int i = 0; i < 100; ++i) {
|
||||||
{
|
int a = rand.Rand(10000);
|
||||||
sled::Cleanup<> c([=, &a]() { a = b; });
|
int b = rand.Rand(10000, 20000);
|
||||||
|
{
|
||||||
|
sled::Cleanup<> c([=, &a]() { a = b; });
|
||||||
|
}
|
||||||
|
CHECK_EQ(a, b);
|
||||||
}
|
}
|
||||||
ASSERT_EQ(a, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
#include <sled/debugging/demangle.h>
|
||||||
|
#include <sled/testing/test.h>
|
||||||
|
|
||||||
|
TEST_SUITE("Demangle")
|
||||||
|
{
|
||||||
|
TEST_CASE("FunctionTemplate")
|
||||||
|
{
|
||||||
|
char tmp[100];
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// int foo(T);
|
||||||
|
//
|
||||||
|
// foo<Wrapper<int>>({ .value = 5 });
|
||||||
|
CHECK(sled::Demangle("_Z3fooIiEiT_", tmp, sizeof(tmp)));
|
||||||
|
CHECK_EQ(doctest::toString(tmp), "foo<>()");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("FunctionTemplateWithNesting")
|
||||||
|
{
|
||||||
|
char tmp[100];
|
||||||
|
|
||||||
|
// template <std::integral T>
|
||||||
|
// int foo(T);
|
||||||
|
//
|
||||||
|
// foo<int>(5);
|
||||||
|
CHECK(sled::Demangle("_Z3fooI7WrapperIiEEiT_", tmp, sizeof(tmp)));
|
||||||
|
CHECK_EQ(doctest::toString(tmp), "foo<>()");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("FunctionTemplateWithNonTypeParamConstraint")
|
||||||
|
{
|
||||||
|
char tmp[100];
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// int foo() requires std::integral<T>;
|
||||||
|
//
|
||||||
|
// foo<int>();
|
||||||
|
CHECK(sled::Demangle("_Z3fooITkSt8integraliEiT_", tmp, sizeof(tmp)));
|
||||||
|
CHECK_EQ(doctest::toString(tmp), "foo<>()");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("AbiTags")
|
||||||
|
{
|
||||||
|
char tmp[100];
|
||||||
|
|
||||||
|
// Mangled name generated via:
|
||||||
|
// struct [[gnu::abi_tag("abc")]] A{};
|
||||||
|
// A a;
|
||||||
|
CHECK(sled::Demangle("_Z1aB3abc", tmp, sizeof(tmp)));
|
||||||
|
CHECK_EQ(doctest::toString(tmp), "a[abi:abc]");
|
||||||
|
|
||||||
|
CHECK(sled::Demangle("_ZN1BC2B3xyzEv", tmp, sizeof(tmp)));
|
||||||
|
CHECK_EQ(doctest::toString(tmp), "B::B[abi:xyz]()");
|
||||||
|
|
||||||
|
CHECK(sled::Demangle("_Z1CB3barB3foov", tmp, sizeof(tmp)));
|
||||||
|
CHECK_EQ(doctest::toString(tmp), "C[abi:bar][abi:foo]()");
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,20 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/debugging/symbolize.h>
|
#include <sled/debugging/symbolize.h>
|
||||||
#include <sled/make_unique.h>
|
#include <sled/make_unique.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
TestFunc1()
|
TrivialFunc()
|
||||||
|
{}
|
||||||
|
|
||||||
|
static void
|
||||||
|
StaticFunc()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
public:
|
public:
|
||||||
Class() {}
|
Class() {}
|
||||||
|
|
||||||
|
static void StaticFunc() {}
|
||||||
|
|
||||||
void MemberFunc1() {}
|
void MemberFunc1() {}
|
||||||
|
|
||||||
int MemberFunc2() { return 0; }
|
int MemberFunc2() { return 0; }
|
||||||
@ -58,20 +63,29 @@ void_cast(TRet (TClass::*mem_func)(Args...))
|
|||||||
return void_casted;
|
return void_casted;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Symbolize, base)
|
TEST_CASE("Trivial Function")
|
||||||
{
|
{
|
||||||
char buf[1024];
|
CHECK_EQ(doctest::String("TrivialFunc()"), TrySymbolize(void_cast(TrivialFunc)));
|
||||||
EXPECT_STREQ("TestFunc1()", TrySymbolize(void_cast(TestFunc1)));
|
CHECK_EQ(doctest::String("TrySymbolizeWithLimit()"), TrySymbolize(void_cast(&TrySymbolizeWithLimit)));
|
||||||
EXPECT_STREQ("Class::MemberFunc1()", TrySymbolize(void_cast(&Class::MemberFunc1)));
|
}
|
||||||
EXPECT_STREQ("Class::MemberFunc2()", TrySymbolize(void_cast(&Class::MemberFunc2)));
|
|
||||||
EXPECT_STREQ("Class::MemberFunc3()", TrySymbolize(void_cast(&Class::MemberFunc3)));
|
TEST_CASE("Static Function") { CHECK_EQ(doctest::String("StaticFunc()"), TrySymbolize(void_cast(StaticFunc))); }
|
||||||
EXPECT_STREQ("TrySymbolizeWithLimit()", TrySymbolize(void_cast(&TrySymbolizeWithLimit)));
|
|
||||||
|
TEST_CASE("Member Function")
|
||||||
|
{
|
||||||
|
CHECK_EQ(doctest::String("Class::MemberFunc1()"), TrySymbolize(void_cast(&Class::MemberFunc1)));
|
||||||
|
CHECK_EQ(doctest::String("Class::MemberFunc2()"), TrySymbolize(void_cast(&Class::MemberFunc2)));
|
||||||
|
CHECK_EQ(doctest::String("Class::MemberFunc3()"), TrySymbolize(void_cast(&Class::MemberFunc3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Static Member Function")
|
||||||
|
{
|
||||||
|
CHECK_EQ(doctest::String("Class::StaticFunc()"), TrySymbolize(void_cast(&Class::StaticFunc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
sled::InitializeSymbolizer(argv[0]);
|
sled::InitializeSymbolizer(argv[0]);
|
||||||
testing::InitGoogleTest(&argc, argv);
|
return doctest::Context(argc, argv).run();
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/exec/exec.h>
|
|
||||||
|
|
||||||
struct cout_receiver {
|
|
||||||
template<typename T>
|
|
||||||
void SetValue(T &&val)
|
|
||||||
{
|
|
||||||
// 这个receiver什么都不干,只对收集到的结果输出
|
|
||||||
std::cout << "Result: " << val << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetError(std::exception_ptr err) { std::terminate(); }
|
|
||||||
|
|
||||||
void SetStopped() { std::terminate(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(Just, basic)
|
|
||||||
{
|
|
||||||
sled::Just(42).Connect(cout_receiver{}).Start();
|
|
||||||
sled::Just(11).Connect(cout_receiver{}).Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Then, basic)
|
|
||||||
{
|
|
||||||
auto s1 = sled::Just(42);
|
|
||||||
auto s2 = sled::Then(s1, [](int x) { return x + 1; });
|
|
||||||
auto s3 = sled::Then(s2, [](int x) { return x + 1; });
|
|
||||||
auto s4 = sled::Then(s3, [](int x) { return x + 1; });
|
|
||||||
s4.Connect(cout_receiver{}).Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SyncWait, basic)
|
|
||||||
{
|
|
||||||
auto s1 = sled::Just(42);
|
|
||||||
auto s2 = sled::Then(s1, [](int x) { return x + 1; });
|
|
||||||
auto s3 = sled::Then(s2, [](int x) { return x + 1; });
|
|
||||||
auto s4 = sled::Then(s3, [](int x) { return x + 1; });
|
|
||||||
auto s5 = sled::SyncWait(s4).value();
|
|
||||||
std::cout << "Result: " << s5 << '\n';
|
|
||||||
}
|
|
@ -1,23 +1,22 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/filesystem/path.h>
|
#include <sled/filesystem/path.h>
|
||||||
|
|
||||||
TEST(Path, TestCurrent)
|
TEST_SUITE("Path")
|
||||||
{
|
{
|
||||||
sled::Path path = sled::Path::Current();
|
TEST_CASE("Current Directory")
|
||||||
std::string str = path.ToString();
|
{
|
||||||
EXPECT_FALSE(str.empty());
|
sled::Path path = sled::Path::Current();
|
||||||
}
|
CHECK_FALSE(path.ToString().empty());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Path, TestHome)
|
TEST_CASE("Home")
|
||||||
{
|
{
|
||||||
sled::Path path = sled::Path::Home();
|
sled::Path path = sled::Path::Home();
|
||||||
std::string str = path.ToString();
|
CHECK_FALSE(path.ToString().empty());
|
||||||
EXPECT_FALSE(str.empty());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Path, TestTempDir)
|
TEST_CASE("Temparory Directory")
|
||||||
{
|
{
|
||||||
sled::Path path = sled::Path::TempDir();
|
sled::Path path = sled::Path::TempDir();
|
||||||
std::string str = path.ToString();
|
CHECK_FALSE(path.ToString().empty());
|
||||||
EXPECT_FALSE(str.empty());
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/futures/detail/just.h>
|
#include <sled/futures/detail/just.h>
|
||||||
|
|
||||||
TEST(Just, basic) { auto s1 = sled::detail::Just(42); }
|
TEST(Just, basic) { auto s1 = sled::detail::Just(42); }
|
||||||
|
@ -1,44 +1,43 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/log/log.h>
|
#include <sled/log/log.h>
|
||||||
|
|
||||||
TEST(format, enum)
|
TEST_SUITE("fmt::format")
|
||||||
{
|
{
|
||||||
enum EnumType {
|
|
||||||
kOne = 1,
|
TEST_CASE("enum")
|
||||||
kTwo = 2,
|
{
|
||||||
kThree = 3,
|
enum EnumType {
|
||||||
|
kOne = 1,
|
||||||
|
kTwo = 2,
|
||||||
|
kThree = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << kOne;
|
||||||
|
|
||||||
|
CHECK_EQ(ss.str(), "1");
|
||||||
|
CHECK_EQ(fmt::format("{}{}{}", kOne, kTwo, kThree), "123");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("neg_enum")
|
||||||
|
{
|
||||||
|
enum EnumType {
|
||||||
|
kOne = -1,
|
||||||
|
kTwo = -2,
|
||||||
|
kThree = -3,
|
||||||
|
};
|
||||||
|
|
||||||
|
CHECK_EQ(fmt::format("{}{}{}", kOne, kTwo, kThree), "-1-2-3");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Streamable {
|
||||||
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::stringstream ss;
|
std::ostream &operator<<(std::ostream &os, const Streamable &s) { return os << s.value; }
|
||||||
ss << kOne;
|
|
||||||
|
|
||||||
EXPECT_EQ(ss.str(), "1");
|
TEST_CASE("streamable")
|
||||||
EXPECT_EQ(fmt::format("{}{}{}", kOne, kTwo, kThree), "123");
|
{
|
||||||
}
|
Streamable s{42};
|
||||||
|
CHECK_EQ(fmt::format("{}", s), "42");
|
||||||
TEST(format, neg_enum)
|
}
|
||||||
{
|
|
||||||
enum EnumType {
|
|
||||||
kOne = -1,
|
|
||||||
kTwo = -2,
|
|
||||||
kThree = -3,
|
|
||||||
};
|
|
||||||
|
|
||||||
EXPECT_EQ(fmt::format("{}{}{}", kOne, kTwo, kThree), "-1-2-3");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Streamable {
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::ostream &
|
|
||||||
operator<<(std::ostream &os, const Streamable &s)
|
|
||||||
{
|
|
||||||
return os << s.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(format, streamable)
|
|
||||||
{
|
|
||||||
Streamable s{42};
|
|
||||||
EXPECT_EQ(fmt::format("{}", s), "42");
|
|
||||||
}
|
}
|
||||||
|
@ -105,8 +105,8 @@ void Log(LogLevel level, const char *tag, const char *fmt, const char *file_name
|
|||||||
#define LOGE_IF(cond, tag, fmt, ...) SLOG_IF(cond, sled::LogLevel::kError, tag, fmt, __VA_ARGS__)
|
#define LOGE_IF(cond, tag, fmt, ...) SLOG_IF(cond, sled::LogLevel::kError, tag, fmt, __VA_ARGS__)
|
||||||
#define LOGF_IF(cond, tag, fmt, ...) SLOG_IF(cond, sled::LogLevel::kFatal, tag, fmt, __VA_ARGS__)
|
#define LOGF_IF(cond, tag, fmt, ...) SLOG_IF(cond, sled::LogLevel::kFatal, tag, fmt, __VA_ARGS__)
|
||||||
|
|
||||||
#define CHECK(cond, fmt, ...) SLOG_ASSERT(cond, "DCHECK", fmt, ##__VA_ARGS__)
|
#define SLED_CHECK(cond, fmt, ...) SLOG_ASSERT(cond, "DCHECK", fmt, ##__VA_ARGS__)
|
||||||
#define DCHECK(cond, fmt, ...) SLOG_ASSERT(cond, "DCHECK", fmt, ##__VA_ARGS__)
|
#define SLED_DCHECK(cond, fmt, ...) SLOG_ASSERT(cond, "DCHECK", fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define LOGV(tag, fmt, ...) SLOG(sled::LogLevel::kTrace, tag, fmt, ##__VA_ARGS__)
|
#define LOGV(tag, fmt, ...) SLOG(sled::LogLevel::kTrace, tag, fmt, ##__VA_ARGS__)
|
||||||
#define LOGD(tag, fmt, ...) SLOG(sled::LogLevel::kDebug, tag, fmt, ##__VA_ARGS__)
|
#define LOGD(tag, fmt, ...) SLOG(sled::LogLevel::kDebug, tag, fmt, ##__VA_ARGS__)
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/rx.h>
|
#include <sled/rx.h>
|
||||||
|
|
||||||
TEST(RX, interval)
|
TEST_SUITE("RxCpp")
|
||||||
{
|
{
|
||||||
// 2 + 4 + 6 = 12
|
TEST_CASE("interval")
|
||||||
sled::observable<>::interval(std::chrono::milliseconds(300))
|
{
|
||||||
.subscribe_on(rxcpp::synchronize_new_thread())
|
// 2 + 4 + 6 = 12
|
||||||
.observe_on(rxcpp::observe_on_new_thread())
|
sled::observable<>::interval(std::chrono::milliseconds(100))
|
||||||
.map([](long value) { return value * 2; })
|
.subscribe_on(rxcpp::synchronize_new_thread())
|
||||||
.take(3)
|
.observe_on(rxcpp::observe_on_new_thread())
|
||||||
.reduce(0, [](int acc, int value) { return acc + value; })
|
.map([](long value) { return value * 2; })
|
||||||
.as_blocking()
|
.take(3)
|
||||||
.subscribe([=](long counter) { EXPECT_EQ(counter, 12); }, []() {});
|
.reduce(0, [](int acc, int value) { return acc + value; })
|
||||||
|
.as_blocking()
|
||||||
|
.subscribe([=](long counter) { CHECK_EQ(counter, 12); }, []() {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,4 +85,7 @@ namespace async {}
|
|||||||
#include "sled/system_time.h"
|
#include "sled/system_time.h"
|
||||||
#include "sled/time_utils.h"
|
#include "sled/time_utils.h"
|
||||||
#include "sled/variant.h"
|
#include "sled/variant.h"
|
||||||
|
|
||||||
|
// testing
|
||||||
|
#include "sled/testing/test.h"
|
||||||
#endif// SLED_SLED_H
|
#endif// SLED_SLED_H
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/log/log.h>
|
#include <sled/log/log.h>
|
||||||
#include <sled/status_or.h>
|
#include <sled/status_or.h>
|
||||||
|
|
||||||
TEST(StatusOr, TestStatusOr)
|
TEST_SUITE("StatusOr")
|
||||||
{
|
{
|
||||||
sled::StatusOr<int> so;
|
TEST_CASE("StatusOr")
|
||||||
EXPECT_FALSE(so.ok());
|
{
|
||||||
so = sled::StatusOr<int>(1);
|
sled::StatusOr<int> so;
|
||||||
EXPECT_TRUE(so.ok());
|
CHECK_FALSE(so.ok());
|
||||||
EXPECT_EQ(so.value(), 1);
|
so = sled::StatusOr<int>(1);
|
||||||
EXPECT_EQ(so.status().code(), sled::StatusCode::kOk);
|
CHECK(so.ok());
|
||||||
}
|
CHECK_EQ(so.value(), 1);
|
||||||
|
CHECK_EQ(so.status().code(), sled::StatusCode::kOk);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(StatusOr, make_status_or)
|
TEST_CASE("MakeStatusOr")
|
||||||
{
|
{
|
||||||
auto from_raw_str = sled::MakeStatusOr("hello");
|
auto from_raw_str = sled::MakeStatusOr("hello");
|
||||||
auto from_string = sled::MakeStatusOr(std::string("world"));
|
auto from_string = sled::MakeStatusOr(std::string("world"));
|
||||||
EXPECT_TRUE(from_raw_str.ok());
|
CHECK(from_raw_str.ok());
|
||||||
EXPECT_TRUE(from_string.ok());
|
CHECK(from_string.ok());
|
||||||
EXPECT_EQ(from_raw_str.value(), "hello");
|
CHECK_EQ(from_raw_str.value(), "hello");
|
||||||
EXPECT_EQ(from_string.value(), "world");
|
CHECK_EQ(from_string.value(), "world");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/log/log.h>
|
#include <sled/log/log.h>
|
||||||
#include <sled/status.h>
|
#include <sled/status.h>
|
||||||
|
|
||||||
TEST(Status, format)
|
TEST_SUITE("Status")
|
||||||
{
|
{
|
||||||
auto status = sled::Status(sled::StatusCode::kOk, "");
|
TEST_CASE("format")
|
||||||
EXPECT_EQ(fmt::format("{}", status), "OK");
|
{
|
||||||
|
auto status = sled::Status(sled::StatusCode::kOk, "");
|
||||||
|
CHECK_EQ(fmt::format("{}", status), "OK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,50 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/strings/base64.h>
|
#include <sled/strings/base64.h>
|
||||||
|
|
||||||
TEST(Base64, EncodedLength)
|
TEST_SUITE("Base64")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(0, sled::Base64::EncodedLength(0));
|
|
||||||
EXPECT_EQ(4, sled::Base64::EncodedLength(1));
|
|
||||||
EXPECT_EQ(4, sled::Base64::EncodedLength(2));
|
|
||||||
EXPECT_EQ(4, sled::Base64::EncodedLength(3));
|
|
||||||
EXPECT_EQ(8, sled::Base64::EncodedLength(4));
|
|
||||||
EXPECT_EQ(8, sled::Base64::EncodedLength(5));
|
|
||||||
EXPECT_EQ(8, sled::Base64::EncodedLength(6));
|
|
||||||
EXPECT_EQ(12, sled::Base64::EncodedLength(7));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Base64, DecodedLength)
|
TEST_CASE("EncodedLength")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(0, sled::Base64::DecodedLength(nullptr, 0));
|
CHECK_EQ(0, sled::Base64::EncodedLength(0));
|
||||||
EXPECT_EQ(1, sled::Base64::DecodedLength(nullptr, 1));
|
CHECK_EQ(4, sled::Base64::EncodedLength(1));
|
||||||
EXPECT_EQ(2, sled::Base64::DecodedLength(nullptr, 2));
|
CHECK_EQ(4, sled::Base64::EncodedLength(2));
|
||||||
EXPECT_EQ(2, sled::Base64::DecodedLength(nullptr, 3));
|
CHECK_EQ(4, sled::Base64::EncodedLength(3));
|
||||||
EXPECT_EQ(3, sled::Base64::DecodedLength(nullptr, 4));
|
CHECK_EQ(8, sled::Base64::EncodedLength(4));
|
||||||
|
CHECK_EQ(8, sled::Base64::EncodedLength(5));
|
||||||
|
CHECK_EQ(8, sled::Base64::EncodedLength(6));
|
||||||
|
CHECK_EQ(12, sled::Base64::EncodedLength(7));
|
||||||
|
}
|
||||||
|
|
||||||
EXPECT_EQ(0, sled::Base64::DecodedLength("", 0));
|
TEST_CASE("DecodedLength")
|
||||||
}
|
{
|
||||||
|
CHECK_EQ(0, sled::Base64::DecodedLength(nullptr, 0));
|
||||||
|
CHECK_EQ(1, sled::Base64::DecodedLength(nullptr, 1));
|
||||||
|
CHECK_EQ(2, sled::Base64::DecodedLength(nullptr, 2));
|
||||||
|
CHECK_EQ(2, sled::Base64::DecodedLength(nullptr, 3));
|
||||||
|
CHECK_EQ(3, sled::Base64::DecodedLength(nullptr, 4));
|
||||||
|
|
||||||
TEST(Base64, Encode)
|
CHECK_EQ(0, sled::Base64::DecodedLength("", 0));
|
||||||
{
|
}
|
||||||
EXPECT_EQ("aGVsbG8gd29ybGQK", sled::Base64::Encode("hello world\n"));
|
|
||||||
EXPECT_EQ("U2VuZCByZWluZm9yY2VtZW50cwo=", sled::Base64::Encode("Send reinforcements\n"));
|
|
||||||
EXPECT_EQ("", sled::Base64::Encode(""));
|
|
||||||
EXPECT_EQ("IA==", sled::Base64::Encode(" "));
|
|
||||||
EXPECT_EQ("AA==", sled::Base64::Encode(std::string("\0", 1)));
|
|
||||||
EXPECT_EQ("AAA=", sled::Base64::Encode(std::string("\0\0", 2)));
|
|
||||||
EXPECT_EQ("AAAA", sled::Base64::Encode(std::string("\0\0\0", 3)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(Base64, Decode)
|
TEST_CASE("Encode")
|
||||||
{
|
{
|
||||||
EXPECT_EQ("hello world\n", sled::Base64::Decode("aGVsbG8gd29ybGQK").value());
|
CHECK_EQ("aGVsbG8gd29ybGQK", sled::Base64::Encode("hello world\n"));
|
||||||
EXPECT_EQ("Send reinforcements\n", sled::Base64::Decode("U2VuZCByZWluZm9yY2VtZW50cwo=").value());
|
CHECK_EQ("U2VuZCByZWluZm9yY2VtZW50cwo=", sled::Base64::Encode("Send reinforcements\n"));
|
||||||
EXPECT_EQ("", sled::Base64::Decode("").value());
|
CHECK_EQ("", sled::Base64::Encode(""));
|
||||||
EXPECT_EQ(" ", sled::Base64::Decode("IA==").value());
|
CHECK_EQ("IA==", sled::Base64::Encode(" "));
|
||||||
EXPECT_EQ(std::string("\0", 1), sled::Base64::Decode("AA==").value());
|
CHECK_EQ("AA==", sled::Base64::Encode(std::string("\0", 1)));
|
||||||
EXPECT_EQ(std::string("\0\0", 2), sled::Base64::Decode("AAA=").value());
|
CHECK_EQ("AAA=", sled::Base64::Encode(std::string("\0\0", 2)));
|
||||||
EXPECT_EQ(std::string("\0\0\0", 3), sled::Base64::Decode("AAAA").value());
|
CHECK_EQ("AAAA", sled::Base64::Encode(std::string("\0\0\0", 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Decode")
|
||||||
|
{
|
||||||
|
CHECK_EQ("hello world\n", sled::Base64::Decode("aGVsbG8gd29ybGQK").value());
|
||||||
|
CHECK_EQ("Send reinforcements\n", sled::Base64::Decode("U2VuZCByZWluZm9yY2VtZW50cwo=").value());
|
||||||
|
CHECK_EQ("", sled::Base64::Decode("").value());
|
||||||
|
CHECK_EQ(" ", sled::Base64::Decode("IA==").value());
|
||||||
|
CHECK_EQ(std::string("\0", 1), sled::Base64::Decode("AA==").value());
|
||||||
|
CHECK_EQ(std::string("\0\0", 2), sled::Base64::Decode("AAA=").value());
|
||||||
|
CHECK_EQ(std::string("\0\0\0", 3), sled::Base64::Decode("AAAA").value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,95 +1,98 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/strings/utils.h>
|
#include <sled/strings/utils.h>
|
||||||
|
|
||||||
TEST(ToLower, Char)
|
TEST_SUITE("String Utils")
|
||||||
{
|
{
|
||||||
for (char c = 'A'; c <= 'Z'; ++c) { EXPECT_EQ(sled::ToLower(c), c + 32) << c; }
|
|
||||||
for (char c = 'a'; c <= 'z'; ++c) { EXPECT_EQ(sled::ToLower(c), c) << c; }
|
|
||||||
EXPECT_EQ(sled::ToLower(' '), ' ');
|
|
||||||
EXPECT_EQ(sled::ToLower('\0'), '\0');
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ToUpper, Char)
|
TEST_CASE("Char")
|
||||||
{
|
{
|
||||||
for (char c = 'A'; c <= 'Z'; ++c) { EXPECT_EQ(sled::ToUpper(c), c) << c; }
|
for (char c = 'A'; c <= 'Z'; ++c) { CHECK_EQ(sled::ToLower(c), c + 32); }
|
||||||
for (char c = 'a'; c <= 'z'; ++c) { EXPECT_EQ(sled::ToUpper(c), c - 32) << c; }
|
for (char c = 'a'; c <= 'z'; ++c) { CHECK_EQ(sled::ToLower(c), c); }
|
||||||
EXPECT_EQ(sled::ToUpper(' '), ' ');
|
CHECK_EQ(sled::ToLower(' '), ' ');
|
||||||
EXPECT_EQ(sled::ToUpper('\0'), '\0');
|
CHECK_EQ(sled::ToLower('\0'), '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ToLower, String)
|
TEST_CASE("Char")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(sled::ToLower("Hello World"), "hello world");
|
for (char c = 'A'; c <= 'Z'; ++c) { CHECK_EQ(sled::ToUpper(c), c); }
|
||||||
EXPECT_EQ(sled::ToLower("HELLO WORLD"), "hello world");
|
for (char c = 'a'; c <= 'z'; ++c) { CHECK_EQ(sled::ToUpper(c), c - 32); }
|
||||||
EXPECT_EQ(sled::ToLower("hello world"), "hello world");
|
CHECK_EQ(sled::ToUpper(' '), ' ');
|
||||||
EXPECT_EQ(sled::ToLower(" "), " ");
|
CHECK_EQ(sled::ToUpper('\0'), '\0');
|
||||||
EXPECT_EQ(sled::ToLower(""), "");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TEST(ToUpper, String)
|
TEST_CASE("String")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(sled::ToUpper("Hello World"), "HELLO WORLD");
|
CHECK_EQ(sled::ToLower("Hello World"), "hello world");
|
||||||
EXPECT_EQ(sled::ToUpper("HELLO WORLD"), "HELLO WORLD");
|
CHECK_EQ(sled::ToLower("HELLO WORLD"), "hello world");
|
||||||
EXPECT_EQ(sled::ToUpper("hello world"), "HELLO WORLD");
|
CHECK_EQ(sled::ToLower("hello world"), "hello world");
|
||||||
EXPECT_EQ(sled::ToUpper(" "), " ");
|
CHECK_EQ(sled::ToLower(" "), " ");
|
||||||
EXPECT_EQ(sled::ToUpper(""), "");
|
CHECK_EQ(sled::ToLower(""), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StrJoin, Empty)
|
TEST_CASE("String")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(sled::StrJoin({}, ","), "");
|
CHECK_EQ(sled::ToUpper("Hello World"), "HELLO WORLD");
|
||||||
EXPECT_EQ(sled::StrJoin({}, ",", true), "");
|
CHECK_EQ(sled::ToUpper("HELLO WORLD"), "HELLO WORLD");
|
||||||
EXPECT_EQ(sled::StrJoin({}, ",", false), "");
|
CHECK_EQ(sled::ToUpper("hello world"), "HELLO WORLD");
|
||||||
}
|
CHECK_EQ(sled::ToUpper(" "), " ");
|
||||||
|
CHECK_EQ(sled::ToUpper(""), "");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(StrJoin, Delim)
|
TEST_CASE("Empty")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(sled::StrJoin({"a", "b", "c"}, ","), "a,b,c");
|
CHECK_EQ(sled::StrJoin({}, ","), "");
|
||||||
EXPECT_EQ(sled::StrJoin({"a", "b", "c"}, ",", true), "a,b,c");
|
CHECK_EQ(sled::StrJoin({}, ",", true), "");
|
||||||
EXPECT_EQ(sled::StrJoin({"a", "b", "c"}, ",", false), "a,b,c");
|
CHECK_EQ(sled::StrJoin({}, ",", false), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StrJoin, DelimSkipEmpty)
|
TEST_CASE("Delim")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(sled::StrJoin({"a", "", "c"}, ","), "a,,c");
|
CHECK_EQ(sled::StrJoin({"a", "b", "c"}, ","), "a,b,c");
|
||||||
EXPECT_EQ(sled::StrJoin({"a", "", "c"}, ",", true), "a,c");
|
CHECK_EQ(sled::StrJoin({"a", "b", "c"}, ",", true), "a,b,c");
|
||||||
EXPECT_EQ(sled::StrJoin({"a", "", "c"}, ",", false), "a,,c");
|
CHECK_EQ(sled::StrJoin({"a", "b", "c"}, ",", false), "a,b,c");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StrSplit, Empty)
|
TEST_CASE("DelimSkipEmpty")
|
||||||
{
|
{
|
||||||
EXPECT_EQ(sled::StrSplit("", ","), std::vector<std::string>());
|
CHECK_EQ(sled::StrJoin({"a", "", "c"}, ","), "a,,c");
|
||||||
EXPECT_EQ(sled::StrSplit("", ",", true), std::vector<std::string>());
|
CHECK_EQ(sled::StrJoin({"a", "", "c"}, ",", true), "a,c");
|
||||||
EXPECT_EQ(sled::StrSplit("", ",", false), std::vector<std::string>());
|
CHECK_EQ(sled::StrJoin({"a", "", "c"}, ",", false), "a,,c");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StrSplit, Delim)
|
TEST_CASE("Empty")
|
||||||
{
|
{
|
||||||
// single delim
|
CHECK_EQ(sled::StrSplit("", ","), std::vector<std::string>());
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c", ","), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("", ",", true), std::vector<std::string>());
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("", ",", false), std::vector<std::string>());
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c", ",", false), std::vector<std::string>({"a", "b", "c"}));
|
}
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c,", ","), std::vector<std::string>({"a", "b", "c", ""}));
|
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c,", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c,", ",", false), std::vector<std::string>({"a", "b", "c", ""}));
|
|
||||||
EXPECT_EQ(sled::StrSplit(",a,b,c", ","), std::vector<std::string>({"", "a", "b", "c"}));
|
|
||||||
EXPECT_EQ(sled::StrSplit(",a,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
|
||||||
EXPECT_EQ(sled::StrSplit(",a,b,c", ",", false), std::vector<std::string>({"", "a", "b", "c"}));
|
|
||||||
|
|
||||||
// multi delim
|
TEST_CASE("Delim")
|
||||||
EXPECT_EQ(sled::StrSplit(",,a,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
{
|
||||||
EXPECT_EQ(sled::StrSplit(",,a,b,c", ",", false), std::vector<std::string>({"", "", "a", "b", "c"}));
|
// single delim
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c,,", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("a,b,c", ","), std::vector<std::string>({"a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,b,c,,", ",", false), std::vector<std::string>({"a", "b", "c", "", ""}));
|
CHECK_EQ(sled::StrSplit("a,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("a,b,c", ",", false), std::vector<std::string>({"a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,,b,c", ",", false), std::vector<std::string>({"a", "", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("a,b,c,", ","), std::vector<std::string>({"a", "b", "c", ""}));
|
||||||
}
|
CHECK_EQ(sled::StrSplit("a,b,c,", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
|
CHECK_EQ(sled::StrSplit("a,b,c,", ",", false), std::vector<std::string>({"a", "b", "c", ""}));
|
||||||
|
CHECK_EQ(sled::StrSplit(",a,b,c", ","), std::vector<std::string>({"", "a", "b", "c"}));
|
||||||
|
CHECK_EQ(sled::StrSplit(",a,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
|
CHECK_EQ(sled::StrSplit(",a,b,c", ",", false), std::vector<std::string>({"", "a", "b", "c"}));
|
||||||
|
|
||||||
TEST(StrSplit, MultiDelim)
|
// multi delim
|
||||||
{
|
CHECK_EQ(sled::StrSplit(",,a,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,b;c", ",;", true), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit(",,a,b,c", ",", false), std::vector<std::string>({"", "", "a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,b;c", ",;", false), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("a,b,c,,", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,b;c,", ",;", true), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("a,b,c,,", ",", false), std::vector<std::string>({"a", "b", "c", "", ""}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,b;c,", ",;", false), std::vector<std::string>({"a", "b", "c", ""}));
|
CHECK_EQ(sled::StrSplit("a,,b,c", ",", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
EXPECT_EQ(sled::StrSplit("a,b;c,", ";,", true), std::vector<std::string>({"a", "b", "c"}));
|
CHECK_EQ(sled::StrSplit("a,,b,c", ",", false), std::vector<std::string>({"a", "", "b", "c"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("MultiDelim")
|
||||||
|
{
|
||||||
|
CHECK_EQ(sled::StrSplit("a,b;c", ",;", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
|
CHECK_EQ(sled::StrSplit("a,b;c", ",;", false), std::vector<std::string>({"a", "b", "c"}));
|
||||||
|
CHECK_EQ(sled::StrSplit("a,b;c,", ",;", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
|
CHECK_EQ(sled::StrSplit("a,b;c,", ",;", false), std::vector<std::string>({"a", "b", "c", ""}));
|
||||||
|
CHECK_EQ(sled::StrSplit("a,b;c,", ";,", true), std::vector<std::string>({"a", "b", "c"}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define SLED_RUN_ON(x) THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
|
#define SLED_RUN_ON(x) THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
|
||||||
#define SLED_DCHECK_RUN_ON(x) DCHECK((x)->IsCurrent(), (x)->ExpectationToString())
|
#define SLED_DCHECK_RUN_ON(x) SLED_DCHECK((x)->IsCurrent(), (x)->ExpectationToString())
|
||||||
|
|
||||||
}// namespace sled
|
}// namespace sled
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/log/log.h>
|
#include <sled/log/log.h>
|
||||||
|
#include <sled/make_unique.h>
|
||||||
#include <sled/synchronization/event.h>
|
#include <sled/synchronization/event.h>
|
||||||
#include <sled/synchronization/sequence_checker.h>
|
#include <sled/synchronization/sequence_checker.h>
|
||||||
#include <sled/system/thread.h>
|
#include <sled/system/thread.h>
|
||||||
@ -13,56 +13,60 @@ RunOnDifferentThread(std::function<void()> func)
|
|||||||
thread_has_run_event.Set();
|
thread_has_run_event.Set();
|
||||||
});
|
});
|
||||||
thread.detach();
|
thread.detach();
|
||||||
EXPECT_TRUE(thread_has_run_event.Wait(sled::TimeDelta::Seconds(1)));
|
CHECK(thread_has_run_event.Wait(sled::TimeDelta::Seconds(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SequenceChecker, CallsAllowedOnSameThread)
|
TEST_SUITE("SequenceChecker")
|
||||||
{
|
{
|
||||||
sled::SequenceChecker sequence_checker;
|
|
||||||
EXPECT_TRUE(sequence_checker.IsCurrent());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SequenceChecker, DestructorAllowedOnDifferentThread)
|
TEST_CASE("CallsAllowedOnSameThread")
|
||||||
{
|
{
|
||||||
auto sequence_checker = std::make_unique<sled::SequenceChecker>();
|
sled::SequenceChecker sequence_checker;
|
||||||
RunOnDifferentThread([&] { sequence_checker.reset(); });
|
CHECK(sequence_checker.IsCurrent());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SequenceChecker, Detach)
|
TEST_CASE("DestructorAllowedOnDifferentThread")
|
||||||
{
|
{
|
||||||
sled::SequenceChecker sequence_checker;
|
auto sequence_checker = sled::MakeUnique<sled::SequenceChecker>();
|
||||||
sequence_checker.Detach();
|
RunOnDifferentThread([&] { sequence_checker.reset(); });
|
||||||
|
}
|
||||||
|
|
||||||
RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
|
TEST_CASE("Detach")
|
||||||
}
|
{
|
||||||
|
|
||||||
TEST(SequenceChecker, OnlyCurrentOnOneThread)
|
|
||||||
{
|
|
||||||
sled::SequenceChecker sequence_checker(sled::SequenceChecker::kDetached);
|
|
||||||
RunOnDifferentThread([&] {
|
|
||||||
EXPECT_TRUE(sequence_checker.IsCurrent());
|
|
||||||
RunOnDifferentThread([&] { EXPECT_FALSE(sequence_checker.IsCurrent()); });
|
|
||||||
EXPECT_TRUE(sequence_checker.IsCurrent());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SequenceChecker, DeatchFromThreadAndUseOnTaskQueue)
|
|
||||||
{
|
|
||||||
auto queue = sled::Thread::Create();
|
|
||||||
ASSERT_TRUE(queue->Start());
|
|
||||||
sled::SequenceChecker sequence_checker;
|
|
||||||
sequence_checker.Detach();
|
|
||||||
queue->BlockingCall([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(SequenceChecker, DetachFromTaskQueueAndUseOnThread)
|
|
||||||
{
|
|
||||||
auto queue = sled::Thread::Create();
|
|
||||||
ASSERT_TRUE(queue->Start());
|
|
||||||
queue->BlockingCall([&] {
|
|
||||||
sled::SequenceChecker sequence_checker;
|
sled::SequenceChecker sequence_checker;
|
||||||
sequence_checker.Detach();
|
sequence_checker.Detach();
|
||||||
RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); });
|
|
||||||
});
|
RunOnDifferentThread([&] { CHECK(sequence_checker.IsCurrent()); });
|
||||||
queue->Stop();
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OnlyCurrentOnOneThread")
|
||||||
|
{
|
||||||
|
sled::SequenceChecker sequence_checker(sled::SequenceChecker::kDetached);
|
||||||
|
RunOnDifferentThread([&] {
|
||||||
|
CHECK(sequence_checker.IsCurrent());
|
||||||
|
RunOnDifferentThread([&] { CHECK_FALSE(sequence_checker.IsCurrent()); });
|
||||||
|
CHECK(sequence_checker.IsCurrent());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DeatchFromThreadAndUseOnTaskQueue")
|
||||||
|
{
|
||||||
|
auto queue = sled::Thread::Create();
|
||||||
|
REQUIRE(queue->Start());
|
||||||
|
sled::SequenceChecker sequence_checker;
|
||||||
|
sequence_checker.Detach();
|
||||||
|
queue->BlockingCall([&] { CHECK(sequence_checker.IsCurrent()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DetachFromTaskQueueAndUseOnThread")
|
||||||
|
{
|
||||||
|
auto queue = sled::Thread::Create();
|
||||||
|
REQUIRE(queue->Start());
|
||||||
|
queue->BlockingCall([&] {
|
||||||
|
sled::SequenceChecker sequence_checker;
|
||||||
|
sequence_checker.Detach();
|
||||||
|
RunOnDifferentThread([&] { CHECK(sequence_checker.IsCurrent()); });
|
||||||
|
});
|
||||||
|
queue->Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,28 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/system/fiber/scheduler.h>
|
#include <sled/system/fiber/scheduler.h>
|
||||||
#include <sled/system/fiber/wait_group.h>
|
#include <sled/system/fiber/wait_group.h>
|
||||||
|
|
||||||
TEST(FiberScheduler, TestFiberScheduler)
|
TEST_SUITE("Fiber")
|
||||||
{
|
{
|
||||||
sled::Scheduler scheduler(sled::Scheduler::Config::allCores());
|
|
||||||
scheduler.bind();
|
|
||||||
defer(scheduler.unbind());
|
|
||||||
|
|
||||||
std::atomic<int> counter = {0};
|
TEST_CASE("FiberScheduler")
|
||||||
sled::WaitGroup wg(1);
|
{
|
||||||
sled::WaitGroup wg2(1000);
|
sled::Scheduler scheduler(sled::Scheduler::Config::allCores());
|
||||||
for (int i = 0; i < 1000; i++) {
|
scheduler.bind();
|
||||||
sled::Schedule([&] {
|
defer(scheduler.unbind());
|
||||||
wg.Wait();
|
|
||||||
wg2.Done();
|
std::atomic<int> counter = {0};
|
||||||
counter++;
|
sled::WaitGroup wg(1);
|
||||||
});
|
sled::WaitGroup wg2(1000);
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
sled::Schedule([&] {
|
||||||
|
wg.Wait();
|
||||||
|
wg2.Done();
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sled::Schedule([=] { wg.Done(); });
|
||||||
|
wg2.Wait();
|
||||||
|
CHECK_EQ(counter.load(), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
sled::Schedule([=] { wg.Done(); });
|
|
||||||
wg2.Wait();
|
|
||||||
ASSERT_EQ(counter.load(), 1000);
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <sled/system/thread_pool.h>
|
#include <sled/system/thread_pool.h>
|
||||||
|
|
||||||
@ -38,28 +37,26 @@ multiply_return(const int a, const int b)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThreadPoolTest : public ::testing::Test {
|
TEST_CASE("ThreadPool")
|
||||||
public:
|
|
||||||
void SetUp() override { tp = new sled::ThreadPool(); }
|
|
||||||
|
|
||||||
void TearDown() override { delete tp; }
|
|
||||||
|
|
||||||
sled::ThreadPool *tp;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(ThreadPoolTest, Output)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 100; ++i) {
|
sled::ThreadPool *tp = new sled::ThreadPool();
|
||||||
int out;
|
REQUIRE_NE(tp, nullptr);
|
||||||
tp->submit(multiply_output, std::ref(out), i, i).get();
|
|
||||||
EXPECT_EQ(out, i * i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ThreadPoolTest, Return)
|
SUBCASE("Output")
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
auto f = tp->submit(multiply_return, i, i);
|
int out;
|
||||||
EXPECT_EQ(f.get(), i * i);
|
tp->submit(multiply_output, std::ref(out), i, i).get();
|
||||||
|
CHECK_EQ(out, i * i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
SUBCASE("Return")
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
auto f = tp->submit(multiply_return, i, i);
|
||||||
|
CHECK_EQ(f.get(), i * i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete tp;
|
||||||
}
|
}
|
||||||
|
7108
src/sled/testing/doctest.h
Normal file
7108
src/sled/testing/doctest.h
Normal file
File diff suppressed because it is too large
Load Diff
7845
src/sled/testing/fakeit.h
Normal file
7845
src/sled/testing/fakeit.h
Normal file
File diff suppressed because it is too large
Load Diff
3
src/sled/testing/test.cc
Normal file
3
src/sled/testing/test.cc
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#define DOCTEST_CONFIG_IMPLEMENT
|
||||||
|
#define SLED_TESTING_TEST_H
|
||||||
|
#include "sled/testing/doctest.h"
|
7
src/sled/testing/test.h
Normal file
7
src/sled/testing/test.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef SLED_TESTING_TEST_H
|
||||||
|
#define SLED_TESTING_TEST_H
|
||||||
|
|
||||||
|
#include "sled/testing/doctest.h"
|
||||||
|
#include "sled/testing/fakeit.h"
|
||||||
|
|
||||||
|
#endif// SLED_TESTING_TEST_H
|
8
src/sled/testing/test_main.cc
Normal file
8
src/sled/testing/test_main.cc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#define SLED_TESTING_TEST_H
|
||||||
|
#include "sled/testing/doctest.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
return doctest::Context(argc, argv).run();
|
||||||
|
}
|
@ -23,7 +23,7 @@ TaskQueueTimeoutFactory::TaskQueueTimeout::Start(DurationMs duration_ms, Timeout
|
|||||||
SLED_DCHECK_RUN_ON(&parent_.thread_checker_);
|
SLED_DCHECK_RUN_ON(&parent_.thread_checker_);
|
||||||
ASSERT(timeout_expiration_ == std::numeric_limits<TimeMs>::max(), "");
|
ASSERT(timeout_expiration_ == std::numeric_limits<TimeMs>::max(), "");
|
||||||
timeout_expiration_ = parent_.get_time_() + duration_ms;
|
timeout_expiration_ = parent_.get_time_() + duration_ms;
|
||||||
timeout_id_ = timeout_id;
|
timeout_id_ = timeout_id;
|
||||||
|
|
||||||
if (timeout_expiration_ >= posted_task_expiration_) { return; }
|
if (timeout_expiration_ >= posted_task_expiration_) { return; }
|
||||||
if (posted_task_expiration_ != std::numeric_limits<TimeMs>::max()) {
|
if (posted_task_expiration_ != std::numeric_limits<TimeMs>::max()) {
|
||||||
@ -35,7 +35,7 @@ TaskQueueTimeoutFactory::TaskQueueTimeout::Start(DurationMs duration_ms, Timeout
|
|||||||
}
|
}
|
||||||
|
|
||||||
posted_task_expiration_ = timeout_expiration_;
|
posted_task_expiration_ = timeout_expiration_;
|
||||||
auto safety_flag = safety_flag_;
|
auto safety_flag = safety_flag_;
|
||||||
|
|
||||||
parent_.task_queue_.PostDelayedTaskWithPrecision(
|
parent_.task_queue_.PostDelayedTaskWithPrecision(
|
||||||
precision_,
|
precision_,
|
||||||
@ -43,16 +43,16 @@ TaskQueueTimeoutFactory::TaskQueueTimeout::Start(DurationMs duration_ms, Timeout
|
|||||||
[timeout_id, this]() {
|
[timeout_id, this]() {
|
||||||
LOGV("timer", "Timeout expired: {}", timeout_id);
|
LOGV("timer", "Timeout expired: {}", timeout_id);
|
||||||
SLED_DCHECK_RUN_ON(&parent_.thread_checker_);
|
SLED_DCHECK_RUN_ON(&parent_.thread_checker_);
|
||||||
DCHECK(posted_task_expiration_ != std::numeric_limits<TimeMs>::max(), "");
|
SLED_DCHECK(posted_task_expiration_ != std::numeric_limits<TimeMs>::max(), "");
|
||||||
posted_task_expiration_ = std::numeric_limits<TimeMs>::max();
|
posted_task_expiration_ = std::numeric_limits<TimeMs>::max();
|
||||||
|
|
||||||
if (timeout_expiration_ == std::numeric_limits<TimeMs>::max()) {
|
if (timeout_expiration_ == std::numeric_limits<TimeMs>::max()) {
|
||||||
// cancelled timer
|
// cancelled timer
|
||||||
// do nothing
|
// do nothing
|
||||||
} else {
|
} else {
|
||||||
const TimeMs now = parent_.get_time_();
|
const TimeMs now = parent_.get_time_();
|
||||||
const DurationMs remaining = timeout_expiration_ - now;
|
const DurationMs remaining = timeout_expiration_ - now;
|
||||||
bool is_expired = timeout_expiration_ <= now;
|
bool is_expired = timeout_expiration_ <= now;
|
||||||
|
|
||||||
timeout_expiration_ = std::numeric_limits<TimeMs>::max();
|
timeout_expiration_ = std::numeric_limits<TimeMs>::max();
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sled/uri.h>
|
#include <sled/uri.h>
|
||||||
|
|
||||||
TEST(URI, Absolute)
|
TEST_CASE("")
|
||||||
{
|
{
|
||||||
sled::URI uri("http://example.com:1234/dir1/dir2/file?a=1#anchor");
|
sled::URI uri("http://example.com:1234/dir1/dir2/file?a=1#anchor");
|
||||||
EXPECT_EQ(uri.scheme(), "http");
|
CHECK_EQ(uri.scheme(), "http");
|
||||||
EXPECT_EQ(uri.host(), "example.com");
|
CHECK_EQ(uri.host(), "example.com");
|
||||||
EXPECT_EQ(uri.port(), 1234);
|
CHECK_EQ(uri.port(), 1234);
|
||||||
EXPECT_EQ(uri.path(), "/dir1/dir2/file");
|
CHECK_EQ(uri.path(), "/dir1/dir2/file");
|
||||||
EXPECT_EQ(uri.query().size(), 1);
|
CHECK_EQ(uri.query().size(), 1);
|
||||||
EXPECT_EQ(uri.query()["a"], "1");
|
CHECK_EQ(uri.query()["a"], "1");
|
||||||
EXPECT_EQ(uri.anchor(), "anchor");
|
CHECK_EQ(uri.anchor(), "anchor");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user