Self-contained HTTP/HTTPS/TCP/UDP reverse proxy manager written in Go, with SQLite storage, a Bootstrap 5 admin UI (Go templates, no JS framework), and a REST API under /api/v1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QTXFrNP1imCW7jtfL5SZrw
88 lines
2.5 KiB
Go
88 lines
2.5 KiB
Go
package database
|
|
|
|
import (
|
|
"database/sql"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/owen/vibeproxy/internal/models"
|
|
)
|
|
|
|
func openTest(t *testing.T) *sql.DB {
|
|
t.Helper()
|
|
db, err := Open(filepath.Join(t.TempDir(), "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { db.Close() })
|
|
return db
|
|
}
|
|
|
|
func TestMigrateAndProxyHostRoundTrip(t *testing.T) {
|
|
db := openTest(t)
|
|
|
|
h := models.ProxyHost{
|
|
Name: "test", Type: models.ProxyHostTypeProxy, Domains: []string{"a.example.com", "b.example.com"},
|
|
ForwardScheme: "http", LoadBalancingMethod: "round_robin", Enabled: true,
|
|
ConnectTimeoutMS: 5000, ReadTimeoutMS: 60000, WriteTimeoutMS: 60000, IdleTimeoutMS: 120000,
|
|
Backends: []models.Backend{
|
|
{Host: "10.0.0.1", Port: 8080, Weight: 1, Enabled: true, HealthCheckType: models.HealthCheckTCP, IntervalSeconds: 10, FailureThreshold: 3, RecoveryThreshold: 2},
|
|
},
|
|
CustomHeaders: []models.CustomHeader{
|
|
{Direction: models.HeaderDirectionResponse, Action: models.HeaderActionSet, Name: "X-Frame-Options", Value: "DENY"},
|
|
},
|
|
}
|
|
id, err := SaveProxyHost(db, &h)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if id == 0 {
|
|
t.Fatal("expected non-zero id")
|
|
}
|
|
|
|
fetched, err := GetProxyHost(db, id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fetched.Name != "test" || len(fetched.Domains) != 2 || len(fetched.Backends) != 1 || len(fetched.CustomHeaders) != 1 {
|
|
t.Fatalf("round trip mismatch: %+v", fetched)
|
|
}
|
|
|
|
// Update should replace domains/backends/headers cleanly.
|
|
fetched.Domains = []string{"only.example.com"}
|
|
fetched.Backends[0].Port = 9090
|
|
if _, err := SaveProxyHost(db, fetched); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
updated, err := GetProxyHost(db, id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(updated.Domains) != 1 || updated.Domains[0] != "only.example.com" {
|
|
t.Fatalf("expected domains replaced, got %v", updated.Domains)
|
|
}
|
|
if updated.Backends[0].Port != 9090 {
|
|
t.Fatalf("expected backend port updated, got %d", updated.Backends[0].Port)
|
|
}
|
|
|
|
if err := DeleteProxyHost(db, id); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := GetProxyHost(db, id); err != ErrNotFound {
|
|
t.Fatalf("expected ErrNotFound after delete, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSettingsRoundTrip(t *testing.T) {
|
|
db := openTest(t)
|
|
if err := SetSetting(db, "acme_email", "ops@example.com"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := GetSetting(db, "acme_email", ""); got != "ops@example.com" {
|
|
t.Fatalf("expected ops@example.com, got %q", got)
|
|
}
|
|
if got := GetSetting(db, "missing_key", "fallback"); got != "fallback" {
|
|
t.Fatalf("expected fallback default, got %q", got)
|
|
}
|
|
}
|