package forage import ( "testing" "git.mleku.dev/mleku/dendrite/pkg/gap" "git.mleku.dev/mleku/dendrite/pkg/ratio" ) func TestAppetite(t *testing.T) { gaps := []gap.Gap{ {Type: "missing_site", Tag: "hashtag", Severity: ratio.Half, Count: 10}, {Type: "orphan_event", Tag: "event", Severity: ratio.New(4, 5), Count: 20}, {Type: "low_occupancy", Tag: "occupancy", Severity: ratio.New(7, 10), Count: 50}, } needs := Appetite(gaps) if len(needs) != 3 { t.Fatalf("expected 3 needs, got %d", len(needs)) } // Highest priority first. if needs[0].Priority.Less(needs[1].Priority) { t.Error("needs should be sorted by priority descending") } // Check need types. if needs[0].Type != NeedSpecification { // orphan_event → specification t.Errorf("expected specification need for orphan, got %s", needs[0].Type) } } func TestURLForNeed(t *testing.T) { tests := []struct { need Need want string }{ { need: Need{Topic: "NIP-42"}, want: "https://raw.githubusercontent.com/nostr-protocol/nips/master/42.md", }, { need: Need{Topic: "encoding/json"}, want: "https://pkg.go.dev/encoding/json", }, { need: Need{Topic: "how to improve occupancy"}, want: "", // no known URL pattern }, } for _, tt := range tests { got := URLForNeed(tt.need) if got != tt.want { t.Errorf("URLForNeed(%q) = %q, want %q", tt.need.Topic, got, tt.want) } } } func TestExtractDomain(t *testing.T) { tests := []struct { url string want string }{ {"https://go.dev/doc/effective_go", "go.dev"}, {"https://pkg.go.dev/encoding/json", "pkg.go.dev"}, {"https://github.com:443/nostr/nips", "github.com"}, {"http://localhost:8080/path", "localhost"}, } for _, tt := range tests { got := extractDomain(tt.url) if got != tt.want { t.Errorf("extractDomain(%q) = %q, want %q", tt.url, got, tt.want) } } } func TestDomainWhitelist(t *testing.T) { f := NewForager() if !f.DomainWhitelist["go.dev"] { t.Error("go.dev should be whitelisted") } if f.DomainWhitelist["evil.com"] { t.Error("evil.com should not be whitelisted") } } func TestDigestMarkdown(t *testing.T) { md := []byte(`# NIP-42: Authentication Relays may require authentication. ` + "```go" + ` func handleAuth(ev *Event) { // verify signature } ` + "```" + ` Create a challenge and send it to the client. `) elems := digestMarkdown(md) if len(elems) == 0 { t.Fatal("expected elements from markdown") } types := make(map[string]int) for _, e := range elems { types[e.Type()]++ } if types["heading"] == 0 { t.Error("expected heading elements") } if types["code"] == 0 { t.Error("expected code elements") } if types["word"] == 0 { t.Error("expected word elements") } } func TestDigestGoSource(t *testing.T) { src := []byte(`package main import "fmt" type Relay struct { Name string } func (r *Relay) Start() { fmt.Println("starting") } `) elems := digestGoSource(src) types := make(map[string]int) for _, e := range elems { types[e.Type()]++ } if types["package"] == 0 { t.Error("expected package element") } if types["import"] == 0 { t.Error("expected import element") } if types["type"] == 0 { t.Error("expected type element") } if types["func"] == 0 { t.Error("expected func element") } } func TestDigestHTML(t *testing.T) { html := []byte(`

Title

Some text here with bold words.

`) elems := digestHTML(html) if len(elems) == 0 { t.Fatal("expected elements from HTML") } } func TestStripHTMLTags(t *testing.T) { html := `

Hello world

` got := stripHTMLTags(html) if got != " Hello world " { t.Errorf("stripHTMLTags = %q", got) } } func TestBandwidthCap(t *testing.T) { f := NewForager() f.MaxBytesPerGen = 100 f.SetGeneration(0) if f.BytesRemaining() != 100 { t.Errorf("expected 100 bytes remaining, got %d", f.BytesRemaining()) } // Simulate usage. f.mu.Lock() f.bytesUsed = 80 f.mu.Unlock() if f.BytesRemaining() != 20 { t.Errorf("expected 20 bytes remaining, got %d", f.BytesRemaining()) } } func TestFilterUsefulSources(t *testing.T) { records := []SourceRecord{ {URL: "https://go.dev/a", BondRatio: 0.8}, {URL: "https://go.dev/b", BondRatio: 0.1}, {URL: "https://go.dev/c", BondRatio: 0.5}, } useful := FilterUsefulSources(records, 0.3) if len(useful) != 2 { t.Errorf("expected 2 useful sources, got %d", len(useful)) } } func TestDigestRoutesCorrectly(t *testing.T) { // Markdown by URL suffix. md := &FetchResult{ URL: "https://example.com/doc.md", Body: []byte("# Hello\n\nWorld"), StatusCode: 200, } elems := Digest(md) if len(elems) == 0 { t.Error("expected elements from .md URL") } // Go source. goSrc := &FetchResult{ URL: "https://example.com/main.go", Body: []byte("package main\n\nfunc main() {}"), StatusCode: 200, } elems = Digest(goSrc) hasFunc := false for _, e := range elems { if e.Type() == "func" { hasFunc = true } } if !hasFunc { t.Error("expected func element from .go source") } // Failed fetch should return nil. failed := &FetchResult{ URL: "https://example.com/404", StatusCode: 404, } if Digest(failed) != nil { t.Error("expected nil from failed fetch") } }