#include #include #include #include "../src/narrative.h" static const char *slurp(FILE *f) { static char buf[4096]; long len = ftell(f); rewind(f); size_t n = fread(buf, 1, (size_t)len, f); buf[n] = '\0'; return buf; } static void test_hard_aspect_shows_base_but_not_harmonious_bonus(void) { Aspect a = { .transiting_planet = PLANET_SATURN, .natal_planet = PLANET_MOON, .type = ASPECT_SQUARE, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 0); const char *text = slurp(f); assert(strstr(text, "depression") != NULL); assert(strstr(text, "past associations") == NULL); fclose(f); printf("PASS test_hard_aspect_shows_base_but_not_harmonious_bonus\n"); } static void test_soft_aspect_adds_harmonious_bonus(void) { Aspect a = { .transiting_planet = PLANET_SATURN, .natal_planet = PLANET_SUN, .type = ASPECT_TRINE, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 0); const char *text = slurp(f); assert(strstr(text, "depression") != NULL); assert(strstr(text, "past associations") != NULL); fclose(f); printf("PASS test_soft_aspect_adds_harmonious_bonus\n"); } static void test_conjunction_is_neutral_prints_base_only(void) { Aspect a = { .transiting_planet = PLANET_SATURN, .natal_planet = PLANET_SUN, .type = ASPECT_CONJUNCTION, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 0); const char *text = slurp(f); assert(strstr(text, "depression") != NULL); assert(strstr(text, "past associations") == NULL); fclose(f); printf("PASS test_conjunction_is_neutral_prints_base_only\n"); } /* The Sun has no unconditional base text (see narrative.c) - a neutral * conjunction to it should print nothing at all. */ static void test_empty_base_and_neutral_aspect_prints_nothing(void) { Aspect a = { .transiting_planet = PLANET_SUN, .natal_planet = PLANET_MOON, .type = ASPECT_CONJUNCTION, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 0); long len = ftell(f); assert(len == 0); fclose(f); printf("PASS test_empty_base_and_neutral_aspect_prints_nothing\n"); } static void test_discordant_aspect_on_empty_base_planet(void) { Aspect a = { .transiting_planet = PLANET_SUN, .natal_planet = PLANET_MOON, .type = ASPECT_OPPOSITION, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 0); const char *text = slurp(f); assert(strstr(text, "Degradation") != NULL); fclose(f); printf("PASS test_discordant_aspect_on_empty_base_planet\n"); } static void test_known_house_adds_area_framing(void) { Aspect a = { .transiting_planet = PLANET_SATURN, .natal_planet = PLANET_MOON, .type = ASPECT_SQUARE, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 3); const char *text = slurp(f); assert(strstr(text, "house 3") != NULL); assert(strstr(text, "communication") != NULL); assert(strstr(text, "depression") != NULL); fclose(f); printf("PASS test_known_house_adds_area_framing\n"); } static void test_unknown_house_omits_area_framing(void) { Aspect a = { .transiting_planet = PLANET_SATURN, .natal_planet = PLANET_MOON, .type = ASPECT_SQUARE, .orb = 1.0 }; FILE *f = tmpfile(); narrative_print(f, " ", &a, 0); /* 0 = "no data" sentinel, not a real house */ const char *text = slurp(f); assert(strstr(text, "house") == NULL); assert(strstr(text, "depression") != NULL); fclose(f); printf("PASS test_unknown_house_omits_area_framing\n"); } int main(void) { test_hard_aspect_shows_base_but_not_harmonious_bonus(); test_soft_aspect_adds_harmonious_bonus(); test_conjunction_is_neutral_prints_base_only(); test_empty_base_and_neutral_aspect_prints_nothing(); test_discordant_aspect_on_empty_base_planet(); test_known_house_adds_area_framing(); test_unknown_house_omits_area_framing(); printf("All narrative tests passed.\n"); return 0; }