Files
aee-arcade/tests/test_scene_flow.cpp
T

160 lines
6.7 KiB
C++

// Smoke tests dels helpers purs del flux d'escenes: parser de debug.yaml i
// classificació de tecles reservades. Stand-alone, sense frameworks externs.
//
// Tests coberts:
// T1 parseStartScene — "LOGO"/"TITLE"/"INTRO"/"GAME" donen l'enum correcte.
// T2 parseStartScene — valor desconegut o fitxer buit → GAME (fallback).
// T3 parseStartScene — YAML invàlid no llança, cau a GAME.
// T4 resolveStartScene — fitxer inexistent → GAME sense crash.
// T5 resolveStartScene — fitxer real amb valor vàlid és respectat.
// T6 resolveStartScene — fitxer real amb valor invàlid → GAME.
// T7 isReservedScancode — F1/F12/Escape reservats després de KeyConfig::load.
// T8 isReservedScancode — SPACE i fletxes no són reservades.
// T9 isReservedScancode — SDL_SCANCODE_UNKNOWN sempre fals.
//
// La lògica d'update/render dels placeholders (transició per timeout o
// keypress) no es testeja ací perquè `update()` crida GlobalInputs, que
// arrossega Screen/Notifier/RenderInfo i tot l'stack SDL. Aquesta integració
// la cobreix el smoke run del binari sota xvfb-run.
//
// Execució:
// make build && cd build && ctest --output-on-failure
// O bé:
// ./build/test_scene_flow
#include <SDL3/SDL.h>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include "core/input/key_config.hpp"
#include "game/debug_config.hpp"
#include "game/scenes/placeholder_input.hpp"
#include "utils/defaults.hpp"
namespace {
int g_failures = 0;
void check(bool cond, const char* msg, const char* file, int line) {
if (!cond) {
std::cerr << " FAIL: " << msg << " (" << file << ":" << line << ")\n";
++g_failures;
}
}
#define CHECK(cond) check((cond), #cond, __FILE__, __LINE__)
void writeTemp(const std::string& path, const std::string& content) {
std::ofstream file(path);
file << content;
}
void testParseStartSceneValid() {
std::cout << "T1 parseStartScene valid\n";
CHECK(DebugConfig::parseStartScene("start_scene: LOGO") == DebugConfig::StartScene::LOGO);
CHECK(DebugConfig::parseStartScene("start_scene: TITLE") == DebugConfig::StartScene::TITLE);
CHECK(DebugConfig::parseStartScene("start_scene: INTRO") == DebugConfig::StartScene::INTRO);
CHECK(DebugConfig::parseStartScene("start_scene: GAME") == DebugConfig::StartScene::GAME);
}
void testParseStartSceneFallback() {
std::cout << "T2 parseStartScene fallback\n";
CHECK(DebugConfig::parseStartScene("") == DebugConfig::StartScene::GAME);
CHECK(DebugConfig::parseStartScene("start_scene: FOO") == DebugConfig::StartScene::GAME);
CHECK(DebugConfig::parseStartScene("other_field: 42") == DebugConfig::StartScene::GAME);
}
void testParseStartSceneInvalidYaml() {
std::cout << "T3 parseStartScene YAML invàlid\n";
// Text amb caràcters que fan petar el parser: indentació incoherent +
// claus desbalancejades. Si el nostre try/catch no està bé, això
// propagaria una excepció i trencaria el test.
CHECK(DebugConfig::parseStartScene("{{{unclosed: [") == DebugConfig::StartScene::GAME);
}
void testResolveStartSceneMissing() {
std::cout << "T4 resolveStartScene fitxer inexistent\n";
CHECK(DebugConfig::resolveStartScene("/tmp/aee_arcade_nonexistent_XYZ.yaml") == DebugConfig::StartScene::GAME);
}
void testResolveStartSceneValid() {
std::cout << "T5 resolveStartScene fitxer vàlid\n";
const auto PATH = std::filesystem::temp_directory_path() / "aee_arcade_test_debug_valid.yaml";
writeTemp(PATH.string(), "start_scene: TITLE\n");
CHECK(DebugConfig::resolveStartScene(PATH.string()) == DebugConfig::StartScene::TITLE);
std::filesystem::remove(PATH);
}
void testResolveStartSceneInvalid() {
std::cout << "T6 resolveStartScene valor invàlid\n";
const auto PATH = std::filesystem::temp_directory_path() / "aee_arcade_test_debug_invalid.yaml";
writeTemp(PATH.string(), "start_scene: WUT\n");
CHECK(DebugConfig::resolveStartScene(PATH.string()) == DebugConfig::StartScene::GAME);
std::filesystem::remove(PATH);
}
void testCreateDefaultIfMissing() {
std::cout << "T7 createDefaultIfMissing\n";
const auto PATH = std::filesystem::temp_directory_path() / "aee_arcade_test_debug_create.yaml";
std::filesystem::remove(PATH);
CHECK(!std::filesystem::exists(PATH));
DebugConfig::createDefaultIfMissing(PATH.string());
CHECK(std::filesystem::exists(PATH));
CHECK(DebugConfig::resolveStartScene(PATH.string()) == DebugConfig::StartScene::GAME);
// Segona invocació: ha de ser idempotent (no reescriu si ja existeix).
writeTemp(PATH.string(), "start_scene: LOGO\n");
DebugConfig::createDefaultIfMissing(PATH.string());
CHECK(DebugConfig::resolveStartScene(PATH.string()) == DebugConfig::StartScene::LOGO);
std::filesystem::remove(PATH);
}
void testIsReservedScancodeAfterLoad() {
std::cout << "T8 isReservedScancode després de KeyConfig::load\n";
KeyConfig::get().load(Defaults::Paths::INPUT_YAML);
CHECK(Placeholder::isReservedScancode(SDL_SCANCODE_F1));
CHECK(Placeholder::isReservedScancode(SDL_SCANCODE_F12));
CHECK(Placeholder::isReservedScancode(SDL_SCANCODE_ESCAPE));
}
void testIsReservedScancodeNonReserved() {
std::cout << "T9 isReservedScancode per tecles no reservades\n";
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_SPACE));
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_RETURN));
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_UP));
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_DOWN));
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_LEFT));
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_RIGHT));
}
void testIsReservedScancodeUnknown() {
std::cout << "T10 isReservedScancode amb UNKNOWN\n";
CHECK(!Placeholder::isReservedScancode(SDL_SCANCODE_UNKNOWN));
}
} // namespace
auto main() -> int {
testParseStartSceneValid();
testParseStartSceneFallback();
testParseStartSceneInvalidYaml();
testResolveStartSceneMissing();
testResolveStartSceneValid();
testResolveStartSceneInvalid();
testCreateDefaultIfMissing();
testIsReservedScancodeAfterLoad();
testIsReservedScancodeNonReserved();
testIsReservedScancodeUnknown();
if (g_failures == 0) {
std::cout << "OK: tots els tests de scene flow passen\n";
return 0;
}
std::cerr << g_failures << " tests han fallat\n";
return 1;
}