0
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-30 22:34:15 -05:00
This commit is contained in:
a 2024-06-18 20:08:38 -05:00
parent b98c89fbb6
commit 01cb878087
No known key found for this signature in database
GPG key ID: 374BC539FE795AF0
4 changed files with 37 additions and 61 deletions

View file

@ -780,7 +780,7 @@ func exitProcess(ctx context.Context, logger *zap.Logger) {
logger.Error("unclean shutdown") logger.Error("unclean shutdown")
} }
// check if we are in test environment, and dont call exit if we are // check if we are in test environment, and dont call exit if we are
if flag.Lookup("test.v") == nil || strings.Contains(os.Args[0], ".test") { if flag.Lookup("test.v") == nil || !strings.Contains(os.Args[0], ".test") {
os.Exit(exitCode) os.Exit(exitCode)
} }
}() }()

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -12,15 +11,11 @@ import (
"net/http" "net/http"
"net/http/cookiejar" "net/http/cookiejar"
"os" "os"
"path"
"reflect"
"runtime"
"strings" "strings"
"time" "time"
caddycmd "github.com/caddyserver/caddy/v2/cmd" caddycmd "github.com/caddyserver/caddy/v2/cmd"
"github.com/caddyserver/caddy/v2/caddyconfig"
// plug in Caddy modules here // plug in Caddy modules here
_ "github.com/caddyserver/caddy/v2/modules/standard" _ "github.com/caddyserver/caddy/v2/modules/standard"
) )
@ -96,7 +91,7 @@ func (tc *Tester) CleanupCaddy() error {
}() }()
_, err := http.Post(fmt.Sprintf("http://localhost:%d/stop", Default.AdminPort), "", nil) _, err := http.Post(fmt.Sprintf("http://localhost:%d/stop", Default.AdminPort), "", nil)
if err != nil { if err != nil {
return fmt.Errorf("couldn't stop caddytest server") return fmt.Errorf("couldn't stop caddytest server: %w", err)
} }
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
for retries := 0; retries < 10; retries++ { for retries := 0; retries < 10; retries++ {
@ -112,7 +107,6 @@ func (tc *Tester) CleanupCaddy() error {
// LoadConfig loads the config to the tester server and also ensures that the config was loaded // LoadConfig loads the config to the tester server and also ensures that the config was loaded
func (tc *Tester) LoadConfig(rawConfig string, configType string) error { func (tc *Tester) LoadConfig(rawConfig string, configType string) error {
originalRawConfig := rawConfig
// normalize JSON config // normalize JSON config
if configType == "json" { if configType == "json" {
var conf any var conf any
@ -157,56 +151,32 @@ func (tc *Tester) LoadConfig(rawConfig string, configType string) error {
} }
tc.configLoaded = true tc.configLoaded = true
return tc.ensureConfigRunning(originalRawConfig, configType)
// if the config is not loaded at this point, it is a bug in caddy's config.Load
// the contract for config.Load states that the config must be loaded before it returns, and that it will
// error if the config fails to apply
return nil
} }
func (tc *Tester) ensureConfigRunning(rawConfig string, configType string) error { func (tc *Tester) GetCurrentConfig(receiver any) error {
expectedBytes := []byte(rawConfig)
if configType != "json" {
adapter := caddyconfig.GetAdapter(configType)
if adapter == nil {
return fmt.Errorf("adapter of config type is missing: %s", configType)
}
expectedBytes, _, _ = adapter.Adapt([]byte(rawConfig), nil)
}
var expected any
err := json.Unmarshal(expectedBytes, &expected)
if err != nil {
return err
}
client := &http.Client{ client := &http.Client{
Timeout: Default.LoadRequestTimeout, Timeout: Default.LoadRequestTimeout,
} }
fetchConfig := func(client *http.Client) any { resp, err := client.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort))
resp, err := client.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort)) if err != nil {
if err != nil { return err
return nil
}
defer resp.Body.Close()
actualBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil
}
var actual any
err = json.Unmarshal(actualBytes, &actual)
if err != nil {
return nil
}
return actual
} }
defer resp.Body.Close()
// TODO: does this really need to be tried more than once? actualBytes, err := io.ReadAll(resp.Body)
// Caddy should block until the new config is loaded, which means needing to wait is a caddy bug if err != nil {
for retries := 3; retries > 0; retries-- { return err
if reflect.DeepEqual(expected, fetchConfig(client)) {
return nil
}
time.Sleep(1 * time.Second)
} }
return errors.New("EnsureConfigRunning: POSTed configuration isn't active") err = json.Unmarshal(actualBytes, receiver)
if err != nil {
return err
}
return nil
} }
const initConfig = `{ const initConfig = `{
@ -258,15 +228,6 @@ func isCaddyAdminRunning() error {
return nil return nil
} }
func getIntegrationDir() string {
_, filename, _, ok := runtime.Caller(1)
if !ok {
panic("unable to determine the current file path")
}
return path.Dir(filename)
}
// CreateTestingTransport creates a testing transport that forces call dialing connections to happen locally // CreateTestingTransport creates a testing transport that forces call dialing connections to happen locally
func CreateTestingTransport() *http.Transport { func CreateTestingTransport() *http.Transport {
dialer := net.Dialer{ dialer := net.Dialer{

View file

@ -19,12 +19,13 @@ func AssertLoadError(t *testing.T, rawConfig string, configType string, expected
require.NoError(t, err) require.NoError(t, err)
err = tc.LaunchCaddy() err = tc.LaunchCaddy()
require.NoError(t, err) require.NoError(t, err)
defer tc.CleanupCaddy()
err = tc.LoadConfig(rawConfig, configType) err = tc.LoadConfig(rawConfig, configType)
if !strings.Contains(err.Error(), expectedError) { if !strings.Contains(err.Error(), expectedError) {
t.Errorf("expected error \"%s\" but got \"%s\"", expectedError, err.Error()) t.Errorf("expected error \"%s\" but got \"%s\"", expectedError, err.Error())
} }
err = tc.CleanupCaddy()
require.NoError(t, err)
} }
// CompareAdapt adapts a config and then compares it against an expected result // CompareAdapt adapts a config and then compares it against an expected result

View file

@ -6,7 +6,9 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"path"
"regexp" "regexp"
"runtime"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -21,6 +23,15 @@ func prependCaddyFilePath(rawConfig string) string {
return r return r
} }
func getIntegrationDir() string {
_, filename, _, ok := runtime.Caller(1)
if !ok {
panic("unable to determine the current file path")
}
return path.Dir(filename)
}
var ( var (
matchKey = regexp.MustCompile(`(/[\w\d\.]+\.key)`) matchKey = regexp.MustCompile(`(/[\w\d\.]+\.key)`)
matchCert = regexp.MustCompile(`(/[\w\d\.]+\.crt)`) matchCert = regexp.MustCompile(`(/[\w\d\.]+\.crt)`)
@ -64,7 +75,9 @@ func (tc *TestHarness) init() {
tc.tester = tester tc.tester = tester
err = tc.tester.LaunchCaddy() err = tc.tester.LaunchCaddy()
if err != nil { if err != nil {
tc.t.Errorf("Failed to launch caddy tester: %s", err) tc.t.Errorf("Failed to launch caddy server: %s", err)
tc.t.FailNow()
return
} }
// cleanup // cleanup
tc.t.Cleanup(func() { tc.t.Cleanup(func() {
@ -87,6 +100,7 @@ func (tc *TestHarness) init() {
err = tc.tester.CleanupCaddy() err = tc.tester.CleanupCaddy()
if err != nil { if err != nil {
tc.t.Errorf("failed to clean up caddy instance: %s", err) tc.t.Errorf("failed to clean up caddy instance: %s", err)
tc.t.FailNow()
} }
}) })
} }