Skip to content

Commit

Permalink
Make Metadata Stringer implementation deterministic
Browse files Browse the repository at this point in the history
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
  • Loading branch information
dims committed Jun 26, 2024
1 parent 98e5dee commit 5e527ea
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 15 deletions.
18 changes: 14 additions & 4 deletions metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package metadata // import "google.golang.org/grpc/metadata"
import (
"context"
"fmt"
"sort"
"strings"

"google.golang.org/grpc/internal"
Expand Down Expand Up @@ -91,15 +92,24 @@ func Pairs(kv ...string) MD {
}

// String implements the Stringer interface for pretty-printing a MD.
// Ordering of the values is non-deterministic as it ranges over a map.
// The value returned by this method is recommended only for diagnostic
// purposes, and users are strongly discouraged from using this for anything
// mission critical.
func (md MD) String() string {
var sb strings.Builder
fmt.Fprintf(&sb, "MD{")
for k, v := range md {
if sb.Len() > 3 {
keys := make([]string, 0, len(md))
for k := range md {
keys = append(keys, k)
}
sort.Strings(keys)
first := true
for _, k := range keys {
if !first {
fmt.Fprintf(&sb, ", ")
}
fmt.Fprintf(&sb, "%s=[%s]", k, strings.Join(v, ", "))
fmt.Fprintf(&sb, "%s=[%s]", k, strings.Join(md[k], ", "))
first = false
}
fmt.Fprintf(&sb, "}")
return sb.String()
Expand Down
21 changes: 10 additions & 11 deletions metadata/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"context"
"reflect"
"strconv"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -342,19 +341,19 @@ func (s) TestAppendToOutgoingContext_FromKVSlice(t *testing.T) {
func TestStringerMD(t *testing.T) {
for _, test := range []struct {
md MD
want []string
want string
}{
{MD{}, []string{"MD{}"}},
{MD{"k1": []string{}}, []string{"MD{k1=[]}"}},
{MD{"k1": []string{"v1", "v2"}}, []string{"MD{k1=[v1, v2]}"}},
{MD{"k1": []string{"v1"}}, []string{"MD{k1=[v1]}"}},
{MD{"k1": []string{"v1", "v2"}, "k2": []string{}, "k3": []string{"1", "2", "3"}}, []string{"MD{", "k1=[v1, v2]", "k2=[]", "k3=[1, 2, 3]", "}"}},
{MD{}, "MD{}"},
{MD{"k1": []string{}}, "MD{k1=[]}"},
{MD{"k1": []string{"v1", "v2"}}, "MD{k1=[v1, v2]}"},
{MD{"k1": []string{"v1"}}, "MD{k1=[v1]}"},
{MD{"k1": []string{"v1", "v2"}, "k2": []string{}, "k3": []string{"1", "2", "3"}}, "MD{k1=[v1, v2], k2=[], k3=[1, 2, 3]}"},
{MD{"k2": []string{}, "k3": []string{"1", "2", "3"}, "k1": []string{"v1", "v2"}}, "MD{k1=[v1, v2], k2=[], k3=[1, 2, 3]}"},
{MD{"k3": []string{"1", "2", "3"}, "k2": []string{}, "k1": []string{"v1", "v2"}}, "MD{k1=[v1, v2], k2=[], k3=[1, 2, 3]}"},
} {
got := test.md.String()
for _, want := range test.want {
if !strings.Contains(got, want) {
t.Fatalf("Metadata string %q is missing %q", got, want)
}
if got != test.want {
t.Fatalf("Metadata string %q should be %q", got, test.want)
}
}
}
Expand Down

0 comments on commit 5e527ea

Please sign in to comment.