upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit')
-rw-r--r--tests/unit/Makefile17
-rw-r--r--tests/unit/stubs/dns_server.h11
-rw-r--r--tests/unit/stubs/esp_wifi_ap_get_sta_list.h38
-rw-r--r--tests/unit/stubs/freertos/task.h7
-rw-r--r--tests/unit/stubs/lwip/etharp.h22
-rw-r--r--tests/unit/stubs/lwip/ip4_addr.h3
-rw-r--r--tests/unit/stubs/lwip/lwip_napt.h (renamed from tests/unit/stubs/lwip/napt.h)0
-rw-r--r--tests/unit/stubs/lwip/netif.h16
-rw-r--r--tests/unit/stubs/lwip/prot/ip.h20
-rw-r--r--tests/unit/stubs/lwip/prot/ip4.h6
-rw-r--r--tests/unit/stubs/lwip/prot/tcp.h13
-rw-r--r--tests/unit/stubs/lwip/sockets.h6
-rwxr-xr-xtests/unit/test_beacon_pricebin0 -> 34808 bytes
-rwxr-xr-xtests/unit/test_cvm_serverbin0 -> 45720 bytes
-rwxr-xr-xtests/unit/test_displaybin0 -> 24816 bytes
-rwxr-xr-xtests/unit/test_firewall_sandboxbin0 -> 30576 bytes
-rw-r--r--tests/unit/test_firewall_sandbox.c94
-rwxr-xr-xtests/unit/test_lightning_payoutbin20552 -> 20552 bytes
-rwxr-xr-xtests/unit/test_lnurl_paybin21304 -> 21312 bytes
-rwxr-xr-xtests/unit/test_marketbin0 -> 48240 bytes
-rwxr-xr-xtests/unit/test_mcp_handlerbin38736 -> 64152 bytes
-rwxr-xr-xtests/unit/test_mining_paymentbin0 -> 28672 bytes
-rw-r--r--tests/unit/test_mining_payment.c92
-rwxr-xr-xtests/unit/test_negentropy_adapterbin0 -> 21216 bytes
-rwxr-xr-xtests/unit/test_nip04bin298776 -> 298784 bytes
-rwxr-xr-xtests/unit/test_session_payment_methodbin0 -> 54008 bytes
-rw-r--r--tests/unit/test_session_payment_method.c74
-rwxr-xr-xtests/unit/test_stratum_proxybin0 -> 40752 bytes
-rw-r--r--tests/unit/test_stratum_proxy.c95
-rwxr-xr-xtests/unit/test_tollgate_clientbin51992 -> 52968 bytes
-rwxr-xr-xtests/unit/test_tollgate_client_miningbin0 -> 47224 bytes
-rw-r--r--tests/unit/test_tollgate_client_mining.c103
32 files changed, 614 insertions, 3 deletions
diff --git a/tests/unit/Makefile b/tests/unit/Makefile
index a06807f..edff73c 100644
--- a/tests/unit/Makefile
+++ b/tests/unit/Makefile
@@ -22,7 +22,7 @@ LDFLAGS := -lmbedcrypto -lcjson -lm
22 22
23SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o 23SECP256K1_OBJ := secp256k1.o precomputed_ecmult.o precomputed_ecmult_gen.o
24 24
25TESTS := test_geohash test_identity test_nostr_event test_cashu test_session test_tollgate_client test_lnurl_pay test_lightning_payout test_mcp_handler test_nip04 test_cvm_server test_display test_negentropy_adapter test_beacon_price test_market test_mint_health 25TESTS := test_geohash test_identity test_nostr_event test_cashu test_session test_tollgate_client test_lnurl_pay test_lightning_payout test_mcp_handler test_nip04 test_cvm_server test_display test_negentropy_adapter test_beacon_price test_market test_mint_health test_mining_payment test_stratum_proxy test_session_payment_method test_tollgate_client_mining test_firewall_sandbox
26 26
27.PHONY: all test clean $(TESTS) 27.PHONY: all test clean $(TESTS)
28 28
@@ -90,5 +90,20 @@ test_beacon_price: test_beacon_price.c $(REPO_ROOT)/main/beacon_price.c
90test_market: test_market.c $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c 90test_market: test_market.c $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c
91 $(CC) $(CFLAGS) -I $(REPO_ROOT)/main $< $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c -o $@ $(LDFLAGS) 91 $(CC) $(CFLAGS) -I $(REPO_ROOT)/main $< $(REPO_ROOT)/main/market.c $(REPO_ROOT)/main/beacon_price.c -o $@ $(LDFLAGS)
92 92
93test_mining_payment: test_mining_payment.c $(REPO_ROOT)/main/mining_payment.c
94 $(CC) $(CFLAGS) $< $(REPO_ROOT)/main/mining_payment.c -o $@ $(LDFLAGS)
95
96test_stratum_proxy: test_stratum_proxy.c $(REPO_ROOT)/main/stratum_proxy.c $(REPO_ROOT)/main/mining_payment.c
97 $(CC) $(CFLAGS) $< $(REPO_ROOT)/main/stratum_proxy.c $(REPO_ROOT)/main/mining_payment.c -o $@ $(LDFLAGS)
98
99test_session_payment_method: test_session_payment_method.c $(REPO_ROOT)/main/session.c $(REPO_ROOT)/main/cashu.c
100 $(CC) $(CFLAGS) $< $(REPO_ROOT)/main/session.c $(REPO_ROOT)/main/cashu.c -o $@ $(LDFLAGS)
101
102test_tollgate_client_mining: test_tollgate_client_mining.c
103 $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
104
105test_firewall_sandbox: test_firewall_sandbox.c $(REPO_ROOT)/main/firewall.c
106 $(CC) $(CFLAGS) -include stubs/dns_server.h $< $(REPO_ROOT)/main/firewall.c -o $@ $(LDFLAGS)
107
93clean: 108clean:
94 rm -f $(TESTS) $(SECP256K1_OBJ) 109 rm -f $(TESTS) $(SECP256K1_OBJ)
diff --git a/tests/unit/stubs/dns_server.h b/tests/unit/stubs/dns_server.h
new file mode 100644
index 0000000..0a9450b
--- /dev/null
+++ b/tests/unit/stubs/dns_server.h
@@ -0,0 +1,11 @@
1#ifndef STUBS_DNS_SERVER_H
2#define STUBS_DNS_SERVER_H
3
4#include <stdint.h>
5#include <stdbool.h>
6
7static inline void dns_server_set_client_authenticated(uint32_t ip, bool auth) {
8 (void)ip; (void)auth;
9}
10
11#endif
diff --git a/tests/unit/stubs/esp_wifi_ap_get_sta_list.h b/tests/unit/stubs/esp_wifi_ap_get_sta_list.h
new file mode 100644
index 0000000..3e98032
--- /dev/null
+++ b/tests/unit/stubs/esp_wifi_ap_get_sta_list.h
@@ -0,0 +1,38 @@
1#ifndef STUBS_ESP_WIFI_AP_GET_STA_LIST_H
2#define STUBS_ESP_WIFI_AP_GET_STA_LIST_H
3
4#include <stdint.h>
5#include <string.h>
6#include "esp_err.h"
7
8#define ESP_WIFI_AP_MAX_STA 10
9
10typedef struct {
11 uint8_t mac[6];
12} wifi_sta_info_t;
13
14typedef struct {
15 int num;
16 wifi_sta_info_t sta[ESP_WIFI_AP_MAX_STA];
17} wifi_sta_list_t;
18
19typedef struct {
20 int num;
21 struct {
22 uint8_t mac[6];
23 esp_ip4_addr_t ip;
24 } sta[ESP_WIFI_AP_MAX_STA];
25} wifi_sta_mac_ip_list_t;
26
27static inline esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta) {
28 memset(sta, 0, sizeof(*sta));
29 return ESP_FAIL;
30}
31
32static inline esp_err_t esp_wifi_ap_get_sta_list_with_ip(const wifi_sta_list_t *sta_in, wifi_sta_mac_ip_list_t *out) {
33 (void)sta_in;
34 memset(out, 0, sizeof(*out));
35 return ESP_FAIL;
36}
37
38#endif
diff --git a/tests/unit/stubs/freertos/task.h b/tests/unit/stubs/freertos/task.h
index 3855d41..ec96156 100644
--- a/tests/unit/stubs/freertos/task.h
+++ b/tests/unit/stubs/freertos/task.h
@@ -6,14 +6,17 @@
6 6
7typedef void *TaskHandle_t; 7typedef void *TaskHandle_t;
8typedef void *SemaphoreHandle_t; 8typedef void *SemaphoreHandle_t;
9typedef int BaseType_t;
10
11#define pdPASS 1
9 12
10static inline void vTaskDelete(TaskHandle_t t) { (void)t; } 13static inline void vTaskDelete(TaskHandle_t t) { (void)t; }
11static inline SemaphoreHandle_t xSemaphoreCreateMutex(void) { return (SemaphoreHandle_t)malloc(1); } 14static inline SemaphoreHandle_t xSemaphoreCreateMutex(void) { return (SemaphoreHandle_t)malloc(1); }
12static inline void vSemaphoreDelete(SemaphoreHandle_t s) { free(s); } 15static inline void vSemaphoreDelete(SemaphoreHandle_t s) { free(s); }
13static inline int xSemaphoreTake(SemaphoreHandle_t s, uint32_t blk) { (void)s; (void)blk; return 1; } 16static inline int xSemaphoreTake(SemaphoreHandle_t s, uint32_t blk) { (void)s; (void)blk; return 1; }
14static inline int xSemaphoreGive(SemaphoreHandle_t s) { (void)s; return 1; } 17static inline int xSemaphoreGive(SemaphoreHandle_t s) { (void)s; return 1; }
15static inline int xTaskCreate(void (*fn)(void*), const char *n, uint32_t st, void *p, uint32_t pri, TaskHandle_t *h) { 18static inline BaseType_t xTaskCreate(void (*fn)(void*), const char *n, uint32_t st, void *p, uint32_t pri, TaskHandle_t *h) {
16 (void)fn; (void)n; (void)st; (void)p; (void)pri; (void)h; return 1; 19 (void)fn; (void)n; (void)st; (void)p; (void)pri; (void)h; return pdPASS;
17} 20}
18 21
19#endif 22#endif
diff --git a/tests/unit/stubs/lwip/etharp.h b/tests/unit/stubs/lwip/etharp.h
new file mode 100644
index 0000000..adc6b7b
--- /dev/null
+++ b/tests/unit/stubs/lwip/etharp.h
@@ -0,0 +1,22 @@
1#ifndef STUBS_LWIP_ETHARP_H
2#define STUBS_LWIP_ETHARP_H
3
4#include <stdint.h>
5#include <stddef.h>
6#include "lwip/ip4_addr.h"
7
8struct eth_addr {
9 uint8_t addr[6];
10};
11
12struct netif;
13
14typedef int err_t;
15#define ERR_OK 0
16
17static inline err_t etharp_get_entry(ssize_t i, ip4_addr_t **ip, struct netif **netif, struct eth_addr **eth) {
18 (void)i; (void)ip; (void)netif; (void)eth;
19 return -1;
20}
21
22#endif
diff --git a/tests/unit/stubs/lwip/ip4_addr.h b/tests/unit/stubs/lwip/ip4_addr.h
index 174211b..9d92ff0 100644
--- a/tests/unit/stubs/lwip/ip4_addr.h
+++ b/tests/unit/stubs/lwip/ip4_addr.h
@@ -3,6 +3,9 @@
3 3
4#include <stdint.h> 4#include <stdint.h>
5 5
6typedef uint32_t u32_t;
7typedef uint16_t u16_t;
8
6typedef struct { 9typedef struct {
7 uint32_t addr; 10 uint32_t addr;
8} ip4_addr_t; 11} ip4_addr_t;
diff --git a/tests/unit/stubs/lwip/napt.h b/tests/unit/stubs/lwip/lwip_napt.h
index c6a5ca1..c6a5ca1 100644
--- a/tests/unit/stubs/lwip/napt.h
+++ b/tests/unit/stubs/lwip/lwip_napt.h
diff --git a/tests/unit/stubs/lwip/netif.h b/tests/unit/stubs/lwip/netif.h
index 461a64e..9415539 100644
--- a/tests/unit/stubs/lwip/netif.h
+++ b/tests/unit/stubs/lwip/netif.h
@@ -1,4 +1,20 @@
1#ifndef STUBS_LWIP_NETIF_H 1#ifndef STUBS_LWIP_NETIF_H
2#define STUBS_LWIP_NETIF_H 2#define STUBS_LWIP_NETIF_H
3 3
4#include <stdint.h>
5#include <stddef.h>
6
7struct pbuf {
8 void *payload;
9 uint16_t len;
10};
11
12static inline uint32_t lwip_ntohl(uint32_t n) {
13 return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n >> 8) & 0xFF00) | ((n >> 24) & 0xFF);
14}
15
16static inline uint16_t lwip_ntohs(uint16_t n) {
17 return ((n & 0xFF) << 8) | ((n >> 8) & 0xFF);
18}
19
4#endif 20#endif
diff --git a/tests/unit/stubs/lwip/prot/ip.h b/tests/unit/stubs/lwip/prot/ip.h
new file mode 100644
index 0000000..0770760
--- /dev/null
+++ b/tests/unit/stubs/lwip/prot/ip.h
@@ -0,0 +1,20 @@
1#ifndef STUBS_LWIP_PROT_IP_H
2#define STUBS_LWIP_PROT_IP_H
3
4#include <stdint.h>
5
6#define IP_PROTO_TCP 6
7#define IP_PROTO_UDP 17
8#define IP_HLEN 20
9
10struct ip_hdr {
11 uint8_t _proto;
12 union {
13 uint32_t addr;
14 } src;
15 union {
16 uint32_t addr;
17 } dest;
18};
19
20#endif
diff --git a/tests/unit/stubs/lwip/prot/ip4.h b/tests/unit/stubs/lwip/prot/ip4.h
new file mode 100644
index 0000000..0f70170
--- /dev/null
+++ b/tests/unit/stubs/lwip/prot/ip4.h
@@ -0,0 +1,6 @@
1#ifndef STUBS_LWIP_PROT_IP4_H
2#define STUBS_LWIP_PROT_IP4_H
3
4#include "ip.h"
5
6#endif
diff --git a/tests/unit/stubs/lwip/prot/tcp.h b/tests/unit/stubs/lwip/prot/tcp.h
new file mode 100644
index 0000000..5841371
--- /dev/null
+++ b/tests/unit/stubs/lwip/prot/tcp.h
@@ -0,0 +1,13 @@
1#ifndef STUBS_LWIP_PROT_TCP_H
2#define STUBS_LWIP_PROT_TCP_H
3
4#include <stdint.h>
5
6#define TCP_HLEN 20
7
8struct tcp_hdr {
9 uint16_t src;
10 uint16_t dest;
11};
12
13#endif
diff --git a/tests/unit/stubs/lwip/sockets.h b/tests/unit/stubs/lwip/sockets.h
index 44f03ac..91bf8b2 100644
--- a/tests/unit/stubs/lwip/sockets.h
+++ b/tests/unit/stubs/lwip/sockets.h
@@ -1,4 +1,10 @@
1#ifndef STUBS_LWIP_SOCKETS_H 1#ifndef STUBS_LWIP_SOCKETS_H
2#define STUBS_LWIP_SOCKETS_H 2#define STUBS_LWIP_SOCKETS_H
3 3
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <arpa/inet.h>
7#include <unistd.h>
8#include <string.h>
9
4#endif 10#endif
diff --git a/tests/unit/test_beacon_price b/tests/unit/test_beacon_price
new file mode 100755
index 0000000..47efd2b
--- /dev/null
+++ b/tests/unit/test_beacon_price
Binary files differ
diff --git a/tests/unit/test_cvm_server b/tests/unit/test_cvm_server
new file mode 100755
index 0000000..bd5e735
--- /dev/null
+++ b/tests/unit/test_cvm_server
Binary files differ
diff --git a/tests/unit/test_display b/tests/unit/test_display
new file mode 100755
index 0000000..9b8364e
--- /dev/null
+++ b/tests/unit/test_display
Binary files differ
diff --git a/tests/unit/test_firewall_sandbox b/tests/unit/test_firewall_sandbox
new file mode 100755
index 0000000..4b85357
--- /dev/null
+++ b/tests/unit/test_firewall_sandbox
Binary files differ
diff --git a/tests/unit/test_firewall_sandbox.c b/tests/unit/test_firewall_sandbox.c
new file mode 100644
index 0000000..66a491b
--- /dev/null
+++ b/tests/unit/test_firewall_sandbox.c
@@ -0,0 +1,94 @@
1#include "test_framework.h"
2#include "../../main/firewall.h"
3#include <stdio.h>
4#include <string.h>
5
6int main(void)
7{
8 printf("=== test_firewall_sandbox ===\n");
9
10 printf("\n--- FW_MAX_MAC_LEN is 18 ---\n");
11 {
12 ASSERT_EQ_INT(18, FW_MAX_MAC_LEN, "MAC length is 18 (17 chars + null)");
13 }
14
15 printf("\n--- esp_ip4_addr_t available ---\n");
16 {
17 esp_ip4_addr_t ip;
18 ip.addr = 0x0102A8C0;
19 ASSERT(ip.addr == 0x0102A8C0, "ip4_addr stores value");
20 }
21
22 printf("\n--- firewall_set_mining_port / set_sandbox_mint_access compile ---\n");
23 {
24 firewall_set_mining_port(3333);
25 firewall_set_mining_port(4033);
26 firewall_set_sandbox_mint_access(true);
27 firewall_set_sandbox_mint_access(false);
28 ASSERT(true, "setters compile and run without crash");
29 }
30
31 printf("\n--- firewall_init + client management ---\n");
32 {
33 esp_ip4_addr_t ap_ip = { .addr = 0x012FA80A };
34 esp_err_t ret = firewall_init(ap_ip);
35 ASSERT_EQ_INT(ESP_OK, (int)ret, "firewall_init succeeds");
36 ASSERT_EQ_INT(0, firewall_client_count(), "no clients after init");
37
38 firewall_grant_access(0x0201A8C0);
39 ASSERT_EQ_INT(1, firewall_client_count(), "1 client after grant");
40 ASSERT(firewall_is_client_allowed(0x0201A8C0), "client is allowed");
41
42 firewall_revoke_access(0x0201A8C0);
43 ASSERT_EQ_INT(0, firewall_client_count(), "0 clients after revoke");
44 ASSERT(!firewall_is_client_allowed(0x0201A8C0), "client not allowed after revoke");
45 }
46
47 printf("\n--- grant same IP twice ---\n");
48 {
49 esp_ip4_addr_t ap_ip = { .addr = 0x012FA80A };
50 firewall_init(ap_ip);
51
52 firewall_grant_access(0x0301A8C0);
53 firewall_grant_access(0x0301A8C0);
54 ASSERT_EQ_INT(1, firewall_client_count(), "duplicate grant does not double count");
55 }
56
57 printf("\n--- revoke non-existent ---\n");
58 {
59 firewall_revoke_access(0x99999999);
60 ASSERT_EQ_INT(1, firewall_client_count(), "revoke non-existent no effect");
61 }
62
63 printf("\n--- revoke_all ---\n");
64 {
65 firewall_grant_access(0x0401A8C0);
66 firewall_grant_access(0x0501A8C0);
67 ASSERT_EQ_INT(3, firewall_client_count(), "3 clients");
68 firewall_revoke_all();
69 ASSERT_EQ_INT(0, firewall_client_count(), "0 after revoke_all");
70 }
71
72 printf("\n--- max clients (10) ---\n");
73 {
74 esp_ip4_addr_t ap_ip = { .addr = 0x012FA80A };
75 firewall_init(ap_ip);
76
77 for (int i = 0; i < 10; i++) {
78 firewall_grant_access(0x0A000000 + i);
79 }
80 ASSERT_EQ_INT(10, firewall_client_count(), "10 clients at max");
81
82 firewall_grant_access(0x0A000100);
83 ASSERT_EQ_INT(10, firewall_client_count(), "still 10 after exceeding max");
84 }
85
86 printf("\n--- is_mac_allowed (no MACs resolved in stub) ---\n");
87 {
88 firewall_init((esp_ip4_addr_t){ .addr = 0x012FA80A });
89 firewall_grant_access(0x0601A8C0);
90 ASSERT(!firewall_is_mac_allowed(""), "empty MAC not allowed");
91 }
92
93 TEST_SUMMARY();
94}
diff --git a/tests/unit/test_lightning_payout b/tests/unit/test_lightning_payout
index b10888c..caa9626 100755
--- a/tests/unit/test_lightning_payout
+++ b/tests/unit/test_lightning_payout
Binary files differ
diff --git a/tests/unit/test_lnurl_pay b/tests/unit/test_lnurl_pay
index 1f16293..1345004 100755
--- a/tests/unit/test_lnurl_pay
+++ b/tests/unit/test_lnurl_pay
Binary files differ
diff --git a/tests/unit/test_market b/tests/unit/test_market
new file mode 100755
index 0000000..9823080
--- /dev/null
+++ b/tests/unit/test_market
Binary files differ
diff --git a/tests/unit/test_mcp_handler b/tests/unit/test_mcp_handler
index b5d6a85..be992f6 100755
--- a/tests/unit/test_mcp_handler
+++ b/tests/unit/test_mcp_handler
Binary files differ
diff --git a/tests/unit/test_mining_payment b/tests/unit/test_mining_payment
new file mode 100755
index 0000000..015deaf
--- /dev/null
+++ b/tests/unit/test_mining_payment
Binary files differ
diff --git a/tests/unit/test_mining_payment.c b/tests/unit/test_mining_payment.c
new file mode 100644
index 0000000..c3834fd
--- /dev/null
+++ b/tests/unit/test_mining_payment.c
@@ -0,0 +1,92 @@
1#include "test_framework.h"
2#include "../../main/mining_payment.h"
3#include <stdio.h>
4#include <string.h>
5#include <math.h>
6
7int main(void)
8{
9 printf("=== test_mining_payment ===\n");
10
11 mining_payment_init();
12
13 printf("\n--- mining_nbits_to_difficulty ---\n");
14 uint64_t d1 = mining_nbits_to_difficulty(0);
15 ASSERT(d1 == UINT64_MAX, "nbits=0 returns max");
16
17 uint64_t d2 = mining_nbits_to_difficulty(0x170309E2);
18 ASSERT(d2 > 0, "mainnet nbits gives positive difficulty");
19 printf(" INFO: difficulty for 0x170309E2 = %llu\n", (unsigned long long)d2);
20
21 uint64_t d3 = mining_nbits_to_difficulty(0x1d00ffff);
22 ASSERT(d3 == 1, "pseudotransaction nbits = difficulty 1");
23
24 printf("\n--- mining_calculate_hashprice ---\n");
25 double hp1 = mining_calculate_hashprice(0);
26 ASSERT(hp1 == 0.0, "nbits=0 gives hashprice 0");
27
28 double hp2 = mining_calculate_hashprice(0x170309E2);
29 ASSERT(hp2 > 0.0, "mainnet nbits gives positive hashprice");
30 printf(" INFO: hashprice for 0x170309E2 = %.6f sat/GH/s/day\n", hp2);
31
32 printf("\n--- mining_calculate_hashprice_override ---\n");
33 double hp3 = mining_calculate_hashprice_override(1000);
34 ASSERT(fabs(hp3 - 1000.0) < 0.001, "override returns exact value");
35
36 printf("\n--- mining_set_current_nbits ---\n");
37 mining_set_current_nbits(0x170309E2);
38 double hp4 = mining_get_current_hashprice();
39 ASSERT(fabs(hp4 - hp2) < 0.0001, "stored hashprice matches calculated");
40
41 printf("\n--- mining_get_or_create_client ---\n");
42 mining_client_stats_t *c1 = mining_get_or_create_client(0x0A010203);
43 ASSERT(c1 != NULL, "created client 1");
44 ASSERT(c1->ip == 0x0A010203, "client 1 IP matches");
45 ASSERT(c1->shares_accepted == 0, "client 1 starts with 0 shares");
46
47 mining_client_stats_t *c2 = mining_get_or_create_client(0x0A010204);
48 ASSERT(c2 != NULL, "created client 2");
49 ASSERT(c2->ip == 0x0A010204, "client 2 IP matches");
50
51 mining_client_stats_t *c1_again = mining_get_or_create_client(0x0A010203);
52 ASSERT(c1_again == c1, "same IP returns same client");
53
54 printf("\n--- mining_update_hashrate ---\n");
55 mining_update_hashrate(0x0A010203, true);
56 mining_update_hashrate(0x0A010203, true);
57 mining_update_hashrate(0x0A010203, false);
58
59 const mining_client_stats_t *c1_stats = mining_get_client_stats(0x0A010203);
60 ASSERT(c1_stats != NULL, "client 1 stats found");
61 ASSERT(c1_stats->shares_accepted == 2, "client 1 has 2 accepted");
62 ASSERT(c1_stats->shares_rejected == 1, "client 1 has 1 rejected");
63
64 printf("\n--- mining_get_client_stats ---\n");
65 const mining_client_stats_t *notfound = mining_get_client_stats(0xFFFFFFFF);
66 ASSERT(notfound == NULL, "nonexistent client returns NULL");
67
68 printf("\n--- mining_shares_to_allotment_ms ---\n");
69 uint64_t allot1 = mining_shares_to_allotment_ms(0.0, 100.0, 21, 60000);
70 ASSERT(allot1 == 0, "zero hashrate = zero allotment");
71
72 uint64_t allot2 = mining_shares_to_allotment_ms(1.0, 100.0, 21, 60000);
73 ASSERT(allot2 > 0, "positive hashrate gives positive allotment");
74 printf(" INFO: 1 GH/s at 100 sat/GH/s/day, 21 sats/60s => %llu ms\n", (unsigned long long)allot2);
75
76 uint64_t allot3 = mining_shares_to_allotment_ms(10.0, 50.0, 10, 30000);
77 ASSERT(allot3 > 0, "10 GH/s at 50 sat gives positive allotment");
78 printf(" INFO: 10 GH/s at 50 sat/GH/s/day, 10 sats/30s => %llu ms\n", (unsigned long long)allot3);
79
80 printf("\n--- mining_shares_to_allotment_bytes ---\n");
81 uint64_t ab1 = mining_shares_to_allotment_bytes(0.0, 100.0, 21, 1048576);
82 ASSERT(ab1 == 0, "zero hashrate = zero bytes");
83
84 uint64_t ab2 = mining_shares_to_allotment_bytes(1.0, 100.0, 21, 1048576);
85 ASSERT(ab2 > 0, "positive hashrate gives positive bytes");
86
87 printf("\n--- mining_validate_share (stub) ---\n");
88 esp_err_t vr = mining_validate_share(NULL, 0, NULL, 0);
89 ASSERT(vr == ESP_OK, "validate share stub returns OK");
90
91 TEST_SUMMARY();
92}
diff --git a/tests/unit/test_negentropy_adapter b/tests/unit/test_negentropy_adapter
new file mode 100755
index 0000000..64b6053
--- /dev/null
+++ b/tests/unit/test_negentropy_adapter
Binary files differ
diff --git a/tests/unit/test_nip04 b/tests/unit/test_nip04
index cb52040..daf5e16 100755
--- a/tests/unit/test_nip04
+++ b/tests/unit/test_nip04
Binary files differ
diff --git a/tests/unit/test_session_payment_method b/tests/unit/test_session_payment_method
new file mode 100755
index 0000000..94c7134
--- /dev/null
+++ b/tests/unit/test_session_payment_method
Binary files differ
diff --git a/tests/unit/test_session_payment_method.c b/tests/unit/test_session_payment_method.c
new file mode 100644
index 0000000..0239140
--- /dev/null
+++ b/tests/unit/test_session_payment_method.c
@@ -0,0 +1,74 @@
1#include "test_framework.h"
2#include "../../main/session.h"
3#include "../../main/firewall.h"
4#include "../../main/config.h"
5#include "../../main/cashu.h"
6#include <string.h>
7#include <stdio.h>
8
9static tollgate_config_t g_test_config;
10
11const tollgate_config_t *tollgate_config_get(void) {
12 return &g_test_config;
13}
14
15esp_err_t firewall_get_mac_for_ip(uint32_t ip, char *mac_out, size_t size) {
16 (void)ip;
17 snprintf(mac_out, size, "AA:BB:CC:DD:EE:FF");
18 return 0;
19}
20
21static uint32_t g_granted_ips[32];
22static int g_granted_count = 0;
23
24void firewall_grant_access(uint32_t ip) {
25 if (g_granted_count < 32) g_granted_ips[g_granted_count++] = ip;
26}
27
28void firewall_revoke_access(uint32_t ip) {
29 (void)ip;
30}
31
32int main(void)
33{
34 printf("=== test_session_payment_method ===\n");
35 memset(&g_test_config, 0, sizeof(g_test_config));
36 strncpy(g_test_config.metric, "milliseconds", sizeof(g_test_config.metric) - 1);
37 g_granted_count = 0;
38
39 printf("\n--- session_create sets PAYMENT_METHOD_CASHU ---\n");
40 session_manager_init();
41 session_t *s1 = session_create(0x0A010001, 60000);
42 ASSERT(s1 != NULL, "session created");
43 ASSERT_EQ_INT(PAYMENT_METHOD_CASHU, (int)s1->payment_method, "cashu session has PAYMENT_METHOD_CASHU");
44
45 printf("\n--- session_create_bytes sets PAYMENT_METHOD_BYTES ---\n");
46 session_manager_init();
47 g_granted_count = 0;
48 session_t *s2 = session_create_bytes(0x0A010002, 1048576);
49 ASSERT(s2 != NULL, "bytes session created");
50 ASSERT_EQ_INT(PAYMENT_METHOD_BYTES, (int)s2->payment_method, "bytes session has PAYMENT_METHOD_BYTES");
51 ASSERT_EQ_UINT64(1048576, s2->allotment_bytes, "allotment_bytes set");
52 ASSERT_EQ_UINT64(0, s2->bytes_consumed, "bytes_consumed starts at 0");
53
54 printf("\n--- payment_method_t enum values are distinct ---\n");
55 ASSERT(PAYMENT_METHOD_CASHU != PAYMENT_METHOD_MINING, "CASHU != MINING");
56 ASSERT(PAYMENT_METHOD_CASHU != PAYMENT_METHOD_BYTES, "CASHU != BYTES");
57 ASSERT(PAYMENT_METHOD_MINING != PAYMENT_METHOD_BYTES, "MINING != BYTES");
58
59 printf("\n--- session extend preserves payment_method ---\n");
60 session_manager_init();
61 g_granted_count = 0;
62 session_t *s3 = session_create(0x0A010003, 60000);
63 ASSERT_EQ_INT(PAYMENT_METHOD_CASHU, (int)s3->payment_method, "initially CASHU");
64 session_extend(s3, 30000);
65 ASSERT_EQ_INT(PAYMENT_METHOD_CASHU, (int)s3->payment_method, "still CASHU after extend");
66
67 printf("\n--- bytes session allotment_ms is INT64_MAX ---\n");
68 session_manager_init();
69 g_granted_count = 0;
70 session_t *s4 = session_create_bytes(0x0A010004, 2097152);
71 ASSERT(s4->allotment_ms == INT64_MAX, "bytes session has INT64_MAX allotment_ms");
72
73 TEST_SUMMARY();
74}
diff --git a/tests/unit/test_stratum_proxy b/tests/unit/test_stratum_proxy
new file mode 100755
index 0000000..608835f
--- /dev/null
+++ b/tests/unit/test_stratum_proxy
Binary files differ
diff --git a/tests/unit/test_stratum_proxy.c b/tests/unit/test_stratum_proxy.c
new file mode 100644
index 0000000..7788911
--- /dev/null
+++ b/tests/unit/test_stratum_proxy.c
@@ -0,0 +1,95 @@
1#include "test_framework.h"
2#include "../../main/stratum_proxy.h"
3#include "../../main/mining_payment.h"
4#include <stdio.h>
5#include <string.h>
6
7int main(void)
8{
9 printf("=== test_stratum_proxy ===\n");
10
11 mining_payment_init();
12
13 printf("\n--- stratum_proxy_set_job / get_current_job ---\n");
14 {
15 stratum_job_t job = {0};
16 job.job_id = 42;
17 job.nbits = 0x170309E2;
18 job.ntime = 0x6789ABCD;
19 job.version = 0x20000000;
20 job.valid = true;
21 memset(job.prevhash, 0xAA, 32);
22 memset(job.merkle_root, 0xBB, 32);
23
24 stratum_proxy_set_job(&job);
25
26 const stratum_job_t *cur = stratum_proxy_get_current_job();
27 ASSERT(cur != NULL, "current job not NULL");
28 ASSERT_EQ_INT(42, (int)cur->job_id, "job_id=42");
29 ASSERT_EQ_INT(0x170309E2, (int)cur->nbits, "nbits preserved");
30 ASSERT_EQ_INT(0x6789ABCD, (int)cur->ntime, "ntime preserved");
31 ASSERT_EQ_INT(0x20000000, (int)cur->version, "version preserved");
32 ASSERT(cur->valid, "job is valid");
33 ASSERT_MEM_EQ(job.prevhash, cur->prevhash, 32, "prevhash preserved");
34 }
35
36 printf("\n--- stratum_proxy_set_job (NULL) ---\n");
37 {
38 stratum_proxy_set_job(NULL);
39 const stratum_job_t *cur = stratum_proxy_get_current_job();
40 ASSERT_EQ_INT(42, (int)cur->job_id, "job unchanged after NULL set");
41 }
42
43 printf("\n--- stratum_proxy_get_stats ---\n");
44 {
45 mining_set_current_nbits(0x170309E2);
46 stratum_proxy_set_job(&(stratum_job_t){
47 .job_id = 1,
48 .nbits = 0x170309E2,
49 .valid = true
50 });
51
52 stratum_proxy_stats_t stats;
53 memset(&stats, 0xFF, sizeof(stats));
54 stratum_proxy_get_stats(&stats);
55
56 ASSERT(stats.current_hashprice > 0.0, "hashprice populated from mining_payment");
57 ASSERT_EQ_INT(0x170309E2, (int)stats.nbits, "nbits in stats");
58 }
59
60 printf("\n--- stratum_proxy_get_stats (NULL) ---\n");
61 {
62 stratum_proxy_get_stats(NULL);
63 ASSERT(true, "get_stats with NULL does not crash");
64 }
65
66 printf("\n--- stratum_job_t initialization ---\n");
67 {
68 stratum_job_t zero = {0};
69 ASSERT(!zero.valid, "zero-initialized job is invalid");
70 ASSERT_EQ_INT(0, (int)zero.job_id, "zero job_id");
71 ASSERT_EQ_INT(0, (int)zero.nbits, "zero nbits");
72 }
73
74 printf("\n--- stratum_proxy_stats_t initialization ---\n");
75 {
76 stratum_proxy_stats_t zero = {0};
77 ASSERT(zero.hashrate_ghs == 0.0, "zero hashrate");
78 ASSERT_EQ_INT(0, (int)zero.active_miners, "zero active miners");
79 ASSERT_EQ_UINT64(0, zero.total_shares, "zero total shares");
80 ASSERT_EQ_UINT64(0, zero.total_accepted, "zero total accepted");
81 ASSERT_EQ_UINT64(0, zero.total_rejected, "zero total rejected");
82 }
83
84 printf("\n--- STRATUM_MAX_JOBS constant ---\n");
85 {
86 ASSERT(STRATUM_MAX_JOBS >= 1, "STRATUM_MAX_JOBS >= 1");
87 }
88
89 printf("\n--- STRATUM_MAX_JOB_ID_LEN constant ---\n");
90 {
91 ASSERT(STRATUM_MAX_JOB_ID_LEN >= 16, "STRATUM_MAX_JOB_ID_LEN >= 16");
92 }
93
94 TEST_SUMMARY();
95}
diff --git a/tests/unit/test_tollgate_client b/tests/unit/test_tollgate_client
index f9b0f7d..b56a6f0 100755
--- a/tests/unit/test_tollgate_client
+++ b/tests/unit/test_tollgate_client
Binary files differ
diff --git a/tests/unit/test_tollgate_client_mining b/tests/unit/test_tollgate_client_mining
new file mode 100755
index 0000000..64b99dd
--- /dev/null
+++ b/tests/unit/test_tollgate_client_mining
Binary files differ
diff --git a/tests/unit/test_tollgate_client_mining.c b/tests/unit/test_tollgate_client_mining.c
new file mode 100644
index 0000000..e270864
--- /dev/null
+++ b/tests/unit/test_tollgate_client_mining.c
@@ -0,0 +1,103 @@
1#include "test_framework.h"
2#include "../../main/config.h"
3#include <string.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <cjson/cJSON.h>
7
8static tollgate_config_t g_test_config;
9
10const tollgate_config_t *tollgate_config_get(void) {
11 return &g_test_config;
12}
13
14uint64_t nucula_wallet_balance(void) { return 100; }
15esp_err_t nucula_wallet_send(uint64_t a, char *b, size_t c) { (void)a; (void)b; (void)c; return ESP_OK; }
16
17#include "freertos/FreeRTOS.h"
18
19#include "../../main/tollgate_client.c"
20
21int main(void)
22{
23 printf("=== test_tollgate_client_mining ===\n");
24
25 memset(&g_test_config, 0, sizeof(g_test_config));
26 g_test_config.client_enabled = true;
27
28 printf("\n--- mining tag: mining_available=true, port=3333 ---\n");
29 {
30 const char *json = "{\"kind\":10021,\"tags\":["
31 "[\"metric\",\"milliseconds\"],"
32 "[\"step_size\",\"60000\"],"
33 "[\"price_per_step\",\"0\",\"mining\",\"3333\",\"sat\"],"
34 "[\"tips\",\"1\",\"2\",\"5\"]"
35 "]}";
36
37 tollgate_discovery_t disc;
38 bool ok = parse_discovery_response(json, &disc);
39 ASSERT(ok, "mining discovery parsed");
40 ASSERT(disc.is_tollgate, "is_tollgate=true");
41 ASSERT(disc.mining_available, "mining_available=true");
42 ASSERT_EQ_INT(3333, (int)disc.mining_port, "mining_port=3333");
43 }
44
45 printf("\n--- mining tag: no mining tag ---\n");
46 {
47 const char *json = "{\"kind\":10021,\"tags\":["
48 "[\"metric\",\"milliseconds\"],"
49 "[\"step_size\",\"60000\"],"
50 "[\"price_per_step\",\"cashu\",\"21\",\"sat\",\"https://testnut.cashu.space\",\"1\"]"
51 "]}";
52
53 tollgate_discovery_t disc;
54 bool ok = parse_discovery_response(json, &disc);
55 ASSERT(ok, "cashu discovery parsed");
56 ASSERT(disc.is_tollgate, "is_tollgate=true");
57 ASSERT(!disc.mining_available, "mining_available=false");
58 ASSERT_EQ_INT(0, (int)disc.mining_port, "mining_port=0 when no mining");
59 ASSERT_EQ_INT(21, disc.price_per_step, "price_per_step=21 for cashu");
60 }
61
62 printf("\n--- mining tag: custom port 4033 ---\n");
63 {
64 const char *json = "{\"kind\":10021,\"tags\":["
65 "[\"metric\",\"milliseconds\"],"
66 "[\"step_size\",\"60000\"],"
67 "[\"price_per_step\",\"0\",\"mining\",\"4033\",\"sat\"]"
68 "]}";
69
70 tollgate_discovery_t disc;
71 bool ok = parse_discovery_response(json, &disc);
72 ASSERT(ok, "mining custom port parsed");
73 ASSERT(disc.mining_available, "mining_available=true");
74 ASSERT_EQ_INT(4033, (int)disc.mining_port, "mining_port=4033");
75 }
76
77 printf("\n--- tollgate_discovery_t zero-init ---\n");
78 {
79 tollgate_discovery_t disc = {0};
80 ASSERT(!disc.is_tollgate, "zero-init: is_tollgate=false");
81 ASSERT(!disc.mining_available, "zero-init: mining_available=false");
82 ASSERT_EQ_INT(0, (int)disc.mining_port, "zero-init: mining_port=0");
83 ASSERT_EQ_INT(0, disc.price_per_step, "zero-init: price=0");
84 }
85
86 printf("\n--- TG_CLIENT_MINING state enum ---\n");
87 {
88 ASSERT(TG_CLIENT_MINING > TG_CLIENT_PAID, "MINING > PAID in enum");
89 ASSERT(TG_CLIENT_MINING < TG_CLIENT_ERROR, "MINING < ERROR in enum");
90 }
91
92 printf("\n--- discovery struct fields ---\n");
93 {
94 tollgate_discovery_t disc;
95 memset(&disc, 0, sizeof(disc));
96 disc.mining_available = true;
97 disc.mining_port = 9999;
98 ASSERT(disc.mining_available, "mining_available set");
99 ASSERT_EQ_INT(9999, (int)disc.mining_port, "mining_port set");
100 }
101
102 TEST_SUMMARY();
103}