mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 16:46:17 +00:00
Refuse to start the DNS server and reject Settings updates whose server_url does not resolve to a routable IP. Without this, a misconfigured hostname caused the DNS server to answer every intercepted Bose hostname with `CNAME .`, leaving speakers unable to reach the service while everything looked healthy. The Settings page now displays the resolved intercept IP (or the resolve error) next to "Target Domain", so misconfigurations are visible up front instead of buried in the DNS log. Refs #269 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
2.3 KiB
Go
87 lines
2.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/gesellix/bose-soundtouch/pkg/service/datastore"
|
|
)
|
|
|
|
func TestDNSSettingsValidation(t *testing.T) {
|
|
tempDir, err := os.MkdirTemp("", "dns-validation-test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
ds := datastore.NewDataStore(tempDir)
|
|
_ = ds.Initialize()
|
|
|
|
r, server := setupRouter("http://localhost:8001", ds)
|
|
|
|
// Test Case 1: Enable DNS with empty upstream (should fallback to system DNS)
|
|
update := map[string]interface{}{
|
|
"server_url": "http://localhost:8001",
|
|
"dns_enabled": true,
|
|
"dns_upstream": "",
|
|
"dns_bind_addr": ":5353",
|
|
}
|
|
|
|
body, err := json.Marshal(update)
|
|
if err != nil {
|
|
t.Fatalf("Failed to marshal update: %v", err)
|
|
}
|
|
req := httptest.NewRequest("POST", "/setup/settings", bytes.NewBuffer(body))
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("Expected status 200 when enabling DNS without upstream (fallback to system), got %d. Body: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
// Verify DNS state in server
|
|
if !server.dnsEnabled {
|
|
t.Error("DNS should be enabled in server state")
|
|
}
|
|
|
|
// Verify it TRIED to start (either it is running, or it failed due to port conflict but state is enabled)
|
|
if !server.dnsEnabled {
|
|
t.Error("DNS state should be enabled")
|
|
}
|
|
|
|
// Test Case 2: Enable DNS with valid upstream
|
|
// Using a random port to avoid conflicts and ensure it's fast
|
|
updateValid := map[string]interface{}{
|
|
"server_url": "http://localhost:8001",
|
|
"dns_enabled": true,
|
|
"dns_upstream": "8.8.8.8",
|
|
"dns_bind_addr": "127.0.0.1:0", // Random port
|
|
}
|
|
|
|
bodyValid, err := json.Marshal(updateValid)
|
|
if err != nil {
|
|
t.Fatalf("Failed to marshal updateValid: %v", err)
|
|
}
|
|
reqValid := httptest.NewRequest("POST", "/setup/settings", bytes.NewBuffer(bodyValid))
|
|
wValid := httptest.NewRecorder()
|
|
r.ServeHTTP(wValid, reqValid)
|
|
|
|
if wValid.Code != http.StatusOK {
|
|
t.Errorf("Expected status 200 when enabling DNS with valid upstream, got %d. Body: %s", wValid.Code, wValid.Body.String())
|
|
}
|
|
|
|
// Verify DNS state in server
|
|
if !server.dnsEnabled {
|
|
t.Error("DNS should be enabled in server state")
|
|
}
|
|
|
|
// Shutdown server to clean up
|
|
if server.dnsDiscovery != nil {
|
|
_ = server.dnsDiscovery.Shutdown()
|
|
}
|
|
}
|