diff --git a/options/options.go b/options/options.go index cda572a6..5749c15e 100644 --- a/options/options.go +++ b/options/options.go @@ -157,6 +157,22 @@ func Metadata(md metadata.Metadata) Option { } } +func MetadataAny(md any) Option { + result := metadata.Metadata{} + switch vt := md.(type) { + case metadata.Metadata: + result = metadata.Copy(vt) + case map[string]string: + result = metadata.Copy(vt) + case []string: + result.Set(vt...) + } + + return func(src interface{}) error { + return Set(src, result, ".Metadata") + } +} + // Namespace to use func Namespace(ns string) Option { return func(src interface{}) error { diff --git a/options/options_test.go b/options/options_test.go index 7d3b6a62..c4b3677c 100644 --- a/options/options_test.go +++ b/options/options_test.go @@ -1,10 +1,13 @@ package options_test import ( + "fmt" "testing" "go.unistack.org/micro/v4/codec" + "go.unistack.org/micro/v4/metadata" "go.unistack.org/micro/v4/options" + "go.unistack.org/micro/v4/util/reflect" ) func TestAddress(t *testing.T) { @@ -84,3 +87,69 @@ func TestLabels(t *testing.T) { t.Fatal("failed to set labels") } } + +func TestMetadataAny(t *testing.T) { + type s struct { + Metadata metadata.Metadata + } + + testCases := []struct { + Name string + Data any + Expected metadata.Metadata + }{ + { + "strings_even", + []string{"key1", "val1", "key2", "val2"}, + metadata.Metadata{ + "Key1": "val1", + "Key2": "val2", + }, + }, + { + "strings_odd", + []string{"key1", "val1", "key2"}, + metadata.Metadata{ + "Key1": "val1", + }, + }, + { + "map", + map[string]string{ + "key1": "val1", + "key2": "val2", + }, + metadata.Metadata{ + "Key1": "val1", + "Key2": "val2", + }, + }, + { + "metadata.Metadata", + metadata.Metadata{ + "key1": "val1", + "key2": "val2", + }, + metadata.Metadata{ + "Key1": "val1", + "Key2": "val2", + }, + }, + } + + for _, tt := range testCases { + t.Run(tt.Name, func(t *testing.T) { + src := &s{} + var opts []options.Option + opts = append(opts, options.MetadataAny(tt.Data)) + for _, o := range opts { + if err := o(src); err != nil { + t.Fatal(err) + } + if !reflect.Equal(tt.Expected, src.Metadata) { + t.Fatal(fmt.Sprintf("expected: %v, actual: %v", tt.Expected, src.Metadata)) + } + } + }) + } +}