func TestOldUnoM(t *testing.T) { popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano())) older := NewPopulatedOldUnoM(popr, true) // need optional field to be always initialized, to check it's lost in this test older.Field1 = proto.String(randStringUnrecognized(popr)) data1, err := proto.Marshal(older) if err != nil { panic(err) } newer := &UnoM{} if err = proto.Unmarshal(data1, newer); err != nil { panic(err) } data2, err := proto.Marshal(newer) if err != nil { panic(err) } older2 := &OldUnoM{} if err := proto.Unmarshal(data2, older2); err != nil { panic(err) } // check that Field1 is lost if older2.Field1 != nil { t.Fatalf("field must be lost, but it's not, older: %#v, older2: %#v", older, older2) } // now restore Field1 and messages should be equal now older2.Field1 = older.Field1 if err := older.VerboseEqual(older2); err != nil { t.Fatalf("%#v !VerboseProto %#v, since %v", older, older2, err) } }
func TestUnmarshalPartiallyPopulatedOptionalFieldsFails(t *testing.T) { // Fill in all fields, then randomly remove one. dataOut := &test.NinOptNative{ Field1: proto.Float64(0), Field2: proto.Float32(0), Field3: proto.Int32(0), Field4: proto.Int64(0), Field5: proto.Uint32(0), Field6: proto.Uint64(0), Field7: proto.Int32(0), Field8: proto.Int64(0), Field9: proto.Uint32(0), Field10: proto.Int32(0), Field11: proto.Uint64(0), Field12: proto.Int64(0), Field13: proto.Bool(false), Field14: proto.String("0"), Field15: []byte("0"), } r := rand.New(rand.NewSource(time.Now().UnixNano())) fieldName := "Field" + strconv.Itoa(r.Intn(15)+1) field := reflect.ValueOf(dataOut).Elem().FieldByName(fieldName) fieldType := field.Type() field.Set(reflect.Zero(fieldType)) encodedMessage, err := proto.Marshal(dataOut) if err != nil { t.Fatalf("Unexpected error when marshalling dataOut: %v", err) } dataIn := NidOptNative{} err = proto.Unmarshal(encodedMessage, &dataIn) if err.Error() != `proto: required field "`+fieldName+`" not set` { t.Fatalf(`err.Error() != "proto: required field "`+fieldName+`" not set"; was "%s" instead`, err.Error()) } }
func TestStringEscaping(t *testing.T) { testCases := []struct { in *pb.Strings out string }{ { // Test data from C++ test (TextFormatTest.StringEscape). // Single divergence: we don't escape apostrophes. &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", }, { // Test data from the same C++ test. &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", }, { // Some UTF-8. &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, `string_field: "\000\001\377\201"` + "\n", }, } for i, tc := range testCases { var buf bytes.Buffer if err := proto.MarshalText(&buf, tc.in); err != nil { t.Errorf("proto.MarsalText: %v", err) continue } s := buf.String() if s != tc.out { t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) continue } // Check round-trip. pb := new(pb.Strings) if err := proto.UnmarshalText(s, pb); err != nil { t.Errorf("#%d: UnmarshalText: %v", i, err) continue } if !proto.Equal(pb, tc.in) { t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) } } }
func init() { ext := &pb.Ext{ Data: proto.String("extension"), } if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { panic("SetExtension: " + err.Error()) } }
func TestExtensionsRoundTrip(t *testing.T) { msg := &pb.MyMessage{} ext1 := &pb.Ext{ Data: proto.String("hi"), } ext2 := &pb.Ext{ Data: proto.String("there"), } exists := proto.HasExtension(msg, pb.E_Ext_More) if exists { t.Error("Extension More present unexpectedly") } if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { t.Error(err) } if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { t.Error(err) } e, err := proto.GetExtension(msg, pb.E_Ext_More) if err != nil { t.Error(err) } x, ok := e.(*pb.Ext) if !ok { t.Errorf("e has type %T, expected testdata.Ext", e) } else if *x.Data != "there" { t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) } proto.ClearExtension(msg, pb.E_Ext_More) if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { t.Errorf("got %v, expected ErrMissingExtension", e) } if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { t.Error("expected bad extension error, got nil") } if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { t.Error("expected extension err") } if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { t.Error("expected some sort of type mismatch error, got nil") } }
func TestMarshalToSucceedsWhenRequiredFieldIsPresent(t *testing.T) { data := RequiredExample{ TheRequiredString: proto.String("present"), } buf, err := proto.Marshal(&data) if err != nil { t.Fatalf("err != nil; was %v instead", err) } if len(buf) == 0 { t.Fatalf(`len(buf) == 0; expected nonzero`) } }
func (g *Generator) GeneratePlugin(p Plugin) { p.Init(g) // Generate the output. The generator runs for every file, even the files // that we don't generate output for, so that we can collate the full list // of exported symbols to support public imports. genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles)) for _, file := range g.genFiles { genFileMap[file] = true } i := 0 for _, file := range g.allFiles { g.Reset() g.writeOutput = genFileMap[file] g.generatePlugin(file, p) if !g.writeOutput { continue } g.Response.File[i] = new(plugin.CodeGeneratorResponse_File) g.Response.File[i].Name = proto.String(goFileName(*file.Name)) g.Response.File[i].Content = proto.String(g.String()) i++ } }
func TestUnmarshalSucceedsWhenRequiredIsNotPresent(t *testing.T) { dataOut := RequiredExample{ TheRequiredString: proto.String("present"), } encodedMessage, err := proto.Marshal(&dataOut) if err != nil { t.Fatalf("Unexpected error when marshalling dataOut: %v", err) } dataIn := RequiredExample{} err = proto.Unmarshal(encodedMessage, &dataIn) if err != nil { t.Fatalf("err != nil; was %v instead", err) } }
func newTestMessage() *pb.MyMessage { msg := &pb.MyMessage{ Count: proto.Int32(42), Name: proto.String("Dave"), Quote: proto.String(`"I didn't want to go."`), Pet: []string{"bunny", "kitty", "horsey"}, Inner: &pb.InnerMessage{ Host: proto.String("footrest.syd"), Port: proto.Int32(7001), Connected: proto.Bool(true), }, Others: []*pb.OtherMessage{ { Key: proto.Int64(0xdeadbeef), Value: []byte{1, 65, 7, 12}, }, { Weight: proto.Float32(6.022), Inner: &pb.InnerMessage{ Host: proto.String("lesha.mtv"), Port: proto.Int32(8002), }, }, }, Bikeshed: pb.MyMessage_BLUE.Enum(), Somegroup: &pb.MyMessage_SomeGroup{ GroupField: proto.Int32(8), }, // One normally wouldn't do this. // This is an undeclared tag 13, as a varint (wire type 0) with value 4. XXX_unrecognized: []byte{13<<3 | 0, 4}, } ext := &pb.Ext{ Data: proto.String("Big gobs for big rats"), } if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { panic(err) } greetings := []string{"adg", "easy", "cow"} if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { panic(err) } // Add an unknown extension. We marshal a pb.Ext, and fake the ID. b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) if err != nil { panic(err) } b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) proto.SetRawExtension(msg, 201, b) // Extensions can be plain fields, too, so let's test that. b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) proto.SetRawExtension(msg, 202, b) return msg }
func TestNilExtension(t *testing.T) { msg := &pb.MyMessage{ Count: proto.Int32(1), } if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { t.Fatal(err) } if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { t.Error("expected SetExtension to fail due to a nil extension") } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { t.Errorf("expected error %v, got %v", want, err) } // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. }
func TestRepeatedNilText(t *testing.T) { m := &pb.MessageList{ Message: []*pb.MessageList_Message{ nil, { Name: proto.String("Horse"), }, nil, }, } want := `Message <nil> Message { name: "Horse" } Message <nil> ` if s := proto.MarshalTextString(m); s != want { t.Errorf(" got: %s\nwant: %s", s, want) } }
func TestTextOneof(t *testing.T) { tests := []struct { m proto.Message want string }{ // zero message {&pb.Communique{}, ``}, // scalar field {&pb.Communique{Union: &pb.Communique_Number{Number: 4}}, `number:4`}, // message field {&pb.Communique{Union: &pb.Communique_Msg{ Msg: &pb.Strings{StringField: proto.String("why hello!")}, }}, `msg:<string_field:"why hello!" >`}, // bad oneof (should not panic) {&pb.Communique{Union: &pb.Communique_Msg{Msg: nil}}, `msg:/* nil */`}, } for _, test := range tests { got := strings.TrimSpace(test.m.String()) if got != test.want { t.Errorf("\n got %s\nwant %s", got, test.want) } } }
func Generate(req *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse { // Begin by allocating a generator. The request and response structures are stored there // so we can do error handling easily - the response structure contains the field to // report failure. g := generator.New() g.Request = req g.CommandLineParameters(g.Request.GetParameter()) // Create a wrapped version of the Descriptors and EnumDescriptors that // point to the file that defines them. g.WrapTypes() g.SetPackageNames() g.BuildTypeNameMap() g.GenerateAllFiles() gtest := generator.New() data, err := proto.Marshal(req) if err != nil { g.Error(err, "failed to marshal modified proto") } if err := proto.Unmarshal(data, gtest.Request); err != nil { g.Error(err, "parsing modified proto") } if len(gtest.Request.FileToGenerate) == 0 { gtest.Fail("no files to generate") } gtest.CommandLineParameters(gtest.Request.GetParameter()) // Create a wrapped version of the Descriptors and EnumDescriptors that // point to the file that defines them. gtest.WrapTypes() gtest.SetPackageNames() gtest.BuildTypeNameMap() gtest.GeneratePlugin(testgen.NewPlugin()) for i := 0; i < len(gtest.Response.File); i++ { if strings.Contains(*gtest.Response.File[i].Content, `//These tests are generated by limbo.services/protobuf/plugin/testgen`) { gtest.Response.File[i].Name = proto.String(strings.Replace(*gtest.Response.File[i].Name, ".pb.go", "pb_test.go", -1)) g.Response.File = append(g.Response.File, gtest.Response.File[i]) } } for i := 0; i < len(g.Response.File); i++ { // Format .go files if path.Ext(g.Response.File[i].GetName()) == ".go" { formatted, err := format.Source([]byte(g.Response.File[i].GetContent())) if err != nil { g.Error(err, "go format error") } fmts := string(formatted) g.Response.File[i].Content = &fmts } // Format .json files if path.Ext(g.Response.File[i].GetName()) == ".json" { formatted := bytes.Buffer{} err := json.Indent(&formatted, []byte(g.Response.File[i].GetContent()), "", " ") if err != nil { g.Error(err, "go format error") } fmts := formatted.String() g.Response.File[i].Content = &fmts } } return g.Response }
marshalerAllOptions = Marshaler{ Indent: " ", } simpleObject = &pb.Simple{ OInt32: proto.Int32(-32), OInt64: proto.Int64(-6400000000), OUint32: proto.Uint32(32), OUint64: proto.Uint64(6400000000), OSint32: proto.Int32(-13), OSint64: proto.Int64(-2600000000), OFloat: proto.Float32(3.14), ODouble: proto.Float64(6.02214179e23), OBool: proto.Bool(true), OString: proto.String("hello \"there\""), OBytes: []byte("beep boop"), OCastBytes: pb.Bytes("wow"), } simpleObjectJSON = `{` + `"o_bool":true,` + `"o_int32":-32,` + `"o_int64":"-6400000000",` + `"o_uint32":32,` + `"o_uint64":"6400000000",` + `"o_sint32":-13,` + `"o_sint64":"-2600000000",` + `"o_float":3.14,` + `"o_double":6.02214179e+23,` + `"o_string":"hello \"there\"",` +
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package proto_test import ( "testing" "limbo.services/protobuf/proto" proto3pb "limbo.services/protobuf/proto/proto3_proto" pb "limbo.services/protobuf/proto/testdata" ) var cloneTestMessage = &pb.MyMessage{ Count: proto.Int32(42), Name: proto.String("Dave"), Pet: []string{"bunny", "kitty", "horsey"}, Inner: &pb.InnerMessage{ Host: proto.String("niles"), Port: proto.Int32(9099), Connected: proto.Bool(true), }, Others: []*pb.OtherMessage{ { Value: []byte("some bytes"), }, }, Somegroup: &pb.MyMessage_SomeGroup{ GroupField: proto.Int32(6), }, RepBytes: [][]byte{[]byte("sham"), []byte("wow")},