tests: add more tests

This commit is contained in:
Fernandez Ludovic 2025-11-22 02:37:28 +01:00
commit 2262d848b1
7 changed files with 168 additions and 21 deletions

View file

@ -1,9 +1,18 @@
package allinkl
import (
"encoding/json"
"encoding/xml"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/go-acme/lego/v4/platform/tester"
"github.com/go-acme/lego/v4/platform/tester/servermock"
"github.com/go-acme/lego/v4/providers/dns/allinkl/internal"
"github.com/stretchr/testify/require"
)
@ -143,3 +152,108 @@ func TestLiveCleanUp(t *testing.T) {
err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
require.NoError(t, err)
}
func mockBuilder() *servermock.Builder[*DNSProvider] {
return servermock.NewBuilder(
func(server *httptest.Server) (*DNSProvider, error) {
config := NewDefaultConfig()
config.Login = "user"
config.Password = "secret"
config.HTTPClient = server.Client()
p, err := NewDNSProviderConfig(config)
if err != nil {
return nil, err
}
p.client.BaseURL, _ = url.Parse(server.URL)
p.identifier.BaseURL, _ = url.Parse(server.URL)
return p, err
},
).Route("POST /KasAuth.php",
servermock.ResponseFromInternal("auth.xml"),
servermock.CheckRequestBodyFromInternal("auth-request.xml").
IgnoreWhitespace(),
)
}
func extractKasRequest(reader io.Reader) (*internal.KasRequest, error) {
type ReqEnvelope struct {
XMLName xml.Name `xml:"Envelope"`
Body struct {
KasAPI struct {
Params string `xml:"Params"`
} `xml:"KasApi"`
} `xml:"Body"`
}
raw, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
reqEnvelope := ReqEnvelope{}
err = xml.Unmarshal(raw, &reqEnvelope)
if err != nil {
return nil, err
}
var kReq internal.KasRequest
err = json.Unmarshal([]byte(reqEnvelope.Body.KasAPI.Params), &kReq)
if err != nil {
return nil, err
}
return &kReq, nil
}
func TestDNSProvider_Present(t *testing.T) {
provider := mockBuilder().
Route("POST /KasApi.php",
http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
kReq, err := extractKasRequest(req.Body)
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
switch kReq.Action {
case "get_dns_settings":
params := kReq.RequestParams.(map[string]any)
if params["zone_host"] == "_acme-challenge.example.com" {
servermock.ResponseFromInternal("get_dns_settings_not_found.xml").ServeHTTP(rw, req)
} else {
servermock.ResponseFromInternal("get_dns_settings.xml").ServeHTTP(rw, req)
}
case "add_dns_settings":
servermock.ResponseFromInternal("add_dns_settings.xml").ServeHTTP(rw, req)
default:
http.Error(rw, fmt.Sprintf("unknown action: %v", kReq.Action), http.StatusBadRequest)
}
}),
).
Build(t)
err := provider.Present("example.com", "abc", "123d==")
require.NoError(t, err)
}
func TestDNSProvider_CleanUp(t *testing.T) {
provider := mockBuilder().
Route("POST /KasApi.php",
servermock.ResponseFromInternal("delete_dns_settings.xml"),
servermock.CheckRequestBodyFromInternal("delete_dns_settings-request.xml").
IgnoreWhitespace()).
Build(t)
provider.recordIDs["abc"] = "57347450"
err := provider.CleanUp("example.com", "abc", "123d==")
require.NoError(t, err)
}

View file

@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
@ -15,7 +16,9 @@ import (
"github.com/go-viper/mapstructure/v2"
)
const apiEndpoint = "https://kasapi.kasserver.com/soap/KasApi.php"
const defaultBaseURL = "https://kasapi.kasserver.com/soap/"
const apiPath = "KasApi.php"
type Authentication interface {
Authentication(ctx context.Context, sessionLifetime int, sessionUpdateLifetime bool) (string, error)
@ -28,15 +31,17 @@ type Client struct {
floodTime time.Time
muFloodTime sync.Mutex
baseURL string
BaseURL *url.URL
HTTPClient *http.Client
}
// NewClient creates a new Client.
func NewClient(login string) *Client {
baseURL, _ := url.Parse(defaultBaseURL)
return &Client{
login: login,
baseURL: apiEndpoint,
BaseURL: baseURL,
HTTPClient: &http.Client{Timeout: 10 * time.Second},
}
}
@ -124,7 +129,9 @@ func (c *Client) newRequest(ctx context.Context, action string, requestParams an
payload := []byte(strings.TrimSpace(fmt.Sprintf(kasAPIEnvelope, body)))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, bytes.NewReader(payload))
endpoint := c.BaseURL.JoinPath(apiPath)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), bytes.NewReader(payload))
if err != nil {
return nil, fmt.Errorf("unable to create request: %w", err)
}

View file

@ -2,6 +2,7 @@ package internal
import (
"net/http/httptest"
"net/url"
"testing"
"github.com/go-acme/lego/v4/platform/tester/servermock"
@ -11,7 +12,7 @@ import (
func setupClient(server *httptest.Server) (*Client, error) {
client := NewClient("user")
client.baseURL = server.URL
client.BaseURL, _ = url.Parse(server.URL)
client.HTTPClient = server.Client()
return client, nil
@ -19,7 +20,7 @@ func setupClient(server *httptest.Server) (*Client, error) {
func TestClient_GetDNSSettings(t *testing.T) {
client := servermock.NewBuilder[*Client](setupClient).
Route("POST /", servermock.ResponseFromFixture("get_dns_settings.xml"),
Route("POST /KasApi.php", servermock.ResponseFromFixture("get_dns_settings.xml"),
servermock.CheckRequestBodyFromFixture("get_dns_settings-request.xml").
IgnoreWhitespace()).
Build(t)
@ -98,7 +99,7 @@ func TestClient_GetDNSSettings(t *testing.T) {
func TestClient_AddDNSSettings(t *testing.T) {
client := servermock.NewBuilder[*Client](setupClient).
Route("POST /", servermock.ResponseFromFixture("add_dns_settings.xml"),
Route("POST /KasApi.php", servermock.ResponseFromFixture("add_dns_settings.xml"),
servermock.CheckRequestBodyFromFixture("add_dns_settings-request.xml").
IgnoreWhitespace()).
Build(t)
@ -118,7 +119,7 @@ func TestClient_AddDNSSettings(t *testing.T) {
func TestClient_DeleteDNSSettings(t *testing.T) {
client := servermock.NewBuilder[*Client](setupClient).
Route("POST /", servermock.ResponseFromFixture("delete_dns_settings.xml"),
Route("POST /KasApi.php", servermock.ResponseFromFixture("delete_dns_settings.xml"),
servermock.CheckRequestBodyFromFixture("delete_dns_settings-request.xml").
IgnoreWhitespace()).
Build(t)

View file

@ -0,0 +1,7 @@
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<KasAuth xmlns="https://kasserver.com/">
<Params>{"kas_login":"user","kas_auth_data":"secret","kas_auth_type":"plain","session_lifetime":60,"session_update_lifetime":"Y"}</Params>
</KasAuth>
</Body>
</Envelope>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>zone_not_found</faultstring>
<faultactor>KasApi</faultactor>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View file

@ -6,14 +6,14 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
)
// authEndpoint represents the Identity API endpoint to call.
const authEndpoint = "https://kasapi.kasserver.com/soap/KasAuth.php"
const authPath = "KasAuth.php"
type token string
@ -24,17 +24,19 @@ type Identifier struct {
login string
password string
authEndpoint string
HTTPClient *http.Client
BaseURL *url.URL
HTTPClient *http.Client
}
// NewIdentifier creates a new Identifier.
func NewIdentifier(login, password string) *Identifier {
baseURL, _ := url.Parse(defaultBaseURL)
return &Identifier{
login: login,
password: password,
authEndpoint: authEndpoint,
HTTPClient: &http.Client{Timeout: 10 * time.Second},
login: login,
password: password,
BaseURL: baseURL,
HTTPClient: &http.Client{Timeout: 10 * time.Second},
}
}
@ -62,7 +64,9 @@ func (c *Identifier) Authentication(ctx context.Context, sessionLifetime int, se
payload := []byte(strings.TrimSpace(fmt.Sprintf(kasAuthEnvelope, body)))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.authEndpoint, bytes.NewReader(payload))
endpoint := c.BaseURL.JoinPath(authPath)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), bytes.NewReader(payload))
if err != nil {
return "", fmt.Errorf("unable to create request: %w", err)
}

View file

@ -3,6 +3,7 @@ package internal
import (
"context"
"net/http/httptest"
"net/url"
"testing"
"github.com/go-acme/lego/v4/platform/tester/servermock"
@ -12,7 +13,7 @@ import (
func setupIdentifierClient(server *httptest.Server) (*Identifier, error) {
client := NewIdentifier("user", "secret")
client.authEndpoint = server.URL
client.BaseURL, _ = url.Parse(server.URL)
client.HTTPClient = server.Client()
return client, nil
@ -26,10 +27,13 @@ func mockContext(t *testing.T) context.Context {
func TestIdentifier_Authentication(t *testing.T) {
client := servermock.NewBuilder[*Identifier](setupIdentifierClient).
Route("POST /", servermock.ResponseFromFixture("auth.xml")).
Route("POST /KasAuth.php",
servermock.ResponseFromFixture("auth.xml"),
servermock.CheckRequestBodyFromFixture("auth-request.xml").
IgnoreWhitespace()).
Build(t)
credentialToken, err := client.Authentication(t.Context(), 60, false)
credentialToken, err := client.Authentication(t.Context(), 60, true)
require.NoError(t, err)
assert.Equal(t, "593959ca04f0de9689b586c6a647d15d", credentialToken)
@ -37,7 +41,7 @@ func TestIdentifier_Authentication(t *testing.T) {
func TestIdentifier_Authentication_error(t *testing.T) {
client := servermock.NewBuilder[*Identifier](setupIdentifierClient).
Route("POST /", servermock.ResponseFromFixture("auth_fault.xml")).
Route("POST /KasAuth.php", servermock.ResponseFromFixture("auth_fault.xml")).
Build(t)
_, err := client.Authentication(t.Context(), 60, false)