2024-06-19 03:44:05 +03:00
|
|
|
package caddytest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/aryann/difflib"
|
|
|
|
"github.com/caddyserver/caddy/v2/caddyconfig"
|
2024-06-19 03:46:43 +03:00
|
|
|
"github.com/stretchr/testify/require"
|
2024-06-19 03:44:05 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// AssertLoadError will load a config and expect an error
|
|
|
|
func AssertLoadError(t *testing.T, rawConfig string, configType string, expectedError string) {
|
2024-06-19 03:46:43 +03:00
|
|
|
tc, err := NewTester()
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = tc.LaunchCaddy()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = tc.LoadConfig(rawConfig, configType)
|
2024-06-19 03:44:05 +03:00
|
|
|
if !strings.Contains(err.Error(), expectedError) {
|
|
|
|
t.Errorf("expected error \"%s\" but got \"%s\"", expectedError, err.Error())
|
|
|
|
}
|
2024-06-19 04:14:51 +03:00
|
|
|
tc.CleanupCaddy()
|
2024-06-19 03:44:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// CompareAdapt adapts a config and then compares it against an expected result
|
|
|
|
func CompareAdapt(t testing.TB, filename, rawConfig string, adapterName string, expectedResponse string) bool {
|
|
|
|
cfgAdapter := caddyconfig.GetAdapter(adapterName)
|
|
|
|
if cfgAdapter == nil {
|
|
|
|
t.Logf("unrecognized config adapter '%s'", adapterName)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
options := make(map[string]any)
|
|
|
|
|
|
|
|
result, warnings, err := cfgAdapter.Adapt([]byte(rawConfig), options)
|
|
|
|
if err != nil {
|
|
|
|
t.Logf("adapting config using %s adapter: %v", adapterName, err)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// prettify results to keep tests human-manageable
|
|
|
|
var prettyBuf bytes.Buffer
|
|
|
|
err = json.Indent(&prettyBuf, result, "", "\t")
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
result = prettyBuf.Bytes()
|
|
|
|
|
|
|
|
if len(warnings) > 0 {
|
|
|
|
for _, w := range warnings {
|
|
|
|
t.Logf("warning: %s:%d: %s: %s", filename, w.Line, w.Directive, w.Message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
diff := difflib.Diff(
|
|
|
|
strings.Split(expectedResponse, "\n"),
|
|
|
|
strings.Split(string(result), "\n"))
|
|
|
|
|
|
|
|
// scan for failure
|
|
|
|
failed := false
|
|
|
|
for _, d := range diff {
|
|
|
|
if d.Delta != difflib.Common {
|
|
|
|
failed = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if failed {
|
|
|
|
for _, d := range diff {
|
|
|
|
switch d.Delta {
|
|
|
|
case difflib.Common:
|
|
|
|
fmt.Printf(" %s\n", d.Payload)
|
|
|
|
case difflib.LeftOnly:
|
|
|
|
fmt.Printf(" - %s\n", d.Payload)
|
|
|
|
case difflib.RightOnly:
|
|
|
|
fmt.Printf(" + %s\n", d.Payload)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// AssertAdapt adapts a config and then tests it against an expected result
|
|
|
|
func AssertAdapt(t testing.TB, rawConfig string, adapterName string, expectedResponse string) {
|
|
|
|
ok := CompareAdapt(t, "Caddyfile", rawConfig, adapterName, expectedResponse)
|
|
|
|
if !ok {
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generic request functions
|
|
|
|
|
|
|
|
func applyHeaders(t testing.TB, req *http.Request, requestHeaders []string) {
|
|
|
|
requestContentType := ""
|
|
|
|
for _, requestHeader := range requestHeaders {
|
|
|
|
arr := strings.SplitAfterN(requestHeader, ":", 2)
|
|
|
|
k := strings.TrimRight(arr[0], ":")
|
|
|
|
v := strings.TrimSpace(arr[1])
|
|
|
|
if k == "Content-Type" {
|
|
|
|
requestContentType = v
|
|
|
|
}
|
|
|
|
t.Logf("Request header: %s => %s", k, v)
|
|
|
|
req.Header.Set(k, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
if requestContentType == "" {
|
|
|
|
t.Logf("Content-Type header not provided")
|
|
|
|
}
|
|
|
|
}
|