]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: handle encoding of different indirects of GobEncoder
authorKyle Lemons <kyle@kylelemons.net>
Mon, 14 Jan 2013 05:07:11 +0000 (16:07 +1100)
committerAndrew Gerrand <adg@golang.org>
Mon, 14 Jan 2013 05:07:11 +0000 (16:07 +1100)
Fixes #4647.

R=r, golang-dev
CC=golang-dev
https://golang.org/cl/7085051

src/pkg/encoding/gob/encoder.go
src/pkg/encoding/gob/gobencdec_test.go

index 284decedead5382a6360592110fc1713702778e1..f669c3d5b24a0dfe982f2a491f61d924deea3b80 100644 (file)
@@ -137,8 +137,8 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
        ut := userType(origt)
        if ut.isGobEncoder {
                // The rules are different: regardless of the underlying type's representation,
-               // we need to tell the other side that this exact type is a GobEncoder.
-               return enc.sendActualType(w, state, ut, ut.user)
+               // we need to tell the other side that the base type is a GobEncoder.
+               return enc.sendActualType(w, state, ut, ut.base)
        }
 
        // It's a concrete value, so drill down to the base type.
index 45240d764dcf474e19effb8bc8670ba740c6b590..58136d3655c86843024d4d48d2affe9255a2cb87 100644 (file)
@@ -142,6 +142,18 @@ type GobTest5 struct {
        V *ValueGobber
 }
 
+type GobTest6 struct {
+       X int // guarantee we have  something in common with GobTest*
+       V ValueGobber
+       W *ValueGobber
+}
+
+type GobTest7 struct {
+       X int // guarantee we have  something in common with GobTest*
+       V *ValueGobber
+       W ValueGobber
+}
+
 type GobTestIgnoreEncoder struct {
        X int // guarantee we have  something in common with GobTest*
 }
@@ -360,6 +372,61 @@ func TestGobEncoderValueEncoder(t *testing.T) {
        }
 }
 
+// Test that we can use a value then a pointer type of a GobEncoder
+// in the same encoded value.  Bug 4647.
+func TestGobEncoderValueThenPointer(t *testing.T) {
+       v := ValueGobber("forty-two")
+       w := ValueGobber("six-by-nine")
+
+       // this was a bug: encoding a GobEncoder by value before a GobEncoder
+       // pointer would cause duplicate type definitions to be sent.
+
+       b := new(bytes.Buffer)
+       enc := NewEncoder(b)
+       if err := enc.Encode(GobTest6{42, v, &w}); err != nil {
+               t.Fatal("encode error:", err)
+       }
+       dec := NewDecoder(b)
+       x := new(GobTest6)
+       if err := dec.Decode(x); err != nil {
+               t.Fatal("decode error:", err)
+       }
+       if got, want := x.V, v; got != want {
+               t.Errorf("v = %q, want %q", got, want)
+       }
+       if got, want := v.W, w; got == nil {
+               t.Errorf("w = nil, want %q", want)
+       } else if *got != want {
+               t.Errorf("w = %q, want %q", *got, want)
+       }
+}
+
+// Test that we can use a pointer then a value type of a GobEncoder
+// in the same encoded value.
+func TestGobEncoderPointerThenValue(t *testing.T) {
+       v := ValueGobber("forty-two")
+       w := ValueGobber("six-by-nine")
+
+       b := new(bytes.Buffer)
+       enc := NewEncoder(b)
+       if err := enc.Encode(GobTest7{42, &v, w}); err != nil {
+               t.Fatal("encode error:", err)
+       }
+       dec := NewDecoder(b)
+       x := new(GobTest7)
+       if err := dec.Decode(x); err != nil {
+               t.Fatal("decode error:", err)
+       }
+       if got, want := x.V, v; got == nil {
+               t.Errorf("v = nil, want %q", want)
+       } else if *got != want {
+               t.Errorf("v = %q, want %q", got, want)
+       }
+       if got, want := v.W, w; got != want {
+               t.Errorf("w = %q, want %q", got, want)
+       }
+}
+
 func TestGobEncoderFieldTypeError(t *testing.T) {
        // GobEncoder to non-decoder: error
        b := new(bytes.Buffer)