Home | History | Annotate | Download | only in proto
      1 // Go support for Protocol Buffers - Google's data interchange format
      2 //
      3 // Copyright 2014 The Go Authors.  All rights reserved.
      4 // https://github.com/golang/protobuf
      5 //
      6 // Redistribution and use in source and binary forms, with or without
      7 // modification, are permitted provided that the following conditions are
      8 // met:
      9 //
     10 //     * Redistributions of source code must retain the above copyright
     11 // notice, this list of conditions and the following disclaimer.
     12 //     * Redistributions in binary form must reproduce the above
     13 // copyright notice, this list of conditions and the following disclaimer
     14 // in the documentation and/or other materials provided with the
     15 // distribution.
     16 //     * Neither the name of Google Inc. nor the names of its
     17 // contributors may be used to endorse or promote products derived from
     18 // this software without specific prior written permission.
     19 //
     20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31 
     32 package proto_test
     33 
     34 import (
     35 	"bytes"
     36 	"testing"
     37 
     38 	"github.com/golang/protobuf/proto"
     39 	pb "github.com/golang/protobuf/proto/proto3_proto"
     40 	tpb "github.com/golang/protobuf/proto/test_proto"
     41 )
     42 
     43 func TestProto3ZeroValues(t *testing.T) {
     44 	tests := []struct {
     45 		desc string
     46 		m    proto.Message
     47 	}{
     48 		{"zero message", &pb.Message{}},
     49 		{"empty bytes field", &pb.Message{Data: []byte{}}},
     50 	}
     51 	for _, test := range tests {
     52 		b, err := proto.Marshal(test.m)
     53 		if err != nil {
     54 			t.Errorf("%s: proto.Marshal: %v", test.desc, err)
     55 			continue
     56 		}
     57 		if len(b) > 0 {
     58 			t.Errorf("%s: Encoding is non-empty: %q", test.desc, b)
     59 		}
     60 	}
     61 }
     62 
     63 func TestRoundTripProto3(t *testing.T) {
     64 	m := &pb.Message{
     65 		Name:         "David",          // (2 | 1<<3): 0x0a 0x05 "David"
     66 		Hilarity:     pb.Message_PUNS,  // (0 | 2<<3): 0x10 0x01
     67 		HeightInCm:   178,              // (0 | 3<<3): 0x18 0xb2 0x01
     68 		Data:         []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto"
     69 		ResultCount:  47,               // (0 | 7<<3): 0x38 0x2f
     70 		TrueScotsman: true,             // (0 | 8<<3): 0x40 0x01
     71 		Score:        8.1,              // (5 | 9<<3): 0x4d <8.1>
     72 
     73 		Key: []uint64{1, 0xdeadbeef},
     74 		Nested: &pb.Nested{
     75 			Bunny: "Monty",
     76 		},
     77 	}
     78 	t.Logf(" m: %v", m)
     79 
     80 	b, err := proto.Marshal(m)
     81 	if err != nil {
     82 		t.Fatalf("proto.Marshal: %v", err)
     83 	}
     84 	t.Logf(" b: %q", b)
     85 
     86 	m2 := new(pb.Message)
     87 	if err := proto.Unmarshal(b, m2); err != nil {
     88 		t.Fatalf("proto.Unmarshal: %v", err)
     89 	}
     90 	t.Logf("m2: %v", m2)
     91 
     92 	if !proto.Equal(m, m2) {
     93 		t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2)
     94 	}
     95 }
     96 
     97 func TestGettersForBasicTypesExist(t *testing.T) {
     98 	var m pb.Message
     99 	if got := m.GetNested().GetBunny(); got != "" {
    100 		t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got)
    101 	}
    102 	if got := m.GetNested().GetCute(); got {
    103 		t.Errorf("m.GetNested().GetCute() = %t, want false", got)
    104 	}
    105 }
    106 
    107 func TestProto3SetDefaults(t *testing.T) {
    108 	in := &pb.Message{
    109 		Terrain: map[string]*pb.Nested{
    110 			"meadow": new(pb.Nested),
    111 		},
    112 		Proto2Field: new(tpb.SubDefaults),
    113 		Proto2Value: map[string]*tpb.SubDefaults{
    114 			"badlands": new(tpb.SubDefaults),
    115 		},
    116 	}
    117 
    118 	got := proto.Clone(in).(*pb.Message)
    119 	proto.SetDefaults(got)
    120 
    121 	// There are no defaults in proto3.  Everything should be the zero value, but
    122 	// we need to remember to set defaults for nested proto2 messages.
    123 	want := &pb.Message{
    124 		Terrain: map[string]*pb.Nested{
    125 			"meadow": new(pb.Nested),
    126 		},
    127 		Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)},
    128 		Proto2Value: map[string]*tpb.SubDefaults{
    129 			"badlands": &tpb.SubDefaults{N: proto.Int64(7)},
    130 		},
    131 	}
    132 
    133 	if !proto.Equal(got, want) {
    134 		t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want)
    135 	}
    136 }
    137 
    138 func TestUnknownFieldPreservation(t *testing.T) {
    139 	b1 := "\x0a\x05David"      // Known tag 1
    140 	b2 := "\xc2\x0c\x06Google" // Unknown tag 200
    141 	b := []byte(b1 + b2)
    142 
    143 	m := new(pb.Message)
    144 	if err := proto.Unmarshal(b, m); err != nil {
    145 		t.Fatalf("proto.Unmarshal: %v", err)
    146 	}
    147 
    148 	if !bytes.Equal(m.XXX_unrecognized, []byte(b2)) {
    149 		t.Fatalf("mismatching unknown fields:\ngot  %q\nwant %q", m.XXX_unrecognized, b2)
    150 	}
    151 }
    152