nostr_core_lib/tests/nip21_test.c

373 lines
12 KiB
C

/*
* NIP-21 URI Scheme Test Suite
* Tests nostr: URI parsing and construction functionality
* Following TESTS POLICY: Shows expected vs actual values
*/
#define _GNU_SOURCE // For strdup on Linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../nostr_core/nip021.h"
#include "../nostr_core/nostr_common.h"
#include "../nostr_core/utils.h"
// Ensure strdup is declared
#ifndef strdup
extern char *strdup(const char *s);
#endif
// Test counter for tracking progress
static int test_count = 0;
static int passed_tests = 0;
void print_test_header(const char* test_name) {
test_count++;
printf("\n=== TEST %d: %s ===\n", test_count, test_name);
}
void print_test_result(int passed, const char* test_name) {
if (passed) {
passed_tests++;
printf("✅ PASS: %s\n", test_name);
} else {
printf("❌ FAIL: %s\n", test_name);
}
}
// Test 1: Parse note URI
int test_parse_note_uri(void) {
print_test_header("Parse note: URI");
// First build a valid note URI, then parse it
unsigned char event_id[32];
nostr_hex_to_bytes("f1e582c90f071c0110cc5bcac2dcc6d8c32250e3cc26fcbe93470d918f2ffaf0", event_id, 32);
char built_uri[200];
int build_result = nostr_build_uri_note(event_id, built_uri, sizeof(built_uri));
if (build_result != NOSTR_SUCCESS) {
printf("Failed to build URI for testing: %d (%s)\n", build_result, nostr_strerror(build_result));
return 0;
}
printf("Input URI: %s\n", built_uri);
nostr_uri_result_t result;
int parse_result = nostr_parse_uri(built_uri, &result);
printf("Expected: NOSTR_SUCCESS (0)\n");
printf("Actual: %d (%s)\n", parse_result, nostr_strerror(parse_result));
if (parse_result != NOSTR_SUCCESS) {
return 0;
}
printf("Expected type: NOSTR_URI_NOTE\n");
printf("Actual type: %d\n", result.type);
if (result.type != NOSTR_URI_NOTE) {
return 0;
}
printf("Expected event ID to be set\n");
printf("Event ID present: %s\n", result.data.event_id[0] ? "yes" : "no");
// Verify the parsed event ID matches the original
int event_id_match = (memcmp(result.data.event_id, event_id, 32) == 0);
printf("Event ID matches original: %s\n", event_id_match ? "yes" : "no");
return (result.type == NOSTR_URI_NOTE && event_id_match);
}
// Test 2: Parse nprofile URI
int test_parse_nprofile_uri(void) {
print_test_header("Parse nprofile: URI");
// First build a valid nprofile URI, then parse it
unsigned char pubkey[32];
nostr_hex_to_bytes("aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4", pubkey, 32);
const char* relays[] = {"wss://relay.example.com"};
char built_uri[300];
int build_result = nostr_build_uri_nprofile(pubkey, relays, 1, built_uri, sizeof(built_uri));
if (build_result != NOSTR_SUCCESS) {
printf("Failed to build URI for testing: %d (%s)\n", build_result, nostr_strerror(build_result));
return 0;
}
printf("Input URI: %s\n", built_uri);
nostr_uri_result_t result;
int parse_result = nostr_parse_uri(built_uri, &result);
printf("Expected: NOSTR_SUCCESS (0)\n");
printf("Actual: %d (%s)\n", parse_result, nostr_strerror(parse_result));
if (parse_result != NOSTR_SUCCESS) {
return 0;
}
printf("Expected type: NOSTR_URI_NPROFILE\n");
printf("Actual type: %d\n", result.type);
if (result.type != NOSTR_URI_NPROFILE) {
return 0;
}
// Verify the parsed pubkey matches the original
int pubkey_match = (memcmp(result.data.nprofile.pubkey, pubkey, 32) == 0);
printf("Pubkey matches original: %s\n", pubkey_match ? "yes" : "no");
// Verify relay count
printf("Expected relay count: 1\n");
printf("Actual relay count: %d\n", result.data.nprofile.relay_count);
return (result.type == NOSTR_URI_NPROFILE && pubkey_match && result.data.nprofile.relay_count == 1);
}
// Test 3: Parse nevent URI
int test_parse_nevent_uri(void) {
print_test_header("Parse nevent: URI");
// First build a valid nevent URI, then parse it
unsigned char event_id[32];
nostr_hex_to_bytes("f1e582c90f071c0110cc5bcac2dcc6d8c32250e3cc26fcbe93470d918f2ffaf0", event_id, 32);
const char* relays[] = {"wss://relay.example.com"};
char built_uri[400];
int build_result = nostr_build_uri_nevent(event_id, relays, 1, NULL, 1, 1234567890, built_uri, sizeof(built_uri));
if (build_result != NOSTR_SUCCESS) {
printf("Failed to build URI for testing: %d (%s)\n", build_result, nostr_strerror(build_result));
return 0;
}
printf("Input URI: %s\n", built_uri);
nostr_uri_result_t result;
int parse_result = nostr_parse_uri(built_uri, &result);
printf("Expected: NOSTR_SUCCESS (0)\n");
printf("Actual: %d (%s)\n", parse_result, nostr_strerror(parse_result));
if (parse_result != NOSTR_SUCCESS) {
return 0;
}
printf("Expected type: NOSTR_URI_NEVENT\n");
printf("Actual type: %d\n", result.type);
if (result.type != NOSTR_URI_NEVENT) {
return 0;
}
// Verify the parsed event ID matches the original
int event_id_match = (memcmp(result.data.nevent.event_id, event_id, 32) == 0);
printf("Event ID matches original: %s\n", event_id_match ? "yes" : "no");
// Verify kind
printf("Expected kind: 1\n");
printf("Actual kind: %d\n", result.data.nevent.kind ? *result.data.nevent.kind : -1);
// Verify relay count
printf("Expected relay count: 1\n");
printf("Actual relay count: %d\n", result.data.nevent.relay_count);
return (result.type == NOSTR_URI_NEVENT && event_id_match && result.data.nevent.relay_count == 1);
}
// Test 4: Parse naddr URI
int test_parse_naddr_uri(void) {
print_test_header("Parse naddr: URI");
// First build a valid naddr URI, then parse it
const char* identifier = "draft";
unsigned char pubkey[32];
nostr_hex_to_bytes("aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4", pubkey, 32);
const char* relays[] = {"wss://relay.example.com"};
char built_uri[400];
int build_result = nostr_build_uri_naddr(identifier, pubkey, 30023, relays, 1, built_uri, sizeof(built_uri));
if (build_result != NOSTR_SUCCESS) {
printf("Failed to build URI for testing: %d (%s)\n", build_result, nostr_strerror(build_result));
return 0;
}
printf("Input URI: %s\n", built_uri);
nostr_uri_result_t result;
int parse_result = nostr_parse_uri(built_uri, &result);
printf("Expected: NOSTR_SUCCESS (0)\n");
printf("Actual: %d (%s)\n", parse_result, nostr_strerror(parse_result));
if (parse_result != NOSTR_SUCCESS) {
return 0;
}
printf("Expected type: NOSTR_URI_NADDR\n");
printf("Actual type: %d\n", result.type);
if (result.type != NOSTR_URI_NADDR) {
return 0;
}
// Verify the parsed identifier matches the original
int identifier_match = (strcmp(result.data.naddr.identifier, identifier) == 0);
printf("Identifier matches original: %s\n", identifier_match ? "yes" : "no");
// Verify kind
printf("Expected kind: 30023\n");
printf("Actual kind: %d\n", result.data.naddr.kind);
// Verify relay count
printf("Expected relay count: 1\n");
printf("Actual relay count: %d\n", result.data.naddr.relay_count);
return (result.type == NOSTR_URI_NADDR && identifier_match && result.data.naddr.relay_count == 1);
}
// Test 5: Invalid URI (wrong prefix)
int test_invalid_uri_prefix(void) {
print_test_header("Invalid URI - Wrong Prefix");
const char* uri = "bitcoin:note1example";
printf("Input URI: %s\n", uri);
nostr_uri_result_t result;
int parse_result = nostr_parse_uri(uri, &result);
printf("Expected: NOSTR_ERROR_INVALID_INPUT (-1)\n");
printf("Actual: %d (%s)\n", parse_result, nostr_strerror(parse_result));
return (parse_result == NOSTR_ERROR_INVALID_INPUT);
}
// Test 6: Invalid URI (missing colon)
int test_invalid_uri_no_colon(void) {
print_test_header("Invalid URI - No Colon");
const char* uri = "nostrnote1example";
printf("Input URI: %s\n", uri);
nostr_uri_result_t result;
int parse_result = nostr_parse_uri(uri, &result);
printf("Expected: NOSTR_ERROR_INVALID_INPUT (-1)\n");
printf("Actual: %d (%s)\n", parse_result, nostr_strerror(parse_result));
return (parse_result == NOSTR_ERROR_INVALID_INPUT);
}
// Test 7: Build note URI
int test_build_note_uri(void) {
print_test_header("Build note: URI");
unsigned char event_id[32];
nostr_hex_to_bytes("f1e582c90f071c0110cc5bcac2dcc6d8c32250e3cc26fcbe93470d918f2ffaf0", event_id, 32);
printf("Input event ID: f1e582c90f071c0110cc5bcac2dcc6d8c32250e3cc26fcbe93470d918f2ffaf0\n");
char uri[200];
int result = nostr_build_uri_note(event_id, uri, sizeof(uri));
printf("Build result: %d (%s)\n", result, nostr_strerror(result));
if (result != NOSTR_SUCCESS) {
return 0;
}
printf("Built URI: %s\n", uri);
int success = (strncmp(uri, "nostr:note1", 11) == 0);
printf("Expected: URI starts with 'nostr:note1'\n");
printf("Actual: %s\n", success ? "yes" : "no");
return success;
}
// Test 8: Build nprofile URI
int test_build_nprofile_uri(void) {
print_test_header("Build nprofile: URI");
unsigned char pubkey[32];
nostr_hex_to_bytes("aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4", pubkey, 32);
const char* relays[] = {"wss://relay.example.com", "wss://relay2.example.com"};
printf("Input pubkey: aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4\n");
char uri[300];
int result = nostr_build_uri_nprofile(pubkey, relays, 2, uri, sizeof(uri));
printf("Build result: %d (%s)\n", result, nostr_strerror(result));
if (result != NOSTR_SUCCESS) {
return 0;
}
printf("Built URI: %s\n", uri);
int success = (strncmp(uri, "nostr:nprofile1", 14) == 0);
printf("Expected: URI starts with 'nostr:nprofile1'\n");
printf("Actual: %s\n", success ? "yes" : "no");
return success;
}
int main(void) {
printf("=== NIP-21 URI Scheme Test Suite ===\n");
printf("Following TESTS POLICY: Shows expected vs actual values\n");
// Initialize crypto library
if (nostr_init() != NOSTR_SUCCESS) {
printf("❌ Failed to initialize nostr library\n");
return 1;
}
int all_passed = 1;
int test_result;
// Valid URI parsing tests
test_result = test_parse_note_uri();
print_test_result(test_result, "Parse note: URI");
if (!test_result) all_passed = 0;
test_result = test_parse_nprofile_uri();
print_test_result(test_result, "Parse nprofile: URI");
if (!test_result) all_passed = 0;
test_result = test_parse_nevent_uri();
print_test_result(test_result, "Parse nevent: URI");
if (!test_result) all_passed = 0;
test_result = test_parse_naddr_uri();
print_test_result(test_result, "Parse naddr: URI");
if (!test_result) all_passed = 0;
// Invalid URI tests
test_result = test_invalid_uri_prefix();
print_test_result(test_result, "Invalid URI - Wrong Prefix");
if (!test_result) all_passed = 0;
test_result = test_invalid_uri_no_colon();
print_test_result(test_result, "Invalid URI - No Colon");
if (!test_result) all_passed = 0;
// URI building tests
test_result = test_build_note_uri();
print_test_result(test_result, "Build note: URI");
if (!test_result) all_passed = 0;
test_result = test_build_nprofile_uri();
print_test_result(test_result, "Build nprofile: URI");
if (!test_result) all_passed = 0;
// Summary
printf("\n=== TEST SUMMARY ===\n");
printf("Total tests: %d\n", test_count);
printf("Passed: %d\n", passed_tests);
printf("Failed: %d\n", test_count - passed_tests);
if (all_passed) {
printf("🎉 ALL TESTS PASSED! NIP-21 URI scheme implementation is working correctly.\n");
} else {
printf("❌ SOME TESTS FAILED. Please review the output above.\n");
}
nostr_cleanup();
return all_passed ? 0 : 1;
}