/* tests.c -- rangkaian test sederhana untuk modul calculator.
 *
 * Tiap test memanggil kalkulator_hitung lalu membandingkan hasil dengan
 * nilai yang diharapkan. Jika ada test yang gagal, program keluar dengan
 * kode bukan nol.
 */

#include "calculator.h"

#include <stdio.h>
#include <math.h>
#include <string.h>

static int test_lulus = 0;
static int test_gagal = 0;

/* Pembanding aman untuk bilangan double. */
static int hampir_sama(double a, double b) {
    return fabs(a - b) < 1e-9;
}

/* Macro untuk mencatat dan melaporkan hasil test. */
#define PERIKSA(kondisi, nama)                                  \
    do {                                                        \
        if (kondisi) {                                          \
            test_lulus++;                                       \
            printf("[LULUS] %s\n", nama);                       \
        } else {                                                \
            test_gagal++;                                       \
            printf("[GAGAL] %s\n", nama);                       \
        }                                                       \
    } while (0)

static void test_tambah(void) {
    double hasil = 0.0;
    CalcStatus s = kalkulator_hitung(OP_TAMBAH, 5.0, 3.0, &hasil);
    PERIKSA(s == CALC_OK && hampir_sama(hasil, 8.0), "Tambah 5 + 3 = 8");
}

static void test_kurang(void) {
    double hasil = 0.0;
    CalcStatus s = kalkulator_hitung(OP_KURANG, 10.0, 4.0, &hasil);
    PERIKSA(s == CALC_OK && hampir_sama(hasil, 6.0), "Kurang 10 - 4 = 6");
}

static void test_kali(void) {
    double hasil = 0.0;
    CalcStatus s = kalkulator_hitung(OP_KALI, 2.5, 4.0, &hasil);
    PERIKSA(s == CALC_OK && hampir_sama(hasil, 10.0), "Kali 2.5 * 4 = 10");
}

static void test_bagi(void) {
    double hasil = 0.0;
    CalcStatus s = kalkulator_hitung(OP_BAGI, 10.0, 4.0, &hasil);
    PERIKSA(s == CALC_OK && hampir_sama(hasil, 2.5), "Bagi 10 / 4 = 2.5");
}

static void test_bagi_nol(void) {
    double hasil = 0.0;
    CalcStatus s = kalkulator_hitung(OP_BAGI, 5.0, 0.0, &hasil);
    PERIKSA(s == CALC_ERR_BAGI_NOL, "Bagi dengan nol menolak");
}

static void test_label_dan_simbol(void) {
    PERIKSA(strcmp(kalkulator_label(OP_TAMBAH), "Tambah") == 0,
           "Label OP_TAMBAH = \"Tambah\"");
    PERIKSA(strcmp(kalkulator_simbol(OP_BAGI), "/") == 0,
           "Simbol OP_BAGI = \"/\"");
}

int main(void) {
    test_tambah();
    test_kurang();
    test_kali();
    test_bagi();
    test_bagi_nol();
    test_label_dan_simbol();

    printf("\nRingkasan: %d lulus, %d gagal\n", test_lulus, test_gagal);
    return test_gagal == 0 ? 0 : 1;
}
