chore: initial commit
Some checks failed
Code Analysis / analysis (push) Failing after 2m59s

This commit is contained in:
2025-12-30 22:34:58 +07:00
commit 35a6349071
63 changed files with 2675 additions and 0 deletions

171
tests/BasicTests.cpp Normal file
View File

@@ -0,0 +1,171 @@
#include <gtest/gtest.h>
#include <grpcpp/grpcpp.h>
#include <memory>
#include <thread>
#include <chrono>
#include "v1/primitives/bool.grpc.pb.h"
#include "v1/primitives/int.grpc.pb.h"
#include "v1/primitives/string.grpc.pb.h"
#include "v1/collections/list.grpc.pb.h"
class RediskaBasicTest : public ::testing::Test {
protected:
void SetUp() override {
channel_ = grpc::CreateChannel(grpc::InsecureChannel("localhost:50051"));
bool_stub_ = std::make_unique<v1::primitives::boolean::BoolCacheService::Stub>(channel_);
int_stub_ = std::make_unique<v1::primitives::integer::IntCacheService::Stub>(channel_);
string_stub_ = std::make_unique<v1::primitives::str::StringCacheService::Stub>(channel_);
list_stub_ = std::make_unique<v1::collections::list::ListCacheService::Stub>(channel_);
}
void TearDown() override {
channel_->Shutdown();
}
std::shared_ptr<grpc::Channel> channel_;
std::unique_ptr<v1::primitives::boolean::BoolCacheService::Stub> bool_stub_;
std::unique_ptr<v1::primitives::integer::IntCacheService::Stub> int_stub_;
std::unique_ptr<v1::primitives::str::StringCacheService::Stub> string_stub_;
std::unique_ptr<v1::collections::list::ListCacheService::Stub> list_stub_;
};
TEST_F(RediskaBasicTest, BooleanOperations) {
// Test SET operation
bool_stub_->Set(v1::primitives::boolean::BoolSetRequest(id="test_bool", value=true));
// Test GET operation
auto response = bool_stub_->Get(v1::primitives::BoolGetRequest(id="test_bool"));
EXPECT_TRUE(response.value());
// Test DELETE operation
auto delete_response = bool_stub_->Delete(v1::primitives::BoolDeleteRequest(id="test_bool"));
EXPECT_TRUE(delete_response.removed_value());
}
TEST_F(RediskaBasicTest, IntegerOperations) {
// Test SET operation
int_stub_->Set(v1::primitives::integer::IntSetRequest(id="test_int", value=42));
// Test GET operation
auto response = int_stub_->Get(v1::primitives::integer::IntGetRequest(id="test_int"));
EXPECT_EQ(response.value(), 42);
// Test DELETE operation
auto delete_response = int_stub_->Delete(v1::primitives::integer::IntDeleteRequest(id="test_int"));
EXPECT_EQ(delete_response.removed_value(), 42);
}
TEST_F(RediskaBasicTest, StringOperations) {
// Test SET operation
string_stub_->Set(v1::primitives::str::StringSetRequest(id="test_string", value="hello"));
// Test GET operation
auto response = string_stub_->Get(v1::primitives::str::StringGetRequest(id="test_string"));
EXPECT_EQ(response.value(), "hello");
// Test DELETE operation
auto delete_response = string_stub_->Delete(v1::primitives::str::StringDeleteRequest(id="test_string"));
EXPECT_EQ(delete_response.removed_value(), "hello");
}
TEST_FediskaBasicTest, ListOperations) {
// Test CREATE operation
auto create_response = list_stub_->Create(v1::collections::list::ListCreateRequest(
element_kind=v1::collections::common::ElementKind::INT,
ttl_seconds=3600
));
std::string list_id = create_response.id;
// Test SET operation
std::vector<v1::collections::common::CollectionElement> elements;
elements.push_back(v1::collections::common::CollectionElement(integer=1));
elements.push_back(v1::collections::common::CollectionElement(integer=2));
elements.push_back(v1::collections::common::CollectionElement(integer=3));
list_stub_->Set(v1::collections::list::ListSetRequest(id=list_id, elements=elements));
// Test GET operation (streaming)
auto get_response = list_stub_->Get(v1::collections::list::ListGetRequest(id=list_id));
int count = 0;
for (auto element : get_response) {
EXPECT_EQ(element.integer(), count + 1);
count++;
}
EXPECT_EQ(count, 3);
// Test LENGTH operation
auto length_response = list_stub_->Length(v1::collections::list::ListLengthRequest(id=list_id));
EXPECT_EQ(length_response.length(), 3);
// Test DELETE operation
list_stub_->Delete(v1::collections::DeleteRequest(id=list_id));
}
TEST_FediskaBasicTest, ConcurrentOperations) {
const int num_threads = 10;
const int operations_per_thread = 100;
std::vector<std::thread> threads;
std::vector<std::exception_ptr<std::exception>> exceptions;
// Запускаем несколько потоков одновременно
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back([&, i, operations_per_thread]() {
try {
for (int j = 0; j < operations_per_thread; ++j) {
std::string key = "test_" + std::to_string(i * operations_per_thread + j);
if (j % 3 == 0) {
bool_stub_->Set(v1::primitives::boolean::BoolSetRequest(key, true));
} else if (j % 3 == 1) {
int_stub_->Set(v1::primitives::integer::IntSetRequest(key, j));
} else {
string_stub_->Set(v1::primitives::str::StringSetRequest(key, "value_" + std::to_string(j)));
}
}
} catch (const std::exception& e) {
exceptions.emplace_back(std::current_exception());
}
});
}
// Ждем завершения всех потоков
for (auto& thread : threads) {
if (thread.joinable()) {
thread.join();
}
}
// Проверяем, что не было исключений
EXPECT_TRUE(exceptions.empty());
}
TEST_FediskaBasicTest, ServerStability) {
// Тест на стабильность сервера при множественных запросов
const int num_requests = 1000;
for (int i = 0; i < num_requests; ++i) {
std::string key = "stability_test_" + std::to_string(i);
if (i % 4 == 0) {
bool_stub_->Set(v1::primitives::boolean::BoolSetRequest(key, true));
} else if (i % 4 == 1) {
int_stub_->Set(v1::primitives::integer::IntSetRequest(key, i));
} else if (i % 4 == 2) {
string_stub_->Set(v1::primitives::str::StringSetRequest(key, "value_" + std::to_string(i)));
} else {
list_stub_->Set(v1::collections::ListSetRequest(
id="list_" + std::to_string(i),
elements={
v1::collections::common::CollectionElement(integer=i)
}
));
}
if (i % 10 == 0) {
auto response = bool_stub_->Get(v1::primitives::boolean::BoolGetRequest(key));
EXPECT_TRUE(response.value());
}
}
}

39
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,39 @@
add_executable(unit_tests
main.cpp
)
target_link_libraries(unit_tests
PRIVATE
worker
cache
frontend
doctest::doctest
)
list(APPEND CMAKE_MODULE_PATH "${doctest_SOURCE_DIR}/scripts/cmake")
include(doctest)
list(POP_BACK CMAKE_MODULE_PATH)
doctest_discover_tests(unit_tests
TEST_PREFIX ""
TEST_SUFFIX ""
)
find_program(CPPCHECK_EXECUTABLE cppcheck)
if(CPPCHECK_EXECUTABLE)
add_test(
NAME static_analysis
COMMAND ${CPPCHECK_EXECUTABLE}
--enable=all
--std=c++23
--error-exitcode=1
--inline-suppr
${CMAKE_SOURCE_DIR}/rediska
)
set_tests_properties(static_analysis PROPERTIES
LABELS "static"
TIMEOUT 120
)
else()
message(WARNING "Cppcheck not found — skipping static analysis test")
endif()

39
tests/README.md Normal file
View File

@@ -0,0 +1,39 @@
# Creating a test group
1. **Create a new test file** \
Place it under `/tests/frontend/` or `/tests/backend/`, following the [naming convention](#naming-convention) below.
2. **Include the testing framework** \
Add the following at the top of the file:
```C++
#include <doctest/doctest.h>
```
3. **Register the file in the build system** \
Add the new test file to `/tests/CMakeLists.txt` so its compiled and executed as part of the test suite.
4. **Start writing tests!** \
See [doctest docs](https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md) for more details.
# Naming convention
File name should match against the following pattern:
`<module>_<feature>_<test_type>_tests.cpp`
Where:
- `<module>` - the component or subsystem under test.
- Backend modules: `cache` | `worker`
- Frontend modules: `work in progress`
- `<feature>` - a concise, kebab-case description of the specific functionality.
- `<test_type>` - one of the following:
- `unit`
- `integration`
- `e2e`
# Examples
| Path | Description |
| :--------------------------------------------- | :------------------------------------------------------------- |
| `backend/cache_lru_unit_tests.cpp` | Unit tests for LRU eviction logic in the cache module |
| `backend/worker_handle-request_unit_tests.cpp` | Unit tests for the request-handling logic in the worker module |

0
tests/backend/.keep Normal file
View File

0
tests/frontend/.keep Normal file
View File

2
tests/main.cpp Normal file
View File

@@ -0,0 +1,2 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>