istanbul-tools/vendor/github.com/naoina/toml/encode_test.go

261 lines
5.5 KiB
Go

package toml
import (
"bytes"
"reflect"
"testing"
"time"
"github.com/kylelemons/godebug/diff"
"github.com/kylelemons/godebug/pretty"
)
func init() {
// These settings make 'mismatch' output look nicer.
pretty.DefaultConfig.ShortList = 80
pretty.CompareConfig.ShortList = 80
}
type testMarshaler struct{ S string }
type testMarshalerPtr struct{ S string }
func (t testMarshaler) MarshalTOML() ([]byte, error) {
return []byte(t.S), nil
}
func (t *testMarshalerPtr) MarshalTOML() ([]byte, error) {
return []byte(t.S), nil
}
type testMarshalerRec struct{ replacement interface{} }
type testMarshalerRecPtr struct{ replacement interface{} }
func (t testMarshalerRec) MarshalTOML() (interface{}, error) {
return t.replacement, nil
}
func (t *testMarshalerRecPtr) MarshalTOML() (interface{}, error) {
return t.replacement, nil
}
var marshalTests = []struct {
v interface{}
expect []byte
}{
// single string:
{
v: struct{ Name string }{"alice"},
expect: []byte("name = \"alice\"\n"),
},
// single int:
{
v: struct{ Age int }{7},
expect: []byte("age = 7\n"),
},
// multiple fields:
{
v: struct {
Name string
Age int
}{"alice", 7},
expect: []byte("name = \"alice\"\nage = 7\n"),
},
// ignored fields:
{
v: struct {
Name string `toml:"-"`
Age int
}{"alice", 7},
expect: []byte("age = 7\n"),
},
// field name override:
{
v: struct {
Name string `toml:"my_name"`
}{"bob"},
expect: []byte("my_name = \"bob\"\n"),
},
{
v: struct {
Name string `toml:"my_name,omitempty"`
}{"bob"},
expect: []byte("my_name = \"bob\"\n"),
},
// omitempty:
{
v: struct {
Name string `toml:",omitempty"`
}{"bob"},
expect: []byte("name = \"bob\"\n"),
},
// slices:
{
v: struct {
Ints []int
}{[]int{1, 2, 3}},
expect: []byte("ints = [1, 2, 3]\n"),
},
{
v: struct {
IntsOfInts [][]int
}{[][]int{{}, {1}, {}, {2}, {3, 4}}},
expect: []byte("ints_of_ints = [[], [1], [], [2], [3, 4]]\n"),
},
{
v: struct {
IntsOfInts [][]int
}{[][]int{{1, 2}, {3, 4}}},
expect: []byte("ints_of_ints = [[1, 2], [3, 4]]\n"),
},
// pointer:
{
v: struct{ Named *Name }{&Name{First: "name"}},
expect: []byte("[named]\nfirst = \"name\"\nlast = \"\"\n"),
},
// canon test document:
{
v: theTestStruct(),
expect: loadTestData("marshal-teststruct.toml"),
},
// funky map key types:
{
v: map[string]interface{}{
"intKeys": map[int]int{1: 1, 2: 2, 3: 3},
"marshalerKeys": map[time.Time]int{time.Time{}: 1},
},
expect: loadTestData("marshal-funkymapkeys.toml"),
},
// Marshaler:
{
v: map[string]interface{}{
"m1": testMarshaler{"1"},
"m2": &testMarshaler{"2"},
"m3": &testMarshalerPtr{"3"},
},
expect: loadTestData("marshal-marshaler.toml"),
},
// MarshalerRec:
{
v: map[string]interface{}{
"m1": testMarshalerRec{1},
"m2": &testMarshalerRec{2},
"m3": &testMarshalerRecPtr{3},
"sub": &testMarshalerRec{map[string]interface{}{
"key": 1,
}},
},
expect: loadTestData("marshal-marshalerrec.toml"),
},
// key escaping:
{
v: map[string]interface{}{
"": "empty",
" ": "space",
"ʎǝʞ": "reverse",
"1": "number (not quoted)",
"-": "dash (not quoted)",
"subtable with space": map[string]interface{}{
"depth": 1,
"subsubtable with space": map[string]interface{}{
"depth": 2,
},
},
},
expect: loadTestData("marshal-key-escape.toml"),
},
}
func TestMarshal(t *testing.T) {
for _, test := range marshalTests {
b, err := Marshal(test.v)
if err != nil {
t.Errorf("Unexpected error %v\nfor value:\n%s", err, pretty.Sprint(test.v))
}
if d := checkOutput(b, test.expect); d != "" {
t.Errorf("Output mismatch:\nValue:\n%s\nDiff:\n%s", pretty.Sprint(test.v), d)
}
}
}
func TestMarshalRoundTrip(t *testing.T) {
v := theTestStruct()
b, err := Marshal(v)
if err != nil {
t.Error("Unexpected Marshal error:", err)
}
dest := testStruct{}
if err := Unmarshal(b, &dest); err != nil {
t.Error("Unmarshal error:", err)
}
if !reflect.DeepEqual(theTestStruct(), &dest) {
t.Errorf("Unmarshaled value mismatch:\n%s", pretty.Compare(v, dest))
}
}
func TestMarshalArrayTableEmptyParent(t *testing.T) {
type Baz struct {
Key int
}
type Bar struct {
Baz Baz
}
type Foo struct {
Bars []Bar
}
v := Foo{[]Bar{{Baz{1}}, {Baz{2}}}}
b, err := Marshal(v)
if err != nil {
t.Fatal(err)
}
if d := checkOutput(b, loadTestData("marshal-arraytable-empty.toml")); d != "" {
t.Errorf("Output mismatch:\n%s", d)
}
}
func TestMarshalPointerError(t *testing.T) {
type X struct{ Sub *X }
want := &marshalNilError{reflect.TypeOf((*X)(nil))}
if _, err := Marshal((*X)(nil)); !reflect.DeepEqual(err, want) {
t.Errorf("Got %q, expected %q", err, want)
}
if _, err := Marshal(&X{nil}); !reflect.DeepEqual(err, want) {
t.Errorf("Got %q, expected %q", err, want)
}
}
func TestMarshalNonStruct(t *testing.T) {
val := []string{}
want := &marshalTableError{reflect.TypeOf(val)}
if _, err := Marshal(val); !reflect.DeepEqual(err, want) {
t.Errorf("Got %q, expected %q", err, want)
}
}
func TestMarshalOmitempty(t *testing.T) {
var x struct {
ZeroArray [0]int `toml:",omitempty"`
ZeroArray2 [10]int `toml:",omitempty"`
Slice []int `toml:",omitempty"`
Pointer *int `toml:",omitempty"`
Int int `toml:",omitempty"`
}
out, err := Marshal(x)
if err != nil {
t.Fatal(err)
}
if len(out) > 0 {
t.Fatalf("want no output, got %q", out)
}
}
func checkOutput(got, want []byte) string {
if bytes.Equal(got, want) {
return ""
}
return diff.Diff(string(got), string(want))
}