Skip to content

Commit 5e527ea

Browse files
committed
Make Metadata Stringer implementation deterministic
Signed-off-by: Davanum Srinivas <[email protected]>
1 parent 98e5dee commit 5e527ea

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

metadata/metadata.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ package metadata // import "google.golang.org/grpc/metadata"
2424
import (
2525
"context"
2626
"fmt"
27+
"sort"
2728
"strings"
2829

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

9394
// String implements the Stringer interface for pretty-printing a MD.
94-
// Ordering of the values is non-deterministic as it ranges over a map.
95+
// The value returned by this method is recommended only for diagnostic
96+
// purposes, and users are strongly discouraged from using this for anything
97+
// mission critical.
9598
func (md MD) String() string {
9699
var sb strings.Builder
97100
fmt.Fprintf(&sb, "MD{")
98-
for k, v := range md {
99-
if sb.Len() > 3 {
101+
keys := make([]string, 0, len(md))
102+
for k := range md {
103+
keys = append(keys, k)
104+
}
105+
sort.Strings(keys)
106+
first := true
107+
for _, k := range keys {
108+
if !first {
100109
fmt.Fprintf(&sb, ", ")
101110
}
102-
fmt.Fprintf(&sb, "%s=[%s]", k, strings.Join(v, ", "))
111+
fmt.Fprintf(&sb, "%s=[%s]", k, strings.Join(md[k], ", "))
112+
first = false
103113
}
104114
fmt.Fprintf(&sb, "}")
105115
return sb.String()

metadata/metadata_test.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"context"
2323
"reflect"
2424
"strconv"
25-
"strings"
2625
"testing"
2726
"time"
2827

@@ -342,19 +341,19 @@ func (s) TestAppendToOutgoingContext_FromKVSlice(t *testing.T) {
342341
func TestStringerMD(t *testing.T) {
343342
for _, test := range []struct {
344343
md MD
345-
want []string
344+
want string
346345
}{
347-
{MD{}, []string{"MD{}"}},
348-
{MD{"k1": []string{}}, []string{"MD{k1=[]}"}},
349-
{MD{"k1": []string{"v1", "v2"}}, []string{"MD{k1=[v1, v2]}"}},
350-
{MD{"k1": []string{"v1"}}, []string{"MD{k1=[v1]}"}},
351-
{MD{"k1": []string{"v1", "v2"}, "k2": []string{}, "k3": []string{"1", "2", "3"}}, []string{"MD{", "k1=[v1, v2]", "k2=[]", "k3=[1, 2, 3]", "}"}},
346+
{MD{}, "MD{}"},
347+
{MD{"k1": []string{}}, "MD{k1=[]}"},
348+
{MD{"k1": []string{"v1", "v2"}}, "MD{k1=[v1, v2]}"},
349+
{MD{"k1": []string{"v1"}}, "MD{k1=[v1]}"},
350+
{MD{"k1": []string{"v1", "v2"}, "k2": []string{}, "k3": []string{"1", "2", "3"}}, "MD{k1=[v1, v2], k2=[], k3=[1, 2, 3]}"},
351+
{MD{"k2": []string{}, "k3": []string{"1", "2", "3"}, "k1": []string{"v1", "v2"}}, "MD{k1=[v1, v2], k2=[], k3=[1, 2, 3]}"},
352+
{MD{"k3": []string{"1", "2", "3"}, "k2": []string{}, "k1": []string{"v1", "v2"}}, "MD{k1=[v1, v2], k2=[], k3=[1, 2, 3]}"},
352353
} {
353354
got := test.md.String()
354-
for _, want := range test.want {
355-
if !strings.Contains(got, want) {
356-
t.Fatalf("Metadata string %q is missing %q", got, want)
357-
}
355+
if got != test.want {
356+
t.Fatalf("Metadata string %q should be %q", got, test.want)
358357
}
359358
}
360359
}

0 commit comments

Comments
 (0)