upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tests/unit/test_client_core.c
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-23 15:26:52 +0530
committerYour Name <you@example.com>2026-05-23 15:26:52 +0530
commitbe4d490e96de3d20cc6c9921f09534cde0ca0765 (patch)
tree624cdbaff079e14a26fc22f7741a1452b54555b9 /tests/unit/test_client_core.c
parent4ce93d0470e8ab2402486c893f50bfdf216752e6 (diff)
Phase 8c-8f: Extract portal, stratum_client, mint_health, client into tollgate_core
New component modules: - tollgate_core_portal.c/h: template rendering, usage calc, captive URI detection - tollgate_core_stratum_client.c/h: Stratum V1 JSON protocol parsing, message building - tollgate_core_mint_health.c/h: mint health state tracking, recovery threshold logic - tollgate_core_client.c/h: discovery/session/usage JSON parsing, renewal check, price calc Main shims updated to delegate pure logic to component: - captive_portal.c: uses tollgate_core_portal_render(), format_usage(), is_captive_uri() - stratum_client.c: uses tollgate_core_stratum_parse_notify/build_*() - mint_health.c: uses tollgate_core_mint_health_update/is_reachable/mark_unreachable() - tollgate_client.c: uses tollgate_core_client_parse_*/should_renew/calc_price_per_min() 4 new unit tests (test_portal, test_stratum_client, test_mint_health_core, test_client_core) All 25 unit tests pass. ESP-IDF build passes (68% partition free).
Diffstat (limited to 'tests/unit/test_client_core.c')
-rw-r--r--tests/unit/test_client_core.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/tests/unit/test_client_core.c b/tests/unit/test_client_core.c
new file mode 100644
index 0000000..7cc6cc7
--- /dev/null
+++ b/tests/unit/test_client_core.c
@@ -0,0 +1,189 @@
1#include "test_framework.h"
2#include "../../components/tollgate_core/src/tollgate_core_client.h"
3#include <cjson/cJSON.h>
4#include <string.h>
5#include <stdio.h>
6
7int main(void)
8{
9 printf("=== test_client_core ===\n");
10
11 printf("\n--- parse_discovery valid ---\n");
12 {
13 const char *json = "{\"kind\":10021,\"content\":\"discovery\","
14 "\"tags\":["
15 "[\"metric\",\"milliseconds\"],"
16 "[\"step_size\",\"60000\"],"
17 "[\"price_per_step\",\"21\",\"21\",\"sha256\",\"https://test.mint\"]"
18 "]}";
19 tollgate_discovery_t disc = {0};
20 bool ok = tollgate_core_client_parse_discovery(json, &disc);
21 ASSERT(ok, "parse_discovery returns true");
22 ASSERT(disc.is_tollgate, "is_tollgate set");
23 ASSERT_EQ_INT(21, disc.price_per_step, "price_per_step");
24 ASSERT_EQ_INT(60000, disc.step_size_ms, "step_size_ms");
25 ASSERT(strcmp(disc.metric, "milliseconds") == 0, "metric");
26 ASSERT(strcmp(disc.mint_url, "https://test.mint") == 0, "mint_url");
27 }
28
29 printf("\n--- parse_discovery wrong kind ---\n");
30 {
31 const char *json = "{\"kind\":9999}";
32 tollgate_discovery_t disc = {0};
33 bool ok = tollgate_core_client_parse_discovery(json, &disc);
34 ASSERT(!ok, "wrong kind returns false");
35 }
36
37 printf("\n--- parse_discovery mining payment ---\n");
38 {
39 const char *json = "{\"kind\":10021,\"content\":\"\","
40 "\"tags\":["
41 "[\"metric\",\"milliseconds\"],"
42 "[\"step_size\",\"60000\"],"
43 "[\"price_per_step\",\"0\",\"mining\",\"3333\",\"extra\"]"
44 "]}";
45 tollgate_discovery_t disc = {0};
46 bool ok = tollgate_core_client_parse_discovery(json, &disc);
47 ASSERT(ok, "parse_discovery mining returns true");
48 ASSERT(disc.mining_available, "mining_available set");
49 ASSERT_EQ_INT(3333, (int)disc.mining_port, "mining_port");
50 }
51
52 printf("\n--- parse_discovery empty tags ---\n");
53 {
54 const char *json = "{\"kind\":10021,\"tags\":[]}";
55 tollgate_discovery_t disc = {0};
56 bool ok = tollgate_core_client_parse_discovery(json, &disc);
57 ASSERT(ok, "empty tags returns true");
58 ASSERT(disc.is_tollgate, "is_tollgate set");
59 }
60
61 printf("\n--- parse_discovery no tags ---\n");
62 {
63 const char *json = "{\"kind\":10021}";
64 tollgate_discovery_t disc = {0};
65 bool ok = tollgate_core_client_parse_discovery(json, &disc);
66 ASSERT(ok, "no tags returns true");
67 }
68
69 printf("\n--- parse_discovery invalid JSON ---\n");
70 {
71 tollgate_discovery_t disc = {0};
72 bool ok = tollgate_core_client_parse_discovery("not json", &disc);
73 ASSERT(!ok, "invalid JSON returns false");
74 }
75
76 printf("\n--- parse_session valid ---\n");
77 {
78 const char *json = "{\"kind\":1022,\"content\":\"session\","
79 "\"tags\":[[\"allotment\",\"120000\"]]}";
80 int64_t allotment = 0;
81 bool ok = tollgate_core_client_parse_session(json, &allotment);
82 ASSERT(ok, "parse_session returns true");
83 ASSERT_EQ_UINT64(120000, (unsigned long long)allotment, "allotment_ms");
84 }
85
86 printf("\n--- parse_session wrong kind ---\n");
87 {
88 const char *json = "{\"kind\":10021}";
89 int64_t allotment = 0;
90 bool ok = tollgate_core_client_parse_session(json, &allotment);
91 ASSERT(!ok, "wrong kind returns false");
92 }
93
94 printf("\n--- parse_session no allotment tag ---\n");
95 {
96 const char *json = "{\"kind\":1022,\"tags\":[]}";
97 int64_t allotment = 999;
98 bool ok = tollgate_core_client_parse_session(json, &allotment);
99 ASSERT(ok, "returns true");
100 ASSERT_EQ_UINT64(999, (unsigned long long)allotment, "allotment unchanged when no tag");
101 }
102
103 printf("\n--- parse_usage valid ---\n");
104 {
105 int64_t remaining = 0, total = 0;
106 bool ok = tollgate_core_client_parse_usage("45000/60000", &remaining, &total);
107 ASSERT(ok, "parse_usage returns true");
108 ASSERT_EQ_UINT64(45000, (unsigned long long)remaining, "remaining");
109 ASSERT_EQ_UINT64(60000, (unsigned long long)total, "total");
110 }
111
112 printf("\n--- parse_usage no slash ---\n");
113 {
114 int64_t remaining = 0, total = 0;
115 bool ok = tollgate_core_client_parse_usage("45000", &remaining, &total);
116 ASSERT(!ok, "no slash returns false");
117 }
118
119 printf("\n--- parse_usage zero values ---\n");
120 {
121 int64_t remaining = 0, total = 0;
122 bool ok = tollgate_core_client_parse_usage("0/0", &remaining, &total);
123 ASSERT(ok, "parse_usage zero values");
124 ASSERT_EQ_UINT64(0, (unsigned long long)remaining, "remaining is 0");
125 ASSERT_EQ_UINT64(0, (unsigned long long)total, "total is 0");
126 }
127
128 printf("\n--- should_renew ---\n");
129 {
130 ASSERT(tollgate_core_client_should_renew(1000, 60000, 20),
131 "1.6% remaining → should renew");
132 ASSERT(tollgate_core_client_should_renew(0, 60000, 20),
133 "0% remaining → should renew");
134 ASSERT(!tollgate_core_client_should_renew(30000, 60000, 20),
135 "50% remaining → should not renew");
136 ASSERT(!tollgate_core_client_should_renew(60000, 60000, 20),
137 "100% remaining → should not renew");
138 ASSERT(tollgate_core_client_should_renew(11999, 60000, 20),
139 "19.99% → should renew");
140 ASSERT(tollgate_core_client_should_renew(12000, 60000, 20),
141 "20% exactly at threshold → should renew");
142 }
143
144 printf("\n--- should_renew default threshold ---\n");
145 {
146 ASSERT(tollgate_core_client_should_renew(1000, 60000, 0),
147 "threshold=0 defaults to 20%");
148 ASSERT(tollgate_core_client_should_renew(1000, 60000, -1),
149 "negative threshold defaults to 20%");
150 }
151
152 printf("\n--- should_renew edge cases ---\n");
153 {
154 ASSERT(!tollgate_core_client_should_renew(-1, 60000, 20),
155 "negative remaining → false");
156 ASSERT(!tollgate_core_client_should_renew(1000, 0, 20),
157 "zero allotment → false");
158 }
159
160 printf("\n--- calc_price_per_min ---\n");
161 {
162 ASSERT_EQ_INT(21, tollgate_core_client_calc_price_per_min(21, 60000),
163 "21 sats/60s = 21 sats/min");
164 ASSERT_EQ_INT(42, tollgate_core_client_calc_price_per_min(21, 30000),
165 "21 sats/30s = 42 sats/min");
166 ASSERT_EQ_INT(21000, tollgate_core_client_calc_price_per_min(21, 60),
167 "21 sats/60ms effective");
168 }
169
170 printf("\n--- calc_price_per_min zero step ---\n");
171 {
172 int result = tollgate_core_client_calc_price_per_min(21, 0);
173 ASSERT(result > 0, "zero step_size_ms doesn't crash");
174 }
175
176 printf("\n--- calc_steps ---\n");
177 {
178 ASSERT_EQ_INT(21, tollgate_core_client_calc_steps(1, 21, 21),
179 "1 step * 21 = 21");
180 ASSERT_EQ_INT(42, tollgate_core_client_calc_steps(2, 21, 21),
181 "2 steps * 21 = 42");
182 ASSERT_EQ_INT(21, tollgate_core_client_calc_steps(0, 21, 21),
183 "0 steps defaults to 1");
184 ASSERT_EQ_INT(21, tollgate_core_client_calc_steps(-1, 21, 21),
185 "negative steps defaults to 1");
186 }
187
188 TEST_SUMMARY();
189}