mirror of
https://github.com/go-acme/lego
synced 2026-03-14 14:35:48 +01:00
294 lines
6.7 KiB
Go
294 lines
6.7 KiB
Go
package internal
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/go-acme/lego/v4/platform/tester/servermock"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func mockBuilder(password string) *servermock.Builder[*Client] {
|
|
return servermock.NewBuilder[*Client](
|
|
func(server *httptest.Server) (*Client, error) {
|
|
client := NewClient("apiuser", password)
|
|
client.HTTPClient = server.Client()
|
|
client.BaseURL = server.URL + "/"
|
|
|
|
return client, nil
|
|
},
|
|
servermock.CheckHeader().WithContentType("text/xml"),
|
|
)
|
|
}
|
|
|
|
func TestClient_AddZoneRecord(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
password string
|
|
domain string
|
|
request string
|
|
response string
|
|
err string
|
|
}{
|
|
{
|
|
desc: "auth ok",
|
|
password: "goodpassword",
|
|
domain: exampleDomain,
|
|
request: addZoneRecordGoodAuth,
|
|
response: responseOk,
|
|
},
|
|
{
|
|
desc: "auth error",
|
|
password: "badpassword",
|
|
domain: exampleDomain,
|
|
request: addZoneRecordBadAuth,
|
|
response: responseAuthError,
|
|
err: "authentication error",
|
|
},
|
|
{
|
|
desc: "unknown error",
|
|
password: "goodpassword",
|
|
domain: "badexample.com",
|
|
request: addZoneRecordNonValidDomain,
|
|
response: responseUnknownError,
|
|
err: `unknown error: "UNKNOWN_ERROR"`,
|
|
},
|
|
{
|
|
desc: "empty response",
|
|
password: "goodpassword",
|
|
domain: "empty.com",
|
|
request: addZoneRecordEmptyResponse,
|
|
response: "",
|
|
err: "unmarshal error: EOF",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
client := mockBuilder(test.password).
|
|
Route("POST /",
|
|
servermock.RawStringResponse(test.response),
|
|
servermock.CheckRequestBody(test.request)).
|
|
Build(t)
|
|
|
|
err := client.AddTXTRecord(t.Context(), test.domain, exampleSubDomain, 123, "TXTrecord")
|
|
if test.err == "" {
|
|
require.NoError(t, err)
|
|
} else {
|
|
require.Error(t, err)
|
|
assert.EqualError(t, err, test.err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClient_RemoveSubdomain(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
password string
|
|
domain string
|
|
request string
|
|
response string
|
|
err string
|
|
}{
|
|
{
|
|
desc: "auth ok",
|
|
password: "goodpassword",
|
|
domain: exampleDomain,
|
|
request: removeSubdomainGoodAuth,
|
|
response: responseOk,
|
|
},
|
|
{
|
|
desc: "auth error",
|
|
password: "badpassword",
|
|
domain: exampleDomain,
|
|
request: removeSubdomainBadAuth,
|
|
response: responseAuthError,
|
|
err: "authentication error",
|
|
},
|
|
{
|
|
desc: "unknown error",
|
|
password: "goodpassword",
|
|
domain: "badexample.com",
|
|
request: removeSubdomainNonValidDomain,
|
|
response: responseUnknownError,
|
|
err: `unknown error: "UNKNOWN_ERROR"`,
|
|
},
|
|
{
|
|
desc: "empty response",
|
|
password: "goodpassword",
|
|
domain: "empty.com",
|
|
request: removeSubdomainEmptyResponse,
|
|
response: "",
|
|
err: "unmarshal error: EOF",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
client := mockBuilder(test.password).
|
|
Route("POST /",
|
|
servermock.RawStringResponse(test.response),
|
|
servermock.CheckRequestBody(test.request)).
|
|
Build(t)
|
|
|
|
err := client.RemoveSubdomain(t.Context(), test.domain, exampleSubDomain)
|
|
if test.err == "" {
|
|
require.NoError(t, err)
|
|
} else {
|
|
require.Error(t, err)
|
|
assert.EqualError(t, err, test.err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClient_RemoveZoneRecord(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
password string
|
|
domain string
|
|
request string
|
|
response string
|
|
err string
|
|
}{
|
|
{
|
|
desc: "auth ok",
|
|
password: "goodpassword",
|
|
domain: exampleDomain,
|
|
request: removeRecordGoodAuth,
|
|
response: responseOk,
|
|
},
|
|
{
|
|
desc: "auth error",
|
|
password: "badpassword",
|
|
domain: exampleDomain,
|
|
request: removeRecordBadAuth,
|
|
response: responseAuthError,
|
|
err: "authentication error",
|
|
},
|
|
{
|
|
desc: "uknown error",
|
|
password: "goodpassword",
|
|
domain: "badexample.com",
|
|
request: removeRecordNonValidDomain,
|
|
response: responseUnknownError,
|
|
err: `unknown error: "UNKNOWN_ERROR"`,
|
|
},
|
|
{
|
|
desc: "empty response",
|
|
password: "goodpassword",
|
|
domain: "empty.com",
|
|
request: removeRecordEmptyResponse,
|
|
response: "",
|
|
err: "unmarshal error: EOF",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
client := mockBuilder(test.password).
|
|
Route("POST /",
|
|
servermock.RawStringResponse(test.response),
|
|
servermock.CheckRequestBody(test.request)).
|
|
Build(t)
|
|
|
|
err := client.RemoveTXTRecord(t.Context(), test.domain, exampleSubDomain, 12345678)
|
|
if test.err == "" {
|
|
require.NoError(t, err)
|
|
} else {
|
|
require.Error(t, err)
|
|
assert.EqualError(t, err, test.err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestClient_GetZoneRecord(t *testing.T) {
|
|
client := mockBuilder("goodpassword").
|
|
Route("POST /",
|
|
servermock.RawStringResponse(getZoneRecordsResponse),
|
|
servermock.CheckRequestBody(getZoneRecords)).
|
|
Build(t)
|
|
|
|
recordObjs, err := client.GetTXTRecords(t.Context(), exampleDomain, exampleSubDomain)
|
|
require.NoError(t, err)
|
|
|
|
expected := []RecordObj{
|
|
{
|
|
Type: "TXT",
|
|
TTL: 300,
|
|
Priority: 0,
|
|
Rdata: exampleRdata,
|
|
RecordID: 12345678,
|
|
},
|
|
}
|
|
assert.Equal(t, expected, recordObjs)
|
|
}
|
|
|
|
func TestClient_rpcCall_404(t *testing.T) {
|
|
client := mockBuilder("apipassword").
|
|
Route("POST /",
|
|
servermock.RawStringResponse("<?xml version='1.0' encoding='UTF-8'?>").
|
|
WithStatusCode(http.StatusNotFound)).
|
|
Build(t)
|
|
|
|
call := &methodCall{
|
|
MethodName: "dummyMethod",
|
|
Params: []param{
|
|
paramString{Value: "test1"},
|
|
},
|
|
}
|
|
|
|
err := client.rpcCall(t.Context(), call, &responseString{})
|
|
require.EqualError(t, err, "unexpected status code: [status code: 404] body: <?xml version='1.0' encoding='UTF-8'?>")
|
|
}
|
|
|
|
func TestClient_rpcCall_RPCError(t *testing.T) {
|
|
client := mockBuilder("apipassword").
|
|
Route("POST /",
|
|
servermock.RawStringResponse(responseRPCError)).
|
|
Build(t)
|
|
|
|
call := &methodCall{
|
|
MethodName: "getDomains",
|
|
Params: []param{
|
|
paramString{Value: "test1"},
|
|
},
|
|
}
|
|
|
|
err := client.rpcCall(t.Context(), call, &responseString{})
|
|
require.EqualError(t, err, "RPC Error: (201) Method signature error: 42")
|
|
}
|
|
|
|
func TestUnmarshallFaultyRecordObject(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
xml string
|
|
}{
|
|
{
|
|
desc: "faulty name",
|
|
xml: "<name>name<name>",
|
|
},
|
|
{
|
|
desc: "faulty string",
|
|
xml: "<value><string>foo<string></value>",
|
|
},
|
|
{
|
|
desc: "faulty int",
|
|
xml: "<value><int>1<int></value>",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
resp := &RecordObj{}
|
|
|
|
err := xml.Unmarshal([]byte(test.xml), resp)
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
}
|