185 lines
4.1 KiB
Go
185 lines
4.1 KiB
Go
|
package logfmt
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
type kv struct {
|
||
|
k, v []byte
|
||
|
}
|
||
|
|
||
|
func (s kv) String() string {
|
||
|
return fmt.Sprintf("{k:%q v:%q}", s.k, s.v)
|
||
|
}
|
||
|
|
||
|
func TestDecoder_scan(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
data string
|
||
|
want [][]kv
|
||
|
}{
|
||
|
{"", nil},
|
||
|
{"\n\n", [][]kv{nil, nil}},
|
||
|
{`x= `, [][]kv{{{[]byte("x"), nil}}}},
|
||
|
{`y=`, [][]kv{{{[]byte("y"), nil}}}},
|
||
|
{`y`, [][]kv{{{[]byte("y"), nil}}}},
|
||
|
{`y=f`, [][]kv{{{[]byte("y"), []byte("f")}}}},
|
||
|
{"y=\"\\tf\"", [][]kv{{{[]byte("y"), []byte("\tf")}}}},
|
||
|
{"a=1\n", [][]kv{{{[]byte("a"), []byte("1")}}}},
|
||
|
{
|
||
|
`a=1 b="bar" ƒ=2h3s r="esc\t" d x=sf `,
|
||
|
[][]kv{{
|
||
|
{[]byte("a"), []byte("1")},
|
||
|
{[]byte("b"), []byte("bar")},
|
||
|
{[]byte("ƒ"), []byte("2h3s")},
|
||
|
{[]byte("r"), []byte("esc\t")},
|
||
|
{[]byte("d"), nil},
|
||
|
{[]byte("x"), []byte("sf")},
|
||
|
}},
|
||
|
},
|
||
|
{
|
||
|
"y=f\ny=g",
|
||
|
[][]kv{
|
||
|
{{[]byte("y"), []byte("f")}},
|
||
|
{{[]byte("y"), []byte("g")}},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"y=f \n\x1e y=g",
|
||
|
[][]kv{
|
||
|
{{[]byte("y"), []byte("f")}},
|
||
|
{{[]byte("y"), []byte("g")}},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"y= d y=g",
|
||
|
[][]kv{{
|
||
|
{[]byte("y"), nil},
|
||
|
{[]byte("d"), nil},
|
||
|
{[]byte("y"), []byte("g")},
|
||
|
}},
|
||
|
},
|
||
|
{
|
||
|
"y=\"f\"\ny=g",
|
||
|
[][]kv{
|
||
|
{{[]byte("y"), []byte("f")}},
|
||
|
{{[]byte("y"), []byte("g")}},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
"y=\"f\\n\"y=g",
|
||
|
[][]kv{{
|
||
|
{[]byte("y"), []byte("f\n")},
|
||
|
{[]byte("y"), []byte("g")},
|
||
|
}},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
var got [][]kv
|
||
|
dec := NewDecoder(strings.NewReader(test.data))
|
||
|
|
||
|
for dec.ScanRecord() {
|
||
|
var kvs []kv
|
||
|
for dec.ScanKeyval() {
|
||
|
k := dec.Key()
|
||
|
v := dec.Value()
|
||
|
if k != nil {
|
||
|
kvs = append(kvs, kv{k, v})
|
||
|
}
|
||
|
}
|
||
|
got = append(got, kvs)
|
||
|
}
|
||
|
if err := dec.Err(); err != nil {
|
||
|
t.Errorf("got err: %v", err)
|
||
|
}
|
||
|
if !reflect.DeepEqual(got, test.want) {
|
||
|
t.Errorf("\n in: %q\n got: %+v\nwant: %+v", test.data, got, test.want)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDecoder_errors(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
data string
|
||
|
want error
|
||
|
}{
|
||
|
{"a=1\n=bar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 1}},
|
||
|
{"a=1\n\"k\"=bar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 1}},
|
||
|
{"a=1\nk\"ey=bar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 2}},
|
||
|
{"a=1\nk=b\"ar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 4}},
|
||
|
{"a=1\nk=b =ar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 5}},
|
||
|
{"a==", &SyntaxError{Msg: "unexpected '='", Line: 1, Pos: 3}},
|
||
|
{"a=1\nk=b=ar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 4}},
|
||
|
{"a=\"1", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 5}},
|
||
|
{"a=\"1\\", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 6}},
|
||
|
{"a=\"\\t1", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 7}},
|
||
|
{"a=\"\\u1\"", &SyntaxError{Msg: "invalid quoted value", Line: 1, Pos: 8}},
|
||
|
{"a\ufffd=bar", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 5}},
|
||
|
{"\x80=bar", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 2}},
|
||
|
{"\x80", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 2}},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
dec := NewDecoder(strings.NewReader(test.data))
|
||
|
|
||
|
for dec.ScanRecord() {
|
||
|
for dec.ScanKeyval() {
|
||
|
}
|
||
|
}
|
||
|
if got, want := dec.Err(), test.want; !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("got: %v, want: %v", got, want)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDecoder_decode_encode(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
in, out string
|
||
|
}{
|
||
|
{"", ""},
|
||
|
{"\n", "\n"},
|
||
|
{"\n \n", "\n\n"},
|
||
|
{
|
||
|
"a=1\nb=2\n",
|
||
|
"a=1\nb=2\n",
|
||
|
},
|
||
|
{
|
||
|
"a=1 b=\"bar\" ƒ=2h3s r=\"esc\\t\" d x=sf ",
|
||
|
"a=1 b=bar ƒ=2h3s r=\"esc\\t\" d= x=sf\n",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
dec := NewDecoder(strings.NewReader(test.in))
|
||
|
buf := bytes.Buffer{}
|
||
|
enc := NewEncoder(&buf)
|
||
|
|
||
|
var err error
|
||
|
loop:
|
||
|
for dec.ScanRecord() && err == nil {
|
||
|
for dec.ScanKeyval() {
|
||
|
if dec.Key() == nil {
|
||
|
continue
|
||
|
}
|
||
|
if err = enc.EncodeKeyval(dec.Key(), dec.Value()); err != nil {
|
||
|
break loop
|
||
|
}
|
||
|
}
|
||
|
enc.EndRecord()
|
||
|
}
|
||
|
if err == nil {
|
||
|
err = dec.Err()
|
||
|
}
|
||
|
if err != nil {
|
||
|
t.Errorf("got err: %v", err)
|
||
|
}
|
||
|
if got, want := buf.String(), test.out; got != want {
|
||
|
t.Errorf("\n got: %q\nwant: %q", got, want)
|
||
|
}
|
||
|
}
|
||
|
}
|