159 lines
6.6 KiB
C++
159 lines
6.6 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"
|
|
|
|
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("data/input/keys.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;
|
|
}
|