136 lines
4.5 KiB
Go
136 lines
4.5 KiB
Go
package server_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context" // Added for mock provider
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"git.cloonar.com/cloonar/updns/internal/config" // Added for mock provider
|
|
"git.cloonar.com/cloonar/updns/internal/server"
|
|
"go.uber.org/zap" // Added for logger
|
|
)
|
|
|
|
// mockProvider is a simple mock for testing router logic without real provider interaction.
|
|
type mockProvider struct {
|
|
updateErr error // Allows simulating update errors
|
|
}
|
|
|
|
func (m *mockProvider) UpdateRecord(ctx context.Context, host, ip string) error {
|
|
return m.updateErr
|
|
}
|
|
|
|
func newTestConfig(provider string) *config.Config {
|
|
return &config.Config{
|
|
Server: config.ServerConfig{
|
|
BindAddress: ":0",
|
|
TLS: config.TLSConfig{Enabled: false},
|
|
},
|
|
Upstream: config.UpstreamConfig{
|
|
Provider: provider,
|
|
Hetzner: config.HetznerConfig{APIToken: "token"},
|
|
},
|
|
Clients: map[string]config.ClientConfig{
|
|
"client1": {
|
|
Secret: "s3cr3t",
|
|
Exact: []string{"a.example.com"},
|
|
Wildcard: []string{"example.net"},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestMetricsEndpoint(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
mockProv := &mockProvider{}
|
|
r := server.NewRouter(newTestConfig("unknown"), logger, mockProv)
|
|
req := httptest.NewRequest("GET", "/metrics", nil)
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 OK, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestUpdateInvalidJSON(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
mockProv := &mockProvider{}
|
|
r := server.NewRouter(newTestConfig("unknown"), logger, mockProv)
|
|
req := httptest.NewRequest("POST", "/update", bytes.NewBufferString("{invalid"))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("expected 400 BadRequest, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestUpdateUnauthorizedKey(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
mockProv := &mockProvider{}
|
|
r := server.NewRouter(newTestConfig("unknown"), logger, mockProv)
|
|
body := map[string]string{"key": "bad", "secret": "x", "host": "a.example.com"}
|
|
data, _ := json.Marshal(body)
|
|
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusUnauthorized {
|
|
t.Errorf("expected 401 Unauthorized, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestUpdateHostForbidden(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
mockProv := &mockProvider{}
|
|
r := server.NewRouter(newTestConfig("unknown"), logger, mockProv)
|
|
body := map[string]string{"key": "client1", "secret": "s3cr3t", "host": "bad.example.com"}
|
|
data, _ := json.Marshal(body)
|
|
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusForbidden {
|
|
t.Errorf("expected 403 Forbidden, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
// Note: This test case name is slightly misleading now. The router itself doesn't care
|
|
// about the provider name from config anymore, as the provider is passed in.
|
|
// The provider initialization logic is tested separately or in StartServer tests.
|
|
// We keep the test to ensure the update path works correctly when auth passes.
|
|
// If the *mock* provider returned an error, we'd get 500.
|
|
func TestUpdateProviderInteraction(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
// Simulate a provider error
|
|
mockProv := &mockProvider{updateErr: errors.New("simulated provider update error")}
|
|
r := server.NewRouter(newTestConfig("hetzner"), logger, mockProv) // Config provider name doesn't matter here
|
|
body := map[string]string{"key": "client1", "secret": "s3cr3t", "host": "a.example.com"}
|
|
data, _ := json.Marshal(body)
|
|
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusInternalServerError {
|
|
t.Errorf("expected 500 InternalServerError, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestUpdateSuccess(t *testing.T) {
|
|
logger := zap.NewNop()
|
|
mockProv := &mockProvider{} // No error for success case
|
|
r := server.NewRouter(newTestConfig("hetzner"), logger, mockProv)
|
|
body := map[string]string{"key": "client1", "secret": "s3cr3t", "host": "a.example.com", "ip": "1.2.3.4"}
|
|
data, _ := json.Marshal(body)
|
|
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
r.ServeHTTP(w, req)
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected 200 OK, got %d", w.Code)
|
|
}
|
|
}
|