1// Copyright 2011 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// This file contains tests of the GobEncoder/GobDecoder support.
6
7package gob
8
9import (
10	"bytes"
11	"errors"
12	"fmt"
13	"io"
14	"net"
15	"strings"
16	"testing"
17	"time"
18)
19
20// Types that implement the GobEncoder/Decoder interfaces.
21
22type ByteStruct struct {
23	a byte // not an exported field
24}
25
26type StringStruct struct {
27	s string // not an exported field
28}
29
30type ArrayStruct struct {
31	a [8192]byte // not an exported field
32}
33
34type Gobber int
35
36type ValueGobber string // encodes with a value, decodes with a pointer.
37
38type BinaryGobber int
39
40type BinaryValueGobber string
41
42type TextGobber int
43
44type TextValueGobber string
45
46// The relevant methods
47
48func (g *ByteStruct) GobEncode() ([]byte, error) {
49	b := make([]byte, 3)
50	b[0] = g.a
51	b[1] = g.a + 1
52	b[2] = g.a + 2
53	return b, nil
54}
55
56func (g *ByteStruct) GobDecode(data []byte) error {
57	if g == nil {
58		return errors.New("NIL RECEIVER")
59	}
60	// Expect N sequential-valued bytes.
61	if len(data) == 0 {
62		return io.EOF
63	}
64	g.a = data[0]
65	for i, c := range data {
66		if c != g.a+byte(i) {
67			return errors.New("invalid data sequence")
68		}
69	}
70	return nil
71}
72
73func (g *StringStruct) GobEncode() ([]byte, error) {
74	return []byte(g.s), nil
75}
76
77func (g *StringStruct) GobDecode(data []byte) error {
78	// Expect N sequential-valued bytes.
79	if len(data) == 0 {
80		return io.EOF
81	}
82	a := data[0]
83	for i, c := range data {
84		if c != a+byte(i) {
85			return errors.New("invalid data sequence")
86		}
87	}
88	g.s = string(data)
89	return nil
90}
91
92func (a *ArrayStruct) GobEncode() ([]byte, error) {
93	return a.a[:], nil
94}
95
96func (a *ArrayStruct) GobDecode(data []byte) error {
97	if len(data) != len(a.a) {
98		return errors.New("wrong length in array decode")
99	}
100	copy(a.a[:], data)
101	return nil
102}
103
104func (g *Gobber) GobEncode() ([]byte, error) {
105	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
106}
107
108func (g *Gobber) GobDecode(data []byte) error {
109	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
110	return err
111}
112
113func (g *BinaryGobber) MarshalBinary() ([]byte, error) {
114	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
115}
116
117func (g *BinaryGobber) UnmarshalBinary(data []byte) error {
118	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
119	return err
120}
121
122func (g *TextGobber) MarshalText() ([]byte, error) {
123	return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
124}
125
126func (g *TextGobber) UnmarshalText(data []byte) error {
127	_, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
128	return err
129}
130
131func (v ValueGobber) GobEncode() ([]byte, error) {
132	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
133}
134
135func (v *ValueGobber) GobDecode(data []byte) error {
136	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
137	return err
138}
139
140func (v BinaryValueGobber) MarshalBinary() ([]byte, error) {
141	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
142}
143
144func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error {
145	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
146	return err
147}
148
149func (v TextValueGobber) MarshalText() ([]byte, error) {
150	return []byte(fmt.Sprintf("VALUE=%s", v)), nil
151}
152
153func (v *TextValueGobber) UnmarshalText(data []byte) error {
154	_, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
155	return err
156}
157
158// Structs that include GobEncodable fields.
159
160type GobTest0 struct {
161	X int // guarantee we have  something in common with GobTest*
162	G *ByteStruct
163}
164
165type GobTest1 struct {
166	X int // guarantee we have  something in common with GobTest*
167	G *StringStruct
168}
169
170type GobTest2 struct {
171	X int    // guarantee we have  something in common with GobTest*
172	G string // not a GobEncoder - should give us errors
173}
174
175type GobTest3 struct {
176	X int // guarantee we have  something in common with GobTest*
177	G *Gobber
178	B *BinaryGobber
179	T *TextGobber
180}
181
182type GobTest4 struct {
183	X  int // guarantee we have  something in common with GobTest*
184	V  ValueGobber
185	BV BinaryValueGobber
186	TV TextValueGobber
187}
188
189type GobTest5 struct {
190	X  int // guarantee we have  something in common with GobTest*
191	V  *ValueGobber
192	BV *BinaryValueGobber
193	TV *TextValueGobber
194}
195
196type GobTest6 struct {
197	X  int // guarantee we have  something in common with GobTest*
198	V  ValueGobber
199	W  *ValueGobber
200	BV BinaryValueGobber
201	BW *BinaryValueGobber
202	TV TextValueGobber
203	TW *TextValueGobber
204}
205
206type GobTest7 struct {
207	X  int // guarantee we have  something in common with GobTest*
208	V  *ValueGobber
209	W  ValueGobber
210	BV *BinaryValueGobber
211	BW BinaryValueGobber
212	TV *TextValueGobber
213	TW TextValueGobber
214}
215
216type GobTestIgnoreEncoder struct {
217	X int // guarantee we have  something in common with GobTest*
218}
219
220type GobTestValueEncDec struct {
221	X int          // guarantee we have  something in common with GobTest*
222	G StringStruct // not a pointer.
223}
224
225type GobTestIndirectEncDec struct {
226	X int             // guarantee we have  something in common with GobTest*
227	G ***StringStruct // indirections to the receiver.
228}
229
230type GobTestArrayEncDec struct {
231	X int         // guarantee we have  something in common with GobTest*
232	A ArrayStruct // not a pointer.
233}
234
235type GobTestIndirectArrayEncDec struct {
236	X int            // guarantee we have  something in common with GobTest*
237	A ***ArrayStruct // indirections to a large receiver.
238}
239
240func TestGobEncoderField(t *testing.T) {
241	b := new(bytes.Buffer)
242	// First a field that's a structure.
243	enc := NewEncoder(b)
244	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
245	if err != nil {
246		t.Fatal("encode error:", err)
247	}
248	dec := NewDecoder(b)
249	x := new(GobTest0)
250	err = dec.Decode(x)
251	if err != nil {
252		t.Fatal("decode error:", err)
253	}
254	if x.G.a != 'A' {
255		t.Errorf("expected 'A' got %c", x.G.a)
256	}
257	// Now a field that's not a structure.
258	b.Reset()
259	gobber := Gobber(23)
260	bgobber := BinaryGobber(24)
261	tgobber := TextGobber(25)
262	err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
263	if err != nil {
264		t.Fatal("encode error:", err)
265	}
266	y := new(GobTest3)
267	err = dec.Decode(y)
268	if err != nil {
269		t.Fatal("decode error:", err)
270	}
271	if *y.G != 23 || *y.B != 24 || *y.T != 25 {
272		t.Errorf("expected '23 got %d", *y.G)
273	}
274}
275
276// Even though the field is a value, we can still take its address
277// and should be able to call the methods.
278func TestGobEncoderValueField(t *testing.T) {
279	b := new(bytes.Buffer)
280	// First a field that's a structure.
281	enc := NewEncoder(b)
282	err := enc.Encode(&GobTestValueEncDec{17, StringStruct{"HIJKL"}})
283	if err != nil {
284		t.Fatal("encode error:", err)
285	}
286	dec := NewDecoder(b)
287	x := new(GobTestValueEncDec)
288	err = dec.Decode(x)
289	if err != nil {
290		t.Fatal("decode error:", err)
291	}
292	if x.G.s != "HIJKL" {
293		t.Errorf("expected `HIJKL` got %s", x.G.s)
294	}
295}
296
297// GobEncode/Decode should work even if the value is
298// more indirect than the receiver.
299func TestGobEncoderIndirectField(t *testing.T) {
300	b := new(bytes.Buffer)
301	// First a field that's a structure.
302	enc := NewEncoder(b)
303	s := &StringStruct{"HIJKL"}
304	sp := &s
305	err := enc.Encode(GobTestIndirectEncDec{17, &sp})
306	if err != nil {
307		t.Fatal("encode error:", err)
308	}
309	dec := NewDecoder(b)
310	x := new(GobTestIndirectEncDec)
311	err = dec.Decode(x)
312	if err != nil {
313		t.Fatal("decode error:", err)
314	}
315	if (***x.G).s != "HIJKL" {
316		t.Errorf("expected `HIJKL` got %s", (***x.G).s)
317	}
318}
319
320// Test with a large field with methods.
321func TestGobEncoderArrayField(t *testing.T) {
322	b := new(bytes.Buffer)
323	enc := NewEncoder(b)
324	var a GobTestArrayEncDec
325	a.X = 17
326	for i := range a.A.a {
327		a.A.a[i] = byte(i)
328	}
329	err := enc.Encode(&a)
330	if err != nil {
331		t.Fatal("encode error:", err)
332	}
333	dec := NewDecoder(b)
334	x := new(GobTestArrayEncDec)
335	err = dec.Decode(x)
336	if err != nil {
337		t.Fatal("decode error:", err)
338	}
339	for i, v := range x.A.a {
340		if v != byte(i) {
341			t.Errorf("expected %x got %x", byte(i), v)
342			break
343		}
344	}
345}
346
347// Test an indirection to a large field with methods.
348func TestGobEncoderIndirectArrayField(t *testing.T) {
349	b := new(bytes.Buffer)
350	enc := NewEncoder(b)
351	var a GobTestIndirectArrayEncDec
352	a.X = 17
353	var array ArrayStruct
354	ap := &array
355	app := &ap
356	a.A = &app
357	for i := range array.a {
358		array.a[i] = byte(i)
359	}
360	err := enc.Encode(a)
361	if err != nil {
362		t.Fatal("encode error:", err)
363	}
364	dec := NewDecoder(b)
365	x := new(GobTestIndirectArrayEncDec)
366	err = dec.Decode(x)
367	if err != nil {
368		t.Fatal("decode error:", err)
369	}
370	for i, v := range (***x.A).a {
371		if v != byte(i) {
372			t.Errorf("expected %x got %x", byte(i), v)
373			break
374		}
375	}
376}
377
378// As long as the fields have the same name and implement the
379// interface, we can cross-connect them. Not sure it's useful
380// and may even be bad but it works and it's hard to prevent
381// without exposing the contents of the object, which would
382// defeat the purpose.
383func TestGobEncoderFieldsOfDifferentType(t *testing.T) {
384	// first, string in field to byte in field
385	b := new(bytes.Buffer)
386	enc := NewEncoder(b)
387	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
388	if err != nil {
389		t.Fatal("encode error:", err)
390	}
391	dec := NewDecoder(b)
392	x := new(GobTest0)
393	err = dec.Decode(x)
394	if err != nil {
395		t.Fatal("decode error:", err)
396	}
397	if x.G.a != 'A' {
398		t.Errorf("expected 'A' got %c", x.G.a)
399	}
400	// now the other direction, byte in field to string in field
401	b.Reset()
402	err = enc.Encode(GobTest0{17, &ByteStruct{'X'}})
403	if err != nil {
404		t.Fatal("encode error:", err)
405	}
406	y := new(GobTest1)
407	err = dec.Decode(y)
408	if err != nil {
409		t.Fatal("decode error:", err)
410	}
411	if y.G.s != "XYZ" {
412		t.Fatalf("expected `XYZ` got %q", y.G.s)
413	}
414}
415
416// Test that we can encode a value and decode into a pointer.
417func TestGobEncoderValueEncoder(t *testing.T) {
418	// first, string in field to byte in field
419	b := new(bytes.Buffer)
420	enc := NewEncoder(b)
421	err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("Καλημέρα"), TextValueGobber("こんにちは")})
422	if err != nil {
423		t.Fatal("encode error:", err)
424	}
425	dec := NewDecoder(b)
426	x := new(GobTest5)
427	err = dec.Decode(x)
428	if err != nil {
429		t.Fatal("decode error:", err)
430	}
431	if *x.V != "hello" || *x.BV != "Καλημέρα" || *x.TV != "こんにちは" {
432		t.Errorf("expected `hello` got %s", *x.V)
433	}
434}
435
436// Test that we can use a value then a pointer type of a GobEncoder
437// in the same encoded value. Bug 4647.
438func TestGobEncoderValueThenPointer(t *testing.T) {
439	v := ValueGobber("forty-two")
440	w := ValueGobber("six-by-nine")
441	bv := BinaryValueGobber("1nanocentury")
442	bw := BinaryValueGobber("πseconds")
443	tv := TextValueGobber("gravitationalacceleration")
444	tw := TextValueGobber("π²ft/s²")
445
446	// this was a bug: encoding a GobEncoder by value before a GobEncoder
447	// pointer would cause duplicate type definitions to be sent.
448
449	b := new(bytes.Buffer)
450	enc := NewEncoder(b)
451	if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil {
452		t.Fatal("encode error:", err)
453	}
454	dec := NewDecoder(b)
455	x := new(GobTest6)
456	if err := dec.Decode(x); err != nil {
457		t.Fatal("decode error:", err)
458	}
459
460	if got, want := x.V, v; got != want {
461		t.Errorf("v = %q, want %q", got, want)
462	}
463	if got, want := x.W, w; got == nil {
464		t.Errorf("w = nil, want %q", want)
465	} else if *got != want {
466		t.Errorf("w = %q, want %q", *got, want)
467	}
468
469	if got, want := x.BV, bv; got != want {
470		t.Errorf("bv = %q, want %q", got, want)
471	}
472	if got, want := x.BW, bw; got == nil {
473		t.Errorf("bw = nil, want %q", want)
474	} else if *got != want {
475		t.Errorf("bw = %q, want %q", *got, want)
476	}
477
478	if got, want := x.TV, tv; got != want {
479		t.Errorf("tv = %q, want %q", got, want)
480	}
481	if got, want := x.TW, tw; got == nil {
482		t.Errorf("tw = nil, want %q", want)
483	} else if *got != want {
484		t.Errorf("tw = %q, want %q", *got, want)
485	}
486}
487
488// Test that we can use a pointer then a value type of a GobEncoder
489// in the same encoded value.
490func TestGobEncoderPointerThenValue(t *testing.T) {
491	v := ValueGobber("forty-two")
492	w := ValueGobber("six-by-nine")
493	bv := BinaryValueGobber("1nanocentury")
494	bw := BinaryValueGobber("πseconds")
495	tv := TextValueGobber("gravitationalacceleration")
496	tw := TextValueGobber("π²ft/s²")
497
498	b := new(bytes.Buffer)
499	enc := NewEncoder(b)
500	if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil {
501		t.Fatal("encode error:", err)
502	}
503	dec := NewDecoder(b)
504	x := new(GobTest7)
505	if err := dec.Decode(x); err != nil {
506		t.Fatal("decode error:", err)
507	}
508
509	if got, want := x.V, v; got == nil {
510		t.Errorf("v = nil, want %q", want)
511	} else if *got != want {
512		t.Errorf("v = %q, want %q", *got, want)
513	}
514	if got, want := x.W, w; got != want {
515		t.Errorf("w = %q, want %q", got, want)
516	}
517
518	if got, want := x.BV, bv; got == nil {
519		t.Errorf("bv = nil, want %q", want)
520	} else if *got != want {
521		t.Errorf("bv = %q, want %q", *got, want)
522	}
523	if got, want := x.BW, bw; got != want {
524		t.Errorf("bw = %q, want %q", got, want)
525	}
526
527	if got, want := x.TV, tv; got == nil {
528		t.Errorf("tv = nil, want %q", want)
529	} else if *got != want {
530		t.Errorf("tv = %q, want %q", *got, want)
531	}
532	if got, want := x.TW, tw; got != want {
533		t.Errorf("tw = %q, want %q", got, want)
534	}
535}
536
537func TestGobEncoderFieldTypeError(t *testing.T) {
538	// GobEncoder to non-decoder: error
539	b := new(bytes.Buffer)
540	enc := NewEncoder(b)
541	err := enc.Encode(GobTest1{17, &StringStruct{"ABC"}})
542	if err != nil {
543		t.Fatal("encode error:", err)
544	}
545	dec := NewDecoder(b)
546	x := &GobTest2{}
547	err = dec.Decode(x)
548	if err == nil {
549		t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
550	}
551	if !strings.Contains(err.Error(), "type") {
552		t.Fatal("expected type error; got", err)
553	}
554	// Non-encoder to GobDecoder: error
555	b.Reset()
556	err = enc.Encode(GobTest2{17, "ABC"})
557	if err != nil {
558		t.Fatal("encode error:", err)
559	}
560	y := &GobTest1{}
561	err = dec.Decode(y)
562	if err == nil {
563		t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
564	}
565	if !strings.Contains(err.Error(), "type") {
566		t.Fatal("expected type error; got", err)
567	}
568}
569
570// Even though ByteStruct is a struct, it's treated as a singleton at the top level.
571func TestGobEncoderStructSingleton(t *testing.T) {
572	b := new(bytes.Buffer)
573	enc := NewEncoder(b)
574	err := enc.Encode(&ByteStruct{'A'})
575	if err != nil {
576		t.Fatal("encode error:", err)
577	}
578	dec := NewDecoder(b)
579	x := new(ByteStruct)
580	err = dec.Decode(x)
581	if err != nil {
582		t.Fatal("decode error:", err)
583	}
584	if x.a != 'A' {
585		t.Errorf("expected 'A' got %c", x.a)
586	}
587}
588
589func TestGobEncoderNonStructSingleton(t *testing.T) {
590	b := new(bytes.Buffer)
591	enc := NewEncoder(b)
592	var g Gobber = 1234
593	err := enc.Encode(&g)
594	if err != nil {
595		t.Fatal("encode error:", err)
596	}
597	dec := NewDecoder(b)
598	var x Gobber
599	err = dec.Decode(&x)
600	if err != nil {
601		t.Fatal("decode error:", err)
602	}
603	if x != 1234 {
604		t.Errorf("expected 1234 got %d", x)
605	}
606}
607
608func TestGobEncoderIgnoreStructField(t *testing.T) {
609	b := new(bytes.Buffer)
610	// First a field that's a structure.
611	enc := NewEncoder(b)
612	err := enc.Encode(GobTest0{17, &ByteStruct{'A'}})
613	if err != nil {
614		t.Fatal("encode error:", err)
615	}
616	dec := NewDecoder(b)
617	x := new(GobTestIgnoreEncoder)
618	err = dec.Decode(x)
619	if err != nil {
620		t.Fatal("decode error:", err)
621	}
622	if x.X != 17 {
623		t.Errorf("expected 17 got %c", x.X)
624	}
625}
626
627func TestGobEncoderIgnoreNonStructField(t *testing.T) {
628	b := new(bytes.Buffer)
629	// First a field that's a structure.
630	enc := NewEncoder(b)
631	gobber := Gobber(23)
632	bgobber := BinaryGobber(24)
633	tgobber := TextGobber(25)
634	err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
635	if err != nil {
636		t.Fatal("encode error:", err)
637	}
638	dec := NewDecoder(b)
639	x := new(GobTestIgnoreEncoder)
640	err = dec.Decode(x)
641	if err != nil {
642		t.Fatal("decode error:", err)
643	}
644	if x.X != 17 {
645		t.Errorf("expected 17 got %c", x.X)
646	}
647}
648
649func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
650	b := new(bytes.Buffer)
651	// First a field that's a structure.
652	enc := NewEncoder(b)
653	err := enc.Encode(GobTest0{X: 18}) // G is nil
654	if err != nil {
655		t.Fatal("encode error:", err)
656	}
657	dec := NewDecoder(b)
658	x := new(GobTest0)
659	err = dec.Decode(x)
660	if err != nil {
661		t.Fatal("decode error:", err)
662	}
663	if x.X != 18 {
664		t.Errorf("expected x.X = 18, got %v", x.X)
665	}
666	if x.G != nil {
667		t.Errorf("expected x.G = nil, got %v", x.G)
668	}
669}
670
671type gobDecoderBug0 struct {
672	foo, bar string
673}
674
675func (br *gobDecoderBug0) String() string {
676	return br.foo + "-" + br.bar
677}
678
679func (br *gobDecoderBug0) GobEncode() ([]byte, error) {
680	return []byte(br.String()), nil
681}
682
683func (br *gobDecoderBug0) GobDecode(b []byte) error {
684	br.foo = "foo"
685	br.bar = "bar"
686	return nil
687}
688
689// This was a bug: the receiver has a different indirection level
690// than the variable.
691func TestGobEncoderExtraIndirect(t *testing.T) {
692	gdb := &gobDecoderBug0{"foo", "bar"}
693	buf := new(bytes.Buffer)
694	e := NewEncoder(buf)
695	if err := e.Encode(gdb); err != nil {
696		t.Fatalf("encode: %v", err)
697	}
698	d := NewDecoder(buf)
699	var got *gobDecoderBug0
700	if err := d.Decode(&got); err != nil {
701		t.Fatalf("decode: %v", err)
702	}
703	if got.foo != gdb.foo || got.bar != gdb.bar {
704		t.Errorf("got = %q, want %q", got, gdb)
705	}
706}
707
708// Another bug: this caused a crash with the new Go1 Time type.
709// We throw in a gob-encoding array, to test another case of isZero,
710// and a struct containing a nil interface, to test a third.
711type isZeroBug struct {
712	T time.Time
713	S string
714	I int
715	A isZeroBugArray
716	F isZeroBugInterface
717}
718
719type isZeroBugArray [2]uint8
720
721// Receiver is value, not pointer, to test isZero of array.
722func (a isZeroBugArray) GobEncode() (b []byte, e error) {
723	b = append(b, a[:]...)
724	return b, nil
725}
726
727func (a *isZeroBugArray) GobDecode(data []byte) error {
728	if len(data) != len(a) {
729		return io.EOF
730	}
731	a[0] = data[0]
732	a[1] = data[1]
733	return nil
734}
735
736type isZeroBugInterface struct {
737	I interface{}
738}
739
740func (i isZeroBugInterface) GobEncode() (b []byte, e error) {
741	return []byte{}, nil
742}
743
744func (i *isZeroBugInterface) GobDecode(data []byte) error {
745	return nil
746}
747
748func TestGobEncodeIsZero(t *testing.T) {
749	x := isZeroBug{time.Unix(1e9, 0), "hello", -55, isZeroBugArray{1, 2}, isZeroBugInterface{}}
750	b := new(bytes.Buffer)
751	enc := NewEncoder(b)
752	err := enc.Encode(x)
753	if err != nil {
754		t.Fatal("encode:", err)
755	}
756	var y isZeroBug
757	dec := NewDecoder(b)
758	err = dec.Decode(&y)
759	if err != nil {
760		t.Fatal("decode:", err)
761	}
762	if x != y {
763		t.Fatalf("%v != %v", x, y)
764	}
765}
766
767func TestGobEncodePtrError(t *testing.T) {
768	var err error
769	b := new(bytes.Buffer)
770	enc := NewEncoder(b)
771	err = enc.Encode(&err)
772	if err != nil {
773		t.Fatal("encode:", err)
774	}
775	dec := NewDecoder(b)
776	err2 := fmt.Errorf("foo")
777	err = dec.Decode(&err2)
778	if err != nil {
779		t.Fatal("decode:", err)
780	}
781	if err2 != nil {
782		t.Fatalf("expected nil, got %v", err2)
783	}
784}
785
786func TestNetIP(t *testing.T) {
787	// Encoding of net.IP{1,2,3,4} in Go 1.1.
788	enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04}
789
790	var ip net.IP
791	err := NewDecoder(bytes.NewReader(enc)).Decode(&ip)
792	if err != nil {
793		t.Fatalf("decode: %v", err)
794	}
795	if ip.String() != "1.2.3.4" {
796		t.Errorf("decoded to %v, want 1.2.3.4", ip.String())
797	}
798}
799