mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-03 23:06:36 +08:00
chore(cordis): sync Wavelet core/pkg/plugins after W1-W9
This commit is contained in:
@@ -180,6 +180,13 @@ func formatEntryValue(value any, secret bool) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
rv := reflect.ValueOf(value)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
if rv.IsNil() {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprint(rv.Elem().Interface())
|
||||
}
|
||||
return fmt.Sprint(value)
|
||||
}
|
||||
|
||||
|
||||
@@ -224,6 +224,54 @@ func TestEntriesRedactSecretsAndReportDefaults(t *testing.T) {
|
||||
assert.Equal(t, "86400", entries["app.session_age"].Value)
|
||||
}
|
||||
|
||||
type optionalBoolConfig struct {
|
||||
RedirectTrailingSlash *bool `config:"redirect_trailing_slash" env:"APP_REDIRECT_TRAILING_SLASH"`
|
||||
}
|
||||
|
||||
func TestBindBoolPointerFromFileAndEnv(t *testing.T) {
|
||||
t.Run("absent stays nil", func(t *testing.T) {
|
||||
r := extpoints.NewConfigRegistry(newFakeSource())
|
||||
require.NoError(t, r.Declare("driver_http", extpoints.ConfigBinding{Prefix: "app", Target: &optionalBoolConfig{}}))
|
||||
require.NoError(t, r.Resolve())
|
||||
|
||||
var got optionalBoolConfig
|
||||
require.NoError(t, r.Bind("app", &got))
|
||||
assert.Nil(t, got.RedirectTrailingSlash)
|
||||
assert.Equal(t, "", r.Origin("app.redirect_trailing_slash"))
|
||||
})
|
||||
|
||||
t.Run("file false", func(t *testing.T) {
|
||||
src := newFakeSource()
|
||||
src.values["app.redirect_trailing_slash"] = false
|
||||
|
||||
r := extpoints.NewConfigRegistry(src)
|
||||
require.NoError(t, r.Declare("driver_http", extpoints.ConfigBinding{Prefix: "app", Target: &optionalBoolConfig{}}))
|
||||
require.NoError(t, r.Resolve())
|
||||
|
||||
var got optionalBoolConfig
|
||||
require.NoError(t, r.Bind("app", &got))
|
||||
require.NotNil(t, got.RedirectTrailingSlash)
|
||||
assert.False(t, *got.RedirectTrailingSlash)
|
||||
assert.Equal(t, extpoints.OriginFile, r.Origin("app.redirect_trailing_slash"))
|
||||
assert.False(t, r.Bool("app.redirect_trailing_slash", true))
|
||||
})
|
||||
|
||||
t.Run("env false", func(t *testing.T) {
|
||||
src := newFakeSource()
|
||||
src.env["APP_REDIRECT_TRAILING_SLASH"] = "false"
|
||||
|
||||
r := extpoints.NewConfigRegistry(src)
|
||||
require.NoError(t, r.Declare("driver_http", extpoints.ConfigBinding{Prefix: "app", Target: &optionalBoolConfig{}}))
|
||||
require.NoError(t, r.Resolve())
|
||||
|
||||
var got optionalBoolConfig
|
||||
require.NoError(t, r.Bind("app", &got))
|
||||
require.NotNil(t, got.RedirectTrailingSlash)
|
||||
assert.False(t, *got.RedirectTrailingSlash)
|
||||
assert.Equal(t, extpoints.OriginEnv, r.Origin("app.redirect_trailing_slash"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestBindRejectsReadsBeforeSourceIsRegistered(t *testing.T) {
|
||||
r := extpoints.NewConfigRegistry(nil)
|
||||
require.NoError(t, r.Declare("cache", extpoints.ConfigBinding{Prefix: "redis", Target: &redisConfig{}}))
|
||||
|
||||
@@ -33,15 +33,38 @@ func convertValue(raw any, typ reflect.Type) (any, error) {
|
||||
return convertSlice(raw, typ)
|
||||
case reflect.Struct:
|
||||
return convertStruct(raw, typ)
|
||||
case reflect.Ptr:
|
||||
return convertPointer(raw, typ)
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: %s is not a supported configuration type", ErrConfigType, typ)
|
||||
}
|
||||
}
|
||||
|
||||
// convertPointer decodes into the element type and returns a non-nil pointer to it.
|
||||
// Nested pointers are rejected so configuration tags stay one level deep.
|
||||
func convertPointer(raw any, typ reflect.Type) (any, error) {
|
||||
elemType := typ.Elem()
|
||||
if elemType.Kind() == reflect.Ptr {
|
||||
return nil, fmt.Errorf("%w: %s is not a supported configuration type", ErrConfigType, typ)
|
||||
}
|
||||
elem, err := convertValue(raw, elemType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ptr := reflect.New(elemType)
|
||||
ptr.Elem().Set(reflect.ValueOf(elem))
|
||||
return ptr.Interface(), nil
|
||||
}
|
||||
|
||||
func convertBool(raw any) (any, error) {
|
||||
switch v := raw.(type) {
|
||||
case bool:
|
||||
return v, nil
|
||||
case *bool:
|
||||
if v == nil {
|
||||
return nil, fmt.Errorf("%w: nil *bool is not a boolean", ErrConfigType)
|
||||
}
|
||||
return *v, nil
|
||||
case string:
|
||||
parsed, err := strconv.ParseBool(strings.TrimSpace(v))
|
||||
if err != nil {
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
// Copyright 2026 Arctel.net
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package extpoints
|
||||
|
||||
import "testing"
|
||||
|
||||
// TestHandleRawPreservesTrailingSlash 验证 HandleRaw 能表达 /x 与 /x/ 两条不同路由,
|
||||
// 而 Handle 会归一化掉尾部斜杠(server 插件的 list 端点历史行为依赖这一点)。
|
||||
func TestHandleRawPreservesTrailingSlash(t *testing.T) {
|
||||
r := &RouterRegistry{}
|
||||
g := r.Group("/api/v1/nodes")
|
||||
@@ -24,29 +19,9 @@ func TestHandleRawPreservesTrailingSlash(t *testing.T) {
|
||||
t.Errorf("HandleRaw(\"/\") path = %q, want %q", slashed.Path, "/api/v1/nodes/")
|
||||
}
|
||||
if slashed.ID == slashless.ID {
|
||||
t.Error("HandleRaw must allocate its own route ID so scoped teardown can unregister both")
|
||||
t.Error("HandleRaw must allocate its own route ID")
|
||||
}
|
||||
if got := len(r.Routes()); got != 2 {
|
||||
t.Errorf("registry routes = %d, want 2", got)
|
||||
}
|
||||
if !r.UnregisterByID(slashed.ID) {
|
||||
t.Error("UnregisterByID(HandleRaw route) = false, want true")
|
||||
}
|
||||
if got := len(r.Routes()); got != 1 {
|
||||
t.Errorf("routes after unregister = %d, want 1", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegistryHandleRawKeepsAbsolutePath 根注册表上 HandleRaw 只做绝对化处理。
|
||||
func TestRegistryHandleRawKeepsAbsolutePath(t *testing.T) {
|
||||
r := &RouterRegistry{}
|
||||
if got := r.HandleRaw("GET", "/health/").Path; got != "/health/" {
|
||||
t.Errorf("path = %q, want %q", got, "/health/")
|
||||
}
|
||||
if got := r.HandleRaw("POST", "submit").Path; got != "/submit" {
|
||||
t.Errorf("path = %q, want %q", got, "/submit")
|
||||
}
|
||||
if got := r.BasePath(); got != "" {
|
||||
t.Errorf("registry BasePath() = %q, want empty", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user