From 58e365847b6d36963fc708af2c0e4eb4ca791c6e Mon Sep 17 00:00:00 2001 From: Paul Wells Date: Thu, 13 Jun 2024 23:22:39 -0700 Subject: [PATCH] add test helper for config yaml tags (#2791) * add test helper for config yaml tags * deps * cleanup * cleanup --- go.mod | 4 +- go.sum | 4 +- pkg/config/config_test.go | 6 +++ pkg/config/configtest/checkyamltag.go | 64 +++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 pkg/config/configtest/checkyamltag.go diff --git a/go.mod b/go.mod index b6574795e..d094e728c 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/jxskiss/base62 v1.1.0 github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 github.com/livekit/mediatransportutil v0.0.0-20240613015318-84b69facfb75 - github.com/livekit/protocol v1.17.1-0.20240614054716-725bc923f98b + github.com/livekit/protocol v1.17.1-0.20240614060801-425cb974f7a4 github.com/livekit/psrpc v0.5.3-0.20240526192918-fbdaf10e6aa5 github.com/mackerelio/go-osstat v0.2.5 github.com/magefile/mage v1.15.0 @@ -48,6 +48,7 @@ require ( github.com/urfave/cli/v2 v2.27.2 github.com/urfave/negroni/v3 v3.1.1 go.uber.org/atomic v1.11.0 + go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 golang.org/x/sync v0.7.0 @@ -97,7 +98,6 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap/exp v0.2.0 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/mod v0.18.0 // indirect diff --git a/go.sum b/go.sum index eb5cbd0f2..a25f10515 100644 --- a/go.sum +++ b/go.sum @@ -120,8 +120,8 @@ github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkD github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ= github.com/livekit/mediatransportutil v0.0.0-20240613015318-84b69facfb75 h1:p60OjeixzXnhGFQL8wmdUwWPxijEDe9ZJFMosq+byec= github.com/livekit/mediatransportutil v0.0.0-20240613015318-84b69facfb75/go.mod h1:jwKUCmObuiEDH0iiuJHaGMXwRs3RjrB4G6qqgkr/5oE= -github.com/livekit/protocol v1.17.1-0.20240614054716-725bc923f98b h1:wRADQpZkCv2ml1W3PZCmFxJKdyAS4T1nleaAdv8rRpY= -github.com/livekit/protocol v1.17.1-0.20240614054716-725bc923f98b/go.mod h1:cN8WmGQR+kWz1+UWcAQdFFUcbW76PnfZDdkLAbYIqd4= +github.com/livekit/protocol v1.17.1-0.20240614060801-425cb974f7a4 h1:5O3/wahQIMnw+PO3O1kgxPSrpJf7PkPcD3GvWmb1TJQ= +github.com/livekit/protocol v1.17.1-0.20240614060801-425cb974f7a4/go.mod h1:cN8WmGQR+kWz1+UWcAQdFFUcbW76PnfZDdkLAbYIqd4= github.com/livekit/psrpc v0.5.3-0.20240526192918-fbdaf10e6aa5 h1:mTZyrjk5WEWMsvaYtJ42pG7DuxysKj21DKPINpGSIto= github.com/livekit/psrpc v0.5.3-0.20240526192918-fbdaf10e6aa5/go.mod h1:CQUBSPfYYAaevg1TNCc6/aYsa8DJH4jSRFdCeSZk5u0= github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o= diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 0e4719fff..833266de6 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -20,6 +20,8 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" + + "github.com/livekit/livekit-server/pkg/config/configtest" ) func TestConfig_UnmarshalKeys(t *testing.T) { @@ -80,3 +82,7 @@ func TestGeneratedFlags(t *testing.T) { require.NotNil(t, conf.RTC.ReconnectOnSubscriptionError) require.False(t, *conf.RTC.ReconnectOnSubscriptionError) } + +func TestYAMLTag(t *testing.T) { + require.NoError(t, configtest.CheckYAMLTags(Config{})) +} diff --git a/pkg/config/configtest/checkyamltag.go b/pkg/config/configtest/checkyamltag.go new file mode 100644 index 000000000..a8ee58371 --- /dev/null +++ b/pkg/config/configtest/checkyamltag.go @@ -0,0 +1,64 @@ +package configtest + +import ( + "fmt" + "reflect" + "slices" + "strings" + + "go.uber.org/multierr" + "google.golang.org/protobuf/proto" +) + +var protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() + +func checkYAMLTags(t reflect.Type, seen map[reflect.Type]struct{}) error { + if _, ok := seen[t]; ok { + return nil + } + seen[t] = struct{}{} + + switch t.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.Pointer: + return checkYAMLTags(t.Elem(), seen) + case reflect.Struct: + if reflect.PointerTo(t).Implements(protoMessageType) { + // ignore protobuf messages + return nil + } + + var errs error + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + if field.Type.Kind() == reflect.Bool { + // ignore boolean fields + continue + } + + if field.Tag.Get("config") == "allowempty" { + // ignore configured exceptions + continue + } + + parts := strings.Split(field.Tag.Get("yaml"), ",") + if parts[0] == "-" { + // ignore unparsed fields + continue + } + + if !slices.Contains(parts, "omitempty") && !slices.Contains(parts, "inline") { + errs = multierr.Append(errs, fmt.Errorf("%s/%s.%s missing omitempty tag", t.PkgPath(), t.Name(), field.Name)) + } + + errs = multierr.Append(errs, checkYAMLTags(field.Type, seen)) + } + return errs + default: + return nil + } +} + +func CheckYAMLTags(config any) error { + return checkYAMLTags(reflect.TypeOf(config), map[reflect.Type]struct{}{}) +}