Skip to content

Commit

Permalink
attributes: print typed nil values instead of panic (#6574)
Browse files Browse the repository at this point in the history
Co-authored-by: Easwar Swaminathan <easwars@google.com>
  • Loading branch information
searKing and easwars authored Sep 22, 2023
1 parent fe0dc22 commit 58e2f2b
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
6 changes: 3 additions & 3 deletions attributes/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ func (a *Attributes) String() string {
return sb.String()
}

func str(x any) string {
func str(x any) (s string) {
if v, ok := x.(fmt.Stringer); ok {
return v.String()
return fmt.Sprint(v)
} else if v, ok := x.(string); ok {
return v
}
return fmt.Sprintf("<%p>", x)
return fmt.Sprintf("%#v", x)
}

// MarshalJSON helps implement the json.Marshaler interface, thereby rendering
Expand Down
38 changes: 38 additions & 0 deletions attributes/attributes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ func (s stringVal) Equal(o any) bool {
return ok && s.s == os.s
}

type stringerVal struct {
s string
}

func (s stringerVal) String() string {
return s.s
}

func ExampleAttributes() {
type keyOne struct{}
type keyTwo struct{}
Expand All @@ -57,6 +65,36 @@ func ExampleAttributes_WithValue() {
// Key two: {two}
}

func ExampleAttributes_String() {
type key struct{}
var typedNil *stringerVal
a1 := attributes.New(key{}, typedNil) // typed nil implements [fmt.Stringer]
a2 := attributes.New(key{}, (*stringerVal)(nil)) // typed nil implements [fmt.Stringer]
a3 := attributes.New(key{}, (*stringVal)(nil)) // typed nil not implements [fmt.Stringer]
a4 := attributes.New(key{}, nil) // untyped nil
a5 := attributes.New(key{}, 1)
a6 := attributes.New(key{}, stringerVal{s: "two"})
a7 := attributes.New(key{}, stringVal{s: "two"})
a8 := attributes.New(1, true)
fmt.Println("a1:", a1.String())
fmt.Println("a2:", a2.String())
fmt.Println("a3:", a3.String())
fmt.Println("a4:", a4.String())
fmt.Println("a5:", a5.String())
fmt.Println("a6:", a6.String())
fmt.Println("a7:", a7.String())
fmt.Println("a8:", a8.String())
// Output:
// a1: {"attributes_test.key{}": "<nil>" }
// a2: {"attributes_test.key{}": "<nil>" }
// a3: {"attributes_test.key{}": "(*attributes_test.stringVal)(nil)" }
// a4: {"attributes_test.key{}": "<nil>" }
// a5: {"attributes_test.key{}": "1" }
// a6: {"attributes_test.key{}": "two" }
// a7: {"attributes_test.key{}": "attributes_test.stringVal{s:\"two\"}" }
// a8: {"1": "true" }
}

// Test that two attributes with the same content are Equal.
func TestEqual(t *testing.T) {
type keyOne struct{}
Expand Down
20 changes: 20 additions & 0 deletions resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,23 @@ func (s) TestResolverAddressesToEndpoints(t *testing.T) {
t.Fatalf("timed out waiting for endpoints")
}
}

// Test ensures that there is no panic if the attributes within
// resolver.State.Addresses contains a typed-nil value.
func (s) TestResolverAddressesWithTypedNilAttribute(t *testing.T) {
r := manual.NewBuilderWithScheme(t.Name())
resolver.Register(r)

addrAttr := attributes.New("typed_nil", (*stringerVal)(nil))
r.InitialState(resolver.State{Addresses: []resolver.Address{{Addr: "addr1", Attributes: addrAttr}}})

cc, err := Dial(r.Scheme()+":///", WithTransportCredentials(insecure.NewCredentials()), WithResolvers(r))
if err != nil {
t.Fatalf("Unexpected error dialing: %v", err)
}
defer cc.Close()
}

type stringerVal struct{ s string }

func (s stringerVal) String() string { return s.s }

0 comments on commit 58e2f2b

Please sign in to comment.