1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package ptypes 6 7import ( 8 "reflect" 9 "testing" 10 11 "github.com/golang/protobuf/proto" 12 13 descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor" 14 anypb "github.com/golang/protobuf/ptypes/any" 15) 16 17func TestMarshalUnmarshal(t *testing.T) { 18 orig := &anypb.Any{Value: []byte("test")} 19 20 packed, err := MarshalAny(orig) 21 if err != nil { 22 t.Errorf("MarshalAny(%+v): got: _, %v exp: _, nil", orig, err) 23 } 24 25 unpacked := &anypb.Any{} 26 err = UnmarshalAny(packed, unpacked) 27 if err != nil || !proto.Equal(unpacked, orig) { 28 t.Errorf("got: %v, %+v; want nil, %+v", err, unpacked, orig) 29 } 30} 31 32func TestIs(t *testing.T) { 33 a, err := MarshalAny(&descriptorpb.FileDescriptorProto{}) 34 if err != nil { 35 t.Fatal(err) 36 } 37 if Is(a, &descriptorpb.DescriptorProto{}) { 38 // No spurious match for message names of different length. 39 t.Error("FileDescriptorProto is not a DescriptorProto, but Is says it is") 40 } 41 if Is(a, &descriptorpb.EnumDescriptorProto{}) { 42 // No spurious match for message names of equal length. 43 t.Error("FileDescriptorProto is not an EnumDescriptorProto, but Is says it is") 44 } 45 if !Is(a, &descriptorpb.FileDescriptorProto{}) { 46 t.Error("FileDescriptorProto is indeed a FileDescriptorProto, but Is says it is not") 47 } 48} 49 50func TestIsDifferentUrlPrefixes(t *testing.T) { 51 m := &descriptorpb.FileDescriptorProto{} 52 a := &anypb.Any{TypeUrl: "foo/bar/" + proto.MessageName(m)} 53 if !Is(a, m) { 54 t.Errorf("message with type url %q didn't satisfy Is for type %q", a.TypeUrl, proto.MessageName(m)) 55 } 56} 57 58func TestIsCornerCases(t *testing.T) { 59 m := &descriptorpb.FileDescriptorProto{} 60 if Is(nil, m) { 61 t.Errorf("message with nil type url incorrectly claimed to be %q", proto.MessageName(m)) 62 } 63 noPrefix := &anypb.Any{TypeUrl: proto.MessageName(m)} 64 if !Is(noPrefix, m) { 65 t.Errorf("message with type url %q didn't satisfy Is for type %q", noPrefix.TypeUrl, proto.MessageName(m)) 66 } 67 shortPrefix := &anypb.Any{TypeUrl: "/" + proto.MessageName(m)} 68 if !Is(shortPrefix, m) { 69 t.Errorf("message with type url %q didn't satisfy Is for type %q", shortPrefix.TypeUrl, proto.MessageName(m)) 70 } 71} 72 73func TestUnmarshalDynamic(t *testing.T) { 74 want := &descriptorpb.FileDescriptorProto{Name: proto.String("foo")} 75 a, err := MarshalAny(want) 76 if err != nil { 77 t.Fatal(err) 78 } 79 var got DynamicAny 80 if err := UnmarshalAny(a, &got); err != nil { 81 t.Fatal(err) 82 } 83 if !proto.Equal(got.Message, want) { 84 t.Errorf("invalid result from UnmarshalAny, got %q want %q", got.Message, want) 85 } 86} 87 88func TestEmpty(t *testing.T) { 89 want := &descriptorpb.FileDescriptorProto{} 90 a, err := MarshalAny(want) 91 if err != nil { 92 t.Fatal(err) 93 } 94 got, err := Empty(a) 95 if err != nil { 96 t.Fatal(err) 97 } 98 if !proto.Equal(got, want) { 99 t.Errorf("unequal empty message, got %q, want %q", got, want) 100 } 101 102 // that's a valid type_url for a message which shouldn't be linked into this 103 // test binary. We want an error. 104 a.TypeUrl = "type.googleapis.com/google.protobuf.FieldMask" 105 if _, err := Empty(a); err == nil { 106 t.Errorf("got no error for an attempt to create a message of type %q, which shouldn't be linked in", a.TypeUrl) 107 } 108} 109 110func TestEmptyCornerCases(t *testing.T) { 111 _, err := Empty(nil) 112 if err == nil { 113 t.Error("expected Empty for nil to fail") 114 } 115 want := &descriptorpb.FileDescriptorProto{} 116 noPrefix := &anypb.Any{TypeUrl: proto.MessageName(want)} 117 got, err := Empty(noPrefix) 118 if err != nil { 119 t.Errorf("Empty for any type %q failed: %s", noPrefix.TypeUrl, err) 120 } 121 if !proto.Equal(got, want) { 122 t.Errorf("Empty for any type %q differs, got %q, want %q", noPrefix.TypeUrl, got, want) 123 } 124 shortPrefix := &anypb.Any{TypeUrl: "/" + proto.MessageName(want)} 125 got, err = Empty(shortPrefix) 126 if err != nil { 127 t.Errorf("Empty for any type %q failed: %s", shortPrefix.TypeUrl, err) 128 } 129 if !proto.Equal(got, want) { 130 t.Errorf("Empty for any type %q differs, got %q, want %q", shortPrefix.TypeUrl, got, want) 131 } 132} 133 134func TestAnyReflect(t *testing.T) { 135 want := &descriptorpb.FileDescriptorProto{Name: proto.String("foo")} 136 a, err := MarshalAny(want) 137 if err != nil { 138 t.Fatal(err) 139 } 140 var got DynamicAny 141 if err := UnmarshalAny(a, &got); err != nil { 142 t.Fatal(err) 143 } 144 wantName := want.ProtoReflect().Descriptor().FullName() 145 gotName := got.ProtoReflect().Descriptor().FullName() 146 if gotName != wantName { 147 t.Errorf("name mismatch: got %v, want %v", gotName, wantName) 148 } 149 wantType := reflect.TypeOf(got) 150 gotType := reflect.TypeOf(got.ProtoReflect().Interface()) 151 if gotType != wantType { 152 t.Errorf("ProtoReflect().Interface() round-trip type mismatch: got %v, want %v", gotType, wantType) 153 } 154 gotType = reflect.TypeOf(got.ProtoReflect().New().Interface()) 155 if gotType != wantType { 156 t.Errorf("ProtoReflect().New().Interface() type mismatch: got %v, want %v", gotType, wantType) 157 } 158 gotType = reflect.TypeOf(got.ProtoReflect().Type().New().Interface()) 159 if gotType != wantType { 160 t.Errorf("ProtoReflect().Type().New().Interface() type mismatch: got %v, want %v", gotType, wantType) 161 } 162 gotType = reflect.TypeOf(got.ProtoReflect().Type().Zero().Interface()) 163 if gotType != wantType { 164 t.Errorf("ProtoReflect().Type().Zero().Interface() type mismatch: got %v, want %v", gotType, wantType) 165 } 166} 167