2009-06-29 16:15:07 -06: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 16:35:38 -07:00
|
|
|
"bytes"
|
|
|
|
"math"
|
|
|
|
"os"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"unsafe"
|
2009-06-29 16:15:07 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// Guarantee encoding format by comparing some encodings to hand-written values
|
|
|
|
type EncodeT struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
x uint64
|
|
|
|
b []byte
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
2009-11-05 15:53:42 -07:00
|
|
|
|
|
|
|
var encodeT = []EncodeT{
|
2010-10-22 11:06:33 -06: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 16:15:07 -06:00
|
|
|
}
|
|
|
|
|
2010-10-22 16:16:34 -06: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 {
|
|
|
|
t.Error(e.(gobError).Error) // Will re-panic if not one of our errors, such as a runtime error.
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2009-06-29 16:15:07 -06:00
|
|
|
// Test basic encode/decode routines for unsigned integers
|
|
|
|
func TestUintCodec(t *testing.T) {
|
2010-10-22 16:16:34 -06:00
|
|
|
defer testError(t)
|
2009-12-15 16:35:38 -07:00
|
|
|
b := new(bytes.Buffer)
|
2010-10-31 14:41:30 -06:00
|
|
|
encState := newEncoderState(nil, b)
|
2009-09-15 10:41:59 -06:00
|
|
|
for _, tt := range encodeT {
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2011-01-11 18:56:45 -07:00
|
|
|
encState.encodeUint(tt.x)
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(tt.b, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes())
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
|
|
|
}
|
2011-01-28 11:53:42 -07:00
|
|
|
decState := newDecodeState(nil, b)
|
2009-11-09 22:13:17 -07:00
|
|
|
for u := uint64(0); ; u = (u + 1) * 7 {
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2011-01-11 18:56:45 -07:00
|
|
|
encState.encodeUint(u)
|
|
|
|
v := decState.decodeUint()
|
2009-06-29 16:15:07 -06:00
|
|
|
if u != v {
|
2010-09-22 21:48:56 -06:00
|
|
|
t.Errorf("Encode/Decode: sent %#x received %#x", u, v)
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
2009-11-05 15:53:42 -07:00
|
|
|
if u&(1<<63) != 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func verifyInt(i int64, t *testing.T) {
|
2010-10-22 16:16:34 -06:00
|
|
|
defer testError(t)
|
2009-12-15 16:35:38 -07:00
|
|
|
var b = new(bytes.Buffer)
|
2010-10-31 14:41:30 -06:00
|
|
|
encState := newEncoderState(nil, b)
|
2011-01-11 18:56:45 -07:00
|
|
|
encState.encodeInt(i)
|
2011-01-28 11:53:42 -07:00
|
|
|
decState := newDecodeState(nil, b)
|
2009-12-15 16:35:38 -07:00
|
|
|
decState.buf = make([]byte, 8)
|
2011-01-11 18:56:45 -07:00
|
|
|
j := decState.decodeInt()
|
2009-06-29 16:15:07 -06:00
|
|
|
if i != j {
|
2010-09-22 21:48:56 -06:00
|
|
|
t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test basic encode/decode routines for signed integers
|
|
|
|
func TestIntCodec(t *testing.T) {
|
2009-11-09 22:13:17 -07:00
|
|
|
for u := uint64(0); ; u = (u + 1) * 7 {
|
2009-06-29 16:15:07 -06:00
|
|
|
// Do positive and negative values
|
2009-12-15 16:35:38 -07:00
|
|
|
i := int64(u)
|
|
|
|
verifyInt(i, t)
|
|
|
|
verifyInt(-i, t)
|
|
|
|
verifyInt(^i, t)
|
2009-11-05 15:53:42 -07:00
|
|
|
if u&(1<<63) != 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
verifyInt(-1<<63, t) // a tricky case
|
2009-06-29 16:15:07 -06:00
|
|
|
}
|
2009-06-30 16:37:46 -06:00
|
|
|
|
2009-07-28 18:20:19 -06:00
|
|
|
// The result of encoding a true boolean with field number 7
|
|
|
|
var boolResult = []byte{0x07, 0x01}
|
|
|
|
// The result of encoding a number 17 with field number 7
|
2009-11-09 22:13:17 -07:00
|
|
|
var signedResult = []byte{0x07, 2 * 17}
|
2009-07-28 18:20:19 -06:00
|
|
|
var unsignedResult = []byte{0x07, 17}
|
|
|
|
var floatResult = []byte{0x07, 0xFE, 0x31, 0x40}
|
2010-06-24 16:07:28 -06:00
|
|
|
// The result of encoding a number 17+19i with field number 7
|
|
|
|
var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
|
|
|
|
// The result of encoding "hello" with field number 7
|
2009-07-28 18:20:19 -06:00
|
|
|
var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
|
2009-07-01 19:25:13 -06:00
|
|
|
|
2009-07-15 17:10:17 -06:00
|
|
|
func newencoderState(b *bytes.Buffer) *encoderState {
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2010-10-31 14:41:30 -06:00
|
|
|
state := newEncoderState(nil, b)
|
2009-12-15 16:35:38 -07:00
|
|
|
state.fieldnum = -1
|
|
|
|
return state
|
2009-07-01 19:25:13 -06:00
|
|
|
}
|
2009-06-30 16:37:46 -06:00
|
|
|
|
|
|
|
// Test instruction execution for encoding.
|
|
|
|
// Do not run the machine yet; instead do individual instructions crafted by hand.
|
|
|
|
func TestScalarEncInstructions(t *testing.T) {
|
2009-12-15 16:35:38 -07:00
|
|
|
var b = new(bytes.Buffer)
|
2009-06-30 16:37:46 -06:00
|
|
|
|
|
|
|
// bool
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
data := struct{ a bool }{true}
|
|
|
|
instr := &encInstr{encBool, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(boolResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a int }{17}
|
|
|
|
instr := &encInstr{encInt, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a uint }{17}
|
|
|
|
instr := &encInstr{encUint, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int8
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a int8 }{17}
|
|
|
|
instr := &encInstr{encInt8, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint8
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a uint8 }{17}
|
|
|
|
instr := &encInstr{encUint8, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int16
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a int16 }{17}
|
|
|
|
instr := &encInstr{encInt16, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint16
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a uint16 }{17}
|
|
|
|
instr := &encInstr{encUint16, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int32
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a int32 }{17}
|
|
|
|
instr := &encInstr{encInt32, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint32
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a uint32 }{17}
|
|
|
|
instr := &encInstr{encUint32, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int64
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a int64 }{17}
|
|
|
|
instr := &encInstr{encInt64, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(signedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint64
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a uint64 }{17}
|
|
|
|
instr := &encInstr{encUint64, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(unsignedResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// float32
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a float32 }{17}
|
|
|
|
instr := &encInstr{encFloat32, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(floatResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// float64
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a float64 }{17}
|
|
|
|
instr := &encInstr{encFloat64, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(floatResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes())
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-02 12:21:01 -06:00
|
|
|
|
|
|
|
// bytes == []uint8
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2010-02-25 17:01:29 -07:00
|
|
|
data := struct{ a []byte }{[]byte("hello")}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &encInstr{encUint8Array, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(bytesResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes())
|
2009-07-02 12:21:01 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// string
|
|
|
|
{
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
data := struct{ a string }{"hello"}
|
|
|
|
instr := &encInstr{encString, 6, 0, 0}
|
|
|
|
state := newencoderState(b)
|
|
|
|
instr.op(instr, state, unsafe.Pointer(&data))
|
2009-09-16 16:15:00 -06:00
|
|
|
if !bytes.Equal(bytesResult, b.Bytes()) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes())
|
2009-07-02 12:21:01 -06:00
|
|
|
}
|
|
|
|
}
|
2009-06-30 16:37:46 -06:00
|
|
|
}
|
2009-06-30 18:59:41 -06: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 13:25:18 -07:00
|
|
|
func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) {
|
2010-10-22 16:16:34 -06:00
|
|
|
defer testError(t)
|
2011-01-11 18:56:45 -07:00
|
|
|
v := int(state.decodeUint())
|
2009-11-09 22:13:17 -07:00
|
|
|
if v+state.fieldnum != 6 {
|
|
|
|
t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr.op(instr, state, decIndirect(p, instr.indir))
|
|
|
|
state.fieldnum = 6
|
2009-07-01 19:25:13 -06: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 13:25:18 -07:00
|
|
|
func newDecodeStateFromData(data []byte) *decoderState {
|
2010-10-22 12:17:40 -06:00
|
|
|
b := bytes.NewBuffer(data)
|
2011-01-28 11:53:42 -07:00
|
|
|
state := newDecodeState(nil, b)
|
2009-12-15 16:35:38 -07:00
|
|
|
state.fieldnum = -1
|
|
|
|
return state
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test instruction execution for decoding.
|
|
|
|
// Do not run the machine yet; instead do individual instructions crafted by hand.
|
|
|
|
func TestScalarDecInstructions(t *testing.T) {
|
2009-12-15 16:35:38 -07:00
|
|
|
ovfl := os.ErrorString("overflow")
|
2009-06-30 18:59:41 -06:00
|
|
|
|
|
|
|
// bool
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a bool
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decBool, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(boolResult)
|
|
|
|
execDec("bool", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != true {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("bool a = %v not true", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// int
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a int
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2011-02-25 10:45:06 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl}
|
2009-12-15 16:35:38 -07:00
|
|
|
state := newDecodeStateFromData(signedResult)
|
|
|
|
execDec("int", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a uint
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2011-02-25 10:45:06 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl}
|
2009-12-15 16:35:38 -07:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
|
|
|
execDec("uint", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int8
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a int8
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decInt8, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(signedResult)
|
|
|
|
execDec("int8", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int8 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint8
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a uint8
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decUint8, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
|
|
|
execDec("uint8", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint8 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int16
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a int16
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decInt16, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(signedResult)
|
|
|
|
execDec("int16", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int16 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint16
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a uint16
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decUint16, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
|
|
|
execDec("uint16", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint16 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int32
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a int32
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decInt32, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(signedResult)
|
|
|
|
execDec("int32", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int32 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint32
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a uint32
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decUint32, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
|
|
|
execDec("uint32", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint32 a = %v not 17", data.a)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uintptr
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a uintptr
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2011-02-25 10:45:06 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl}
|
2009-12-15 16:35:38 -07:00
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
|
|
|
execDec("uintptr", instr, state, t, unsafe.Pointer(&data))
|
2009-07-28 13:59:39 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uintptr a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// int64
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a int64
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decInt64, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(signedResult)
|
|
|
|
execDec("int64", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("int64 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint64
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a uint64
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decUint64, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(unsignedResult)
|
|
|
|
execDec("uint64", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("uint64 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// float32
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a float32
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decFloat32, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(floatResult)
|
|
|
|
execDec("float32", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("float32 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// float64
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a float64
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decFloat64, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(floatResult)
|
|
|
|
execDec("float64", instr, state, t, unsafe.Pointer(&data))
|
2009-06-30 18:59:41 -06:00
|
|
|
if data.a != 17 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("float64 a = %v not 17", data.a)
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-02 12:21:01 -06:00
|
|
|
|
2010-06-24 16:07:28 -06:00
|
|
|
// complex64
|
|
|
|
{
|
|
|
|
var data struct {
|
|
|
|
a complex64
|
|
|
|
}
|
2011-02-25 10:45:06 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl}
|
2010-06-24 16:07:28 -06:00
|
|
|
state := newDecodeStateFromData(complexResult)
|
|
|
|
execDec("complex", instr, state, t, unsafe.Pointer(&data))
|
|
|
|
if data.a != 17+19i {
|
|
|
|
t.Errorf("complex a = %v not 17+19i", data.a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// complex128
|
|
|
|
{
|
|
|
|
var data struct {
|
|
|
|
a complex128
|
|
|
|
}
|
2011-02-25 10:45:06 -07:00
|
|
|
instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl}
|
2010-06-24 16:07:28 -06:00
|
|
|
state := newDecodeStateFromData(complexResult)
|
|
|
|
execDec("complex", instr, state, t, unsafe.Pointer(&data))
|
|
|
|
if data.a != 17+19i {
|
|
|
|
t.Errorf("complex a = %v not 17+19i", data.a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-02 12:21:01 -06:00
|
|
|
// bytes == []uint8
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a []byte
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decUint8Array, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(bytesResult)
|
|
|
|
execDec("bytes", instr, state, t, unsafe.Pointer(&data))
|
2009-07-02 12:21:01 -06:00
|
|
|
if string(data.a) != "hello" {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf(`bytes a = %q not "hello"`, string(data.a))
|
2009-07-02 12:21:01 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// string
|
|
|
|
{
|
2009-11-05 15:53:42 -07:00
|
|
|
var data struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
a string
|
2009-11-05 15:53:42 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
instr := &decInstr{decString, 6, 0, 0, ovfl}
|
|
|
|
state := newDecodeStateFromData(bytesResult)
|
|
|
|
execDec("bytes", instr, state, t, unsafe.Pointer(&data))
|
2009-07-02 12:21:01 -06:00
|
|
|
if data.a != "hello" {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf(`bytes a = %q not "hello"`, data.a)
|
2009-07-02 12:21:01 -06:00
|
|
|
}
|
|
|
|
}
|
2009-06-30 18:59:41 -06:00
|
|
|
}
|
2009-07-01 19:25:13 -06:00
|
|
|
|
2009-07-02 19:02:42 -06:00
|
|
|
func TestEndToEnd(t *testing.T) {
|
2009-07-02 14:43:47 -06:00
|
|
|
type T2 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
T string
|
2009-07-02 14:43:47 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
s1 := "string1"
|
|
|
|
s2 := "string2"
|
2009-07-02 09:21:42 -06:00
|
|
|
type T1 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A, B, C int
|
2011-01-19 21:09:00 -07:00
|
|
|
M map[string]*float64
|
|
|
|
N *[3]float64
|
2011-01-11 14:44:00 -07:00
|
|
|
Strs *[2]string
|
|
|
|
Int64s *[]int64
|
|
|
|
RI complex64
|
|
|
|
S string
|
|
|
|
Y []byte
|
|
|
|
T *T2
|
2009-07-02 12:21:01 -06:00
|
|
|
}
|
2010-05-05 17:46:39 -06:00
|
|
|
pi := 3.14159
|
|
|
|
e := 2.71828
|
2009-07-02 12:21:01 -06:00
|
|
|
t1 := &T1{
|
2011-01-11 14:44:00 -07:00
|
|
|
A: 17,
|
|
|
|
B: 18,
|
|
|
|
C: -5,
|
2011-01-19 21:09:00 -07:00
|
|
|
M: map[string]*float64{"pi": &pi, "e": &e},
|
|
|
|
N: &[3]float64{1.5, 2.5, 3.5},
|
2011-01-11 14:44:00 -07:00
|
|
|
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 16:35:38 -07:00
|
|
|
}
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
err := NewEncoder(b).Encode(t1)
|
2009-11-17 00:32:30 -07:00
|
|
|
if err != nil {
|
|
|
|
t.Error("encode:", err)
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var _t1 T1
|
|
|
|
err = NewDecoder(b).Decode(&_t1)
|
2009-11-17 00:32:30 -07:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal("decode:", err)
|
|
|
|
}
|
2009-07-01 19:25:13 -06:00
|
|
|
if !reflect.DeepEqual(t1, &_t1) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("encode expected %v got %v", *t1, _t1)
|
2009-07-01 19:25:13 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-02 09:21:42 -06:00
|
|
|
|
2009-07-28 13:59:39 -06:00
|
|
|
func TestOverflow(t *testing.T) {
|
|
|
|
type inputT struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi int64
|
|
|
|
Mini int64
|
|
|
|
Maxu uint64
|
|
|
|
Maxf float64
|
|
|
|
Minf float64
|
|
|
|
Maxc complex128
|
|
|
|
Minc complex128
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
|
|
|
var it inputT
|
|
|
|
var err os.Error
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
enc := NewEncoder(b)
|
|
|
|
dec := NewDecoder(b)
|
2009-07-28 13:59:39 -06:00
|
|
|
|
|
|
|
// int8
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi: math.MaxInt8 + 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outi8 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi int8
|
|
|
|
Mini int8
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o1 outi8
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o1)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxi" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for int8:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Mini: math.MinInt8 - 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
|
|
|
b.Reset()
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o1)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Mini" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong underflow error for int8:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// int16
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi: math.MaxInt16 + 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outi16 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi int16
|
|
|
|
Mini int16
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o2 outi16
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o2)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxi" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for int16:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Mini: math.MinInt16 - 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
|
|
|
b.Reset()
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o2)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Mini" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong underflow error for int16:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// int32
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi: math.MaxInt32 + 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outi32 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxi int32
|
|
|
|
Mini int32
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o3 outi32
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o3)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxi" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for int32:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Mini: math.MinInt32 - 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
|
|
|
b.Reset()
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o3)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Mini" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong underflow error for int32:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// uint8
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxu: math.MaxUint8 + 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outu8 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxu uint8
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o4 outu8
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o4)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxu" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for uint8:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// uint16
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxu: math.MaxUint16 + 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outu16 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxu uint16
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o5 outu16
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o5)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxu" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for uint16:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// uint32
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxu: math.MaxUint32 + 1,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outu32 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxu uint32
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o6 outu32
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o6)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxu" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for uint32:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// float32
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
2009-11-05 15:53:42 -07:00
|
|
|
it = inputT{
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxf: math.MaxFloat32 * 2,
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
type outf32 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxf float32
|
|
|
|
Minf float32
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
var o7 outf32
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o7)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxf" out of range` {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("wrong overflow error for float32:", err)
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
2010-06-24 16:07:28 -06:00
|
|
|
|
|
|
|
// complex64
|
|
|
|
b.Reset()
|
|
|
|
it = inputT{
|
2011-01-19 21:09:00 -07:00
|
|
|
Maxc: complex(math.MaxFloat32*2, math.MaxFloat32*2),
|
2010-06-24 16:07:28 -06:00
|
|
|
}
|
|
|
|
type outc64 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Maxc complex64
|
|
|
|
Minc complex64
|
2010-06-24 16:07:28 -06:00
|
|
|
}
|
|
|
|
var o8 outc64
|
|
|
|
enc.Encode(it)
|
|
|
|
err = dec.Decode(&o8)
|
2011-01-11 14:44:00 -07:00
|
|
|
if err == nil || err.String() != `value for "Maxc" out of range` {
|
2010-06-24 16:07:28 -06:00
|
|
|
t.Error("wrong overflow error for complex64:", err)
|
|
|
|
}
|
2009-07-28 13:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-09 15:33:43 -06:00
|
|
|
func TestNesting(t *testing.T) {
|
|
|
|
type RT struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A string
|
|
|
|
Next *RT
|
2009-12-15 16:35:38 -07:00
|
|
|
}
|
|
|
|
rt := new(RT)
|
2011-01-11 14:44:00 -07:00
|
|
|
rt.A = "level1"
|
|
|
|
rt.Next = new(RT)
|
|
|
|
rt.Next.A = "level2"
|
2009-12-15 16:35:38 -07:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
NewEncoder(b).Encode(rt)
|
|
|
|
var drt RT
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
err := dec.Decode(&drt)
|
2009-11-17 00:32:30 -07:00
|
|
|
if err != nil {
|
2011-01-11 14:44:00 -07:00
|
|
|
t.Fatal("decoder error:", err)
|
2009-11-17 00:32:30 -07:00
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if drt.A != rt.A {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("nesting: encode expected %v got %v", *rt, drt)
|
2009-07-09 15:33:43 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if drt.Next == nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("nesting: recursion failed")
|
2009-07-09 15:33:43 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if drt.Next.A != rt.Next.A {
|
|
|
|
t.Errorf("nesting: encode expected %v got %v", *rt.Next, *drt.Next)
|
2009-07-09 15:33:43 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-02 09:21:42 -06:00
|
|
|
// These three structures have the same data with different indirections
|
|
|
|
type T0 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A int
|
|
|
|
B int
|
|
|
|
C int
|
|
|
|
D int
|
2009-07-02 09:21:42 -06:00
|
|
|
}
|
|
|
|
type T1 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A int
|
|
|
|
B *int
|
|
|
|
C **int
|
|
|
|
D ***int
|
2009-07-02 09:21:42 -06:00
|
|
|
}
|
|
|
|
type T2 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A ***int
|
|
|
|
B **int
|
|
|
|
C *int
|
|
|
|
D int
|
2009-07-02 09:21:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAutoIndirection(t *testing.T) {
|
2009-07-02 10:22:38 -06:00
|
|
|
// First transfer t1 into t0
|
2009-12-15 16:35:38 -07:00
|
|
|
var t1 T1
|
2011-01-11 14:44:00 -07: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 16:35:38 -07:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
enc := NewEncoder(b)
|
|
|
|
enc.Encode(t1)
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
var t0 T0
|
|
|
|
dec.Decode(&t0)
|
2011-01-11 14:44:00 -07:00
|
|
|
if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("t1->t0: expected {17 177 1777 17777}; got %v", t0)
|
2009-07-02 09:21:42 -06:00
|
|
|
}
|
|
|
|
|
2009-07-02 10:22:38 -06:00
|
|
|
// Now transfer t2 into t0
|
2009-12-15 16:35:38 -07:00
|
|
|
var t2 T2
|
2011-01-11 14:44:00 -07: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 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
enc.Encode(t2)
|
|
|
|
t0 = T0{}
|
|
|
|
dec.Decode(&t0)
|
2011-01-11 14:44:00 -07:00
|
|
|
if t0.A != 17 || t0.B != 177 || t0.C != 1777 || t0.D != 17777 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("t2->t0 expected {17 177 1777 17777}; got %v", t0)
|
2009-07-02 09:21:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now transfer t0 into t1
|
2009-12-15 16:35:38 -07:00
|
|
|
t0 = T0{17, 177, 1777, 17777}
|
|
|
|
b.Reset()
|
|
|
|
enc.Encode(t0)
|
|
|
|
t1 = T1{}
|
|
|
|
dec.Decode(&t1)
|
2011-01-11 14:44:00 -07: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 09:21:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now transfer t0 into t2
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
enc.Encode(t0)
|
|
|
|
t2 = T2{}
|
|
|
|
dec.Decode(&t2)
|
2011-01-11 14:44:00 -07: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 09:21:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now do t2 again but without pre-allocated pointers.
|
2009-12-15 16:35:38 -07:00
|
|
|
b.Reset()
|
|
|
|
enc.Encode(t0)
|
2011-01-11 14:44:00 -07:00
|
|
|
***t2.A = 0
|
|
|
|
**t2.B = 0
|
|
|
|
*t2.C = 0
|
|
|
|
t2.D = 0
|
2009-12-15 16:35:38 -07:00
|
|
|
dec.Decode(&t2)
|
2011-01-11 14:44:00 -07: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 09:21:42 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-16 18:55:16 -06:00
|
|
|
|
|
|
|
type RT0 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A int
|
|
|
|
B string
|
2011-01-19 21:09:00 -07:00
|
|
|
C float64
|
2009-07-16 18:55:16 -06:00
|
|
|
}
|
|
|
|
type RT1 struct {
|
2011-01-19 21:09:00 -07:00
|
|
|
C float64
|
2011-01-11 14:44:00 -07:00
|
|
|
B string
|
|
|
|
A int
|
|
|
|
NotSet string
|
2009-07-16 18:55:16 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestReorderedFields(t *testing.T) {
|
2009-12-15 16:35:38 -07:00
|
|
|
var rt0 RT0
|
2011-01-11 14:44:00 -07:00
|
|
|
rt0.A = 17
|
|
|
|
rt0.B = "hello"
|
|
|
|
rt0.C = 3.14159
|
2009-12-15 16:35:38 -07:00
|
|
|
b := new(bytes.Buffer)
|
|
|
|
NewEncoder(b).Encode(rt0)
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
var rt1 RT1
|
2009-07-16 18:55:16 -06:00
|
|
|
// Wire type is RT0, local type is RT1.
|
2009-12-15 16:35:38 -07:00
|
|
|
err := dec.Decode(&rt1)
|
2009-11-17 00:32:30 -07:00
|
|
|
if err != nil {
|
2011-01-11 14:44:00 -07:00
|
|
|
t.Fatal("decode error:", err)
|
2009-11-17 00:32:30 -07:00
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if rt0.A != rt1.A || rt0.B != rt1.B || rt0.C != rt1.C {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("rt1->rt0: expected %v; got %v", rt0, rt1)
|
2009-07-16 18:55:16 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Like an RT0 but with fields we'll ignore on the decode side.
|
|
|
|
type IT0 struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A int64
|
|
|
|
B string
|
|
|
|
Ignore_d []int
|
2011-01-19 21:09:00 -07:00
|
|
|
Ignore_e [3]float64
|
2011-01-11 14:44:00 -07:00
|
|
|
Ignore_f bool
|
|
|
|
Ignore_g string
|
|
|
|
Ignore_h []byte
|
|
|
|
Ignore_i *RT1
|
|
|
|
Ignore_m map[string]int
|
2011-01-19 21:09:00 -07:00
|
|
|
C float64
|
2009-07-16 18:55:16 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestIgnoredFields(t *testing.T) {
|
2009-12-15 16:35:38 -07:00
|
|
|
var it0 IT0
|
2011-01-11 14:44:00 -07: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 16:35:38 -07:00
|
|
|
|
|
|
|
b := new(bytes.Buffer)
|
|
|
|
NewEncoder(b).Encode(it0)
|
|
|
|
dec := NewDecoder(b)
|
|
|
|
var rt1 RT1
|
2009-07-16 18:55:16 -06:00
|
|
|
// Wire type is IT0, local type is RT1.
|
2009-12-15 16:35:38 -07:00
|
|
|
err := dec.Decode(&rt1)
|
2009-07-17 12:38:31 -06:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("error: ", err)
|
2009-07-17 12:38:31 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07: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 18:55:16 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-29 18:24:25 -06:00
|
|
|
|
2011-02-23 10:49:35 -07: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")
|
|
|
|
} else if strings.Index(err.String(), "recursive") < 0 {
|
|
|
|
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.
|
|
|
|
}
|
|
|
|
|
2009-07-29 18:24:25 -06:00
|
|
|
type Bad0 struct {
|
2011-02-23 10:49:35 -07:00
|
|
|
CH chan int
|
|
|
|
C float64
|
2009-07-29 18:24:25 -06:00
|
|
|
}
|
|
|
|
|
2010-10-22 12:17:40 -06:00
|
|
|
|
2009-07-29 18:24:25 -06:00
|
|
|
func TestInvalidField(t *testing.T) {
|
2009-12-15 16:35:38 -07:00
|
|
|
var bad0 Bad0
|
2011-02-23 10:49:35 -07:00
|
|
|
bad0.CH = make(chan int)
|
2009-12-15 16:35:38 -07:00
|
|
|
b := new(bytes.Buffer)
|
2011-02-23 10:49:35 -07:00
|
|
|
var nilEncoder *Encoder
|
2011-02-22 13:31:57 -07:00
|
|
|
err := nilEncoder.encode(b, reflect.NewValue(&bad0), userType(reflect.Typeof(&bad0)))
|
2009-07-29 18:24:25 -06:00
|
|
|
if err == nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("expected error; got none")
|
2010-10-22 12:17:40 -06:00
|
|
|
} else if strings.Index(err.String(), "type") < 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("expected type error; got", err)
|
2009-07-29 18:24:25 -06:00
|
|
|
}
|
|
|
|
}
|
2010-05-06 11:45:18 -06:00
|
|
|
|
|
|
|
type Indirect struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A ***[3]int
|
|
|
|
S ***[]int
|
|
|
|
M ****map[string]int
|
2010-05-06 11:45:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type Direct struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
A [3]int
|
|
|
|
S []int
|
|
|
|
M map[string]int
|
2010-05-06 11:45:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestIndirectSliceMapArray(t *testing.T) {
|
|
|
|
// Marshal indirect, unmarshal to direct.
|
|
|
|
i := new(Indirect)
|
2011-01-11 14:44:00 -07: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 11:45:18 -06: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 14:44:00 -07: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 11:45:18 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07: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 11:45:18 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07: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 11:45:18 -06:00
|
|
|
}
|
|
|
|
// Marshal direct, unmarshal to indirect.
|
2011-01-11 14:44:00 -07: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 11:45:18 -06:00
|
|
|
i = new(Indirect)
|
|
|
|
b.Reset()
|
|
|
|
NewEncoder(b).Encode(d)
|
|
|
|
dec = NewDecoder(b)
|
|
|
|
err = dec.Decode(&i)
|
|
|
|
if err != nil {
|
2011-01-11 14:44:00 -07:00
|
|
|
t.Fatal("error: ", err)
|
2010-05-06 11:45:18 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07: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 11:45:18 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07: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 11:45:18 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07: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 11:45:18 -06:00
|
|
|
}
|
|
|
|
}
|
2010-10-22 12:17:40 -06: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 21:09:00 -07:00
|
|
|
type Float float64
|
2010-10-22 12:17:40 -06: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 14:41:30 -06:00
|
|
|
type Point struct {
|
2011-01-22 01:10:11 -07:00
|
|
|
X, Y int
|
2010-10-31 14:41:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p Point) Square() int {
|
2011-01-22 01:10:11 -07:00
|
|
|
return p.X*p.X + p.Y*p.Y
|
2010-10-31 14:41:30 -06:00
|
|
|
}
|
|
|
|
|
2010-10-22 12:17:40 -06:00
|
|
|
// A struct with interfaces in it.
|
|
|
|
type InterfaceItem struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
I int
|
|
|
|
Sq1, Sq2, Sq3 Squarer
|
2011-01-19 21:09:00 -07:00
|
|
|
F float64
|
2011-01-11 14:44:00 -07:00
|
|
|
Sq []Squarer
|
2010-10-22 12:17:40 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// The same struct without interfaces
|
|
|
|
type NoInterfaceItem struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
I int
|
2011-01-19 21:09:00 -07:00
|
|
|
F float64
|
2010-10-22 12:17:40 -06: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 14:44:00 -07:00
|
|
|
if item2.I != item1.I {
|
2010-10-22 12:17:40 -06:00
|
|
|
t.Error("normal int did not decode correctly")
|
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if item2.Sq1 == nil || item2.Sq1.Square() != iVal.Square() {
|
2010-10-22 12:17:40 -06:00
|
|
|
t.Error("Int did not decode correctly")
|
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if item2.Sq2 == nil || item2.Sq2.Square() != fVal.Square() {
|
2010-10-22 12:17:40 -06:00
|
|
|
t.Error("Float did not decode correctly")
|
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if item2.Sq3 == nil || item2.Sq3.Square() != vVal.Square() {
|
2010-10-22 12:17:40 -06:00
|
|
|
t.Error("Vector did not decode correctly")
|
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if item2.F != item1.F {
|
2010-10-22 12:17:40 -06: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 14:44:00 -07: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 12:17:40 -06:00
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
for i, v1 := range item1.Sq {
|
|
|
|
v2 := item2.Sq[i]
|
2010-10-22 12:17:40 -06:00
|
|
|
if v1 == nil || v2 == nil {
|
|
|
|
if v1 != nil || v2 != nil {
|
|
|
|
t.Errorf("item %d inconsistent nils", i)
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
if v1.Square() != v2.Square() {
|
2010-12-07 14:42:54 -07:00
|
|
|
t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
|
2010-10-22 12:17:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-26 18:07:39 -06: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 21:09:00 -07:00
|
|
|
Float32, Float64 interface{}
|
|
|
|
Complex64, Complex128 interface{}
|
2010-10-26 18:07:39 -06: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 21:09:00 -07:00
|
|
|
float32(1), 1.0,
|
2011-01-28 11:53:42 -07:00
|
|
|
complex64(1i), complex128(1i),
|
2010-10-26 18:07:39 -06: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 11:36:27 -06:00
|
|
|
type String string
|
|
|
|
|
|
|
|
type PtrInterfaceItem struct {
|
2011-01-11 14:44:00 -07:00
|
|
|
Str1 interface{} // basic
|
|
|
|
Str2 interface{} // derived
|
2010-11-05 11:36:27 -06: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 14:44:00 -07:00
|
|
|
if v, ok := item2.Str1.(string); !ok || v != str1 {
|
2010-11-05 11:36:27 -06:00
|
|
|
t.Errorf("basic string failed: %q should be %q", v, str1)
|
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if v, ok := item2.Str2.(String); !ok || v != str2 {
|
2010-11-05 11:36:27 -06:00
|
|
|
t.Errorf("derived type String failed: %q should be %q", v, str2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-22 12:17:40 -06:00
|
|
|
func TestIgnoreInterface(t *testing.T) {
|
|
|
|
iVal := Int(3)
|
|
|
|
fVal := Float(5)
|
2010-10-31 14:41:30 -06:00
|
|
|
// Sending a Point will require that the receiver define a type in the middle of
|
2010-10-22 12:17:40 -06:00
|
|
|
// receiving the value for item2.
|
2010-10-31 14:41:30 -06:00
|
|
|
pVal := Point{2, 3}
|
2010-10-22 12:17:40 -06:00
|
|
|
b := new(bytes.Buffer)
|
2010-10-31 14:41:30 -06:00
|
|
|
item1 := &InterfaceItem{1, iVal, fVal, pVal, 11.5, nil}
|
2010-10-22 12:17:40 -06:00
|
|
|
// Register the types.
|
|
|
|
Register(Int(0))
|
|
|
|
Register(Float(0))
|
2010-10-31 14:41:30 -06:00
|
|
|
Register(Point{})
|
2010-10-22 12:17:40 -06: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 14:44:00 -07:00
|
|
|
if item2.I != item1.I {
|
2010-10-22 12:17:40 -06:00
|
|
|
t.Error("normal int did not decode correctly")
|
|
|
|
}
|
2011-01-11 14:44:00 -07:00
|
|
|
if item2.F != item2.F {
|
2010-10-22 12:17:40 -06:00
|
|
|
t.Error("normal float did not decode correctly")
|
|
|
|
}
|
|
|
|
}
|
2010-10-29 16:07:56 -06:00
|
|
|
|
2011-01-11 14:44:00 -07:00
|
|
|
type U struct {
|
|
|
|
A int
|
|
|
|
B string
|
2011-01-19 21:09:00 -07:00
|
|
|
c float64
|
2011-01-11 14:44:00 -07: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 12:28:53 -07: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 16:07:56 -06: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 14:44:00 -07:00
|
|
|
A int
|
2010-10-29 16:07:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type DT struct {
|
|
|
|
// X OnTheFly
|
2011-01-11 14:44:00 -07:00
|
|
|
A int
|
|
|
|
B string
|
2011-01-19 21:09:00 -07:00
|
|
|
C float64
|
2011-01-11 14:44:00 -07:00
|
|
|
I interface{}
|
|
|
|
J interface{}
|
|
|
|
I_nil interface{}
|
|
|
|
M map[string]int
|
|
|
|
T [3]int
|
|
|
|
S []string
|
2010-10-29 16:07:56 -06:00
|
|
|
}
|
|
|
|
|
2011-01-21 12:28:53 -07:00
|
|
|
func TestDebugStruct(t *testing.T) {
|
2010-10-29 16:07:56 -06:00
|
|
|
if debugFunc == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
Register(OnTheFly{})
|
|
|
|
var dt DT
|
2011-01-11 14:44:00 -07: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"}
|
2010-10-29 16:07:56 -06: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)
|
|
|
|
}
|