/* Mini marco de pruebas (solo cabecera). Cada CHECK que falla se cuenta e imprime. */ #ifndef TGB_TEST_H #define TGB_TEST_H #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include "tahgibu/tahgibu.h" #pragma GCC diagnostic ignored "-Wunused-function" /* no todas las pruebas usan todos los ayudantes */ static int g_fail = 0, g_checks = 0; #define CHECK(cond) do { g_checks++; if (!(cond)) { g_fail++; printf(" FALLO %s:%d: %s\n", __FILE__, __LINE__, #cond); } } while (0) #define CHECK_EQ(a, b) do { long long _a = (long long)(a), _b = (long long)(b); g_checks++; \ if (_a != _b) { g_fail++; printf(" FALLO %s:%d: %s == %s (%lld != %lld)\n", __FILE__, __LINE__, #a, #b, _a, _b); } } while (0) /* Espera un estado concreto (éxito = TGB_OK). */ #define CHECK_STATUS(expr, expected) do { tgb_status _s = (expr); g_checks++; \ if (_s != (expected)) { g_fail++; printf(" FALLO %s:%d: %s devolvió %s, se esperaba %s (%s)\n", __FILE__, __LINE__, #expr, \ tgb_status_name(_s), tgb_status_name(expected), tgb_last_error()); } } while (0) #define CHECK_OK(expr) CHECK_STATUS(expr, TGB_OK) #define TEST(name) static void name(void) #define RUN(name) do { int _before = g_fail; name(); printf("%s %s\n", g_fail == _before ? "[ok] " : "[FALLO]", #name); } while (0) #define TEST_SUMMARY() do { printf("\n%d comprobaciones, %d fallos\n", g_checks, g_fail); return g_fail ? 1 : 0; } while (0) static int _rm_cb(const char *path, const struct stat *sb, int flag, struct FTW *ftw) { (void)sb; (void)flag; (void)ftw; return remove(path); } static void tgb_test_rmtree(const char *root) { nftw(root, _rm_cb, 16, FTW_DEPTH | FTW_PHYS); } /* Crea un contexto cuyas carpetas viven en un directorio temporal propio. */ static tgb_context *tgb_test_context(char *root, size_t cap) { char tmpl[] = "/tmp/tgb-test-XXXXXX"; if (!mkdtemp(tmpl)) { printf("no se pudo crear carpeta temporal\n"); exit(2); } snprintf(root, cap, "%s", tmpl); char c[600], d[600], k[600], s[600]; snprintf(c, sizeof c, "%s/config", root); snprintf(d, sizeof d, "%s/data", root); snprintf(k, sizeof k, "%s/cache", root); snprintf(s, sizeof s, "%s/state", root); tgb_context_config cfg = {c, d, k, s}; tgb_context *ctx = NULL; if (tgb_context_create(&cfg, &ctx) != TGB_OK) { printf("contexto: %s\n", tgb_last_error()); exit(2); } return ctx; } /* Contexto sobre las MISMAS carpetas que otro (para simular otro proceso o un reinicio). */ static tgb_context *tgb_test_context_at(const char *root) { char c[600], d[600], k[600], s[600]; snprintf(c, sizeof c, "%s/config", root); snprintf(d, sizeof d, "%s/data", root); snprintf(k, sizeof k, "%s/cache", root); snprintf(s, sizeof s, "%s/state", root); tgb_context_config cfg = {c, d, k, s}; tgb_context *ctx = NULL; if (tgb_context_create(&cfg, &ctx) != TGB_OK) { printf("contexto: %s\n", tgb_last_error()); exit(2); } return ctx; } static const tgb_color RED = {255, 0, 0, 255}, BLUE = {0, 0, 255, 255}, BLACK = {0, 0, 0, 255}, GREEN = {0, 255, 0, 255}; static size_t count_alpha(const tgb_canvas *c) { size_t n = 0; for (int y = 0; y < tgb_canvas_height(c); y++) for (int x = 0; x < tgb_canvas_width(c); x++) if (tgb_canvas_get(c, x, y).a) n++; return n; } static bool is_px(const tgb_canvas *c, int x, int y, tgb_color col) { tgb_color p = tgb_canvas_get(c, x, y); return p.r == col.r && p.g == col.g && p.b == col.b && p.a == col.a; } /* Dibuja un punto en la celda (frame_index, layer_index) con sesión de edición. */ static tgb_status paint_px(tgb_document *doc, size_t f, size_t l, int x, int y, tgb_color col) { tgb_status s = tgb_edit_begin(doc, tgb_frame_id(doc, f), tgb_layer_id(doc, l), "Punto"); if (s != TGB_OK) return s; tgb_canvas_set(tgb_edit_canvas(doc), x, y, col); return tgb_edit_end(doc); } static tgb_color px_at(const tgb_document *doc, size_t f, size_t l, int x, int y) { return tgb_canvas_get(tgb_frame_cel(doc, f, l), x, y); } #endif