/
smychkov
/
SStorage
Обзор
Документация
Войти
/
smychkov
/
SStorage
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/test_sstable_corrupt.cpp
124 строки
4 KB
Андрей Смычков
feat: SSTable writer + reader with atomic writes
25 апр 2026, 09:09
25 апр 2026, 09:09
79efb83
Код
Авторство
О чём код?
//============================================================================ // Тесты на устойчивость SSTable reader к повреждённым файлам //============================================================================ #include "../src/sstable/sstable_writer.hpp" #include "../src/sstable/sstable_reader.hpp" #include <cstdlib> #include <filesystem> #include <fstream> #include <iostream> #include <string> #include <unistd.h> 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) static std::string makeTempPath(const std::string& prefix) { return "/tmp/sstorage_" + prefix + "_" + std::to_string(::getpid()) + "_" + std::to_string(rand()) + ".sst"; } // Создать валидный SSTable и вернуть путь static std::string createValidSSTable(const std::string& prefix) { auto path = makeTempPath(prefix); SSTableWriter w(path, 256); // маленькие блоки w.open(); for (int i = 0; i < 20; ++i) { w.add(Record("key_" + std::to_string(i), "value_" + std::to_string(i), i)); } w.finish(); return path; } // Перезаписать N байт в файле начиная с offset значением 'X' static void corruptFile(const std::string& path, size_t offset, size_t nBytes) { std::fstream f(path, std::ios::binary | std::ios::in | std::ios::out); f.seekp(offset); std::string garbage(nBytes, 'X'); f.write(garbage.data(), nBytes); } // Обрезать файл до указанного размера static void truncateFile(const std::string& path, size_t newSize) { ::truncate(path.c_str(), newSize); } int main() { // 1. Обрезанный файл (короче footer) { auto path = createValidSSTable("short"); truncateFile(path, 30); // меньше 64 байт footer SSTableReader r(path); CHECK(!r.open()); std::filesystem::remove(path); } // 2. Битый footer magic { auto path = createValidSSTable("magic"); size_t size = std::filesystem::file_size(path); corruptFile(path, size - 8, 8); // магия в конце SSTableReader r(path); CHECK(!r.open()); std::filesystem::remove(path); } // 3. Битый footer CRC (портим поле) { auto path = createValidSSTable("fcrc"); size_t size = std::filesystem::file_size(path); corruptFile(path, size - kFooterSize, 1); // портим первый байт footer SSTableReader r(path); CHECK(!r.open()); std::filesystem::remove(path); } // 4. Битый data block (CRC блока) { auto path = createValidSSTable("bcrc"); // Первые несколько байт файла — начало первого блока corruptFile(path, kBlockHeaderSize + 2, 1); SSTableReader r(path); CHECK(r.open()); // footer ещё валиден // Но чтение данных должно вернуть nullopt auto rec = r.find("key_0"); CHECK(!rec.has_value()); std::filesystem::remove(path); } // 5. Несуществующий файл { SSTableReader r("/tmp/does_not_exist_xyz.sst"); CHECK(!r.open()); } // 6. Полностью мусорный файл (64+ байт) { auto path = makeTempPath("garbage"); { std::ofstream f(path, std::ios::binary); std::string garbage(200, 'Z'); f.write(garbage.data(), garbage.size()); } SSTableReader r(path); CHECK(!r.open()); std::filesystem::remove(path); } std::cout << "test_sstable_corrupt: passed=" << g_passed << " failed=" << g_failed << "\n"; return g_failed == 0 ? 0 : 1; }