First commit on a late git install
This commit is contained in:
318
tests/relay_pool_test.c
Normal file
318
tests/relay_pool_test.c
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* NOSTR Relay Pool Test Program (READ-ONLY)
|
||||
*
|
||||
* Tests the relay pool event processing functionality by:
|
||||
* - Creating a pool with hardcoded relays
|
||||
* - Subscribing to kind 1 events (text notes) from other users
|
||||
* - Using the new event processing functions
|
||||
* - Displaying raw data output without interpretation
|
||||
*
|
||||
* IMPORTANT: This test is READ-ONLY and never publishes events.
|
||||
* It only sends REQ (subscription) messages and receives EVENT responses.
|
||||
* Any test events seen in output are from other users or previous test runs.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include "../nostr_core/nostr_core.h"
|
||||
#include "../cjson/cJSON.h"
|
||||
|
||||
// Global variables for clean shutdown
|
||||
static volatile int keep_running = 1;
|
||||
static nostr_relay_pool_t* g_pool = NULL;
|
||||
static nostr_pool_subscription_t* g_subscription = NULL;
|
||||
|
||||
// Statistics tracking
|
||||
static int events_received = 0;
|
||||
static int events_per_relay[3] = {0, 0, 0}; // Track events per relay
|
||||
static const char* relay_urls[] = {
|
||||
"wss://relay.laantungir.net",
|
||||
"ws://127.0.0.1:7777",
|
||||
"wss://nostr.mom"
|
||||
};
|
||||
static const int relay_count = 3;
|
||||
|
||||
// Signal handler for clean shutdown
|
||||
void signal_handler(int sig) {
|
||||
(void)sig; // Unused parameter
|
||||
printf("\n🛑 Received shutdown signal, cleaning up...\n");
|
||||
keep_running = 0;
|
||||
}
|
||||
|
||||
// Event callback - called when events are received
|
||||
void on_event_received(cJSON* event, const char* relay_url, void* user_data) {
|
||||
(void)user_data; // Unused parameter
|
||||
|
||||
events_received++;
|
||||
|
||||
// Track events per relay
|
||||
for (int i = 0; i < relay_count; i++) {
|
||||
if (strcmp(relay_url, relay_urls[i]) == 0) {
|
||||
events_per_relay[i]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Print raw event data
|
||||
char* event_json = cJSON_Print(event);
|
||||
if (event_json) {
|
||||
printf("\n📨 EVENT from %s:\n", relay_url);
|
||||
printf("Raw JSON: %s\n", event_json);
|
||||
printf("---\n");
|
||||
free(event_json);
|
||||
}
|
||||
|
||||
// Also extract and display key fields for readability
|
||||
cJSON* id = cJSON_GetObjectItem(event, "id");
|
||||
cJSON* pubkey = cJSON_GetObjectItem(event, "pubkey");
|
||||
cJSON* created_at = cJSON_GetObjectItem(event, "created_at");
|
||||
cJSON* content = cJSON_GetObjectItem(event, "content");
|
||||
|
||||
printf("📄 Parsed fields:\n");
|
||||
if (id && cJSON_IsString(id)) {
|
||||
printf(" ID: %s\n", cJSON_GetStringValue(id));
|
||||
}
|
||||
if (pubkey && cJSON_IsString(pubkey)) {
|
||||
printf(" Author: %s\n", cJSON_GetStringValue(pubkey));
|
||||
}
|
||||
if (created_at && cJSON_IsNumber(created_at)) {
|
||||
time_t timestamp = (time_t)cJSON_GetNumberValue(created_at);
|
||||
printf(" Created: %s", ctime(×tamp));
|
||||
}
|
||||
if (content && cJSON_IsString(content)) {
|
||||
const char* text = cJSON_GetStringValue(content);
|
||||
printf(" Content: %.100s%s\n", text, strlen(text) > 100 ? "..." : "");
|
||||
}
|
||||
printf("===============================\n");
|
||||
}
|
||||
|
||||
// EOSE callback - called when all relays have sent "End of Stored Events"
|
||||
void on_eose_received(void* user_data) {
|
||||
(void)user_data; // Unused parameter
|
||||
printf("✅ EOSE: All relays have finished sending stored events\n");
|
||||
}
|
||||
|
||||
// Display relay status
|
||||
void display_relay_status() {
|
||||
char** urls;
|
||||
nostr_pool_relay_status_t* statuses;
|
||||
|
||||
int count = nostr_relay_pool_list_relays(g_pool, &urls, &statuses);
|
||||
if (count > 0) {
|
||||
printf("\n🔗 RELAY STATUS:\n");
|
||||
for (int i = 0; i < count; i++) {
|
||||
const char* status_icon;
|
||||
const char* status_text;
|
||||
|
||||
switch (statuses[i]) {
|
||||
case NOSTR_POOL_RELAY_CONNECTED:
|
||||
status_icon = "🟢";
|
||||
status_text = "Connected";
|
||||
break;
|
||||
case NOSTR_POOL_RELAY_CONNECTING:
|
||||
status_icon = "🟡";
|
||||
status_text = "Connecting...";
|
||||
break;
|
||||
case NOSTR_POOL_RELAY_DISCONNECTED:
|
||||
status_icon = "🔴";
|
||||
status_text = "Disconnected";
|
||||
break;
|
||||
case NOSTR_POOL_RELAY_ERROR:
|
||||
status_icon = "❌";
|
||||
status_text = "Error";
|
||||
break;
|
||||
default:
|
||||
status_icon = "❓";
|
||||
status_text = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
// Get publish and query latency statistics
|
||||
double query_latency = nostr_relay_pool_get_relay_query_latency(g_pool, urls[i]);
|
||||
const nostr_relay_stats_t* stats = nostr_relay_pool_get_relay_stats(g_pool, urls[i]);
|
||||
|
||||
// Get events count from relay statistics (more accurate)
|
||||
int relay_events = 0;
|
||||
if (stats) {
|
||||
relay_events = stats->events_received;
|
||||
} else {
|
||||
// Fallback to local counter
|
||||
for (int j = 0; j < relay_count; j++) {
|
||||
if (strcmp(urls[i], relay_urls[j]) == 0) {
|
||||
relay_events = events_per_relay[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display status with latency information
|
||||
if (query_latency >= 0.0) {
|
||||
printf(" %s %-25s %s (query: %.0fms, events: %d)\n",
|
||||
status_icon, urls[i], status_text, query_latency, relay_events);
|
||||
} else {
|
||||
printf(" %s %-25s %s (query: ---, events: %d)\n",
|
||||
status_icon, urls[i], status_text, relay_events);
|
||||
}
|
||||
|
||||
// Show additional latency statistics if available
|
||||
if (stats) {
|
||||
if (stats->publish_samples > 0) {
|
||||
printf(" 📊 Publish latency: avg=%.0fms (%d samples)\n",
|
||||
stats->publish_latency_avg, stats->publish_samples);
|
||||
}
|
||||
if (stats->query_samples > 0) {
|
||||
printf(" 📊 Query latency: avg=%.0fms (%d samples)\n",
|
||||
stats->query_latency_avg, stats->query_samples);
|
||||
}
|
||||
if (stats->events_published > 0) {
|
||||
printf(" 📤 Published: %d events (%d OK, %d failed)\n",
|
||||
stats->events_published, stats->events_published_ok,
|
||||
stats->events_published_failed);
|
||||
}
|
||||
}
|
||||
|
||||
free(urls[i]);
|
||||
}
|
||||
free(urls);
|
||||
free(statuses);
|
||||
|
||||
printf("📊 Total events received: %d\n", events_received);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("🚀 NOSTR Relay Pool Test Program\n");
|
||||
printf("=================================\n");
|
||||
printf("Testing relays:\n");
|
||||
for (int i = 0; i < relay_count; i++) {
|
||||
printf(" - %s\n", relay_urls[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Set up signal handler for clean shutdown
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
|
||||
// Initialize NOSTR core library
|
||||
printf("🔧 Initializing NOSTR core library...\n");
|
||||
if (nostr_init() != NOSTR_SUCCESS) {
|
||||
fprintf(stderr, "❌ Failed to initialize NOSTR core library\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create relay pool
|
||||
printf("🏊 Creating relay pool...\n");
|
||||
g_pool = nostr_relay_pool_create();
|
||||
if (!g_pool) {
|
||||
fprintf(stderr, "❌ Failed to create relay pool\n");
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add relays to pool
|
||||
printf("➕ Adding relays to pool...\n");
|
||||
for (int i = 0; i < relay_count; i++) {
|
||||
printf(" Adding: %s\n", relay_urls[i]);
|
||||
int result = nostr_relay_pool_add_relay(g_pool, relay_urls[i]);
|
||||
if (result != NOSTR_SUCCESS) {
|
||||
printf(" ⚠️ Warning: Failed to add relay %s (error: %s)\n",
|
||||
relay_urls[i], nostr_strerror(result));
|
||||
}
|
||||
}
|
||||
|
||||
// Create filter for kind 1 events (text notes)
|
||||
printf("🔍 Creating subscription filter for kind 1 events...\n");
|
||||
cJSON* filter = cJSON_CreateObject();
|
||||
if (!filter) {
|
||||
fprintf(stderr, "❌ Failed to create filter\n");
|
||||
nostr_relay_pool_destroy(g_pool);
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add kinds array with kind 1 (text notes)
|
||||
cJSON* kinds = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1));
|
||||
cJSON_AddItemToObject(filter, "kinds", kinds);
|
||||
|
||||
// Limit to recent events to avoid flooding
|
||||
cJSON_AddNumberToObject(filter, "limit", 1);
|
||||
|
||||
// Subscribe to events from all relays
|
||||
printf("📡 Subscribing to events from all relays...\n");
|
||||
g_subscription = nostr_relay_pool_subscribe(
|
||||
g_pool,
|
||||
relay_urls,
|
||||
relay_count,
|
||||
filter,
|
||||
on_event_received,
|
||||
on_eose_received,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!g_subscription) {
|
||||
fprintf(stderr, "❌ Failed to create subscription\n");
|
||||
cJSON_Delete(filter);
|
||||
nostr_relay_pool_destroy(g_pool);
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("✅ Subscription created successfully!\n");
|
||||
printf("⏱️ Starting event processing...\n");
|
||||
printf(" (Press Ctrl+C to stop)\n\n");
|
||||
|
||||
// Display initial status
|
||||
display_relay_status();
|
||||
|
||||
printf("<EFBFBD> Starting continuous monitoring...\n\n");
|
||||
|
||||
// Run event processing loop
|
||||
time_t last_status_update = time(NULL);
|
||||
|
||||
while (keep_running) {
|
||||
// Process events for 1 second
|
||||
int events_processed = nostr_relay_pool_run(g_pool, 1000);
|
||||
|
||||
// Display status every 5 seconds
|
||||
if (time(NULL) - last_status_update >= 5) {
|
||||
display_relay_status();
|
||||
last_status_update = time(NULL);
|
||||
}
|
||||
|
||||
// Small status indicator
|
||||
if (events_processed > 0) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\n🏁 Test completed!\n");
|
||||
|
||||
// Final status display
|
||||
display_relay_status();
|
||||
|
||||
// Cleanup
|
||||
printf("🧹 Cleaning up...\n");
|
||||
if (g_subscription) {
|
||||
nostr_pool_subscription_close(g_subscription);
|
||||
}
|
||||
if (g_pool) {
|
||||
nostr_relay_pool_destroy(g_pool);
|
||||
}
|
||||
cJSON_Delete(filter);
|
||||
nostr_cleanup();
|
||||
|
||||
printf("✅ Test program finished successfully!\n");
|
||||
printf("📈 Final stats:\n");
|
||||
printf(" Total events: %d\n", events_received);
|
||||
for (int i = 0; i < relay_count; i++) {
|
||||
printf(" %s: %d events\n", relay_urls[i], events_per_relay[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user