/
smychkov
/
SStorage
Обзор
Документация
Войти
/
smychkov
/
SStorage
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/test_block_cache.cpp
134 строки
4 KB
Андрей Смычков
feat: LSM tree with levels, flush, compaction, recovery, block cache
25 апр 2026, 09:14
25 апр 2026, 09:14
4631f83
Код
Авторство
О чём код?
//============================================================================ // Тесты для BlockCache (LRU, eviction, invalidate) //============================================================================ #include "../src/cache/block_cache.hpp" #include <iostream> #include <memory> #include <string> #include <thread> #include <vector> using namespace sstorage; static int g_passed = 0; static int g_failed = 0; #define CHECK(cond) do { \ if (cond) { ++g_passed; } \ else { ++g_failed; std::cerr << "FAIL: " #cond " at line " << __LINE__ << "\n"; } \ } while (0) // Helper: создать блок заданного размера static std::shared_ptr<const std::string> makeBlock(size_t size, char fill = 'A') { return std::make_shared<std::string>(size, fill); } int main() { // 1. Пустой кэш — miss { BlockCache c(1024); CHECK(c.get("file", 0) == nullptr); CHECK(c.count() == 0); CHECK(c.currentBytes() == 0); } // 2. put + get { BlockCache c(10000); auto block = makeBlock(100); c.put("file", 0, block); auto got = c.get("file", 0); CHECK(got != nullptr); CHECK(got->size() == 100); CHECK(c.count() == 1); CHECK(c.currentBytes() == 100); } // 3. Несколько ключей { BlockCache c(10000); c.put("file1", 0, makeBlock(100)); c.put("file1", 1000, makeBlock(200)); c.put("file2", 0, makeBlock(300)); CHECK(c.count() == 3); CHECK(c.currentBytes() == 600); CHECK(c.get("file1", 0)->size() == 100); CHECK(c.get("file1", 1000)->size() == 200); CHECK(c.get("file2", 0)->size() == 300); } // 4. LRU eviction { BlockCache c(300); // capacity 300 c.put("f", 0, makeBlock(100, 'A')); c.put("f", 1, makeBlock(100, 'B')); c.put("f", 2, makeBlock(100, 'C')); CHECK(c.count() == 3); CHECK(c.currentBytes() == 300); // Дотрагиваемся до 0 — теперь 1 стал самый старый CHECK(c.get("f", 0) != nullptr); // Добавляем новый — вытеснится 1 (LRU) c.put("f", 3, makeBlock(100, 'D')); CHECK(c.count() == 3); CHECK(c.get("f", 0) != nullptr); // остался CHECK(c.get("f", 1) == nullptr); // вытеснен CHECK(c.get("f", 2) != nullptr); // остался CHECK(c.get("f", 3) != nullptr); // новый } // 5. Обновление существующего ключа { BlockCache c(10000); c.put("f", 0, makeBlock(100)); c.put("f", 0, makeBlock(200)); CHECK(c.count() == 1); CHECK(c.currentBytes() == 200); CHECK(c.get("f", 0)->size() == 200); } // 6. invalidateFile { BlockCache c(10000); c.put("f1", 0, makeBlock(100)); c.put("f1", 1, makeBlock(100)); c.put("f2", 0, makeBlock(100)); c.invalidateFile("f1"); CHECK(c.count() == 1); CHECK(c.get("f1", 0) == nullptr); CHECK(c.get("f2", 0) != nullptr); } // 7. clear { BlockCache c(10000); c.put("f", 0, makeBlock(100)); c.put("f", 1, makeBlock(100)); c.clear(); CHECK(c.count() == 0); CHECK(c.currentBytes() == 0); } // 8. Concurrency: параллельные put/get не крашат { BlockCache c(100000); std::vector<std::thread> threads; for (int t = 0; t < 8; ++t) { threads.emplace_back([&, t]() { for (int i = 0; i < 500; ++i) { auto block = makeBlock(50); c.put("file_" + std::to_string(t), i, block); c.get("file_" + std::to_string(t), i); } }); } for (auto& th : threads) th.join(); CHECK(c.currentBytes() <= 100000); // не превысили capacity } std::cout << "test_block_cache: passed=" << g_passed << " failed=" << g_failed << "\n"; return g_failed == 0 ? 0 : 1; }