github.com/whiteCcinn/protobuf-go@v1.0.9/types/known/anypb/any_test.go (about)

     1  // Copyright 2020 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  
     5  package anypb_test
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/whiteCcinn/protobuf-go/proto"
    12  	"github.com/whiteCcinn/protobuf-go/reflect/protoreflect"
    13  	"github.com/whiteCcinn/protobuf-go/testing/protocmp"
    14  
    15  	testpb "github.com/whiteCcinn/protobuf-go/internal/testprotos/test"
    16  	apb "github.com/whiteCcinn/protobuf-go/types/known/anypb"
    17  	epb "github.com/whiteCcinn/protobuf-go/types/known/emptypb"
    18  	wpb "github.com/whiteCcinn/protobuf-go/types/known/wrapperspb"
    19  )
    20  
    21  func mustMarshal(m proto.Message) []byte {
    22  	b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(m)
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  	return b
    27  }
    28  
    29  func TestMessage(t *testing.T) {
    30  	tests := []struct {
    31  		inAny    *apb.Any
    32  		inTarget proto.Message
    33  		wantIs   bool
    34  		wantName protoreflect.FullName
    35  	}{{
    36  		inAny:    nil,
    37  		inTarget: nil,
    38  		wantIs:   false,
    39  		wantName: "",
    40  	}, {
    41  		inAny:    new(apb.Any),
    42  		inTarget: nil,
    43  		wantIs:   false,
    44  		wantName: "",
    45  	}, {
    46  		inAny:    new(apb.Any),
    47  		inTarget: (*testpb.TestAllTypes)(nil),
    48  		wantIs:   false,
    49  		wantName: "",
    50  	}, {
    51  		inAny:    &apb.Any{TypeUrl: "foo"},
    52  		inTarget: (*testpb.TestAllTypes)(nil),
    53  		wantIs:   false,
    54  		wantName: "foo",
    55  	}, {
    56  		inAny:    &apb.Any{TypeUrl: "foo$"},
    57  		inTarget: (*testpb.TestAllTypes)(nil),
    58  		wantIs:   false,
    59  		wantName: "",
    60  	}, {
    61  		inAny:    &apb.Any{TypeUrl: "/foo"},
    62  		inTarget: (*testpb.TestAllTypes)(nil),
    63  		wantIs:   false,
    64  		wantName: "foo",
    65  	}, {
    66  		inAny:    &apb.Any{TypeUrl: "/bar/foo"},
    67  		inTarget: (*testpb.TestAllTypes)(nil),
    68  		wantIs:   false,
    69  		wantName: "foo",
    70  	}, {
    71  		inAny:    &apb.Any{TypeUrl: "google.golang.org/bar/foo"},
    72  		inTarget: (*testpb.TestAllTypes)(nil),
    73  		wantIs:   false,
    74  		wantName: "foo",
    75  	}, {
    76  		inAny:    &apb.Any{TypeUrl: "goproto.proto.test.TestAllTypes"},
    77  		inTarget: (*testpb.TestAllTypes)(nil),
    78  		wantIs:   true,
    79  		wantName: "goproto.proto.test.TestAllTypes",
    80  	}, {
    81  		inAny:    &apb.Any{TypeUrl: "goproto.proto.test.TestAllTypes$"},
    82  		inTarget: (*testpb.TestAllTypes)(nil),
    83  		wantIs:   false,
    84  		wantName: "",
    85  	}, {
    86  		inAny:    &apb.Any{TypeUrl: "/goproto.proto.test.TestAllTypes"},
    87  		inTarget: (*testpb.TestAllTypes)(nil),
    88  		wantIs:   true,
    89  		wantName: "goproto.proto.test.TestAllTypes",
    90  	}, {
    91  		inAny:    &apb.Any{TypeUrl: "google.golang.org/foo/goproto.proto.test.TestAllTypes"},
    92  		inTarget: (*testpb.TestAllTypes)(nil),
    93  		wantIs:   true,
    94  		wantName: "goproto.proto.test.TestAllTypes",
    95  	}}
    96  
    97  	for _, tt := range tests {
    98  		gotIs := tt.inAny.MessageIs(tt.inTarget)
    99  		if gotIs != tt.wantIs {
   100  			t.Errorf("MessageIs(%v, %v) = %v, want %v", tt.inAny, tt.inTarget, gotIs, tt.wantIs)
   101  		}
   102  		gotName := tt.inAny.MessageName()
   103  		if gotName != tt.wantName {
   104  			t.Errorf("MessageName(%v) = %v, want %v", tt.inAny, gotName, tt.wantName)
   105  		}
   106  	}
   107  }
   108  
   109  func TestRoundtrip(t *testing.T) {
   110  	tests := []struct {
   111  		msg proto.Message
   112  		any *apb.Any
   113  	}{{
   114  		msg: &testpb.TestAllTypes{},
   115  		any: &apb.Any{
   116  			TypeUrl: "type.googleapis.com/goproto.proto.test.TestAllTypes",
   117  		},
   118  	}, {
   119  		msg: &testpb.TestAllTypes{
   120  			OptionalString: proto.String("hello, world!"),
   121  		},
   122  		any: &apb.Any{
   123  			TypeUrl: "type.googleapis.com/goproto.proto.test.TestAllTypes",
   124  			Value: mustMarshal(&testpb.TestAllTypes{
   125  				OptionalString: proto.String("hello, world!"),
   126  			}),
   127  		},
   128  	}, {
   129  		msg: &wpb.StringValue{Value: ""},
   130  		any: &apb.Any{
   131  			TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
   132  		},
   133  	}, {
   134  		msg: wpb.String("hello, world"),
   135  		any: &apb.Any{
   136  			TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
   137  			Value:   mustMarshal(wpb.String("hello, world")),
   138  		},
   139  	}, {
   140  		msg: &apb.Any{
   141  			TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
   142  			Value:   mustMarshal(wpb.String("hello, world")),
   143  		},
   144  		any: &apb.Any{
   145  			TypeUrl: "type.googleapis.com/google.protobuf.Any",
   146  			Value: mustMarshal(&apb.Any{
   147  				TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
   148  				Value:   mustMarshal(wpb.String("hello, world")),
   149  			}),
   150  		},
   151  	}}
   152  
   153  	for _, tt := range tests {
   154  		// Unmarshal to the wrong message type.
   155  		var empty epb.Empty
   156  		if err := tt.any.UnmarshalTo(&empty); err == nil {
   157  			t.Errorf("UnmarshalTo(empty) = nil, want non-nil")
   158  		}
   159  
   160  		gotAny := new(apb.Any)
   161  		if err := gotAny.MarshalFrom(tt.msg); err != nil {
   162  			t.Errorf("MarshalFrom() error: %v", err)
   163  		}
   164  		if diff := cmp.Diff(tt.any, gotAny, protocmp.Transform()); diff != "" {
   165  			t.Errorf("MarshalFrom() output mismatch (-want +got):\n%s", diff)
   166  		}
   167  
   168  		gotPB := tt.msg.ProtoReflect().New().Interface()
   169  		if err := tt.any.UnmarshalTo(gotPB); err != nil {
   170  			t.Errorf("UnmarshalTo() error: %v", err)
   171  		}
   172  		if diff := cmp.Diff(tt.msg, gotPB, protocmp.Transform()); diff != "" {
   173  			t.Errorf("UnmarshalTo() output mismatch (-want +got):\n%s", diff)
   174  		}
   175  
   176  		gotPB, err := tt.any.UnmarshalNew()
   177  		if err != nil {
   178  			t.Errorf("UnmarshalNew() error: %v", err)
   179  		}
   180  		if diff := cmp.Diff(tt.msg, gotPB, protocmp.Transform()); diff != "" {
   181  			t.Errorf("UnmarshalNew() output mismatch (-want +got):\n%s", diff)
   182  		}
   183  	}
   184  }