Files
unibots/tools/http/http_test.go
T
agent fc644ecd6e feat: import agents_and_robots platform as unibots (Matrix-out, unibus transport)
Reemplaza el scaffold del echobot por la plataforma completa de bots traida
desde ~/DataProyects/Github/agents_and_robots tras la operacion Matrix-out:
los bots ya no hablan por Matrix sino por el bus unibus (modelo todo-rooms +
E2E via shell/transportunibus sobre github.com/enmanuel/unibus/pkg/client).

- go.mod: replace de unibus -> ../unibus y de fn-registry -> ../../../.. (paths
  relativos reajustados a la nueva ubicacion dentro de fn_registry).
- app.md: bump a 0.2.0, descripcion + arquitectura + comandos + gotchas reales.
- modulo Go conservado como github.com/enmanuel/agents (sin reescribir imports).

agents_and_robots queda archivado como museo de la era Matrix.
2026-06-07 11:50:13 +02:00

125 lines
3.1 KiB
Go

package http
import (
"net"
"testing"
)
func TestValidateDomain_EmptyAllowed(t *testing.T) {
if err := validateDomain("example.com", nil); err != nil {
t.Fatalf("empty list should allow all: %v", err)
}
}
func TestValidateDomain_Allowed(t *testing.T) {
if err := validateDomain("api.example.com", []string{"api.example.com"}); err != nil {
t.Fatalf("should be allowed: %v", err)
}
}
func TestValidateDomain_Denied(t *testing.T) {
if err := validateDomain("evil.com", []string{"api.example.com"}); err == nil {
t.Fatal("should be denied")
}
}
func TestValidateDomain_CaseInsensitive(t *testing.T) {
if err := validateDomain("API.Example.COM", []string{"api.example.com"}); err != nil {
t.Fatalf("should be case-insensitive: %v", err)
}
}
func TestRejectInternalHost_Localhost(t *testing.T) {
if err := rejectInternalHost("localhost"); err == nil {
t.Fatal("localhost should be blocked")
}
}
func TestRejectInternalHost_Loopback(t *testing.T) {
if err := rejectInternalHost("127.0.0.1"); err == nil {
t.Fatal("loopback should be blocked")
}
}
func TestRejectInternalHost_IPv6Loopback(t *testing.T) {
if err := rejectInternalHost("::1"); err == nil {
t.Fatal("IPv6 loopback should be blocked")
}
}
func TestRejectInternalHost_PrivateA(t *testing.T) {
if err := rejectInternalHost("10.0.0.1"); err == nil {
t.Fatal("10.x should be blocked")
}
}
func TestRejectInternalHost_PrivateB(t *testing.T) {
if err := rejectInternalHost("172.16.0.1"); err == nil {
t.Fatal("172.16.x should be blocked")
}
}
func TestRejectInternalHost_PrivateC(t *testing.T) {
if err := rejectInternalHost("192.168.1.1"); err == nil {
t.Fatal("192.168.x should be blocked")
}
}
func TestRejectInternalHost_LinkLocal(t *testing.T) {
if err := rejectInternalHost("169.254.1.1"); err == nil {
t.Fatal("link-local should be blocked")
}
}
func TestRejectInternalHost_Metadata(t *testing.T) {
if err := rejectInternalHost("169.254.169.254"); err == nil {
t.Fatal("metadata IP should be blocked")
}
}
func TestRejectInternalHost_PublicIP(t *testing.T) {
if err := rejectInternalHost("8.8.8.8"); err != nil {
t.Fatalf("public IP should be allowed: %v", err)
}
}
func TestIsPrivateIP(t *testing.T) {
cases := []struct {
ip string
want bool
}{
{"127.0.0.1", true},
{"10.0.0.1", true},
{"172.16.0.1", true},
{"192.168.0.1", true},
{"169.254.169.254", true},
{"8.8.8.8", false},
{"1.1.1.1", false},
}
for _, c := range cases {
ip := net.ParseIP(c.ip)
got := isPrivateIP(ip)
if got != c.want {
t.Errorf("isPrivateIP(%s) = %v, want %v", c.ip, got, c.want)
}
}
}
func TestValidateURL_Valid(t *testing.T) {
if err := validateURL("https://example.com/api", nil); err != nil {
t.Fatalf("public URL should pass: %v", err)
}
}
func TestValidateURL_InternalIP(t *testing.T) {
if err := validateURL("http://127.0.0.1:8080/admin", nil); err == nil {
t.Fatal("internal IP in URL should be blocked")
}
}
func TestValidateURL_NoHost(t *testing.T) {
if err := validateURL("file:///etc/passwd", nil); err == nil {
t.Fatal("URL with no host should be rejected")
}
}