2009-06-29 15:15:07 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package gob
|
|
|
|
|
|
|
|
|
|
import (
|
2009-12-15 15:35:38 -08:00
|
|
|
"bytes"
|
2011-11-01 22:04:37 -04:00
|
|
|
"errors"
|
2012-07-13 14:23:51 -07:00
|
|
|
"flag"
|
2009-12-15 15:35:38 -08:00
|
|
|
"math"
|
2012-02-06 14:02:12 +11:00
|
|
|
"math/rand"
|
2009-12-15 15:35:38 -08:00
|
|
|
"reflect"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
2012-02-06 14:02:12 +11:00
|
|
|
"time"
|
2009-06-29 15:15:07 -07:00
|
|
|
)
|
|
|
|
|
|
2012-07-13 14:23:51 -07:00
|
|
|
var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow")
|
|
|
|
|
|
2009-06-29 15:15:07 -07:00
|
|
|
// Guarantee encoding format by comparing some encodings to hand-written values
|
|
|
|
|
type EncodeT struct {
|
2009-12-15 15:35:38 -08:00
|
|
|
x uint64
|
|
|
|
|
b []byte
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
2009-11-05 14:53:42 -08:00
|
|
|
|
|
|
|
|
var encodeT = []EncodeT{
|
2010-10-22 10:06:33 -07:00
|
|
|
{0x00, []byte{0x00}},
|
|
|
|
|
{0x0F, []byte{0x0F}},
|
|
|
|
|
{0xFF, []byte{0xFF, 0xFF}},
|
|
|
|
|
{0xFFFF, []byte{0xFE, 0xFF, 0xFF}},
|
|
|
|
|
{0xFFFFFF, []byte{0xFD, 0xFF, 0xFF, 0xFF}},
|
|
|
|
|
{0xFFFFFFFF, []byte{0xFC, 0xFF, 0xFF, 0xFF, 0xFF}},
|
|
|
|
|
{0xFFFFFFFFFF, []byte{0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
|
|
|
|
|
{0xFFFFFFFFFFFF, []byte{0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
|
|
|
|
|
{0xFFFFFFFFFFFFFF, []byte{0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
|
|
|
|
|
{0xFFFFFFFFFFFFFFFF, []byte{0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
|
|
|
|
|
{0x1111, []byte{0xFE, 0x11, 0x11}},
|
|
|
|
|
{0x1111111111111111, []byte{0xF8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
|
|
|
|
|
{0x8888888888888888, []byte{0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}},
|
|
|
|
|
{1 << 63, []byte{0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
|
2010-10-22 15:16:34 -07:00
|
|
|
// testError is meant to be used as a deferred function to turn a panic(gobError) into a
|
|
|
|
|
// plain test.Error call.
|
|
|
|
|
func testError(t *testing.T) {
|
|
|
|
|
if e := recover(); e != nil {
|
2011-10-27 20:20:59 -07:00
|
|
|
t.Error(e.(gobError).err) // Will re-panic if not one of our errors, such as a runtime error.
|
2010-10-22 15:16:34 -07:00
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-20 07:33:08 -07:00
|
|
|
func newDecBuffer(data []byte) *decBuffer {
|
|
|
|
|
return &decBuffer{
|
|
|
|
|
data: data,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-29 15:15:07 -07:00
|
|
|
// Test basic encode/decode routines for unsigned integers
|
|
|
|
|
func TestUintCodec(t *testing.T) {
|
2010-10-22 15:16:34 -07:00
|
|
|
defer testError(t)
|
2014-10-17 20:51:15 -07:00
|
|
|
b := new(encBuffer)
|
2011-03-15 21:30:07 -07:00
|
|
|
encState := newEncoderState(b)
|
2009-09-15 09:41:59 -07:00
|
|
|
for _, tt := range encodeT {
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2011-01-11 17:56:45 -08:00
|
|
|
encState.encodeUint(tt.x)
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(tt.b, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-11-09 21:13:17 -08:00
|
|
|
for u := uint64(0); ; u = (u + 1) * 7 {
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2011-01-11 17:56:45 -08:00
|
|
|
encState.encodeUint(u)
|
2014-10-20 07:33:08 -07:00
|
|
|
decState := newDecodeState(newDecBuffer(b.Bytes()))
|
2011-01-11 17:56:45 -08:00
|
|
|
v := decState.decodeUint()
|
2009-06-29 15:15:07 -07:00
|
|
|
if u != v {
|
2010-09-23 13:48:56 +10:00
|
|
|
t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
2009-11-05 14:53:42 -08:00
|
|
|
if u&(1<<63) != 0 {
|
2009-11-09 12:07:39 -08:00
|
|
|
break
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func verifyInt(i int64, t *testing.T) {
|
2010-10-22 15:16:34 -07:00
|
|
|
defer testError(t)
|
2014-10-17 20:51:15 -07:00
|
|
|
var b = new(encBuffer)
|
2011-03-15 21:30:07 -07:00
|
|
|
encState := newEncoderState(b)
|
2011-01-11 17:56:45 -08:00
|
|
|
encState.encodeInt(i)
|
2014-10-20 07:33:08 -07:00
|
|
|
decState := newDecodeState(newDecBuffer(b.Bytes()))
|
2009-12-15 15:35:38 -08:00
|
|
|
decState.buf = make([]byte, 8)
|
2011-01-11 17:56:45 -08:00
|
|
|
j := decState.decodeInt()
|
2009-06-29 15:15:07 -07:00
|
|
|
if i != j {
|
2010-09-23 13:48:56 +10:00
|
|
|
t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test basic encode/decode routines for signed integers
|
|
|
|
|
func TestIntCodec(t *testing.T) {
|
2009-11-09 21:13:17 -08:00
|
|
|
for u := uint64(0); ; u = (u + 1) * 7 {
|
2009-06-29 15:15:07 -07:00
|
|
|
// Do positive and negative values
|
2009-12-15 15:35:38 -08:00
|
|
|
i := int64(u)
|
|
|
|
|
verifyInt(i, t)
|
|
|
|
|
verifyInt(-i, t)
|
|
|
|
|
verifyInt(^i, t)
|
2009-11-05 14:53:42 -08:00
|
|
|
if u&(1<<63) != 0 {
|
2009-11-09 12:07:39 -08:00
|
|
|
break
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
verifyInt(-1<<63, t) // a tricky case
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
2009-06-30 15:37:46 -07:00
|
|
|
|
2009-07-28 17:20:19 -07:00
|
|
|
// The result of encoding a true boolean with field number 7
|
|
|
|
|
var boolResult = []byte{0x07, 0x01}
|
2011-12-16 15:43:06 -08:00
|
|
|
|
2009-07-28 17:20:19 -07:00
|
|
|
// The result of encoding a number 17 with field number 7
|
2009-11-09 21:13:17 -08:00
|
|
|
var signedResult = []byte{0x07, 2 * 17}
|
2009-07-28 17:20:19 -07:00
|
|
|
var unsignedResult = []byte{0x07, 17}
|
|
|
|
|
var floatResult = []byte{0x07, 0xFE, 0x31, 0x40}
|
2011-12-16 15:43:06 -08:00
|
|
|
|
2010-06-24 15:07:28 -07:00
|
|
|
// The result of encoding a number 17+19i with field number 7
|
|
|
|
|
var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
|
2011-12-16 15:43:06 -08:00
|
|
|
|
2010-06-24 15:07:28 -07:00
|
|
|
// The result of encoding "hello" with field number 7
|
2009-07-28 17:20:19 -07:00
|
|
|
var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
|
2009-07-01 18:25:13 -07:00
|
|
|
|
2014-10-20 07:33:08 -07:00
|
|
|
func newDecodeState(buf *decBuffer) *decoderState {
|
2011-03-15 21:30:07 -07:00
|
|
|
d := new(decoderState)
|
|
|
|
|
d.b = buf
|
|
|
|
|
d.buf = make([]byte, uint64Size)
|
|
|
|
|
return d
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-17 20:51:15 -07:00
|
|
|
func newEncoderState(b *encBuffer) *encoderState {
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2011-03-15 21:30:07 -07:00
|
|
|
state := &encoderState{enc: nil, b: b}
|
2009-12-15 15:35:38 -08:00
|
|
|
state.fieldnum = -1
|
|
|
|
|
return state
|
2009-07-01 18:25:13 -07:00
|
|
|
}
|
2009-06-30 15:37:46 -07:00
|
|
|
|
|
|
|
|
// Test instruction execution for encoding.
|
|
|
|
|
// Do not run the machine yet; instead do individual instructions crafted by hand.
|
|
|
|
|
func TestScalarEncInstructions(t *testing.T) {
|
2014-10-17 20:51:15 -07:00
|
|
|
var b = new(encBuffer)
|
2009-06-30 15:37:46 -07:00
|
|
|
|
|
|
|
|
// bool
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data bool = true
|
|
|
|
|
instr := &encInstr{encBool, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(boolResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int = 17
|
|
|
|
|
instr := &encInstr{encInt, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint = 17
|
|
|
|
|
instr := &encInstr{encUint, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int8
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int8 = 17
|
|
|
|
|
instr := &encInstr{encInt, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint8
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint8 = 17
|
|
|
|
|
instr := &encInstr{encUint, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int16
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int16 = 17
|
|
|
|
|
instr := &encInstr{encInt, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint16
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint16 = 17
|
|
|
|
|
instr := &encInstr{encUint, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int32
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int32 = 17
|
|
|
|
|
instr := &encInstr{encInt, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint32
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint32 = 17
|
|
|
|
|
instr := &encInstr{encUint, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int64
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int64 = 17
|
|
|
|
|
instr := &encInstr{encInt, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint64
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint64 = 17
|
|
|
|
|
instr := &encInstr{encUint, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// float32
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data float32 = 17
|
|
|
|
|
instr := &encInstr{encFloat, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(floatResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// float64
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data float64 = 17
|
|
|
|
|
instr := &encInstr{encFloat, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(floatResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes())
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-02 11:21:01 -07:00
|
|
|
|
|
|
|
|
// bytes == []uint8
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
data := []byte("hello")
|
|
|
|
|
instr := &encInstr{encUint8Array, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(bytesResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes())
|
2009-07-02 11:21:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// string
|
|
|
|
|
{
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2014-06-30 11:06:47 -07:00
|
|
|
var data string = "hello"
|
|
|
|
|
instr := &encInstr{encString, 6, nil, 0}
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newEncoderState(b)
|
2014-06-30 11:06:47 -07:00
|
|
|
instr.op(instr, state, reflect.ValueOf(data))
|
2009-09-16 15:15:00 -07:00
|
|
|
if !bytes.Equal(bytesResult, b.Bytes()) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes())
|
2009-07-02 11:21:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-06-30 15:37:46 -07:00
|
|
|
}
|
2009-06-30 17:59:41 -07:00
|
|
|
|
2014-06-30 11:06:47 -07:00
|
|
|
func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, value reflect.Value) {
|
2010-10-22 15:16:34 -07:00
|
|
|
defer testError(t)
|
2011-01-11 17:56:45 -08:00
|
|
|
v := int(state.decodeUint())
|
2009-11-09 21:13:17 -08:00
|
|
|
if v+state.fieldnum != 6 {
|
|
|
|
|
t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
2014-07-01 14:19:27 -04:00
|
|
|
instr.op(instr, state, value.Elem())
|
2009-12-15 15:35:38 -08:00
|
|
|
state.fieldnum = 6
|
2009-07-01 18:25:13 -07:00
|
|
|
}
|
|
|
|
|
|
gob: beginning of support for GobEncoder/GobDecoder interfaces.
This allows a data item that can marshal itself to be transmitted by its
own encoding, enabling some types to be handled that cannot be
normally, plus providing a way to use gobs on data with unexported
fields.
In this CL, the necessary methods are protected by leading _, so only
package gob can use the facilities (in its tests, of course); this
code is not ready for real use yet. I could be talked into enabling
it for experimentation, though. The main drawback is that the
methods must be implemented by the actual type passed through,
not by an indirection from it. For instance, if *T implements
GobEncoder, you must send a *T, not a T. This will be addressed
in due course.
Also there is improved commentary and a couple of unrelated
minor bug fixes.
R=rsc
CC=golang-dev
https://golang.org/cl/4243056
2011-03-04 12:25:18 -08:00
|
|
|
func newDecodeStateFromData(data []byte) *decoderState {
|
2014-10-20 07:33:08 -07:00
|
|
|
b := newDecBuffer(data)
|
2011-03-15 21:30:07 -07:00
|
|
|
state := newDecodeState(b)
|
2009-12-15 15:35:38 -08:00
|
|
|
state.fieldnum = -1
|
|
|
|
|
return state
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test instruction execution for decoding.
|
|
|
|
|
// Do not run the machine yet; instead do individual instructions crafted by hand.
|
|
|
|
|
func TestScalarDecInstructions(t *testing.T) {
|
2011-11-01 22:04:37 -04:00
|
|
|
ovfl := errors.New("overflow")
|
2009-06-30 17:59:41 -07:00
|
|
|
|
|
|
|
|
// bool
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data bool
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decBool, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(boolResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("bool", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != true {
|
|
|
|
|
t.Errorf("bool a = %v not true", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// int
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Int], 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(signedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("int", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("int a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Uint], 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("uint", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("uint a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int8
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int8
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decInt8, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(signedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("int8", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("int8 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint8
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint8
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decUint8, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("uint8", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("uint8 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int16
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int16
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decInt16, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(signedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("int16", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("int16 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint16
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint16
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decUint16, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("uint16", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("uint16 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int32
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int32
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decInt32, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(signedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("int32", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("int32 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint32
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint32
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decUint32, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("uint32", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("uint32 a = %v not 17", data)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uintptr
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uintptr
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Uintptr], 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("uintptr", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("uintptr a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int64
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data int64
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decInt64, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(signedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("int64", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("int64 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint64
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data uint64
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decUint64, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("uint64", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("uint64 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// float32
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data float32
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decFloat32, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(floatResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("float32", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("float32 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// float64
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data float64
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decFloat64, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(floatResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("float64", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17 {
|
|
|
|
|
t.Errorf("float64 a = %v not 17", data)
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-02 11:21:01 -07:00
|
|
|
|
2010-06-24 15:07:28 -07:00
|
|
|
// complex64
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data complex64
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Complex64], 6, nil, ovfl}
|
2010-06-24 15:07:28 -07:00
|
|
|
state := newDecodeStateFromData(complexResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("complex", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17+19i {
|
|
|
|
|
t.Errorf("complex a = %v not 17+19i", data)
|
2010-06-24 15:07:28 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// complex128
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data complex128
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Complex128], 6, nil, ovfl}
|
2010-06-24 15:07:28 -07:00
|
|
|
state := newDecodeStateFromData(complexResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("complex", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != 17+19i {
|
|
|
|
|
t.Errorf("complex a = %v not 17+19i", data)
|
2010-06-24 15:07:28 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-02 11:21:01 -07:00
|
|
|
// bytes == []uint8
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data []byte
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decUint8Slice, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(bytesResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("bytes", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if string(data) != "hello" {
|
|
|
|
|
t.Errorf(`bytes a = %q not "hello"`, string(data))
|
2009-07-02 11:21:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// string
|
|
|
|
|
{
|
2014-06-30 11:06:47 -07:00
|
|
|
var data string
|
2014-06-30 15:47:11 -07:00
|
|
|
instr := &decInstr{decString, 6, nil, ovfl}
|
2009-12-15 15:35:38 -08:00
|
|
|
state := newDecodeStateFromData(bytesResult)
|
2014-06-30 11:06:47 -07:00
|
|
|
execDec("bytes", instr, state, t, reflect.ValueOf(&data))
|
|
|
|
|
if data != "hello" {
|
|
|
|
|
t.Errorf(`bytes a = %q not "hello"`, data)
|
2009-07-02 11:21:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-06-30 17:59:41 -07:00
|
|
|
}
|
2009-07-01 18:25:13 -07:00
|
|
|
|
2009-07-02 18:02:42 -07:00
|
|
|
func TestEndToEnd(t *testing.T) {
|
2009-07-02 13:43:47 -07:00
|
|
|
type T2 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
T string
|
2009-07-02 13:43:47 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
s1 := "string1"
|
|
|
|
|
s2 := "string2"
|
2009-07-02 08:21:42 -07:00
|
|
|
type T1 struct {
|
2011-07-21 10:27:11 +10:00
|
|
|
A, B, C int
|
|
|
|
|
M map[string]*float64
|
|
|
|
|
EmptyMap map[string]int // to check that we receive a non-nil map.
|
|
|
|
|
N *[3]float64
|
|
|
|
|
Strs *[2]string
|
|
|
|
|
Int64s *[]int64
|
|
|
|
|
RI complex64
|
|
|
|
|
S string
|
|
|
|
|
Y []byte
|
|
|
|
|
T *T2
|
2009-07-02 11:21:01 -07:00
|
|
|
}
|
2010-05-05 16:46:39 -07:00
|
|
|
pi := 3.14159
|
|
|
|
|
e := 2.71828
|
2009-07-02 11:21:01 -07:00
|
|
|
t1 := &T1{
|
2011-07-21 10:27:11 +10:00
|
|
|
A: 17,
|
|
|
|
|
B: 18,
|
|
|
|
|
C: -5,
|
|
|
|
|
M: map[string]*float64{"pi": &pi, "e": &e},
|
|
|
|
|
EmptyMap: make(map[string]int),
|
|
|
|
|
N: &[3]float64{1.5, 2.5, 3.5},
|
|
|
|
|
Strs: &[2]string{s1, s2},
|
|
|
|
|
Int64s: &[]int64{77, 89, 123412342134},
|
|
|
|
|
RI: 17 - 23i,
|
|
|
|
|
S: "Now is the time",
|
|
|
|
|
Y: []byte("hello, sailor"),
|
|
|
|
|
T: &T2{"this is T2"},
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
err := NewEncoder(b).Encode(t1)
|
2009-11-16 23:32:30 -08:00
|
|
|
if err != nil {
|
|
|
|
|
t.Error("encode:", err)
|
|
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var _t1 T1
|
|
|
|
|
err = NewDecoder(b).Decode(&_t1)
|
2009-11-16 23:32:30 -08:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
|
}
|
2009-07-01 18:25:13 -07:00
|
|
|
if !reflect.DeepEqual(t1, &_t1) {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("encode expected %v got %v", *t1, _t1)
|
2009-07-01 18:25:13 -07:00
|
|
|
}
|
2011-07-21 10:27:11 +10:00
|
|
|
// Be absolutely sure the received map is non-nil.
|
|
|
|
|
if t1.EmptyMap == nil {
|
|
|
|
|
t.Errorf("nil map sent")
|
|
|
|
|
}
|
|
|
|
|
if _t1.EmptyMap == nil {
|
|
|
|
|
t.Errorf("nil map received")
|
|
|
|
|
}
|
2009-07-01 18:25:13 -07:00
|
|
|
}
|
2009-07-02 08:21:42 -07:00
|
|
|
|
2009-07-28 12:59:39 -07:00
|
|
|
func TestOverflow(t *testing.T) {
|
|
|
|
|
type inputT struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi int64
|
|
|
|
|
Mini int64
|
|
|
|
|
Maxu uint64
|
|
|
|
|
Maxf float64
|
|
|
|
|
Minf float64
|
|
|
|
|
Maxc complex128
|
|
|
|
|
Minc complex128
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
|
|
|
|
var it inputT
|
2011-11-01 22:04:37 -04:00
|
|
|
var err error
|
2009-12-15 15:35:38 -08:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
enc := NewEncoder(b)
|
|
|
|
|
dec := NewDecoder(b)
|
2009-07-28 12:59:39 -07:00
|
|
|
|
|
|
|
|
// int8
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi: math.MaxInt8 + 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outi8 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi int8
|
|
|
|
|
Mini int8
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o1 outi8
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o1)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxi" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for int8:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Mini: math.MinInt8 - 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
|
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o1)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Mini" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong underflow error for int8:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int16
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi: math.MaxInt16 + 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outi16 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi int16
|
|
|
|
|
Mini int16
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o2 outi16
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o2)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxi" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for int16:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Mini: math.MinInt16 - 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
|
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o2)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Mini" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong underflow error for int16:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int32
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi: math.MaxInt32 + 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outi32 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxi int32
|
|
|
|
|
Mini int32
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o3 outi32
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o3)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxi" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for int32:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Mini: math.MinInt32 - 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
|
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o3)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Mini" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong underflow error for int32:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint8
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxu: math.MaxUint8 + 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outu8 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxu uint8
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o4 outu8
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o4)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxu" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for uint8:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint16
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxu: math.MaxUint16 + 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outu16 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxu uint16
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o5 outu16
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o5)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxu" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for uint16:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// uint32
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxu: math.MaxUint32 + 1,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outu32 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxu uint32
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o6 outu32
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o6)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxu" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for uint32:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// float32
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
2009-11-05 14:53:42 -08:00
|
|
|
it = inputT{
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxf: math.MaxFloat32 * 2,
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
type outf32 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxf float32
|
|
|
|
|
Minf float32
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
var o7 outf32
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o7)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxf" out of range` {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("wrong overflow error for float32:", err)
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
2010-06-24 15:07:28 -07:00
|
|
|
|
|
|
|
|
// complex64
|
|
|
|
|
b.Reset()
|
|
|
|
|
it = inputT{
|
2011-01-19 23:09:00 -05:00
|
|
|
Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2),
|
2010-06-24 15:07:28 -07:00
|
|
|
}
|
|
|
|
|
type outc64 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Maxc complex64
|
|
|
|
|
Minc complex64
|
2010-06-24 15:07:28 -07:00
|
|
|
}
|
|
|
|
|
var o8 outc64
|
|
|
|
|
enc.Encode(it)
|
|
|
|
|
err = dec.Decode(&o8)
|
2011-11-01 22:04:37 -04:00
|
|
|
if err == nil || err.Error() != `value for "Maxc" out of range` {
|
2010-06-24 15:07:28 -07:00
|
|
|
t.Error("wrong overflow error for complex64:", err)
|
|
|
|
|
}
|
2009-07-28 12:59:39 -07:00
|
|
|
}
|
|
|
|
|
|
2009-07-09 14:33:43 -07:00
|
|
|
func TestNesting(t *testing.T) {
|
|
|
|
|
type RT struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A string
|
|
|
|
|
Next *RT
|
2009-12-15 15:35:38 -08:00
|
|
|
}
|
|
|
|
|
rt := new(RT)
|
2011-01-11 13:44:00 -08:00
|
|
|
rt.A = "level1"
|
|
|
|
|
rt.Next = new(RT)
|
|
|
|
|
rt.Next.A = "level2"
|
2009-12-15 15:35:38 -08:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
NewEncoder(b).Encode(rt)
|
|
|
|
|
var drt RT
|
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
|
err := dec.Decode(&drt)
|
2009-11-16 23:32:30 -08:00
|
|
|
if err != nil {
|
2011-01-11 13:44:00 -08:00
|
|
|
t.Fatal("decoder error:", err)
|
2009-11-16 23:32:30 -08:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if drt.A != rt.A {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("nesting: encode expected %v got %v", *rt, drt)
|
2009-07-09 14:33:43 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if drt.Next == nil {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("nesting: recursion failed")
|
2009-07-09 14:33:43 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if drt.Next.A != rt.Next.A {
|
|
|
|
|
t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next)
|
2009-07-09 14:33:43 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-02 08:21:42 -07:00
|
|
|
// These three structures have the same data with different indirections
|
|
|
|
|
type T0 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A int
|
|
|
|
|
B int
|
|
|
|
|
C int
|
|
|
|
|
D int
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
type T1 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A int
|
|
|
|
|
B *int
|
|
|
|
|
C **int
|
|
|
|
|
D ***int
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
type T2 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A ***int
|
|
|
|
|
B **int
|
|
|
|
|
C *int
|
|
|
|
|
D int
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAutoIndirection(t *testing.T) {
|
2009-07-02 09:22:38 -07:00
|
|
|
// First transfer t1 into t0
|
2009-12-15 15:35:38 -08:00
|
|
|
var t1 T1
|
2011-01-11 13:44:00 -08:00
|
|
|
t1.A = 17
|
|
|
|
|
t1.B = new(int)
|
|
|
|
|
*t1.B = 177
|
|
|
|
|
t1.C = new(*int)
|
|
|
|
|
*t1.C = new(int)
|
|
|
|
|
**t1.C = 1777
|
|
|
|
|
t1.D = new(**int)
|
|
|
|
|
*t1.D = new(*int)
|
|
|
|
|
**t1.D = new(int)
|
|
|
|
|
***t1.D = 17777
|
2009-12-15 15:35:38 -08:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
enc := NewEncoder(b)
|
|
|
|
|
enc.Encode(t1)
|
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
|
var t0 T0
|
|
|
|
|
dec.Decode(&t0)
|
2011-01-11 13:44:00 -08:00
|
|
|
if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0)
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
|
2009-07-02 09:22:38 -07:00
|
|
|
// Now transfer t2 into t0
|
2009-12-15 15:35:38 -08:00
|
|
|
var t2 T2
|
2011-01-11 13:44:00 -08:00
|
|
|
t2.D = 17777
|
|
|
|
|
t2.C = new(int)
|
|
|
|
|
*t2.C = 1777
|
|
|
|
|
t2.B = new(*int)
|
|
|
|
|
*t2.B = new(int)
|
|
|
|
|
**t2.B = 177
|
|
|
|
|
t2.A = new(**int)
|
|
|
|
|
*t2.A = new(*int)
|
|
|
|
|
**t2.A = new(int)
|
|
|
|
|
***t2.A = 17
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(t2)
|
|
|
|
|
t0 = T0{}
|
|
|
|
|
dec.Decode(&t0)
|
2011-01-11 13:44:00 -08:00
|
|
|
if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0)
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now transfer t0 into t1
|
2009-12-15 15:35:38 -08:00
|
|
|
t0 = T0{17, 177, 1777, 17777}
|
|
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(t0)
|
|
|
|
|
t1 = T1{}
|
|
|
|
|
dec.Decode(&t1)
|
2011-01-11 13:44:00 -08:00
|
|
|
if t1.A != 17 || *t1.B != 177 || **t1.C != 1777 || ***t1.D != 17777 {
|
|
|
|
|
t.Errorf("t0->t1 expected {17 177 1777 17777}; got {%d %d %d %d}", t1.A, *t1.B, **t1.C, ***t1.D)
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now transfer t0 into t2
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(t0)
|
|
|
|
|
t2 = T2{}
|
|
|
|
|
dec.Decode(&t2)
|
2011-01-11 13:44:00 -08:00
|
|
|
if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
|
|
|
|
|
t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now do t2 again but without pre-allocated pointers.
|
2009-12-15 15:35:38 -08:00
|
|
|
b.Reset()
|
|
|
|
|
enc.Encode(t0)
|
2011-01-11 13:44:00 -08:00
|
|
|
***t2.A = 0
|
|
|
|
|
**t2.B = 0
|
|
|
|
|
*t2.C = 0
|
|
|
|
|
t2.D = 0
|
2009-12-15 15:35:38 -08:00
|
|
|
dec.Decode(&t2)
|
2011-01-11 13:44:00 -08:00
|
|
|
if ***t2.A != 17 || **t2.B != 177 || *t2.C != 1777 || t2.D != 17777 {
|
|
|
|
|
t.Errorf("t0->t2 expected {17 177 1777 17777}; got {%d %d %d %d}", ***t2.A, **t2.B, *t2.C, t2.D)
|
2009-07-02 08:21:42 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-16 17:55:16 -07:00
|
|
|
|
|
|
|
|
type RT0 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A int
|
|
|
|
|
B string
|
2011-01-19 23:09:00 -05:00
|
|
|
C float64
|
2009-07-16 17:55:16 -07:00
|
|
|
}
|
|
|
|
|
type RT1 struct {
|
2011-01-19 23:09:00 -05:00
|
|
|
C float64
|
2011-01-11 13:44:00 -08:00
|
|
|
B string
|
|
|
|
|
A int
|
|
|
|
|
NotSet string
|
2009-07-16 17:55:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestReorderedFields(t *testing.T) {
|
2009-12-15 15:35:38 -08:00
|
|
|
var rt0 RT0
|
2011-01-11 13:44:00 -08:00
|
|
|
rt0.A = 17
|
|
|
|
|
rt0.B = "hello"
|
|
|
|
|
rt0.C = 3.14159
|
2009-12-15 15:35:38 -08:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
NewEncoder(b).Encode(rt0)
|
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
|
var rt1 RT1
|
2009-07-16 17:55:16 -07:00
|
|
|
// Wire type is RT0, local type is RT1.
|
2009-12-15 15:35:38 -08:00
|
|
|
err := dec.Decode(&rt1)
|
2009-11-16 23:32:30 -08:00
|
|
|
if err != nil {
|
2011-01-11 13:44:00 -08:00
|
|
|
t.Fatal("decode error:", err)
|
2009-11-16 23:32:30 -08:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1)
|
2009-07-16 17:55:16 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Like an RT0 but with fields we'll ignore on the decode side.
|
|
|
|
|
type IT0 struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A int64
|
|
|
|
|
B string
|
|
|
|
|
Ignore_d []int
|
2011-01-19 23:09:00 -05:00
|
|
|
Ignore_e [3]float64
|
2011-01-11 13:44:00 -08:00
|
|
|
Ignore_f bool
|
|
|
|
|
Ignore_g string
|
|
|
|
|
Ignore_h []byte
|
|
|
|
|
Ignore_i *RT1
|
|
|
|
|
Ignore_m map[string]int
|
2011-01-19 23:09:00 -05:00
|
|
|
C float64
|
2009-07-16 17:55:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestIgnoredFields(t *testing.T) {
|
2009-12-15 15:35:38 -08:00
|
|
|
var it0 IT0
|
2011-01-11 13:44:00 -08:00
|
|
|
it0.A = 17
|
|
|
|
|
it0.B = "hello"
|
|
|
|
|
it0.C = 3.14159
|
|
|
|
|
it0.Ignore_d = []int{1, 2, 3}
|
|
|
|
|
it0.Ignore_e[0] = 1.0
|
|
|
|
|
it0.Ignore_e[1] = 2.0
|
|
|
|
|
it0.Ignore_e[2] = 3.0
|
|
|
|
|
it0.Ignore_f = true
|
|
|
|
|
it0.Ignore_g = "pay no attention"
|
|
|
|
|
it0.Ignore_h = []byte("to the curtain")
|
|
|
|
|
it0.Ignore_i = &RT1{3.1, "hi", 7, "hello"}
|
|
|
|
|
it0.Ignore_m = map[string]int{"one": 1, "two": 2}
|
2009-12-15 15:35:38 -08:00
|
|
|
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
NewEncoder(b).Encode(it0)
|
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
|
var rt1 RT1
|
2009-07-16 17:55:16 -07:00
|
|
|
// Wire type is IT0, local type is RT1.
|
2009-12-15 15:35:38 -08:00
|
|
|
err := dec.Decode(&rt1)
|
2009-07-17 11:38:31 -07:00
|
|
|
if err != nil {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Error("error: ", err)
|
2009-07-17 11:38:31 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if int(it0.A) != rt1.A || it0.B != rt1.B || it0.C != rt1.C {
|
|
|
|
|
t.Errorf("rt0->rt1: expected %v; got %v", it0, rt1)
|
2009-07-16 17:55:16 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-29 17:24:25 -07:00
|
|
|
|
2011-02-23 09:49:35 -08:00
|
|
|
func TestBadRecursiveType(t *testing.T) {
|
|
|
|
|
type Rec ***Rec
|
|
|
|
|
var rec Rec
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
err := NewEncoder(b).Encode(&rec)
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Error("expected error; got none")
|
2011-11-01 22:04:37 -04:00
|
|
|
} else if strings.Index(err.Error(), "recursive") < 0 {
|
2011-02-23 09:49:35 -08:00
|
|
|
t.Error("expected recursive type error; got", err)
|
|
|
|
|
}
|
|
|
|
|
// Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-06 10:45:18 -07:00
|
|
|
type Indirect struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A ***[3]int
|
|
|
|
|
S ***[]int
|
|
|
|
|
M ****map[string]int
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Direct struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A [3]int
|
|
|
|
|
S []int
|
|
|
|
|
M map[string]int
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestIndirectSliceMapArray(t *testing.T) {
|
|
|
|
|
// Marshal indirect, unmarshal to direct.
|
|
|
|
|
i := new(Indirect)
|
2011-01-11 13:44:00 -08:00
|
|
|
i.A = new(**[3]int)
|
|
|
|
|
*i.A = new(*[3]int)
|
|
|
|
|
**i.A = new([3]int)
|
|
|
|
|
***i.A = [3]int{1, 2, 3}
|
|
|
|
|
i.S = new(**[]int)
|
|
|
|
|
*i.S = new(*[]int)
|
|
|
|
|
**i.S = new([]int)
|
|
|
|
|
***i.S = []int{4, 5, 6}
|
|
|
|
|
i.M = new(***map[string]int)
|
|
|
|
|
*i.M = new(**map[string]int)
|
|
|
|
|
**i.M = new(*map[string]int)
|
|
|
|
|
***i.M = new(map[string]int)
|
|
|
|
|
****i.M = map[string]int{"one": 1, "two": 2, "three": 3}
|
2010-05-06 10:45:18 -07:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
NewEncoder(b).Encode(i)
|
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
|
var d Direct
|
|
|
|
|
err := dec.Decode(&d)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error("error: ", err)
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(d.A) != 3 || d.A[0] != 1 || d.A[1] != 2 || d.A[2] != 3 {
|
|
|
|
|
t.Errorf("indirect to direct: d.A is %v not %v", d.A, ***i.A)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(d.S) != 3 || d.S[0] != 4 || d.S[1] != 5 || d.S[2] != 6 {
|
|
|
|
|
t.Errorf("indirect to direct: d.S is %v not %v", d.S, ***i.S)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(d.M) != 3 || d.M["one"] != 1 || d.M["two"] != 2 || d.M["three"] != 3 {
|
|
|
|
|
t.Errorf("indirect to direct: d.M is %v not %v", d.M, ***i.M)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
|
|
|
|
// Marshal direct, unmarshal to indirect.
|
2011-01-11 13:44:00 -08:00
|
|
|
d.A = [3]int{11, 22, 33}
|
|
|
|
|
d.S = []int{44, 55, 66}
|
|
|
|
|
d.M = map[string]int{"four": 4, "five": 5, "six": 6}
|
2010-05-06 10:45:18 -07:00
|
|
|
i = new(Indirect)
|
|
|
|
|
b.Reset()
|
|
|
|
|
NewEncoder(b).Encode(d)
|
|
|
|
|
dec = NewDecoder(b)
|
|
|
|
|
err = dec.Decode(&i)
|
|
|
|
|
if err != nil {
|
2011-01-11 13:44:00 -08:00
|
|
|
t.Fatal("error: ", err)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(***i.A) != 3 || (***i.A)[0] != 11 || (***i.A)[1] != 22 || (***i.A)[2] != 33 {
|
|
|
|
|
t.Errorf("direct to indirect: ***i.A is %v not %v", ***i.A, d.A)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(***i.S) != 3 || (***i.S)[0] != 44 || (***i.S)[1] != 55 || (***i.S)[2] != 66 {
|
|
|
|
|
t.Errorf("direct to indirect: ***i.S is %v not %v", ***i.S, ***i.S)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(****i.M) != 3 || (****i.M)["four"] != 4 || (****i.M)["five"] != 5 || (****i.M)["six"] != 6 {
|
|
|
|
|
t.Errorf("direct to indirect: ****i.M is %v not %v", ****i.M, d.M)
|
2010-05-06 10:45:18 -07:00
|
|
|
}
|
|
|
|
|
}
|
2010-10-22 11:17:40 -07:00
|
|
|
|
|
|
|
|
// An interface with several implementations
|
|
|
|
|
type Squarer interface {
|
|
|
|
|
Square() int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Int int
|
|
|
|
|
|
|
|
|
|
func (i Int) Square() int {
|
|
|
|
|
return int(i * i)
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-19 23:09:00 -05:00
|
|
|
type Float float64
|
2010-10-22 11:17:40 -07:00
|
|
|
|
|
|
|
|
func (f Float) Square() int {
|
|
|
|
|
return int(f * f)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Vector []int
|
|
|
|
|
|
|
|
|
|
func (v Vector) Square() int {
|
|
|
|
|
sum := 0
|
|
|
|
|
for _, x := range v {
|
|
|
|
|
sum += x * x
|
|
|
|
|
}
|
|
|
|
|
return sum
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-31 13:41:30 -07:00
|
|
|
type Point struct {
|
2011-01-22 00:10:11 -08:00
|
|
|
X, Y int
|
2010-10-31 13:41:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p Point) Square() int {
|
2011-01-22 00:10:11 -08:00
|
|
|
return p.X*p.X + p.Y*p.Y
|
2010-10-31 13:41:30 -07:00
|
|
|
}
|
|
|
|
|
|
2010-10-22 11:17:40 -07:00
|
|
|
// A struct with interfaces in it.
|
|
|
|
|
type InterfaceItem struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
I int
|
|
|
|
|
Sq1, Sq2, Sq3 Squarer
|
2011-01-19 23:09:00 -05:00
|
|
|
F float64
|
2011-01-11 13:44:00 -08:00
|
|
|
Sq []Squarer
|
2010-10-22 11:17:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The same struct without interfaces
|
|
|
|
|
type NoInterfaceItem struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
I int
|
2011-01-19 23:09:00 -05:00
|
|
|
F float64
|
2010-10-22 11:17:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestInterface(t *testing.T) {
|
|
|
|
|
iVal := Int(3)
|
|
|
|
|
fVal := Float(5)
|
|
|
|
|
// Sending a Vector will require that the receiver define a type in the middle of
|
|
|
|
|
// receiving the value for item2.
|
|
|
|
|
vVal := Vector{1, 2, 3}
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
item1 := &InterfaceItem{1, iVal, fVal, vVal, 11.5, []Squarer{iVal, fVal, nil, vVal}}
|
|
|
|
|
// Register the types.
|
|
|
|
|
Register(Int(0))
|
|
|
|
|
Register(Float(0))
|
|
|
|
|
Register(Vector{})
|
|
|
|
|
err := NewEncoder(b).Encode(item1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error("expected no encode error; got", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item2 := InterfaceItem{}
|
|
|
|
|
err = NewDecoder(b).Decode(&item2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.I != item1.I {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("normal int did not decode correctly")
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("Int did not decode correctly")
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("Float did not decode correctly")
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("Vector did not decode correctly")
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.F != item1.F {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("normal float did not decode correctly")
|
|
|
|
|
}
|
|
|
|
|
// Now check that we received a slice of Squarers correctly, including a nil element
|
2011-01-11 13:44:00 -08:00
|
|
|
if len(item1.Sq) != len(item2.Sq) {
|
|
|
|
|
t.Fatalf("[]Squarer length wrong: got %d; expected %d", len(item2.Sq), len(item1.Sq))
|
2010-10-22 11:17:40 -07:00
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
for i, v1 := range item1.Sq {
|
|
|
|
|
v2 := item2.Sq[i]
|
2010-10-22 11:17:40 -07:00
|
|
|
if v1 == nil || v2 == nil {
|
|
|
|
|
if v1 != nil || v2 != nil {
|
|
|
|
|
t.Errorf("item %d inconsistent nils", i)
|
|
|
|
|
}
|
2013-03-22 14:22:55 -07:00
|
|
|
} else if v1.Square() != v2.Square() {
|
|
|
|
|
t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
|
2010-10-22 11:17:40 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-26 17:07:39 -07:00
|
|
|
// A struct with all basic types, stored in interfaces.
|
|
|
|
|
type BasicInterfaceItem struct {
|
|
|
|
|
Int, Int8, Int16, Int32, Int64 interface{}
|
|
|
|
|
Uint, Uint8, Uint16, Uint32, Uint64 interface{}
|
2011-01-19 23:09:00 -05:00
|
|
|
Float32, Float64 interface{}
|
|
|
|
|
Complex64, Complex128 interface{}
|
2010-10-26 17:07:39 -07:00
|
|
|
Bool interface{}
|
|
|
|
|
String interface{}
|
|
|
|
|
Bytes interface{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestInterfaceBasic(t *testing.T) {
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
item1 := &BasicInterfaceItem{
|
|
|
|
|
int(1), int8(1), int16(1), int32(1), int64(1),
|
|
|
|
|
uint(1), uint8(1), uint16(1), uint32(1), uint64(1),
|
2011-01-19 23:09:00 -05:00
|
|
|
float32(1), 1.0,
|
2011-01-28 10:53:42 -08:00
|
|
|
complex64(1i), complex128(1i),
|
2010-10-26 17:07:39 -07:00
|
|
|
true,
|
|
|
|
|
"hello",
|
|
|
|
|
[]byte("sailor"),
|
|
|
|
|
}
|
|
|
|
|
err := NewEncoder(b).Encode(item1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error("expected no encode error; got", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item2 := &BasicInterfaceItem{}
|
|
|
|
|
err = NewDecoder(b).Decode(&item2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
|
}
|
|
|
|
|
if !reflect.DeepEqual(item1, item2) {
|
|
|
|
|
t.Errorf("encode expected %v got %v", item1, item2)
|
|
|
|
|
}
|
|
|
|
|
// Hand check a couple for correct types.
|
|
|
|
|
if v, ok := item2.Bool.(bool); !ok || !v {
|
|
|
|
|
t.Error("boolean should be true")
|
|
|
|
|
}
|
|
|
|
|
if v, ok := item2.String.(string); !ok || v != item1.String.(string) {
|
|
|
|
|
t.Errorf("string should be %v is %v", item1.String, v)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-05 10:36:27 -07:00
|
|
|
type String string
|
|
|
|
|
|
|
|
|
|
type PtrInterfaceItem struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
Str1 interface{} // basic
|
|
|
|
|
Str2 interface{} // derived
|
2010-11-05 10:36:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We'll send pointers; should receive values.
|
|
|
|
|
// Also check that we can register T but send *T.
|
|
|
|
|
func TestInterfacePointer(t *testing.T) {
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
str1 := "howdy"
|
|
|
|
|
str2 := String("kiddo")
|
|
|
|
|
item1 := &PtrInterfaceItem{
|
|
|
|
|
&str1,
|
|
|
|
|
&str2,
|
|
|
|
|
}
|
|
|
|
|
// Register the type.
|
|
|
|
|
Register(str2)
|
|
|
|
|
err := NewEncoder(b).Encode(item1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error("expected no encode error; got", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item2 := &PtrInterfaceItem{}
|
|
|
|
|
err = NewDecoder(b).Decode(&item2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
|
}
|
|
|
|
|
// Hand test for correct types and values.
|
2011-01-11 13:44:00 -08:00
|
|
|
if v, ok := item2.Str1.(string); !ok || v != str1 {
|
2010-11-05 10:36:27 -07:00
|
|
|
t.Errorf("basic string failed: %q should be %q", v, str1)
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if v, ok := item2.Str2.(String); !ok || v != str2 {
|
2010-11-05 10:36:27 -07:00
|
|
|
t.Errorf("derived type String failed: %q should be %q", v, str2)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-22 11:17:40 -07:00
|
|
|
func TestIgnoreInterface(t *testing.T) {
|
|
|
|
|
iVal := Int(3)
|
|
|
|
|
fVal := Float(5)
|
2010-10-31 13:41:30 -07:00
|
|
|
// Sending a Point will require that the receiver define a type in the middle of
|
2010-10-22 11:17:40 -07:00
|
|
|
// receiving the value for item2.
|
2010-10-31 13:41:30 -07:00
|
|
|
pVal := Point{2, 3}
|
2010-10-22 11:17:40 -07:00
|
|
|
b := new(bytes.Buffer)
|
2010-10-31 13:41:30 -07:00
|
|
|
item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil}
|
2010-10-22 11:17:40 -07:00
|
|
|
// Register the types.
|
|
|
|
|
Register(Int(0))
|
|
|
|
|
Register(Float(0))
|
2010-10-31 13:41:30 -07:00
|
|
|
Register(Point{})
|
2010-10-22 11:17:40 -07:00
|
|
|
err := NewEncoder(b).Encode(item1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error("expected no encode error; got", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
item2 := NoInterfaceItem{}
|
|
|
|
|
err = NewDecoder(b).Decode(&item2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.I != item1.I {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("normal int did not decode correctly")
|
|
|
|
|
}
|
2011-01-11 13:44:00 -08:00
|
|
|
if item2.F != item2.F {
|
2010-10-22 11:17:40 -07:00
|
|
|
t.Error("normal float did not decode correctly")
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-29 15:07:56 -07:00
|
|
|
|
2011-01-11 13:44:00 -08:00
|
|
|
type U struct {
|
|
|
|
|
A int
|
|
|
|
|
B string
|
2011-01-19 23:09:00 -05:00
|
|
|
c float64
|
2011-01-11 13:44:00 -08:00
|
|
|
D uint
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUnexportedFields(t *testing.T) {
|
|
|
|
|
var u0 U
|
|
|
|
|
u0.A = 17
|
|
|
|
|
u0.B = "hello"
|
|
|
|
|
u0.c = 3.14159
|
|
|
|
|
u0.D = 23
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
NewEncoder(b).Encode(u0)
|
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
|
var u1 U
|
|
|
|
|
u1.c = 1234.
|
|
|
|
|
err := dec.Decode(&u1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("decode error:", err)
|
|
|
|
|
}
|
|
|
|
|
if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
|
|
|
|
|
t.Errorf("u1->u0: expected %v; got %v", u0, u1)
|
|
|
|
|
}
|
|
|
|
|
if u1.c != 1234. {
|
|
|
|
|
t.Error("u1.c modified")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-21 11:28:53 -08:00
|
|
|
var singletons = []interface{}{
|
|
|
|
|
true,
|
|
|
|
|
7,
|
|
|
|
|
3.2,
|
|
|
|
|
"hello",
|
|
|
|
|
[3]int{11, 22, 33},
|
|
|
|
|
[]float32{0.5, 0.25, 0.125},
|
|
|
|
|
map[string]int{"one": 1, "two": 2},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestDebugSingleton(t *testing.T) {
|
|
|
|
|
if debugFunc == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
// Accumulate a number of values and print them out all at once.
|
|
|
|
|
for _, x := range singletons {
|
|
|
|
|
err := NewEncoder(b).Encode(x)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("encode:", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
debugFunc(b)
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-29 15:07:56 -07:00
|
|
|
// A type that won't be defined in the gob until we send it in an interface value.
|
|
|
|
|
type OnTheFly struct {
|
2011-01-11 13:44:00 -08:00
|
|
|
A int
|
2010-10-29 15:07:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type DT struct {
|
|
|
|
|
// X OnTheFly
|
2011-01-11 13:44:00 -08:00
|
|
|
A int
|
|
|
|
|
B string
|
2011-01-19 23:09:00 -05:00
|
|
|
C float64
|
2011-01-11 13:44:00 -08:00
|
|
|
I interface{}
|
|
|
|
|
J interface{}
|
|
|
|
|
I_nil interface{}
|
|
|
|
|
M map[string]int
|
|
|
|
|
T [3]int
|
|
|
|
|
S []string
|
2010-10-29 15:07:56 -07:00
|
|
|
}
|
|
|
|
|
|
2014-01-30 07:54:57 +01:00
|
|
|
func newDT() DT {
|
2010-10-29 15:07:56 -07:00
|
|
|
var dt DT
|
2011-01-11 13:44:00 -08:00
|
|
|
dt.A = 17
|
|
|
|
|
dt.B = "hello"
|
|
|
|
|
dt.C = 3.14159
|
|
|
|
|
dt.I = 271828
|
|
|
|
|
dt.J = OnTheFly{3}
|
|
|
|
|
dt.I_nil = nil
|
|
|
|
|
dt.M = map[string]int{"one": 1, "two": 2}
|
|
|
|
|
dt.T = [3]int{11, 22, 33}
|
|
|
|
|
dt.S = []string{"hi", "joe"}
|
2014-01-30 07:54:57 +01:00
|
|
|
return dt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestDebugStruct(t *testing.T) {
|
|
|
|
|
if debugFunc == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
Register(OnTheFly{})
|
|
|
|
|
dt := newDT()
|
2010-10-29 15:07:56 -07:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
|
err := NewEncoder(b).Encode(dt)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("encode:", err)
|
|
|
|
|
}
|
|
|
|
|
debugBuffer := bytes.NewBuffer(b.Bytes())
|
|
|
|
|
dt2 := &DT{}
|
|
|
|
|
err = NewDecoder(b).Decode(&dt2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error("decode:", err)
|
|
|
|
|
}
|
|
|
|
|
debugFunc(debugBuffer)
|
|
|
|
|
}
|
2012-02-06 14:02:12 +11:00
|
|
|
|
|
|
|
|
func encFuzzDec(rng *rand.Rand, in interface{}) error {
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
|
enc := NewEncoder(buf)
|
|
|
|
|
if err := enc.Encode(&in); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b := buf.Bytes()
|
|
|
|
|
for i, bi := range b {
|
|
|
|
|
if rng.Intn(10) < 3 {
|
|
|
|
|
b[i] = bi + uint8(rng.Intn(256))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dec := NewDecoder(buf)
|
|
|
|
|
var e interface{}
|
|
|
|
|
if err := dec.Decode(&e); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This does some "fuzz testing" by attempting to decode a sequence of random bytes.
|
|
|
|
|
func TestFuzz(t *testing.T) {
|
2012-07-13 14:23:51 -07:00
|
|
|
if !*doFuzzTests {
|
|
|
|
|
t.Logf("disabled; run with -gob.fuzz to enable")
|
2012-02-06 14:02:12 +11:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// all possible inputs
|
|
|
|
|
input := []interface{}{
|
|
|
|
|
new(int),
|
|
|
|
|
new(float32),
|
|
|
|
|
new(float64),
|
|
|
|
|
new(complex128),
|
|
|
|
|
&ByteStruct{255},
|
|
|
|
|
&ArrayStruct{},
|
|
|
|
|
&StringStruct{"hello"},
|
|
|
|
|
&GobTest1{0, &StringStruct{"hello"}},
|
|
|
|
|
}
|
|
|
|
|
testFuzz(t, time.Now().UnixNano(), 100, input...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestFuzzRegressions(t *testing.T) {
|
2012-07-13 14:23:51 -07:00
|
|
|
if !*doFuzzTests {
|
|
|
|
|
t.Logf("disabled; run with -gob.fuzz to enable")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 14:02:12 +11:00
|
|
|
// An instance triggering a type name of length ~102 GB.
|
|
|
|
|
testFuzz(t, 1328492090837718000, 100, new(float32))
|
2012-03-01 15:57:54 +11:00
|
|
|
// An instance triggering a type name of 1.6 GB.
|
2012-07-13 14:23:51 -07:00
|
|
|
// Note: can take several minutes to run.
|
|
|
|
|
testFuzz(t, 1330522872628565000, 100, new(int))
|
2012-02-06 14:02:12 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) {
|
|
|
|
|
for _, e := range input {
|
2012-03-01 15:57:54 +11:00
|
|
|
t.Logf("seed=%d n=%d e=%T", seed, n, e)
|
2012-02-06 14:02:12 +11:00
|
|
|
rng := rand.New(rand.NewSource(seed))
|
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
|
encFuzzDec(rng, e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-30 07:54:57 +01:00
|
|
|
|
|
|
|
|
// TestFuzzOneByte tries to decode corrupted input sequences
|
|
|
|
|
// and checks that no panic occurs.
|
|
|
|
|
func TestFuzzOneByte(t *testing.T) {
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
|
Register(OnTheFly{})
|
|
|
|
|
dt := newDT()
|
|
|
|
|
if err := NewEncoder(buf).Encode(dt); err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
s := buf.String()
|
|
|
|
|
|
|
|
|
|
indices := make([]int, 0, len(s))
|
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
|
switch i {
|
|
|
|
|
case 14, 167, 231, 265: // a slice length, corruptions are not handled yet.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
indices = append(indices, i)
|
|
|
|
|
}
|
|
|
|
|
if testing.Short() {
|
|
|
|
|
indices = []int{1, 111, 178} // known fixed panics
|
|
|
|
|
}
|
|
|
|
|
for _, i := range indices {
|
|
|
|
|
for j := 0; j < 256; j += 3 {
|
|
|
|
|
b := []byte(s)
|
|
|
|
|
b[i] ^= byte(j)
|
|
|
|
|
var e DT
|
|
|
|
|
func() {
|
|
|
|
|
defer func() {
|
|
|
|
|
if p := recover(); p != nil {
|
|
|
|
|
t.Errorf("crash for b[%d] ^= 0x%x", i, j)
|
|
|
|
|
panic(p)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
err := NewDecoder(bytes.NewReader(b)).Decode(&e)
|
|
|
|
|
_ = err
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-28 23:07:05 +01:00
|
|
|
|
|
|
|
|
// Don't crash, just give error with invalid type id.
|
|
|
|
|
// Issue 9649.
|
|
|
|
|
func TestErrorInvalidTypeId(t *testing.T) {
|
|
|
|
|
data := []byte{0x01, 0x00, 0x01, 0x00}
|
|
|
|
|
d := NewDecoder(bytes.NewReader(data))
|
|
|
|
|
// When running d.Decode(&foo) the first time the decoder stops
|
|
|
|
|
// after []byte{0x01, 0x00} and reports an errBadType. Running
|
|
|
|
|
// d.Decode(&foo) again on exactly the same input sequence should
|
|
|
|
|
// give another errBadType, but instead caused a panic because
|
|
|
|
|
// decoderMap wasn't cleaned up properly after the first error.
|
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
|
var foo struct{}
|
|
|
|
|
err := d.Decode(&foo)
|
|
|
|
|
if err != errBadType {
|
2015-08-11 15:29:40 +10:00
|
|
|
t.Fatalf("decode: expected %s, got %s", errBadType, err)
|
2015-01-28 23:07:05 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|