1package daemon23import (4 "context"5 "encoding/json"6 "net/http"7 "net/http/httptest"8 "testing"9 "time"1011 "github.com/FelineStateMachine/tinyrelay/internal/policy"12)1314func TestCapabilityRegistryReportsHonestOptionalFeatures(t *testing.T) {15 monitor, err := NewPeerMonitor(PeerMonitorConfig{Peers: []string{"https://peer.example"}, Publish: false})16 if err != nil {17 t.Fatal(err)18 }19 capabilities := CapabilityRegistryWithServices(policy.Policy{Features: policy.Features{Grasp: true}}, true, true, monitor)20 got := map[string]Capability{}21 for _, capability := range capabilities {22 got[capability.ID] = capability23 }24 if got["NIP-34"].Status != "enabled" || got["GRASP"].Status != "enabled" {25 t.Fatalf("Git capabilities = %#v", got)26 }27 if got["BUD-01"].Status != "enabled" || got["BUD-06"].Status != "enabled" || got["NIP-66"].Status != "configured" {28 t.Fatalf("optional capabilities = %#v", got)29 }30 if got["NIP-94"].Status != "enabled" || got["NIP-96"].Status != "enabled" {31 t.Fatalf("file capabilities = %#v", got)32 }33 if got["BUD-08"].Status != "enabled" || got["BUD-13"].Status != "enabled" {34 t.Fatalf("file metadata and upload capabilities = %#v", got)35 }36}3738func TestPublishPeerStatusStoresSignedDiscoveryEvent(t *testing.T) {39 _, tenant := testTenant(t)40 if err := tenant.PublishPeerStatus(context.Background(), []PeerStatus{{URL: "https://peer.example", Up: true}}); err != nil {41 t.Fatal(err)42 }43 var raw string44 if err := tenant.store.DB().QueryRow(`SELECT raw FROM events WHERE kind=? ORDER BY seq DESC LIMIT 1`, 30166).Scan(&raw); err != nil {45 t.Fatal(err)46 }47 var stored struct {48 ID string `json:"id"`49 PubKey string `json:"pubkey"`50 Sig string `json:"sig"`51 }52 if err := json.Unmarshal([]byte(raw), &stored); err != nil {53 t.Fatal(err)54 }55 if stored.ID == "" || stored.PubKey == "" || stored.Sig == "" {56 t.Fatalf("discovery event is not signed: %#v", stored)57 }58 if stored.PubKey != tenant.records.PublicKey() {59 t.Fatalf("publisher = %q, relay identity = %q", stored.PubKey, tenant.records.PublicKey())60 }61}6263func TestCapabilityRegistryDisablesUnmountedBlobDoors(t *testing.T) {64 for _, capability := range CapabilityRegistry(policy.Policy{}, false, nil) {65 if len(capability.ID) > 4 && capability.ID[:4] == "BUD-" && capability.Status == "enabled" {66 t.Fatalf("unmounted blob capability advertised: %#v", capability)67 }68 }69}7071func TestPeerMonitorProbesOnlyConfiguredPeers(t *testing.T) {72 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {73 if r.Header.Get("Accept") != "application/nostr+json" {74 t.Errorf("accept = %q", r.Header.Get("Accept"))75 }76 w.WriteHeader(http.StatusOK)77 }))78 defer server.Close()79 var outcomes []string80 monitor, err := NewPeerMonitor(PeerMonitorConfig{Peers: []string{server.URL}, Timeout: time.Second, Observe: func(outcome string, _ time.Duration) { outcomes = append(outcomes, outcome) }})81 if err != nil {82 t.Fatal(err)83 }84 if err := monitor.Probe(context.Background()); err != nil {85 t.Fatal(err)86 }87 peers := monitor.Peers()88 if len(peers) != 1 || peers[0] != server.URL {89 t.Fatalf("peers = %#v", peers)90 }91 snapshot := monitor.Snapshot()92 if len(snapshot) != 1 || !snapshot[0].Up || snapshot[0].LastSuccess.IsZero() || len(outcomes) != 1 || outcomes[0] != "ok" {93 t.Fatalf("snapshot = %#v outcomes = %#v", snapshot, outcomes)94 }95}9697func TestPeerMonitorRejectsUnboundedConfiguration(t *testing.T) {98 if _, err := NewPeerMonitor(PeerMonitorConfig{Peers: []string{"wss://public.example", "not a URL"}}); err == nil {99 t.Fatal("invalid peer configuration accepted")100 }101}102103func TestPeerMonitorPublicationRequiresPublisher(t *testing.T) {104 withoutPublisher, err := NewPeerMonitor(PeerMonitorConfig{Peers: []string{"https://peer.example"}, Publish: true})105 if err != nil {106 t.Fatal(err)107 }108 if withoutPublisher.PublicationEnabled() {109 t.Fatal("publication marked enabled without publisher")110 }111 withPublisher, err := NewPeerMonitor(PeerMonitorConfig{Peers: []string{"https://peer.example"}, Publish: true, PublishFunc: func(context.Context, []PeerStatus) error { return nil }})112 if err != nil {113 t.Fatal(err)114 }115 if !withPublisher.PublicationEnabled() {116 t.Fatal("configured publisher not recognized")117 }118}