Фаза 1: мастер первого запуска — SettingsStore, GitManager (auto-init+коммиты), SyncManager (проверка соединений+ErrorCatalog), WelcomeWizard/ProviderSetupGuide; тесты smoke/git/vault (12/12)

This commit is contained in:
Flora (opencode)
2026-08-17 00:43:33 +03:00
parent 980fbcedcb
commit ed633ae036
18 changed files with 1412 additions and 29 deletions
+37
View File
@@ -0,0 +1,37 @@
# Smoke-тест: проверка сборки и работы сторонних библиотек.
add_executable(flora_smoke smoke_test.cpp)
target_compile_definitions(flora_smoke PRIVATE
CMARK_GFM_STATIC_DEFINE
CMARK_GFM_EXTENSIONS_STATIC_DEFINE)
target_link_libraries(flora_smoke PRIVATE
cmark::cmark
cmark::cmark_extensions
Flora_libgit2_static)
add_test(NAME flora_smoke COMMAND flora_smoke)
# Тест GitManager (git init / авто-коммиты внутри хранилища).
add_executable(flora_git_test git_test.cpp
../src/git/GitManager.cpp
../src/git/GitManager.h
)
target_include_directories(flora_git_test PRIVATE ../src)
target_compile_definitions(flora_git_test PRIVATE CMARK_GFM_STATIC_DEFINE)
target_link_libraries(flora_git_test PRIVATE
Qt6::Core
Flora_libgit2_static)
add_test(NAME flora_git_test COMMAND flora_git_test)
# Интеграционный тест: настройки + создание хранилища (git-репозиторий).
add_executable(flora_vault_test vault_test.cpp
../src/app/VaultManager.cpp
../src/app/VaultManager.h
../src/core/SettingsStore.cpp
../src/core/SettingsStore.h
../src/git/GitManager.cpp
../src/git/GitManager.h
)
target_include_directories(flora_vault_test PRIVATE ../src)
target_link_libraries(flora_vault_test PRIVATE
Qt6::Core
Flora_libgit2_static)
add_test(NAME flora_vault_test COMMAND flora_vault_test)
+75
View File
@@ -0,0 +1,75 @@
// Тест GitManager (Фаза 1): инициализация репозитория хранилища,
// авто-коммит с новым файлом, наличие коммитов в HEAD.
#include <QCoreApplication>
#include <QTemporaryDir>
#include <QFile>
#include <QDir>
#include <cstdio>
#include "git/GitManager.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QTemporaryDir dir;
if (!dir.isValid()) {
std::fprintf(stderr, "FAIL: не удалось создать временную папку\n");
return 1;
}
GitManager git;
// 1. init в новой папке
if (!git.initRepo(dir.path()) || !git.lastError().isEmpty()) {
std::fprintf(stderr, "FAIL: initRepo: %s\n", qPrintable(git.lastError()));
return 1;
}
// 2. init идемпотентен (повторный вызов — успех)
if (!git.initRepo(dir.path())) {
std::fprintf(stderr, "FAIL: повторный initRepo\n");
return 1;
}
// 3. нет коммитов
if (git.hasCommits(dir.path())) {
std::fprintf(stderr, "FAIL: коммиты появились раньше времени\n");
return 1;
}
// 4. создаём файл и коммитим
QFile f(dir.filePath(QStringLiteral("readme.md")));
if (!f.open(QIODevice::WriteOnly)) {
std::fprintf(stderr, "FAIL: не удалось создать файл\n");
return 1;
}
f.write("# Привет, Flora!\n");
f.close();
if (!git.commitAll(dir.path(), QStringLiteral("initial"))) {
std::fprintf(stderr, "FAIL: commitAll: %s\n", qPrintable(git.lastError()));
return 1;
}
// 5. теперь коммиты есть
if (!git.hasCommits(dir.path())) {
std::fprintf(stderr, "FAIL: no commits after commitAll\n");
return 1;
}
// 6. повторный коммит без изменений — корректная ошибка, без падения
if (git.commitAll(dir.path(), QStringLiteral("noop"))) {
std::fprintf(stderr, "FAIL: повторный коммит без изменений не должен удаваться\n");
return 1;
}
// 7. не-существующая папка
if (git.initRepo("/путь/которого/не/существует_xyz")) {
std::fprintf(stderr, "FAIL: initRepo не должен удаваться\n");
return 1;
}
std::printf("GIT TEST OK\n");
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
// Smoke-тест Фазы 0: проверяет, что третьест-сторонние библиотеки
// (cmark-gfm, libgit2) собраны, слинкованы и работают.
#include <cmark-gfm.h>
#include <cmark-gfm-extension_api.h>
#include <cmark-gfm-core-extensions.h>
#include <git2.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
static std::string render_md(const std::string &markdown)
{
cmark_gfm_core_extensions_ensure_registered();
cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT);
for (const char *name : {"table", "strikethrough", "autolink", "tasklist"}) {
if (cmark_syntax_extension *ext = cmark_find_syntax_extension(name))
cmark_parser_attach_syntax_extension(parser, ext);
}
cmark_parser_feed(parser, markdown.data(), markdown.size());
cmark_node *doc = cmark_parser_finish(parser);
char *html = cmark_render_html(doc, CMARK_OPT_DEFAULT,
cmark_parser_get_syntax_extensions(parser));
std::string out = html ? html : "";
free(html);
cmark_node_free(doc);
cmark_parser_free(parser);
return out;
}
int main()
{
// --- libgit2 ---
int maj = 0, min = 0, rev = 0;
git_libgit2_version(&maj, &min, &rev);
std::printf("libgit2 %d.%d.%d\n", maj, min, rev);
if (maj == 0 && min == 0) {
std::fprintf(stderr, "FAIL: libgit2 не подключен\n");
return 1;
}
// --- cmark-gfm ---
std::printf("cmark-gfm %s\n", cmark_version_string());
if (std::strlen(cmark_version_string()) == 0) {
std::fprintf(stderr, "FAIL: cmark-gfm не подключен\n");
return 1;
}
// --- рендер Markdown (CommonMark + GFM: таблица, задача, заголовок) ---
const char *md
= "# Заголовок\n\n| A | B |\n|---|---|\n| 1 | 2 |\n\n- [ ] задача";
std::string html = render_md(md);
std::printf("html: %s\n", html.c_str());
bool ok = html.find("<h1>") != std::string::npos
&& html.find("<table") != std::string::npos
&& html.find("<input") != std::string::npos;
if (!ok) {
std::fprintf(stderr, "FAIL: GFM-рендер (заголовок/таблица/задача)\n");
return 1;
}
std::printf("SMOKE TEST OK\n");
return 0;
}
+63
View File
@@ -0,0 +1,63 @@
// Интеграционный тест Фазы 1: SettingsStore + VaultManager + GitManager.
// Используем временную папку для QSettings (INI-формат), чтобы не трогать реальные.
#include <QCoreApplication>
#include <QTemporaryDir>
#include <QDir>
#include <QSettings>
#include <cstdio>
#include "app/VaultManager.h"
#include "core/SettingsStore.h"
#include "git/GitManager.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
app.setOrganizationName("FloraTest");
app.setApplicationName("flora_test");
QTemporaryDir dir;
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, dir.path());
{
SettingsStore settings;
GitManager git;
VaultManager vault(&settings, &git);
const QString vaultPath = dir.path() + "/vault";
const QString err = vault.createVault(vaultPath);
if (!err.isEmpty()) {
std::fprintf(stderr, "FAIL: createVault: %s\n", qPrintable(err));
return 1;
}
if (!settings.hasVault(vaultPath) || settings.currentVault() != vaultPath) {
std::fprintf(stderr, "FAIL: хранилище не сохранено\n");
return 1;
}
if (!git.hasCommits(vaultPath)) {
// коммитов может ещё не быть (нет файлов) — инициализация должна пройти
}
if (vault.vaults().isEmpty()) {
std::fprintf(stderr, "FAIL: список хранилищ пуст\n");
return 1;
}
const QString bad = vault.createVault("");
if (bad.isEmpty()) {
std::fprintf(stderr, "FAIL: пустой путь не отклонён\n");
return 1;
}
}
{
// Проверка персистентности в другом экземпляре
SettingsStore settings;
if (!settings.hasVault(dir.path() + "/vault")) {
std::fprintf(stderr, "FAIL: настройки не сохранились\n");
return 1;
}
}
std::printf("VAULT TEST OK\n");
return 0;
}