250 lines
5.7 KiB
C++
250 lines
5.7 KiB
C++
#include "../lib/Utilities.hpp"
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <thread>
|
|
#include <chrono>
|
|
#include <vector>
|
|
#include <future>
|
|
|
|
void test_lock_free_queue()
|
|
{
|
|
std::cout << "Testing lock-free queue...\n";
|
|
|
|
reactor::LockFreeQueue<int> queue;
|
|
assert(queue.empty());
|
|
|
|
queue.enqueue(1);
|
|
queue.enqueue(2);
|
|
queue.enqueue(3);
|
|
assert(!queue.empty());
|
|
|
|
int val;
|
|
assert(queue.dequeue(val) && val == 1);
|
|
assert(queue.dequeue(val) && val == 2);
|
|
assert(queue.dequeue(val) && val == 3);
|
|
assert(queue.empty());
|
|
assert(!queue.dequeue(val));
|
|
|
|
std::cout << "✓ Lock-free queue basic operations passed\n";
|
|
}
|
|
|
|
void test_lock_free_queue_concurrent()
|
|
{
|
|
std::cout << "Testing lock-free queue concurrency...\n";
|
|
|
|
reactor::LockFreeQueue<int> queue;
|
|
constexpr int num_items = 1000;
|
|
constexpr int num_producers = 4;
|
|
constexpr int num_consumers = 2;
|
|
|
|
std::vector<std::thread> producers;
|
|
std::vector<std::thread> consumers;
|
|
std::atomic<int> consumed_count{0};
|
|
std::atomic<bool> stop_consumers{false};
|
|
|
|
for (int p = 0; p < num_producers; ++p) {
|
|
producers.emplace_back([&queue, p, num_items]() {
|
|
for (int i = 0; i < num_items; ++i) {
|
|
queue.enqueue(p * num_items + i);
|
|
}
|
|
});
|
|
}
|
|
|
|
for (int c = 0; c < num_consumers; ++c) {
|
|
consumers.emplace_back([&queue, &consumed_count, &stop_consumers]() {
|
|
int val;
|
|
while (!stop_consumers) {
|
|
if (queue.dequeue(val)) {
|
|
consumed_count++;
|
|
} else {
|
|
std::this_thread::yield();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
for (auto& p : producers) {
|
|
p.join();
|
|
}
|
|
|
|
while (consumed_count < num_producers * num_items) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
|
|
stop_consumers = true;
|
|
for (auto& c : consumers) {
|
|
c.join();
|
|
}
|
|
|
|
assert(consumed_count == num_producers * num_items);
|
|
std::cout << "✓ Lock-free queue concurrency passed\n";
|
|
}
|
|
|
|
void test_object_pool()
|
|
{
|
|
std::cout << "Testing object pool...\n";
|
|
|
|
struct TestObject
|
|
{
|
|
int value = 42;
|
|
TestObject() { std::cout << "TestObject constructed\n"; }
|
|
~TestObject() { std::cout << "TestObject destructed\n"; }
|
|
};
|
|
|
|
auto pool = std::make_shared<reactor::ObjectPool<TestObject>>();
|
|
|
|
{
|
|
auto obj1 = pool->getObject();
|
|
auto obj2 = pool->getObject();
|
|
assert(obj1->value == 42);
|
|
assert(obj2->value == 42);
|
|
assert(obj1.get() != obj2.get());
|
|
}
|
|
|
|
{
|
|
auto obj3 = pool->getObject();
|
|
assert(obj3->value == 42);
|
|
}
|
|
|
|
std::cout << "✓ Object pool passed\n";
|
|
}
|
|
|
|
void test_logger()
|
|
{
|
|
std::cout << "Testing logger...\n";
|
|
|
|
reactor::Logger::setLevel(reactor::LogLevel::DEBUG);
|
|
|
|
reactor::Logger(reactor::LogLevel::DEBUG) << "Debug message";
|
|
reactor::Logger(reactor::LogLevel::INFO) << "Info message with number: " << 42;
|
|
reactor::Logger(reactor::LogLevel::WARN) << "Warning message";
|
|
reactor::Logger(reactor::LogLevel::ERROR) << "Error message";
|
|
|
|
reactor::Logger::setLevel(reactor::LogLevel::ERROR);
|
|
reactor::Logger(reactor::LogLevel::DEBUG) << "This should not appear";
|
|
reactor::Logger(reactor::LogLevel::INFO) << "This should not appear";
|
|
reactor::Logger(reactor::LogLevel::ERROR) << "This should appear";
|
|
|
|
reactor::Logger::setLevel(reactor::LogLevel::DEBUG);
|
|
|
|
std::cout << "✓ Logger passed\n";
|
|
}
|
|
|
|
void test_concurrent_task_queue()
|
|
{
|
|
std::cout << "Testing concurrent task queue...\n";
|
|
|
|
reactor::ConcurrentTaskQueue queue(2, "TestQueue");
|
|
assert(queue.getName() == "TestQueue");
|
|
|
|
std::atomic<int> counter{0};
|
|
std::promise<void> all_done;
|
|
auto future = all_done.get_future();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
queue.runTaskInQueue([&counter, i, &all_done]() {
|
|
counter++;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
if (counter == 10) {
|
|
all_done.set_value();
|
|
}
|
|
});
|
|
}
|
|
|
|
future.wait();
|
|
assert(counter == 10);
|
|
|
|
std::cout << "✓ Concurrent task queue passed\n";
|
|
}
|
|
|
|
void test_sync_task()
|
|
{
|
|
std::cout << "Testing sync task execution...\n";
|
|
|
|
reactor::ConcurrentTaskQueue queue(1, "SyncTest");
|
|
bool task_executed = false;
|
|
|
|
queue.syncTaskInQueue([&task_executed]() {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
task_executed = true;
|
|
});
|
|
|
|
assert(task_executed);
|
|
std::cout << "✓ Sync task execution passed\n";
|
|
}
|
|
|
|
void test_utility_functions()
|
|
{
|
|
std::cout << "Testing utility functions...\n";
|
|
|
|
std::size_t seed = 0;
|
|
reactor::hashCombine(seed, 42);
|
|
reactor::hashCombine(seed, std::string("test"));
|
|
assert(seed != 0);
|
|
|
|
std::string text = "hello,world,test,data";
|
|
auto parts = reactor::splitString(text, ",");
|
|
assert(parts.size() == 4);
|
|
assert(parts[0] == "hello");
|
|
assert(parts[1] == "world");
|
|
assert(parts[2] == "test");
|
|
assert(parts[3] == "data");
|
|
|
|
auto single = reactor::splitString("single", ",");
|
|
assert(single.size() == 1);
|
|
assert(single[0] == "single");
|
|
|
|
std::cout << "✓ Utility functions passed\n";
|
|
}
|
|
|
|
void test_network_utilities()
|
|
{
|
|
std::cout << "Testing network utilities...\n";
|
|
|
|
uint64_t original = 0x123456789ABCDEF0ULL;
|
|
uint64_t network = reactor::hton64(original);
|
|
uint64_t back = reactor::ntoh64(network);
|
|
|
|
assert(back == original);
|
|
|
|
std::cout << "✓ Network utilities passed\n";
|
|
}
|
|
|
|
void test_non_copyable()
|
|
{
|
|
std::cout << "Testing NonCopyable...\n";
|
|
|
|
class TestClass : public reactor::NonCopyable
|
|
{
|
|
public:
|
|
int value = 42;
|
|
TestClass() = default;
|
|
TestClass(TestClass&& other) noexcept : value(other.value) { other.value = 0; }
|
|
};
|
|
|
|
TestClass obj1;
|
|
TestClass obj2 = std::move(obj1);
|
|
assert(obj2.value == 42);
|
|
assert(obj1.value == 0);
|
|
|
|
std::cout << "✓ NonCopyable passed\n";
|
|
}
|
|
|
|
int main()
|
|
{
|
|
std::cout << "=== Utilities Tests ===\n";
|
|
|
|
test_lock_free_queue();
|
|
test_lock_free_queue_concurrent();
|
|
test_object_pool();
|
|
test_logger();
|
|
test_concurrent_task_queue();
|
|
test_sync_task();
|
|
test_utility_functions();
|
|
test_network_utilities();
|
|
test_non_copyable();
|
|
|
|
std::cout << "All utilities tests passed! ✓\n";
|
|
return 0;
|
|
}
|