Просмотр исходного кода

Fix handling of RequiredNotSetError being returned by fields that implement Marshaler.

This has a chance of breaking some code, but only if they were already
silently broken.
David Symonds 10 лет назад
Родитель
Сommit
68c687dc49
2 измененных файлов с 32 добавлено и 11 удалено
  1. 31 10
      proto/all_test.go
  2. 1 1
      proto/encode.go

+ 31 - 10
proto/all_test.go

@@ -401,17 +401,18 @@ type fakeMarshaler struct {
 	err error
 }
 
-func (f fakeMarshaler) Marshal() ([]byte, error) {
-	return f.b, f.err
-}
+func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err }
+func (f *fakeMarshaler) String() string           { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) }
+func (f *fakeMarshaler) ProtoMessage()            {}
+func (f *fakeMarshaler) Reset()                   {}
 
-func (f fakeMarshaler) String() string {
-	return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err)
+type msgWithFakeMarshaler struct {
+	M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"`
 }
 
-func (f fakeMarshaler) ProtoMessage() {}
-
-func (f fakeMarshaler) Reset() {}
+func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) }
+func (m *msgWithFakeMarshaler) ProtoMessage()  {}
+func (m *msgWithFakeMarshaler) Reset()         {}
 
 // Simple tests for proto messages that implement the Marshaler interface.
 func TestMarshalerEncoding(t *testing.T) {
@@ -423,7 +424,7 @@ func TestMarshalerEncoding(t *testing.T) {
 	}{
 		{
 			name: "Marshaler that fails",
-			m: fakeMarshaler{
+			m: &fakeMarshaler{
 				err: errors.New("some marshal err"),
 				b:   []byte{5, 6, 7},
 			},
@@ -431,9 +432,25 @@ func TestMarshalerEncoding(t *testing.T) {
 			want:    nil,
 			wantErr: errors.New("some marshal err"),
 		},
+		{
+			name: "Marshaler that fails with RequiredNotSetError",
+			m: &msgWithFakeMarshaler{
+				M: &fakeMarshaler{
+					err: &RequiredNotSetError{},
+					b:   []byte{5, 6, 7},
+				},
+			},
+			// Since there's an error that can be continued after,
+			// the buffer should be written.
+			want: []byte{
+				10, 3, // for &msgWithFakeMarshaler
+				5, 6, 7, // for &fakeMarshaler
+			},
+			wantErr: &RequiredNotSetError{},
+		},
 		{
 			name: "Marshaler that succeeds",
-			m: fakeMarshaler{
+			m: &fakeMarshaler{
 				b: []byte{0, 1, 2, 3, 4, 127, 255},
 			},
 			want:    []byte{0, 1, 2, 3, 4, 127, 255},
@@ -443,6 +460,10 @@ func TestMarshalerEncoding(t *testing.T) {
 	for _, test := range tests {
 		b := NewBuffer(nil)
 		err := b.Marshal(test.m)
+		if _, ok := err.(*RequiredNotSetError); ok {
+			// We're not in package proto, so we can only assert the type in this case.
+			err = &RequiredNotSetError{}
+		}
 		if !reflect.DeepEqual(test.wantErr, err) {
 			t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr)
 		}

+ 1 - 1
proto/encode.go

@@ -529,7 +529,7 @@ func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
 		}
 		o.buf = append(o.buf, p.tagcode...)
 		o.EncodeRawBytes(data)
-		return nil
+		return state.err
 	}
 
 	o.buf = append(o.buf, p.tagcode...)