Commit 89d4f00e authored by Kirill Smelkov's avatar Kirill Smelkov Committed by Kamil Kisiel

tests: Split TestDecode into main driver + worker that tests 1 particular pickle

We are going to modify the main tests table and for every case (e.g.
int(1) add pickles with various encoding that all represent the same
object when decoded. The main TestDecode driver will iterate over all
those input data and hand it over for particular testing to testDecode
worker.

Use t.Run for spawning each case - it is less typing (we do not need to
manually print test.name on errors, etc), and it allows to select which
subtests to run via e.g. `go test -run Decode/int`
parent 81e5b5e7
......@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"io"
"math/big"
"reflect"
......@@ -91,32 +92,44 @@ var tests = []struct {
{"STACK_GLOBAL opcode", "S'foo'\nS'bar'\n\x93.", Class{Module: "foo", Name: "bar"}},
}
// TestDecode verifies ogórek decoder.
func TestDecode(t *testing.T) {
for _, test := range tests {
t.Run(fmt.Sprintf("%s/%q", test.name, test.input), func(t *testing.T) {
testDecode(t, test.expected, test.input)
})
}
}
// testDecode decodes input and verifies it is == object.
//
// It also verifies decoder robustness - via feeding it various kinds of
// corrupt data derived from input.
func testDecode(t *testing.T, object interface{}, input string) {
// decode(input) -> expected
buf := bytes.NewBufferString(test.input)
buf := bytes.NewBufferString(input)
dec := NewDecoder(buf)
v, err := dec.Decode()
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(v, test.expected) {
t.Errorf("%s: decode:\nhave: %#v\nwant: %#v", test.name, v, test.expected)
if !reflect.DeepEqual(v, object) {
t.Errorf("decode:\nhave: %#v\nwant: %#v", v, object)
}
// decode more -> EOF
v, err = dec.Decode()
if !(v == nil && err == io.EOF) {
t.Errorf("%s: decode: no EOF at end: v = %#v err = %#v", test.name, v, err)
t.Errorf("decode: no EOF at end: v = %#v err = %#v", v, err)
}
// expected (= decoded(input)) -> encode -> decode = identity
buf.Reset()
enc := NewEncoder(buf)
err = enc.Encode(test.expected)
err = enc.Encode(object)
if err != nil {
t.Errorf("%s: encode(expected): %v", test.name, err)
t.Errorf("encode(expected): %v", err)
} else {
dec := NewDecoder(buf)
v, err := dec.Decode()
......@@ -124,37 +137,35 @@ func TestDecode(t *testing.T) {
t.Error(err)
}
if !reflect.DeepEqual(v, test.expected) {
t.Errorf("%s: expected -> decode -> encode != identity\nhave: %#v\nwant: %#v", test.name, v, test.expected)
if !reflect.DeepEqual(v, object) {
t.Errorf("expected -> decode -> encode != identity\nhave: %#v\nwant: %#v", v, object)
}
}
// for truncated input io.ErrUnexpectedEOF must be returned
for l := len(test.input) - 1; l > 0; l-- {
buf := bytes.NewBufferString(test.input[:l])
// decode(truncated input) -> must return io.ErrUnexpectedEOF
for l := len(input) - 1; l > 0; l-- {
buf := bytes.NewBufferString(input[:l])
dec := NewDecoder(buf)
//println(test.name, l)
v, err := dec.Decode()
if !(v == nil && err == io.ErrUnexpectedEOF) {
t.Errorf("%s: no ErrUnexpectedEOF on [:%d] truncated stream: v = %#v err = %#v", test.name, l, v, err)
t.Errorf("no ErrUnexpectedEOF on [:%d] truncated stream: v = %#v err = %#v", l, v, err)
}
}
// by using input with omitted prefix we can test how code handles pickle stack overflow:
// it must not panic
for i := 0; i < len(test.input); i++ {
buf := bytes.NewBufferString(test.input[i:])
// decode(input with omitted prefix) - tests how code handles pickle stack overflow:
// it must not panic.
for i := 0; i < len(input); i++ {
buf := bytes.NewBufferString(input[i:])
dec := NewDecoder(buf)
func() {
defer func() {
if r := recover(); r != nil {
t.Errorf("%s: panic on input[%d:]: %v", test.name, i, r)
t.Errorf("panic on input[%d:]: %v", i, r)
}
}()
dec.Decode()
}()
}
}
}
// test that .Decode() decodes only until stop opcode, and can continue
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment