Initial vibeproxy implementation
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
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user