upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests/unit/test_mint_health.c
blob: d170d55be7a35f43a239ffa7983bbc37293cfdfa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "mint_health.h"

static int test_count = 0;
static int pass_count = 0;

#define TEST(name) do { \
    test_count++; \
    printf("  TEST: %s ... ", name); \
} while(0)

#define PASS() do { \
    pass_count++; \
    printf("PASS\n"); \
} while(0)

#define FAIL(msg) do { \
    printf("FAIL: %s\n", msg); \
} while(0)

#define ASSERT_EQ(a, b, msg) do { \
    if ((a) != (b)) { FAIL(msg); return; } \
} while(0)

#define ASSERT_TRUE(a, msg) do { \
    if (!(a)) { FAIL(msg); return; } \
} while(0)

#define ASSERT_FALSE(a, msg) do { \
    if ((a)) { FAIL(msg); return; } \
} while(0)

static void test_init_basic(void) {
    TEST("init with 4 mints");
    const char urls[4][256] = {
        "https://mint.minibits.cash/Bitcoin",
        "https://mint.coinos.io",
        "https://21mint.me",
        "https://mint.lnvoltz.com"
    };
    esp_err_t err = mint_health_init(urls, 4);
    ASSERT_EQ(err, 0, "init should return ESP_OK");
    PASS();
}

static void test_get_all(void) {
    TEST("get_all returns correct count");
    int count = 0;
    const mint_status_t *mints = mint_health_get_all(&count);
    ASSERT_EQ(count, 4, "should have 4 mints");
    ASSERT_TRUE(mints != NULL, "mints should not be NULL");
    PASS();
}

static void test_initial_state_unreachable(void) {
    TEST("initial state: all mints unreachable (no probes run)");
    const char *expected_urls[] = {
        "https://mint.minibits.cash/Bitcoin",
        "https://mint.coinos.io",
        "https://21mint.me",
        "https://mint.lnvoltz.com"
    };
    int count = 0;
    const mint_status_t *mints = mint_health_get_all(&count);
    ASSERT_EQ(count, 4, "should have 4 mints");
    for (int i = 0; i < count; i++) {
        ASSERT_FALSE(mints[i].reachable, "initial mint should be unreachable");
        ASSERT_EQ(mints[i].consecutive_successes, 0, "initial successes should be 0");
        ASSERT_TRUE(strcmp(mints[i].url, expected_urls[i]) == 0, "URL mismatch");
    }
    PASS();
}

static void test_is_reachable_before_probes(void) {
    TEST("is_reachable returns false before probes");
    bool r = mint_health_is_reachable("https://mint.minibits.cash/Bitcoin");
    ASSERT_FALSE(r, "should be unreachable before probes");
    PASS();
}

static void test_is_reachable_null(void) {
    TEST("is_reachable returns false for NULL");
    bool r = mint_health_is_reachable(NULL);
    ASSERT_FALSE(r, "NULL should return false");
    PASS();
}

static void test_is_reachable_unknown_url(void) {
    TEST("is_reachable returns false for unknown URL");
    bool r = mint_health_is_reachable("https://unknown.mint.example.com");
    ASSERT_FALSE(r, "unknown URL should return false");
    PASS();
}

static void test_mark_unreachable(void) {
    TEST("mark_unreachable on already-unreachable mint");
    mint_health_mark_unreachable("https://mint.coinos.io");
    bool r = mint_health_is_reachable("https://mint.coinos.io");
    ASSERT_FALSE(r, "should still be unreachable");
    PASS();
}

static void test_mark_unreachable_null(void) {
    TEST("mark_unreachable with NULL does not crash");
    mint_health_mark_unreachable(NULL);
    PASS();
}

static void test_init_overflow(void) {
    TEST("init with more than MAX mints truncates");
    const char urls[MINT_HEALTH_MAX + 2][256];
    for (int i = 0; i < MINT_HEALTH_MAX + 2; i++) {
        snprintf((char *)urls[i], 256, "https://mint%d.example.com", i);
    }
    esp_err_t err = mint_health_init(urls, MINT_HEALTH_MAX + 2);
    ASSERT_EQ(err, 0, "init should succeed");

    int count = 0;
    mint_health_get_all(&count);
    ASSERT_EQ(count, MINT_HEALTH_MAX, "should be truncated to MAX");
    PASS();
}

static void test_init_empty(void) {
    TEST("init with 0 mints");
    esp_err_t err = mint_health_init(NULL, 0);
    ASSERT_EQ(err, 0, "init with 0 should succeed");

    int count = -1;
    mint_health_get_all(&count);
    ASSERT_EQ(count, 0, "should have 0 mints");
    PASS();
}

static void dummy_cb(void) { }

static void test_register_callback(void) {
    TEST("register_callback does not crash");
    mint_health_register_callback(dummy_cb);
    PASS();
}

static void test_register_callback_null(void) {
    TEST("register_callback NULL does not crash");
    mint_health_register_callback(NULL);
    PASS();
}

static void test_reinit_resets_state(void) {
    TEST("re-init resets state");
    const char urls[2][256] = {
        "https://mint-a.example.com",
        "https://mint-b.example.com"
    };
    mint_health_init(urls, 2);

    int count = 0;
    const mint_status_t *mints = mint_health_get_all(&count);
    ASSERT_EQ(count, 2, "should have 2 mints");
    ASSERT_TRUE(strcmp(mints[0].url, "https://mint-a.example.com") == 0, "first URL");
    ASSERT_TRUE(strcmp(mints[1].url, "https://mint-b.example.com") == 0, "second URL");
    PASS();
}

static void test_start_stop(void) {
    TEST("start/stop do not crash (task stubbed)");
    mint_health_start();
    mint_health_stop();
    PASS();
}

int main(void) {
    printf("\n=== Mint Health Unit Tests ===\n\n");

    test_init_basic();
    test_get_all();
    test_initial_state_unreachable();
    test_is_reachable_before_probes();
    test_is_reachable_null();
    test_is_reachable_unknown_url();
    test_mark_unreachable();
    test_mark_unreachable_null();
    test_init_overflow();
    test_init_empty();
    test_register_callback();
    test_register_callback_null();
    test_reinit_resets_state();
    test_start_stop();

    printf("\n=== Results: %d passed, %d failed ===\n\n", pass_count, test_count - pass_count);
    return (pass_count == test_count) ? 0 : 1;
}