...

Source file src/github.com/pelletier/go-toml/v2/internal/imported_tests/unmarshal_imported_test.go

Documentation: github.com/pelletier/go-toml/v2/internal/imported_tests

     1  package imported_tests
     2  
     3  // Those tests were imported directly from go-toml v1
     4  // https://raw.githubusercontent.com/pelletier/go-toml/a2e52561804c6cd9392ebf0048ca64fe4af67a43/marshal_test.go
     5  // They have been cleaned up to only include Unmarshal tests, and only depend
     6  // on the public API. Tests related to strict mode have been commented out and
     7  // marked as skipped until we figure out if that's something we want in v2.
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"fmt"
    13  	"reflect"
    14  	"strconv"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/pelletier/go-toml/v2"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  type basicMarshalTestStruct struct {
    24  	String     string   `toml:"Zstring"`
    25  	StringList []string `toml:"Ystrlist"`
    26  	BasicMarshalTestSubAnonymousStruct
    27  	Sub     basicMarshalTestSubStruct   `toml:"Xsubdoc"`
    28  	SubList []basicMarshalTestSubStruct `toml:"Wsublist"`
    29  }
    30  
    31  type basicMarshalTestSubStruct struct {
    32  	String2 string
    33  }
    34  
    35  type BasicMarshalTestSubAnonymousStruct struct {
    36  	String3 string
    37  }
    38  
    39  var basicTestData = basicMarshalTestStruct{
    40  	String:                             "Hello",
    41  	StringList:                         []string{"Howdy", "Hey There"},
    42  	BasicMarshalTestSubAnonymousStruct: BasicMarshalTestSubAnonymousStruct{"One"},
    43  	Sub:                                basicMarshalTestSubStruct{"Two"},
    44  	SubList:                            []basicMarshalTestSubStruct{{"Three"}, {"Four"}},
    45  }
    46  
    47  var basicTestToml = []byte(`String3 = "One"
    48  Ystrlist = ["Howdy", "Hey There"]
    49  Zstring = "Hello"
    50  
    51  [[Wsublist]]
    52    String2 = "Three"
    53  
    54  [[Wsublist]]
    55    String2 = "Four"
    56  
    57  [Xsubdoc]
    58    String2 = "Two"
    59  `)
    60  
    61  var marshalTestToml = []byte(`title = "TOML Marshal Testing"
    62  
    63  [basic]
    64    bool = true
    65    date = 1979-05-27T07:32:00Z
    66    float = 123.4
    67    float64 = 123.456782132399
    68    int = 5000
    69    string = "Bite me"
    70    uint = 5001
    71  
    72  [basic_lists]
    73    bools = [true, false, true]
    74    dates = [1979-05-27T07:32:00Z, 1980-05-27T07:32:00Z]
    75    floats = [12.3, 45.6, 78.9]
    76    ints = [8001, 8001, 8002]
    77    strings = ["One", "Two", "Three"]
    78    uints = [5002, 5003]
    79  
    80  [basic_map]
    81    one = "one"
    82    two = "two"
    83  
    84  [subdoc]
    85  
    86    [subdoc.first]
    87      name = "First"
    88  
    89    [subdoc.second]
    90      name = "Second"
    91  
    92  [[subdoclist]]
    93    name = "List.First"
    94  
    95  [[subdoclist]]
    96    name = "List.Second"
    97  
    98  [[subdocptrs]]
    99    name = "Second"
   100  `)
   101  
   102  type Conf struct {
   103  	Name  string
   104  	Age   int
   105  	Inter interface{}
   106  }
   107  
   108  type NestedStruct struct {
   109  	FirstName string
   110  	LastName  string
   111  	Age       int
   112  }
   113  
   114  var doc = []byte(`Name = "rui"
   115  Age = 18
   116  
   117  [Inter]
   118    FirstName = "wang"
   119    LastName = "jl"
   120    Age = 100`)
   121  
   122  func TestInterface(t *testing.T) {
   123  	var config Conf
   124  	config.Inter = &NestedStruct{}
   125  	err := toml.Unmarshal(doc, &config)
   126  	require.NoError(t, err)
   127  	expected := Conf{
   128  		Name: "rui",
   129  		Age:  18,
   130  		Inter: map[string]interface{}{
   131  			"FirstName": "wang",
   132  			"LastName":  "jl",
   133  			"Age":       int64(100),
   134  		},
   135  	}
   136  	assert.Equal(t, expected, config)
   137  }
   138  
   139  func TestBasicUnmarshal(t *testing.T) {
   140  	result := basicMarshalTestStruct{}
   141  	err := toml.Unmarshal(basicTestToml, &result)
   142  	require.NoError(t, err)
   143  	require.Equal(t, basicTestData, result)
   144  }
   145  
   146  type quotedKeyMarshalTestStruct struct {
   147  	String  string                      `toml:"Z.string-àéù"`
   148  	Float   float64                     `toml:"Yfloat-𝟘"`
   149  	Sub     basicMarshalTestSubStruct   `toml:"Xsubdoc-àéù"`
   150  	SubList []basicMarshalTestSubStruct `toml:"W.sublist-𝟘"`
   151  }
   152  
   153  // TODO: Remove nolint once var is used by a test
   154  //
   155  //nolint:deadcode,unused,varcheck
   156  var quotedKeyMarshalTestData = quotedKeyMarshalTestStruct{
   157  	String:  "Hello",
   158  	Float:   3.5,
   159  	Sub:     basicMarshalTestSubStruct{"One"},
   160  	SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
   161  }
   162  
   163  // TODO: Remove nolint once var is used by a test
   164  //
   165  //nolint:deadcode,unused,varcheck
   166  var quotedKeyMarshalTestToml = []byte(`"Yfloat-𝟘" = 3.5
   167  "Z.string-àéù" = "Hello"
   168  
   169  [["W.sublist-𝟘"]]
   170    String2 = "Two"
   171  
   172  [["W.sublist-𝟘"]]
   173    String2 = "Three"
   174  
   175  ["Xsubdoc-àéù"]
   176    String2 = "One"
   177  `)
   178  
   179  type testDoc struct {
   180  	Title       string            `toml:"title"`
   181  	BasicLists  testDocBasicLists `toml:"basic_lists"`
   182  	SubDocPtrs  []*testSubDoc     `toml:"subdocptrs"`
   183  	BasicMap    map[string]string `toml:"basic_map"`
   184  	Subdocs     testDocSubs       `toml:"subdoc"`
   185  	Basics      testDocBasics     `toml:"basic"`
   186  	SubDocList  []testSubDoc      `toml:"subdoclist"`
   187  	err         int               `toml:"shouldntBeHere"` // nolint:structcheck,unused
   188  	unexported  int               `toml:"shouldntBeHere"`
   189  	Unexported2 int               `toml:"-"`
   190  }
   191  
   192  type testMapDoc struct {
   193  	Title    string            `toml:"title"`
   194  	BasicMap map[string]string `toml:"basic_map"`
   195  	LongMap  map[string]string `toml:"long_map"`
   196  }
   197  
   198  type testDocBasics struct {
   199  	Uint       uint      `toml:"uint"`
   200  	Bool       bool      `toml:"bool"`
   201  	Float32    float32   `toml:"float"`
   202  	Float64    float64   `toml:"float64"`
   203  	Int        int       `toml:"int"`
   204  	String     *string   `toml:"string"`
   205  	Date       time.Time `toml:"date"`
   206  	unexported int       `toml:"shouldntBeHere"`
   207  }
   208  
   209  type testDocBasicLists struct {
   210  	Floats  []*float32  `toml:"floats"`
   211  	Bools   []bool      `toml:"bools"`
   212  	Dates   []time.Time `toml:"dates"`
   213  	Ints    []int       `toml:"ints"`
   214  	UInts   []uint      `toml:"uints"`
   215  	Strings []string    `toml:"strings"`
   216  }
   217  
   218  type testDocSubs struct {
   219  	Second *testSubDoc `toml:"second"`
   220  	First  testSubDoc  `toml:"first"`
   221  }
   222  
   223  type testSubDoc struct {
   224  	Name       string `toml:"name"`
   225  	unexported int    `toml:"shouldntBeHere"`
   226  }
   227  
   228  var (
   229  	biteMe         = "Bite me"
   230  	float1 float32 = 12.3
   231  	float2 float32 = 45.6
   232  	float3 float32 = 78.9
   233  	subdoc         = testSubDoc{"Second", 0}
   234  )
   235  
   236  var docData = testDoc{
   237  	Title:       "TOML Marshal Testing",
   238  	unexported:  0,
   239  	Unexported2: 0,
   240  	Basics: testDocBasics{
   241  		Bool:       true,
   242  		Date:       time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
   243  		Float32:    123.4,
   244  		Float64:    123.456782132399,
   245  		Int:        5000,
   246  		Uint:       5001,
   247  		String:     &biteMe,
   248  		unexported: 0,
   249  	},
   250  	BasicLists: testDocBasicLists{
   251  		Bools: []bool{true, false, true},
   252  		Dates: []time.Time{
   253  			time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
   254  			time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC),
   255  		},
   256  		Floats:  []*float32{&float1, &float2, &float3},
   257  		Ints:    []int{8001, 8001, 8002},
   258  		Strings: []string{"One", "Two", "Three"},
   259  		UInts:   []uint{5002, 5003},
   260  	},
   261  	BasicMap: map[string]string{
   262  		"one": "one",
   263  		"two": "two",
   264  	},
   265  	Subdocs: testDocSubs{
   266  		First:  testSubDoc{"First", 0},
   267  		Second: &subdoc,
   268  	},
   269  	SubDocList: []testSubDoc{
   270  		{"List.First", 0},
   271  		{"List.Second", 0},
   272  	},
   273  	SubDocPtrs: []*testSubDoc{&subdoc},
   274  }
   275  
   276  // TODO: Remove nolint once var is used by a test
   277  //
   278  //nolint:deadcode,unused,varcheck
   279  var mapTestDoc = testMapDoc{
   280  	Title: "TOML Marshal Testing",
   281  	BasicMap: map[string]string{
   282  		"one": "one",
   283  		"two": "two",
   284  	},
   285  	LongMap: map[string]string{
   286  		"h1":  "8",
   287  		"i2":  "9",
   288  		"b3":  "2",
   289  		"d4":  "4",
   290  		"f5":  "6",
   291  		"e6":  "5",
   292  		"a7":  "1",
   293  		"c8":  "3",
   294  		"j9":  "10",
   295  		"g10": "7",
   296  	},
   297  }
   298  
   299  func TestDocUnmarshal(t *testing.T) {
   300  	result := testDoc{}
   301  	err := toml.Unmarshal(marshalTestToml, &result)
   302  	expected := docData
   303  	require.NoError(t, err)
   304  	assert.Equal(t, expected, result)
   305  }
   306  
   307  type unexportedMarshalTestStruct struct {
   308  	String      string                      `toml:"string"`
   309  	StringList  []string                    `toml:"strlist"`
   310  	Sub         basicMarshalTestSubStruct   `toml:"subdoc"`
   311  	SubList     []basicMarshalTestSubStruct `toml:"sublist"`
   312  	unexported  int                         `toml:"shouldntBeHere"`
   313  	Unexported2 int                         `toml:"-"`
   314  }
   315  
   316  var unexportedTestData = unexportedMarshalTestStruct{
   317  	String:      "Hello",
   318  	StringList:  []string{"Howdy", "Hey There"},
   319  	Sub:         basicMarshalTestSubStruct{"One"},
   320  	SubList:     []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
   321  	unexported:  0,
   322  	Unexported2: 0,
   323  }
   324  
   325  var unexportedTestToml = []byte(`string = "Hello"
   326  strlist = ["Howdy","Hey There"]
   327  unexported = 1
   328  shouldntBeHere = 2
   329  
   330  [subdoc]
   331    String2 = "One"
   332  
   333  [[sublist]]
   334    String2 = "Two"
   335  
   336  [[sublist]]
   337    String2 = "Three"
   338  `)
   339  
   340  func TestUnexportedUnmarshal(t *testing.T) {
   341  	result := unexportedMarshalTestStruct{}
   342  	err := toml.Unmarshal(unexportedTestToml, &result)
   343  	require.NoError(t, err)
   344  	assert.Equal(t, unexportedTestData, result)
   345  }
   346  
   347  type errStruct struct {
   348  	Bool   bool      `toml:"bool"`
   349  	Date   time.Time `toml:"date"`
   350  	Float  float64   `toml:"float"`
   351  	Int    int16     `toml:"int"`
   352  	String *string   `toml:"string"`
   353  }
   354  
   355  type mapErr struct {
   356  	Vals map[string]float64
   357  }
   358  
   359  type intErr struct {
   360  	Int1  int
   361  	Int2  int8
   362  	Int3  int16
   363  	Int4  int32
   364  	Int5  int64
   365  	UInt1 uint
   366  	UInt2 uint8
   367  	UInt3 uint16
   368  	UInt4 uint32
   369  	UInt5 uint64
   370  	Flt1  float32
   371  	Flt2  float64
   372  }
   373  
   374  var intErrTomls = []string{
   375  	"Int1 = []\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   376  	"Int1 = 1\nInt2 = []\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   377  	"Int1 = 1\nInt2 = 2\nInt3 = []\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   378  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = []\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   379  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = []\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   380  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = []\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   381  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = []\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   382  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = []\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   383  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = []\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
   384  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = []\nFlt1 = 1.0\nFlt2 = 2.0",
   385  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0",
   386  	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []",
   387  }
   388  
   389  func TestErrUnmarshal(t *testing.T) {
   390  	errTomls := []string{
   391  		"bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
   392  		"bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
   393  		"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"",
   394  		"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"",
   395  		"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
   396  		"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
   397  		"bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
   398  		"bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
   399  		"bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"",
   400  		"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"",
   401  		"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1",
   402  	}
   403  
   404  	for ind, x := range errTomls {
   405  		t.Run(fmt.Sprintf("Base Case %d", ind), func(t *testing.T) {
   406  			result := errStruct{}
   407  			err := toml.Unmarshal([]byte(x), &result)
   408  			if err == nil {
   409  				t.Errorf("Expected err from case %d\n", ind)
   410  			}
   411  		})
   412  	}
   413  	result2 := mapErr{}
   414  	err := toml.Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2)
   415  	if err == nil {
   416  		t.Errorf("Expected err from map")
   417  	}
   418  	for ind, x := range intErrTomls {
   419  		result3 := intErr{}
   420  		err := toml.Unmarshal([]byte(x), &result3)
   421  		if err == nil {
   422  			t.Errorf("Expected int err from case %d\n", ind)
   423  		}
   424  	}
   425  }
   426  
   427  var emptyTestToml = []byte(`bool = false
   428  int = 0
   429  string = ""
   430  stringlist = []
   431  title = "Placeholder"
   432  
   433  [map]
   434  `)
   435  
   436  func TestEmptytomlUnmarshal(t *testing.T) {
   437  	type emptyMarshalTestStruct struct {
   438  		Title      string                  `toml:"title"`
   439  		Bool       bool                    `toml:"bool"`
   440  		Int        int                     `toml:"int"`
   441  		String     string                  `toml:"string"`
   442  		StringList []string                `toml:"stringlist"`
   443  		Ptr        *basicMarshalTestStruct `toml:"ptr"`
   444  		Map        map[string]string       `toml:"map"`
   445  	}
   446  
   447  	emptyTestData := emptyMarshalTestStruct{
   448  		Title:      "Placeholder",
   449  		Bool:       false,
   450  		Int:        0,
   451  		String:     "",
   452  		StringList: []string{},
   453  		Ptr:        nil,
   454  		Map:        nil,
   455  	}
   456  
   457  	result := emptyMarshalTestStruct{}
   458  	err := toml.Unmarshal(emptyTestToml, &result)
   459  	require.NoError(t, err)
   460  	assert.Equal(t, emptyTestData, result)
   461  }
   462  
   463  type pointerMarshalTestStruct struct {
   464  	Str       *string
   465  	List      *[]string
   466  	ListPtr   *[]*string
   467  	Map       *map[string]string
   468  	MapPtr    *map[string]*string
   469  	EmptyStr  *string
   470  	EmptyList *[]string
   471  	EmptyMap  *map[string]string
   472  	DblPtr    *[]*[]*string
   473  }
   474  
   475  var (
   476  	pointerStr      = "Hello"
   477  	pointerList     = []string{"Hello back"}
   478  	pointerListPtr  = []*string{&pointerStr}
   479  	pointerMap      = map[string]string{"response": "Goodbye"}
   480  	pointerMapPtr   = map[string]*string{"alternate": &pointerStr}
   481  	pointerTestData = pointerMarshalTestStruct{
   482  		Str:       &pointerStr,
   483  		List:      &pointerList,
   484  		ListPtr:   &pointerListPtr,
   485  		Map:       &pointerMap,
   486  		MapPtr:    &pointerMapPtr,
   487  		EmptyStr:  nil,
   488  		EmptyList: nil,
   489  		EmptyMap:  nil,
   490  	}
   491  )
   492  
   493  var pointerTestToml = []byte(`List = ["Hello back"]
   494  ListPtr = ["Hello"]
   495  Str = "Hello"
   496  
   497  [Map]
   498    response = "Goodbye"
   499  
   500  [MapPtr]
   501    alternate = "Hello"
   502  `)
   503  
   504  func TestPointerUnmarshal(t *testing.T) {
   505  	result := pointerMarshalTestStruct{}
   506  	err := toml.Unmarshal(pointerTestToml, &result)
   507  	require.NoError(t, err)
   508  	assert.Equal(t, pointerTestData, result)
   509  }
   510  
   511  func TestUnmarshalTypeMismatch(t *testing.T) {
   512  	result := pointerMarshalTestStruct{}
   513  	err := toml.Unmarshal([]byte("List = 123"), &result)
   514  	assert.Error(t, err)
   515  }
   516  
   517  type nestedMarshalTestStruct struct {
   518  	String [][]string
   519  	// Struct [][]basicMarshalTestSubStruct
   520  	StringPtr *[]*[]*string
   521  	// StructPtr *[]*[]*basicMarshalTestSubStruct
   522  }
   523  
   524  var (
   525  	str1    = "Three"
   526  	str2    = "Four"
   527  	strPtr  = []*string{&str1, &str2}
   528  	strPtr2 = []*[]*string{&strPtr}
   529  )
   530  
   531  var nestedTestData = nestedMarshalTestStruct{
   532  	String:    [][]string{{"Five", "Six"}, {"One", "Two"}},
   533  	StringPtr: &strPtr2,
   534  }
   535  
   536  var nestedTestToml = []byte(`String = [["Five", "Six"], ["One", "Two"]]
   537  StringPtr = [["Three", "Four"]]
   538  `)
   539  
   540  func TestNestedUnmarshal(t *testing.T) {
   541  	result := nestedMarshalTestStruct{}
   542  	err := toml.Unmarshal(nestedTestToml, &result)
   543  	require.NoError(t, err)
   544  	assert.Equal(t, nestedTestData, result)
   545  }
   546  
   547  type customMarshalerParent struct {
   548  	Self    customMarshaler   `toml:"me"`
   549  	Friends []customMarshaler `toml:"friends"`
   550  }
   551  
   552  type customMarshaler struct {
   553  	FirstName string
   554  	LastName  string
   555  }
   556  
   557  func (c customMarshaler) MarshalTOML() ([]byte, error) {
   558  	fullName := fmt.Sprintf("%s %s", c.FirstName, c.LastName)
   559  	return []byte(fullName), nil
   560  }
   561  
   562  var customMarshalerData = customMarshaler{FirstName: "Sally", LastName: "Fields"}
   563  
   564  // TODO: Remove nolint once var is used by a test
   565  //
   566  //nolint:deadcode,unused,varcheck
   567  var customMarshalerToml = []byte(`Sally Fields`)
   568  
   569  // TODO: Remove nolint once var is used by a test
   570  //
   571  //nolint:deadcode,unused,varcheck
   572  var nestedCustomMarshalerData = customMarshalerParent{
   573  	Self:    customMarshaler{FirstName: "Maiku", LastName: "Suteda"},
   574  	Friends: []customMarshaler{customMarshalerData},
   575  }
   576  
   577  // TODO: Remove nolint once var is used by a test
   578  //
   579  //nolint:deadcode,unused,varcheck
   580  var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"]
   581  me = "Maiku Suteda"
   582  `)
   583  
   584  var nestedCustomMarshalerTomlForUnmarshal = []byte(`[friends]
   585  FirstName = "Sally"
   586  LastName = "Fields"`)
   587  
   588  type IntOrString string
   589  
   590  func (x *IntOrString) MarshalTOML() ([]byte, error) {
   591  	s := *(*string)(x)
   592  	_, err := strconv.Atoi(s)
   593  	if err != nil {
   594  		return []byte(fmt.Sprintf(`"%s"`, s)), nil
   595  	}
   596  	return []byte(s), nil
   597  }
   598  
   599  func TestUnmarshalTextMarshaler(t *testing.T) {
   600  	nested := struct {
   601  		Friends textMarshaler `toml:"friends"`
   602  	}{}
   603  
   604  	expected := struct {
   605  		Friends textMarshaler `toml:"friends"`
   606  	}{
   607  		Friends: textMarshaler{FirstName: "Sally", LastName: "Fields"},
   608  	}
   609  
   610  	err := toml.Unmarshal(nestedCustomMarshalerTomlForUnmarshal, &nested)
   611  	if err != nil {
   612  		t.Fatal(err)
   613  	}
   614  	if !reflect.DeepEqual(nested, expected) {
   615  		t.Errorf("Bad unmarshal: expected %v, got %v", expected, nested)
   616  	}
   617  }
   618  
   619  // TODO: Remove nolint once type and methods are used by a test
   620  //
   621  //nolint:unused
   622  type precedentMarshaler struct {
   623  	FirstName string
   624  	LastName  string
   625  }
   626  
   627  //nolint:unused
   628  func (m precedentMarshaler) MarshalText() ([]byte, error) {
   629  	return []byte("shadowed"), nil
   630  }
   631  
   632  //nolint:unused
   633  func (m precedentMarshaler) MarshalTOML() ([]byte, error) {
   634  	fullName := fmt.Sprintf("%s %s", m.FirstName, m.LastName)
   635  	return []byte(fullName), nil
   636  }
   637  
   638  // TODO: Remove nolint once type and method are used by a test
   639  //
   640  //nolint:unused
   641  type customPointerMarshaler struct {
   642  	FirstName string
   643  	LastName  string
   644  }
   645  
   646  //nolint:unused
   647  func (m *customPointerMarshaler) MarshalTOML() ([]byte, error) {
   648  	return []byte(`"hidden"`), nil
   649  }
   650  
   651  // TODO: Remove nolint once type and method are used by a test
   652  //
   653  //nolint:unused
   654  type textPointerMarshaler struct {
   655  	FirstName string
   656  	LastName  string
   657  }
   658  
   659  //nolint:unused
   660  func (m *textPointerMarshaler) MarshalText() ([]byte, error) {
   661  	return []byte("hidden"), nil
   662  }
   663  
   664  // TODO: Remove nolint once var is used by a test
   665  //
   666  //nolint:deadcode,unused,varcheck
   667  var commentTestToml = []byte(`
   668  # it's a comment on type
   669  [postgres]
   670    # isCommented = "dvalue"
   671    noComment = "cvalue"
   672  
   673    # A comment on AttrB with a
   674    # break line
   675    password = "bvalue"
   676  
   677    # A comment on AttrA
   678    user = "avalue"
   679  
   680    [[postgres.My]]
   681  
   682      # a comment on my on typeC
   683      My = "Foo"
   684  
   685    [[postgres.My]]
   686  
   687      # a comment on my on typeC
   688      My = "Baar"
   689  `)
   690  
   691  type mapsTestStruct struct {
   692  	Simple map[string]string
   693  	Paths  map[string]string
   694  	Other  map[string]float64
   695  	X      struct {
   696  		Y struct {
   697  			Z map[string]bool
   698  		}
   699  	}
   700  }
   701  
   702  // TODO: Remove nolint once var is used by a test
   703  //
   704  //nolint:deadcode,unused,varcheck
   705  var mapsTestData = mapsTestStruct{
   706  	Simple: map[string]string{
   707  		"one plus one": "two",
   708  		"next":         "three",
   709  	},
   710  	Paths: map[string]string{
   711  		"/this/is/a/path": "/this/is/also/a/path",
   712  		"/heloo.txt":      "/tmp/lololo.txt",
   713  	},
   714  	Other: map[string]float64{
   715  		"testing": 3.9999,
   716  	},
   717  	X: struct{ Y struct{ Z map[string]bool } }{
   718  		Y: struct{ Z map[string]bool }{
   719  			Z: map[string]bool{
   720  				"is.Nested": true,
   721  			},
   722  		},
   723  	},
   724  }
   725  
   726  // TODO: Remove nolint once var is used by a test
   727  //
   728  //nolint:deadcode,unused,varcheck
   729  var mapsTestToml = []byte(`
   730  [Other]
   731    "testing" = 3.9999
   732  
   733  [Paths]
   734    "/heloo.txt" = "/tmp/lololo.txt"
   735    "/this/is/a/path" = "/this/is/also/a/path"
   736  
   737  [Simple]
   738    "next" = "three"
   739    "one plus one" = "two"
   740  
   741  [X]
   742  
   743    [X.Y]
   744  
   745      [X.Y.Z]
   746        "is.Nested" = true
   747  `)
   748  
   749  // TODO: Remove nolint once type is used by a test
   750  //
   751  //nolint:deadcode,unused
   752  type structArrayNoTag struct {
   753  	A struct {
   754  		B []int64
   755  		C []int64
   756  	}
   757  }
   758  
   759  // TODO: Remove nolint once var is used by a test
   760  //
   761  //nolint:deadcode,unused,varcheck
   762  var customTagTestToml = []byte(`
   763  [postgres]
   764    password = "bvalue"
   765    user = "avalue"
   766  
   767    [[postgres.My]]
   768      My = "Foo"
   769  
   770    [[postgres.My]]
   771      My = "Baar"
   772  `)
   773  
   774  // TODO: Remove nolint once var is used by a test
   775  //
   776  //nolint:deadcode,unused,varcheck
   777  var customCommentTagTestToml = []byte(`
   778  # db connection
   779  [postgres]
   780  
   781    # db pass
   782    password = "bvalue"
   783  
   784    # db user
   785    user = "avalue"
   786  `)
   787  
   788  // TODO: Remove nolint once var is used by a test
   789  //
   790  //nolint:deadcode,unused,varcheck
   791  var customCommentedTagTestToml = []byte(`
   792  [postgres]
   793    # password = "bvalue"
   794    # user = "avalue"
   795  `)
   796  
   797  func TestUnmarshalTabInStringAndQuotedKey(t *testing.T) {
   798  	type Test struct {
   799  		Field1 string `toml:"Fie	ld1"`
   800  		Field2 string
   801  	}
   802  
   803  	type TestCase struct {
   804  		desc     string
   805  		input    []byte
   806  		expected Test
   807  	}
   808  
   809  	testCases := []TestCase{
   810  		{
   811  			desc:  "multiline string with tab",
   812  			input: []byte("Field2 = \"\"\"\nhello\tworld\"\"\""),
   813  			expected: Test{
   814  				Field2: "hello\tworld",
   815  			},
   816  		},
   817  		{
   818  			desc:  "quoted key with tab",
   819  			input: []byte("\"Fie\tld1\" = \"key with tab\""),
   820  			expected: Test{
   821  				Field1: "key with tab",
   822  			},
   823  		},
   824  		{
   825  			desc:  "basic string tab",
   826  			input: []byte("Field2 = \"hello\tworld\""),
   827  			expected: Test{
   828  				Field2: "hello\tworld",
   829  			},
   830  		},
   831  	}
   832  
   833  	for _, test := range testCases {
   834  		t.Run(test.desc, func(t *testing.T) {
   835  			result := Test{}
   836  			err := toml.Unmarshal(test.input, &result)
   837  			require.NoError(t, err)
   838  			assert.Equal(t, test.expected, result)
   839  		})
   840  	}
   841  }
   842  
   843  // TODO: Remove nolint once var is used by a test
   844  //
   845  //nolint:deadcode,unused,varcheck
   846  var customMultilineTagTestToml = []byte(`int_slice = [
   847    1,
   848    2,
   849    3,
   850  ]
   851  `)
   852  
   853  // TODO: Remove nolint once var is used by a test
   854  //
   855  //nolint:deadcode,unused,varcheck
   856  var testDocBasicToml = []byte(`
   857  [document]
   858    bool_val = true
   859    date_val = 1979-05-27T07:32:00Z
   860    float_val = 123.4
   861    int_val = 5000
   862    string_val = "Bite me"
   863    uint_val = 5001
   864  `)
   865  
   866  // TODO: Remove nolint once type is used by a test
   867  //
   868  //nolint:deadcode
   869  type testDocCustomTag struct {
   870  	Doc testDocBasicsCustomTag `file:"document"`
   871  }
   872  
   873  // TODO: Remove nolint once type is used by a test
   874  //
   875  //nolint:deadcode
   876  type testDocBasicsCustomTag struct {
   877  	Bool       bool      `file:"bool_val"`
   878  	Date       time.Time `file:"date_val"`
   879  	Float      float32   `file:"float_val"`
   880  	Int        int       `file:"int_val"`
   881  	Uint       uint      `file:"uint_val"`
   882  	String     *string   `file:"string_val"`
   883  	unexported int       `file:"shouldntBeHere"`
   884  }
   885  
   886  // TODO: Remove nolint once var is used by a test
   887  //
   888  //nolint:deadcode,varcheck
   889  var testDocCustomTagData = testDocCustomTag{
   890  	Doc: testDocBasicsCustomTag{
   891  		Bool:       true,
   892  		Date:       time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
   893  		Float:      123.4,
   894  		Int:        5000,
   895  		Uint:       5001,
   896  		String:     &biteMe,
   897  		unexported: 0,
   898  	},
   899  }
   900  
   901  func TestUnmarshalMap(t *testing.T) {
   902  	testToml := []byte(`
   903  		a = 1
   904  		b = 2
   905  		c = 3
   906  		`)
   907  	var result map[string]int
   908  	err := toml.Unmarshal(testToml, &result)
   909  	if err != nil {
   910  		t.Errorf("Received unexpected error: %s", err)
   911  		return
   912  	}
   913  
   914  	expected := map[string]int{
   915  		"a": 1,
   916  		"b": 2,
   917  		"c": 3,
   918  	}
   919  
   920  	if !reflect.DeepEqual(result, expected) {
   921  		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
   922  	}
   923  }
   924  
   925  func TestUnmarshalMapWithTypedKey(t *testing.T) {
   926  	testToml := []byte(`
   927  		a = 1
   928  		b = 2
   929  		c = 3
   930  		`)
   931  
   932  	type letter string
   933  	var result map[letter]int
   934  	err := toml.Unmarshal(testToml, &result)
   935  	if err != nil {
   936  		t.Errorf("Received unexpected error: %s", err)
   937  		return
   938  	}
   939  
   940  	expected := map[letter]int{
   941  		"a": 1,
   942  		"b": 2,
   943  		"c": 3,
   944  	}
   945  
   946  	if !reflect.DeepEqual(result, expected) {
   947  		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
   948  	}
   949  }
   950  
   951  func TestUnmarshalTypeTableHeader(t *testing.T) {
   952  	testToml := []byte(`
   953  		[test]
   954  		a = 1
   955  		`)
   956  
   957  	type header string
   958  	var result map[header]map[string]int
   959  	err := toml.Unmarshal(testToml, &result)
   960  	if err != nil {
   961  		t.Errorf("Received unexpected error: %s", err)
   962  		return
   963  	}
   964  
   965  	expected := map[header]map[string]int{
   966  		"test": map[string]int{"a": 1},
   967  	}
   968  
   969  	if !reflect.DeepEqual(result, expected) {
   970  		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
   971  	}
   972  }
   973  
   974  func TestUnmarshalNonPointer(t *testing.T) {
   975  	a := 1
   976  	err := toml.Unmarshal([]byte{}, a)
   977  	if err == nil {
   978  		t.Fatal("unmarshal should err when given a non pointer")
   979  	}
   980  }
   981  
   982  func TestUnmarshalInvalidPointerKind(t *testing.T) {
   983  	t.Skipf("should this really be an error?")
   984  	a := 1
   985  	err := toml.Unmarshal([]byte{}, &a)
   986  	assert.Error(t, err)
   987  }
   988  
   989  // TODO: Remove nolint once var is used by a test
   990  //
   991  //nolint:deadcode,unused
   992  type testDuration struct {
   993  	Nanosec   time.Duration  `toml:"nanosec"`
   994  	Microsec1 time.Duration  `toml:"microsec1"`
   995  	Microsec2 *time.Duration `toml:"microsec2"`
   996  	Millisec  time.Duration  `toml:"millisec"`
   997  	Sec       time.Duration  `toml:"sec"`
   998  	Min       time.Duration  `toml:"min"`
   999  	Hour      time.Duration  `toml:"hour"`
  1000  	Mixed     time.Duration  `toml:"mixed"`
  1001  	AString   string         `toml:"a_string"`
  1002  }
  1003  
  1004  // TODO: Remove nolint once var is used by a test
  1005  //
  1006  //nolint:deadcode,unused,varcheck
  1007  var testDurationToml = []byte(`
  1008  nanosec = "1ns"
  1009  microsec1 = "1us"
  1010  microsec2 = "1µs"
  1011  millisec = "1ms"
  1012  sec = "1s"
  1013  min = "1m"
  1014  hour = "1h"
  1015  mixed = "1h1m1s1ms1µs1ns"
  1016  a_string = "15s"
  1017  `)
  1018  
  1019  // TODO: Remove nolint once var is used by a test
  1020  //
  1021  //nolint:deadcode,unused,varcheck
  1022  var testDurationToml2 = []byte(`a_string = "15s"
  1023  hour = "1h0m0s"
  1024  microsec1 = "1µs"
  1025  microsec2 = "1µs"
  1026  millisec = "1ms"
  1027  min = "1m0s"
  1028  mixed = "1h1m1.001001001s"
  1029  nanosec = "1ns"
  1030  sec = "1s"
  1031  `)
  1032  
  1033  // TODO: Remove nolint once type is used by a test
  1034  //
  1035  //nolint:deadcode,unused
  1036  type testBadDuration struct {
  1037  	Val time.Duration `toml:"val"`
  1038  }
  1039  
  1040  // TODO: add back camelCase test
  1041  var testCamelCaseKeyToml = []byte(`fooBar = 10`) //nolint:unused
  1042  
  1043  //nolint:unused
  1044  func TestUnmarshalCamelCaseKey(t *testing.T) {
  1045  	t.Skipf("don't know if it is a good idea to automatically convert like that yet")
  1046  	var x struct {
  1047  		FooBar int
  1048  		B      int
  1049  	}
  1050  
  1051  	if err := toml.Unmarshal(testCamelCaseKeyToml, &x); err != nil {
  1052  		t.Fatal(err)
  1053  	}
  1054  
  1055  	if x.FooBar != 10 {
  1056  		t.Fatal("Did not set camelCase'd key")
  1057  	}
  1058  }
  1059  
  1060  func TestUnmarshalNegativeUint(t *testing.T) {
  1061  	t.Skipf("not sure if we this should always error")
  1062  	type check struct{ U uint } // nolint:unused
  1063  	err := toml.Unmarshal([]byte("U = -1"), &check{})
  1064  	assert.Error(t, err)
  1065  }
  1066  
  1067  func TestUnmarshalCheckConversionFloatInt(t *testing.T) {
  1068  	type conversionCheck struct {
  1069  		U uint
  1070  		I int
  1071  		F float64
  1072  	}
  1073  
  1074  	type TestCase struct {
  1075  		desc  string
  1076  		input string
  1077  	}
  1078  
  1079  	testCases := []TestCase{
  1080  		{
  1081  			desc:  "unsigned int",
  1082  			input: `U = 1e300`,
  1083  		},
  1084  		{
  1085  			desc:  "int",
  1086  			input: `I = 1e300`,
  1087  		},
  1088  	}
  1089  
  1090  	for _, test := range testCases {
  1091  		t.Run(test.desc, func(t *testing.T) {
  1092  			err := toml.Unmarshal([]byte(test.input), &conversionCheck{})
  1093  			require.Error(t, err)
  1094  		})
  1095  	}
  1096  }
  1097  
  1098  func TestUnmarshalOverflow(t *testing.T) {
  1099  	type overflow struct {
  1100  		U8  uint8
  1101  		I8  int8
  1102  		F32 float32
  1103  	}
  1104  
  1105  	type TestCase struct {
  1106  		desc  string
  1107  		input string
  1108  	}
  1109  
  1110  	testCases := []TestCase{
  1111  		{
  1112  			desc:  "byte",
  1113  			input: `U8 = 300`,
  1114  		},
  1115  		{
  1116  			desc:  "int8",
  1117  			input: `I8 = 300`,
  1118  		},
  1119  		{
  1120  			desc:  "float32",
  1121  			input: `F32 = 1e300`,
  1122  		},
  1123  	}
  1124  
  1125  	for _, test := range testCases {
  1126  		t.Run(test.desc, func(t *testing.T) {
  1127  			err := toml.Unmarshal([]byte(test.input), &overflow{})
  1128  			require.Error(t, err)
  1129  		})
  1130  	}
  1131  }
  1132  
  1133  func TestUnmarshalDefault(t *testing.T) {
  1134  	t.Skipf("don't know if it is a good idea to have `default`")
  1135  	t.Run("main", func(t *testing.T) {
  1136  		type EmbeddedStruct struct {
  1137  			StringField string `default:"c"`
  1138  		}
  1139  
  1140  		type aliasUint uint
  1141  
  1142  		var doc struct {
  1143  			StringField       string        `default:"a"`
  1144  			BoolField         bool          `default:"true"`
  1145  			UintField         uint          `default:"1"`
  1146  			Uint8Field        uint8         `default:"8"`
  1147  			Uint16Field       uint16        `default:"16"`
  1148  			Uint32Field       uint32        `default:"32"`
  1149  			Uint64Field       uint64        `default:"64"`
  1150  			IntField          int           `default:"-1"`
  1151  			Int8Field         int8          `default:"-8"`
  1152  			Int16Field        int16         `default:"-16"`
  1153  			Int32Field        int32         `default:"-32"`
  1154  			Int64Field        int64         `default:"-64"`
  1155  			Float32Field      float32       `default:"32.1"`
  1156  			Float64Field      float64       `default:"64.1"`
  1157  			DurationField     time.Duration `default:"120ms"`
  1158  			DurationField2    time.Duration `default:"120000000"`
  1159  			NonEmbeddedStruct struct {
  1160  				StringField string `default:"b"`
  1161  			}
  1162  			EmbeddedStruct
  1163  			AliasUintField aliasUint `default:"1000"`
  1164  		}
  1165  
  1166  		err := toml.Unmarshal([]byte(``), &doc)
  1167  		if err != nil {
  1168  			t.Fatal(err)
  1169  		}
  1170  		if doc.BoolField != true {
  1171  			t.Errorf("BoolField should be true, not %t", doc.BoolField)
  1172  		}
  1173  		if doc.StringField != "a" {
  1174  			t.Errorf("StringField should be \"a\", not %s", doc.StringField)
  1175  		}
  1176  		if doc.UintField != 1 {
  1177  			t.Errorf("UintField should be 1, not %d", doc.UintField)
  1178  		}
  1179  		if doc.Uint8Field != 8 {
  1180  			t.Errorf("Uint8Field should be 8, not %d", doc.Uint8Field)
  1181  		}
  1182  		if doc.Uint16Field != 16 {
  1183  			t.Errorf("Uint16Field should be 16, not %d", doc.Uint16Field)
  1184  		}
  1185  		if doc.Uint32Field != 32 {
  1186  			t.Errorf("Uint32Field should be 32, not %d", doc.Uint32Field)
  1187  		}
  1188  		if doc.Uint64Field != 64 {
  1189  			t.Errorf("Uint64Field should be 64, not %d", doc.Uint64Field)
  1190  		}
  1191  		if doc.IntField != -1 {
  1192  			t.Errorf("IntField should be -1, not %d", doc.IntField)
  1193  		}
  1194  		if doc.Int8Field != -8 {
  1195  			t.Errorf("Int8Field should be -8, not %d", doc.Int8Field)
  1196  		}
  1197  		if doc.Int16Field != -16 {
  1198  			t.Errorf("Int16Field should be -16, not %d", doc.Int16Field)
  1199  		}
  1200  		if doc.Int32Field != -32 {
  1201  			t.Errorf("Int32Field should be -32, not %d", doc.Int32Field)
  1202  		}
  1203  		if doc.Int64Field != -64 {
  1204  			t.Errorf("Int64Field should be -64, not %d", doc.Int64Field)
  1205  		}
  1206  		if doc.Float32Field != 32.1 {
  1207  			t.Errorf("Float32Field should be 32.1, not %f", doc.Float32Field)
  1208  		}
  1209  		if doc.Float64Field != 64.1 {
  1210  			t.Errorf("Float64Field should be 64.1, not %f", doc.Float64Field)
  1211  		}
  1212  		if doc.DurationField != 120*time.Millisecond {
  1213  			t.Errorf("DurationField should be 120ms, not %s", doc.DurationField.String())
  1214  		}
  1215  		if doc.DurationField2 != 120*time.Millisecond {
  1216  			t.Errorf("DurationField2 should be 120000000, not %d", doc.DurationField2)
  1217  		}
  1218  		if doc.NonEmbeddedStruct.StringField != "b" {
  1219  			t.Errorf("StringField should be \"b\", not %s", doc.NonEmbeddedStruct.StringField)
  1220  		}
  1221  		if doc.EmbeddedStruct.StringField != "c" {
  1222  			t.Errorf("StringField should be \"c\", not %s", doc.EmbeddedStruct.StringField)
  1223  		}
  1224  		if doc.AliasUintField != 1000 {
  1225  			t.Errorf("AliasUintField should be 1000, not %d", doc.AliasUintField)
  1226  		}
  1227  	})
  1228  
  1229  	t.Run("failure bool", func(t *testing.T) {
  1230  		var doc struct {
  1231  			Field bool `default:"blah"`
  1232  		}
  1233  
  1234  		err := toml.Unmarshal([]byte(``), &doc)
  1235  		if err == nil {
  1236  			t.Fatal("should error")
  1237  		}
  1238  	})
  1239  
  1240  	t.Run("failure int", func(t *testing.T) {
  1241  		var doc struct {
  1242  			Field int `default:"blah"`
  1243  		}
  1244  
  1245  		err := toml.Unmarshal([]byte(``), &doc)
  1246  		if err == nil {
  1247  			t.Fatal("should error")
  1248  		}
  1249  	})
  1250  
  1251  	t.Run("failure int64", func(t *testing.T) {
  1252  		var doc struct {
  1253  			Field int64 `default:"blah"`
  1254  		}
  1255  
  1256  		err := toml.Unmarshal([]byte(``), &doc)
  1257  		if err == nil {
  1258  			t.Fatal("should error")
  1259  		}
  1260  	})
  1261  
  1262  	t.Run("failure float64", func(t *testing.T) {
  1263  		var doc struct {
  1264  			Field float64 `default:"blah"`
  1265  		}
  1266  
  1267  		err := toml.Unmarshal([]byte(``), &doc)
  1268  		if err == nil {
  1269  			t.Fatal("should error")
  1270  		}
  1271  	})
  1272  
  1273  	t.Run("failure duration", func(t *testing.T) {
  1274  		var doc struct {
  1275  			Field time.Duration `default:"blah"`
  1276  		}
  1277  
  1278  		err := toml.Unmarshal([]byte(``), &doc)
  1279  		if err == nil {
  1280  			t.Fatal("should error")
  1281  		}
  1282  	})
  1283  
  1284  	t.Run("failure unsupported", func(t *testing.T) {
  1285  		var doc struct {
  1286  			Field struct{} `default:"blah"`
  1287  		}
  1288  
  1289  		err := toml.Unmarshal([]byte(``), &doc)
  1290  		if err == nil {
  1291  			t.Fatal("should error")
  1292  		}
  1293  	})
  1294  }
  1295  
  1296  func TestUnmarshalNestedAnonymousStructs(t *testing.T) {
  1297  	type Nested struct {
  1298  		Value string `toml:"nested_field"`
  1299  	}
  1300  	type Deep struct {
  1301  		Nested
  1302  	}
  1303  	type Document struct {
  1304  		Deep
  1305  		Value string `toml:"own_field"`
  1306  	}
  1307  
  1308  	var doc Document
  1309  
  1310  	err := toml.Unmarshal([]byte(`nested_field = "nested value"`+"\n"+`own_field = "own value"`), &doc)
  1311  	if err != nil {
  1312  		t.Fatal("should not error")
  1313  	}
  1314  	if doc.Value != "own value" || doc.Nested.Value != "nested value" {
  1315  		t.Fatal("unexpected values")
  1316  	}
  1317  }
  1318  
  1319  func TestUnmarshalNestedAnonymousStructs_Controversial(t *testing.T) {
  1320  	t.Skipf("TODO: what does encoding/json do?")
  1321  	type Nested struct {
  1322  		Value string `toml:"nested"`
  1323  	}
  1324  	type Deep struct {
  1325  		Nested
  1326  	}
  1327  	type Document struct {
  1328  		Deep
  1329  		Value string `toml:"own"`
  1330  	}
  1331  
  1332  	var doc Document
  1333  
  1334  	err := toml.Unmarshal([]byte(`nested = "nested value"`+"\n"+`own = "own value"`), &doc)
  1335  	if err == nil {
  1336  		t.Fatal("should error")
  1337  	}
  1338  }
  1339  
  1340  type unexportedFieldPreservationTest struct {
  1341  	Exported   string `toml:"exported"`
  1342  	unexported string
  1343  	Nested1    unexportedFieldPreservationTestNested    `toml:"nested1"`
  1344  	Nested2    *unexportedFieldPreservationTestNested   `toml:"nested2"`
  1345  	Nested3    *unexportedFieldPreservationTestNested   `toml:"nested3"`
  1346  	Slice1     []unexportedFieldPreservationTestNested  `toml:"slice1"`
  1347  	Slice2     []*unexportedFieldPreservationTestNested `toml:"slice2"`
  1348  }
  1349  
  1350  type unexportedFieldPreservationTestNested struct {
  1351  	Exported1   string `toml:"exported1"`
  1352  	unexported1 string
  1353  }
  1354  
  1355  func TestUnmarshalPreservesUnexportedFields(t *testing.T) {
  1356  	doc := `
  1357  	exported = "visible"
  1358  	unexported = "ignored"
  1359  
  1360  	[nested1]
  1361  	exported1 = "visible1"
  1362  	unexported1 = "ignored1"
  1363  
  1364  	[nested2]
  1365  	exported1 = "visible2"
  1366  	unexported1 = "ignored2"
  1367  
  1368  	[nested3]
  1369  	exported1 = "visible3"
  1370  	unexported1 = "ignored3"
  1371  
  1372  	[[slice1]]
  1373  	exported1 = "visible3"
  1374  
  1375  	[[slice1]]
  1376  	exported1 = "visible4"
  1377  
  1378  	[[slice2]]
  1379  	exported1 = "visible5"
  1380  	`
  1381  
  1382  	t.Run("unexported field should not be set from toml", func(t *testing.T) {
  1383  		var actual unexportedFieldPreservationTest
  1384  		err := toml.Unmarshal([]byte(doc), &actual)
  1385  		if err != nil {
  1386  			t.Fatal("did not expect an error")
  1387  		}
  1388  
  1389  		expect := unexportedFieldPreservationTest{
  1390  			Exported:   "visible",
  1391  			unexported: "",
  1392  			Nested1:    unexportedFieldPreservationTestNested{"visible1", ""},
  1393  			Nested2:    &unexportedFieldPreservationTestNested{"visible2", ""},
  1394  			Nested3:    &unexportedFieldPreservationTestNested{"visible3", ""},
  1395  			Slice1: []unexportedFieldPreservationTestNested{
  1396  				{Exported1: "visible3"},
  1397  				{Exported1: "visible4"},
  1398  			},
  1399  			Slice2: []*unexportedFieldPreservationTestNested{
  1400  				{Exported1: "visible5"},
  1401  			},
  1402  		}
  1403  
  1404  		if !reflect.DeepEqual(actual, expect) {
  1405  			t.Fatalf("%+v did not equal %+v", actual, expect)
  1406  		}
  1407  	})
  1408  
  1409  	t.Run("unexported field should be preserved", func(t *testing.T) {
  1410  		actual := unexportedFieldPreservationTest{
  1411  			Exported:   "foo",
  1412  			unexported: "bar",
  1413  			Nested1:    unexportedFieldPreservationTestNested{"baz", "bax"},
  1414  			Nested2:    nil,
  1415  			Nested3:    &unexportedFieldPreservationTestNested{"baz", "bax"},
  1416  		}
  1417  		err := toml.Unmarshal([]byte(doc), &actual)
  1418  		if err != nil {
  1419  			t.Fatal("did not expect an error")
  1420  		}
  1421  
  1422  		expect := unexportedFieldPreservationTest{
  1423  			Exported:   "visible",
  1424  			unexported: "bar",
  1425  			Nested1:    unexportedFieldPreservationTestNested{"visible1", "bax"},
  1426  			Nested2:    &unexportedFieldPreservationTestNested{"visible2", ""},
  1427  			Nested3:    &unexportedFieldPreservationTestNested{"visible3", "bax"},
  1428  			Slice1: []unexportedFieldPreservationTestNested{
  1429  				{Exported1: "visible3"},
  1430  				{Exported1: "visible4"},
  1431  			},
  1432  			Slice2: []*unexportedFieldPreservationTestNested{
  1433  				{Exported1: "visible5"},
  1434  			},
  1435  		}
  1436  
  1437  		if !reflect.DeepEqual(actual, expect) {
  1438  			t.Fatalf("%+v did not equal %+v", actual, expect)
  1439  		}
  1440  	})
  1441  }
  1442  
  1443  func TestUnmarshalLocalDate(t *testing.T) {
  1444  	t.Run("ToLocalDate", func(t *testing.T) {
  1445  		type dateStruct struct {
  1446  			Date toml.LocalDate
  1447  		}
  1448  
  1449  		doc := `date = 1979-05-27`
  1450  
  1451  		var obj dateStruct
  1452  
  1453  		err := toml.Unmarshal([]byte(doc), &obj)
  1454  		if err != nil {
  1455  			t.Fatal(err)
  1456  		}
  1457  
  1458  		if obj.Date.Year != 1979 {
  1459  			t.Errorf("expected year 1979, got %d", obj.Date.Year)
  1460  		}
  1461  		if obj.Date.Month != 5 {
  1462  			t.Errorf("expected month 5, got %d", obj.Date.Month)
  1463  		}
  1464  		if obj.Date.Day != 27 {
  1465  			t.Errorf("expected day 27, got %d", obj.Date.Day)
  1466  		}
  1467  	})
  1468  
  1469  	t.Run("ToLocalDate", func(t *testing.T) {
  1470  		type dateStruct struct {
  1471  			Date time.Time
  1472  		}
  1473  
  1474  		doc := `date = 1979-05-27`
  1475  
  1476  		var obj dateStruct
  1477  
  1478  		err := toml.Unmarshal([]byte(doc), &obj)
  1479  		if err != nil {
  1480  			t.Fatal(err)
  1481  		}
  1482  
  1483  		if obj.Date.Year() != 1979 {
  1484  			t.Errorf("expected year 1979, got %d", obj.Date.Year())
  1485  		}
  1486  		if obj.Date.Month() != 5 {
  1487  			t.Errorf("expected month 5, got %d", obj.Date.Month())
  1488  		}
  1489  		if obj.Date.Day() != 27 {
  1490  			t.Errorf("expected day 27, got %d", obj.Date.Day())
  1491  		}
  1492  	})
  1493  }
  1494  
  1495  func TestUnmarshalLocalDateTime(t *testing.T) {
  1496  	examples := []struct {
  1497  		name string
  1498  		in   string
  1499  		out  toml.LocalDateTime
  1500  	}{
  1501  		{
  1502  			name: "normal",
  1503  			in:   "1979-05-27T07:32:00",
  1504  			out: toml.LocalDateTime{
  1505  				LocalDate: toml.LocalDate{
  1506  					Year:  1979,
  1507  					Month: 5,
  1508  					Day:   27,
  1509  				},
  1510  				LocalTime: toml.LocalTime{
  1511  					Hour:       7,
  1512  					Minute:     32,
  1513  					Second:     0,
  1514  					Nanosecond: 0,
  1515  				},
  1516  			},
  1517  		},
  1518  		{
  1519  			name: "with nanoseconds",
  1520  			in:   "1979-05-27T00:32:00.999999",
  1521  			out: toml.LocalDateTime{
  1522  				LocalDate: toml.LocalDate{
  1523  					Year:  1979,
  1524  					Month: 5,
  1525  					Day:   27,
  1526  				},
  1527  				LocalTime: toml.LocalTime{
  1528  					Hour:       0,
  1529  					Minute:     32,
  1530  					Second:     0,
  1531  					Nanosecond: 999999000,
  1532  					Precision:  6,
  1533  				},
  1534  			},
  1535  		},
  1536  	}
  1537  
  1538  	for i, example := range examples {
  1539  		doc := fmt.Sprintf(`date = %s`, example.in)
  1540  
  1541  		t.Run(fmt.Sprintf("ToLocalDateTime_%d_%s", i, example.name), func(t *testing.T) {
  1542  			type dateStruct struct {
  1543  				Date toml.LocalDateTime
  1544  			}
  1545  
  1546  			var obj dateStruct
  1547  
  1548  			err := toml.Unmarshal([]byte(doc), &obj)
  1549  			if err != nil {
  1550  				t.Fatal(err)
  1551  			}
  1552  
  1553  			if obj.Date != example.out {
  1554  				t.Errorf("expected '%s', got '%s'", example.out, obj.Date)
  1555  			}
  1556  		})
  1557  
  1558  		t.Run(fmt.Sprintf("ToTime_%d_%s", i, example.name), func(t *testing.T) {
  1559  			type dateStruct struct {
  1560  				Date time.Time
  1561  			}
  1562  
  1563  			var obj dateStruct
  1564  
  1565  			err := toml.Unmarshal([]byte(doc), &obj)
  1566  			if err != nil {
  1567  				t.Fatal(err)
  1568  			}
  1569  
  1570  			if obj.Date.Year() != example.out.Year {
  1571  				t.Errorf("expected year %d, got %d", example.out.Year, obj.Date.Year())
  1572  			}
  1573  			if obj.Date.Month() != time.Month(example.out.Month) {
  1574  				t.Errorf("expected month %d, got %d", example.out.Month, obj.Date.Month())
  1575  			}
  1576  			if obj.Date.Day() != example.out.Day {
  1577  				t.Errorf("expected day %d, got %d", example.out.Day, obj.Date.Day())
  1578  			}
  1579  			if obj.Date.Hour() != example.out.Hour {
  1580  				t.Errorf("expected hour %d, got %d", example.out.Hour, obj.Date.Hour())
  1581  			}
  1582  			if obj.Date.Minute() != example.out.Minute {
  1583  				t.Errorf("expected minute %d, got %d", example.out.Minute, obj.Date.Minute())
  1584  			}
  1585  			if obj.Date.Second() != example.out.Second {
  1586  				t.Errorf("expected second %d, got %d", example.out.Second, obj.Date.Second())
  1587  			}
  1588  			if obj.Date.Nanosecond() != example.out.Nanosecond {
  1589  				t.Errorf("expected nanoseconds %d, got %d", example.out.Nanosecond, obj.Date.Nanosecond())
  1590  			}
  1591  		})
  1592  	}
  1593  }
  1594  
  1595  func TestUnmarshalLocalTime(t *testing.T) {
  1596  	examples := []struct {
  1597  		name string
  1598  		in   string
  1599  		out  toml.LocalTime
  1600  	}{
  1601  		{
  1602  			name: "normal",
  1603  			in:   "07:32:00",
  1604  			out: toml.LocalTime{
  1605  				Hour:       7,
  1606  				Minute:     32,
  1607  				Second:     0,
  1608  				Nanosecond: 0,
  1609  			},
  1610  		},
  1611  		{
  1612  			name: "with nanoseconds",
  1613  			in:   "00:32:00.999999",
  1614  			out: toml.LocalTime{
  1615  				Hour:       0,
  1616  				Minute:     32,
  1617  				Second:     0,
  1618  				Nanosecond: 999999000,
  1619  				Precision:  6,
  1620  			},
  1621  		},
  1622  	}
  1623  
  1624  	for i, example := range examples {
  1625  		doc := fmt.Sprintf(`Time = %s`, example.in)
  1626  
  1627  		t.Run(fmt.Sprintf("ToLocalTime_%d_%s", i, example.name), func(t *testing.T) {
  1628  			type dateStruct struct {
  1629  				Time toml.LocalTime
  1630  			}
  1631  
  1632  			var obj dateStruct
  1633  
  1634  			err := toml.Unmarshal([]byte(doc), &obj)
  1635  			if err != nil {
  1636  				t.Fatal(err)
  1637  			}
  1638  
  1639  			if obj.Time != example.out {
  1640  				t.Errorf("expected '%s', got '%s'", example.out, obj.Time)
  1641  			}
  1642  		})
  1643  	}
  1644  }
  1645  
  1646  // test case for issue #339
  1647  func TestUnmarshalSameInnerField(t *testing.T) {
  1648  	type InterStruct2 struct {
  1649  		Test string
  1650  		Name string
  1651  		Age  int
  1652  	}
  1653  	type Inter2 struct {
  1654  		Name         string
  1655  		Age          int
  1656  		InterStruct2 InterStruct2
  1657  	}
  1658  	type Server struct {
  1659  		Name   string `toml:"name"`
  1660  		Inter2 Inter2 `toml:"inter2"`
  1661  	}
  1662  
  1663  	var server Server
  1664  
  1665  	if err := toml.Unmarshal([]byte(`name = "123"
  1666  [inter2]
  1667  name = "inter2"
  1668  age = 222`), &server); err == nil {
  1669  		expected := Server{
  1670  			Name: "123",
  1671  			Inter2: Inter2{
  1672  				Name: "inter2",
  1673  				Age:  222,
  1674  			},
  1675  		}
  1676  		if !reflect.DeepEqual(server, expected) {
  1677  			t.Errorf("Bad unmarshal: expected %v, got %v", expected, server)
  1678  		}
  1679  	} else {
  1680  		t.Fatalf("unexpected error: %v", err)
  1681  	}
  1682  }
  1683  
  1684  func TestUnmarshalToNilInterface(t *testing.T) {
  1685  	doc := []byte(`
  1686  PrimitiveField = "Hello"
  1687  ArrayField = [1,2,3]
  1688  InterfacePointerField = "World"
  1689  
  1690  [StructField]
  1691  Field1 = 123
  1692  Field2 = "Field2"
  1693  
  1694  [MapField]
  1695  MapField1 = [4,5,6]
  1696  MapField2 = {A = "A"}
  1697  MapField3 = false
  1698  
  1699  [[StructArrayField]]
  1700  Name = "Allen"
  1701  Age = 20
  1702  
  1703  [[StructArrayField]]
  1704  Name = "Jack"
  1705  Age = 23
  1706  `)
  1707  
  1708  	type OuterStruct struct {
  1709  		PrimitiveField        interface{}
  1710  		ArrayField            interface{}
  1711  		StructArrayField      interface{}
  1712  		MapField              map[string]interface{}
  1713  		StructField           interface{}
  1714  		NilField              interface{}
  1715  		InterfacePointerField *interface{}
  1716  	}
  1717  
  1718  	var s interface{} = "World"
  1719  	expected := OuterStruct{
  1720  		PrimitiveField: "Hello",
  1721  		ArrayField:     []interface{}{int64(1), int64(2), int64(3)},
  1722  		StructField: map[string]interface{}{
  1723  			"Field1": int64(123),
  1724  			"Field2": "Field2",
  1725  		},
  1726  		MapField: map[string]interface{}{
  1727  			"MapField1": []interface{}{int64(4), int64(5), int64(6)},
  1728  			"MapField2": map[string]interface{}{
  1729  				"A": "A",
  1730  			},
  1731  			"MapField3": false,
  1732  		},
  1733  		NilField:              nil,
  1734  		InterfacePointerField: &s,
  1735  		StructArrayField: []interface{}{
  1736  			map[string]interface{}{
  1737  				"Name": "Allen",
  1738  				"Age":  int64(20),
  1739  			},
  1740  			map[string]interface{}{
  1741  				"Name": "Jack",
  1742  				"Age":  int64(23),
  1743  			},
  1744  		},
  1745  	}
  1746  	actual := OuterStruct{}
  1747  	err := toml.Unmarshal(doc, &actual)
  1748  	require.NoError(t, err)
  1749  	assert.Equal(t, expected, actual)
  1750  }
  1751  
  1752  func TestUnmarshalToNonNilInterface(t *testing.T) {
  1753  	doc := []byte(`
  1754  PrimitiveField = "Allen"
  1755  ArrayField = [1,2,3]
  1756  
  1757  [StructField]
  1758  InnerField = "After1"
  1759  
  1760  [PointerField]
  1761  InnerField = "After2"
  1762  
  1763  [InterfacePointerField]
  1764  InnerField = "After"
  1765  
  1766  [MapField]
  1767  MapField1 = [4,5,6]
  1768  MapField2 = {A = "A"}
  1769  MapField3 = false
  1770  
  1771  [[StructArrayField]]
  1772  InnerField = "After3"
  1773  
  1774  [[StructArrayField]]
  1775  InnerField = "After4"
  1776  `)
  1777  	type InnerStruct struct {
  1778  		InnerField interface{}
  1779  	}
  1780  
  1781  	type OuterStruct struct {
  1782  		PrimitiveField        interface{}
  1783  		ArrayField            interface{}
  1784  		StructArrayField      interface{}
  1785  		MapField              map[string]interface{}
  1786  		StructField           interface{}
  1787  		PointerField          interface{}
  1788  		NilField              interface{}
  1789  		InterfacePointerField *interface{}
  1790  	}
  1791  
  1792  	var s interface{} = InnerStruct{"After"}
  1793  	expected := OuterStruct{
  1794  		PrimitiveField: "Allen",
  1795  		ArrayField:     []interface{}{int64(1), int64(2), int64(3)},
  1796  		StructField:    map[string]interface{}{"InnerField": "After1"},
  1797  		MapField: map[string]interface{}{
  1798  			"MapField1": []interface{}{int64(4), int64(5), int64(6)},
  1799  			"MapField2": map[string]interface{}{
  1800  				"A": "A",
  1801  			},
  1802  			"MapField3": false,
  1803  		},
  1804  		PointerField:          map[string]interface{}{"InnerField": "After2"},
  1805  		NilField:              nil,
  1806  		InterfacePointerField: &s,
  1807  		StructArrayField: []interface{}{
  1808  			map[string]interface{}{"InnerField": "After3"},
  1809  			map[string]interface{}{"InnerField": "After4"},
  1810  		},
  1811  	}
  1812  	actual := OuterStruct{
  1813  		PrimitiveField: "aaa",
  1814  		ArrayField:     []int{100, 200, 300, 400},
  1815  		StructField:    InnerStruct{InnerField: "Before1"},
  1816  		MapField: map[string]interface{}{
  1817  			"MapField1": []int{4, 5, 6},
  1818  			"MapField2": map[string]string{
  1819  				"B": "BBB",
  1820  			},
  1821  			"MapField3": true,
  1822  		},
  1823  		PointerField:          &InnerStruct{InnerField: "Before2"},
  1824  		NilField:              nil,
  1825  		InterfacePointerField: &s,
  1826  		StructArrayField: []InnerStruct{
  1827  			{InnerField: "Before3"},
  1828  			{InnerField: "Before4"},
  1829  		},
  1830  	}
  1831  
  1832  	err := toml.Unmarshal(doc, &actual)
  1833  	require.NoError(t, err)
  1834  	assert.Equal(t, expected, actual)
  1835  }
  1836  
  1837  func TestUnmarshalNil(t *testing.T) {
  1838  	assert.Error(t, toml.Unmarshal([]byte(`whatever = "whatever"`), nil))
  1839  	assert.Error(t, toml.Unmarshal([]byte(`whatever = "whatever"`), (*struct{})(nil)))
  1840  }
  1841  
  1842  var sliceTomlDemo = []byte(`str_slice = ["Howdy","Hey There"]
  1843  str_slice_ptr= ["Howdy","Hey There"]
  1844  int_slice=[1,2]
  1845  int_slice_ptr=[1,2]
  1846  [[struct_slice]]
  1847  String2="1"
  1848  [[struct_slice]]
  1849  String2="2"
  1850  [[struct_slice_ptr]]
  1851  String2="1"
  1852  [[struct_slice_ptr]]
  1853  String2="2"
  1854  `)
  1855  
  1856  type sliceStruct struct {
  1857  	Slice          []string                     `  toml:"str_slice"  `
  1858  	SlicePtr       *[]string                    `  toml:"str_slice_ptr"  `
  1859  	IntSlice       []int                        `  toml:"int_slice"  `
  1860  	IntSlicePtr    *[]int                       `  toml:"int_slice_ptr"  `
  1861  	StructSlice    []basicMarshalTestSubStruct  `  toml:"struct_slice"  `
  1862  	StructSlicePtr *[]basicMarshalTestSubStruct `  toml:"struct_slice_ptr"  `
  1863  }
  1864  
  1865  type arrayStruct struct {
  1866  	Slice          [4]string                     `  toml:"str_slice"  `
  1867  	SlicePtr       *[4]string                    `  toml:"str_slice_ptr"  `
  1868  	IntSlice       [4]int                        `  toml:"int_slice"  `
  1869  	IntSlicePtr    *[4]int                       `  toml:"int_slice_ptr"  `
  1870  	StructSlice    [4]basicMarshalTestSubStruct  `  toml:"struct_slice"  `
  1871  	StructSlicePtr *[4]basicMarshalTestSubStruct `  toml:"struct_slice_ptr"  `
  1872  }
  1873  
  1874  type arrayTooSmallStruct struct {
  1875  	Slice       [1]string                    `  toml:"str_slice"  `
  1876  	StructSlice [1]basicMarshalTestSubStruct `  toml:"struct_slice"  `
  1877  }
  1878  
  1879  func TestUnmarshalSlice(t *testing.T) {
  1880  	var actual sliceStruct
  1881  	err := toml.Unmarshal(sliceTomlDemo, &actual)
  1882  	require.NoError(t, err)
  1883  	expected := sliceStruct{
  1884  		Slice:          []string{"Howdy", "Hey There"},
  1885  		SlicePtr:       &[]string{"Howdy", "Hey There"},
  1886  		IntSlice:       []int{1, 2},
  1887  		IntSlicePtr:    &[]int{1, 2},
  1888  		StructSlice:    []basicMarshalTestSubStruct{{"1"}, {"2"}},
  1889  		StructSlicePtr: &[]basicMarshalTestSubStruct{{"1"}, {"2"}},
  1890  	}
  1891  	assert.Equal(t, expected, actual)
  1892  }
  1893  
  1894  func TestUnmarshalSliceFail(t *testing.T) {
  1895  	var actual sliceStruct
  1896  	assert.Error(t, toml.Unmarshal([]byte(`str_slice = [1, 2]`), &actual))
  1897  }
  1898  
  1899  func TestUnmarshalSliceFail2(t *testing.T) {
  1900  	doc := `str_slice=[1,2]`
  1901  	var actual sliceStruct
  1902  	assert.Error(t, toml.Unmarshal([]byte(doc), &actual))
  1903  }
  1904  
  1905  func TestUnmarshalMixedTypeSlice(t *testing.T) {
  1906  	type TestStruct struct {
  1907  		ArrayField []interface{}
  1908  	}
  1909  
  1910  	//doc := []byte(`ArrayField = [3.14,100,true,"hello world",{Field = "inner1"},[{Field = "inner2"},{Field = "inner3"}]]
  1911  	//`)
  1912  
  1913  	doc := []byte(`ArrayField = [{Field = "inner1"},[{Field = "inner2"},{Field = "inner3"}]]
  1914  `)
  1915  
  1916  	actual := TestStruct{}
  1917  	expected := TestStruct{
  1918  		ArrayField: []interface{}{
  1919  			//3.14,
  1920  			//int64(100),
  1921  			//true,
  1922  			//"hello world",
  1923  			map[string]interface{}{
  1924  				"Field": "inner1",
  1925  			},
  1926  			[]interface{}{
  1927  				map[string]interface{}{"Field": "inner2"},
  1928  				map[string]interface{}{"Field": "inner3"},
  1929  			},
  1930  		},
  1931  	}
  1932  	err := toml.Unmarshal(doc, &actual)
  1933  	require.NoError(t, err)
  1934  	assert.Equal(t, expected, actual)
  1935  }
  1936  
  1937  func TestUnmarshalArray(t *testing.T) {
  1938  	var err error
  1939  
  1940  	var actual arrayStruct
  1941  	err = toml.Unmarshal(sliceTomlDemo, &actual)
  1942  	require.NoError(t, err)
  1943  
  1944  	expected := arrayStruct{
  1945  		Slice:          [4]string{"Howdy", "Hey There"},
  1946  		SlicePtr:       &[4]string{"Howdy", "Hey There"},
  1947  		IntSlice:       [4]int{1, 2},
  1948  		IntSlicePtr:    &[4]int{1, 2},
  1949  		StructSlice:    [4]basicMarshalTestSubStruct{{"1"}, {"2"}},
  1950  		StructSlicePtr: &[4]basicMarshalTestSubStruct{{"1"}, {"2"}},
  1951  	}
  1952  	assert.Equal(t, expected, actual)
  1953  }
  1954  
  1955  func TestUnmarshalArrayFail3(t *testing.T) {
  1956  	doc := `[[struct_slice]]
  1957  String2="1"
  1958  [[struct_slice]]
  1959  String2="2"`
  1960  
  1961  	var actual arrayTooSmallStruct
  1962  	err := toml.Unmarshal([]byte(doc), &actual)
  1963  	assert.Error(t, err)
  1964  }
  1965  
  1966  func decoder(doc string) *toml.Decoder {
  1967  	return toml.NewDecoder(bytes.NewReader([]byte(doc)))
  1968  }
  1969  
  1970  func strictDecoder(doc string) *toml.Decoder {
  1971  	d := decoder(doc)
  1972  	d.DisallowUnknownFields()
  1973  	return d
  1974  }
  1975  
  1976  func TestDecoderStrict(t *testing.T) {
  1977  	input := `
  1978  	[decoded]
  1979  	 key = ""
  1980  	
  1981  	[undecoded]
  1982  	 key = ""
  1983  	
  1984  	 [undecoded.inner]
  1985  		key = ""
  1986  	
  1987  	 [[undecoded.array]]
  1988  		key = ""
  1989  	
  1990  	 [[undecoded.array]]
  1991  		key = ""
  1992  	
  1993  	`
  1994  	var doc struct {
  1995  		Decoded struct {
  1996  			Key string
  1997  		}
  1998  	}
  1999  
  2000  	err := strictDecoder(input).Decode(&doc)
  2001  	require.Error(t, err)
  2002  	require.IsType(t, &toml.StrictMissingError{}, err)
  2003  	se := err.(*toml.StrictMissingError)
  2004  
  2005  	keys := []toml.Key{}
  2006  
  2007  	for _, e := range se.Errors {
  2008  		keys = append(keys, e.Key())
  2009  	}
  2010  
  2011  	expectedKeys := []toml.Key{
  2012  		{"undecoded"},
  2013  		{"undecoded", "inner"},
  2014  		{"undecoded", "array"},
  2015  		{"undecoded", "array"},
  2016  	}
  2017  
  2018  	require.Equal(t, expectedKeys, keys)
  2019  
  2020  	err = decoder(input).Decode(&doc)
  2021  	require.NoError(t, err)
  2022  
  2023  	var m map[string]interface{}
  2024  	err = decoder(input).Decode(&m)
  2025  }
  2026  
  2027  func TestDecoderStrictValid(t *testing.T) {
  2028  	input := `
  2029  	[decoded]
  2030  	 key = ""
  2031  	`
  2032  	var doc struct {
  2033  		Decoded struct {
  2034  			Key string
  2035  		}
  2036  	}
  2037  
  2038  	err := strictDecoder(input).Decode(&doc)
  2039  	require.NoError(t, err)
  2040  }
  2041  
  2042  type docUnmarshalTOML struct {
  2043  	Decoded struct {
  2044  		Key string
  2045  	}
  2046  }
  2047  
  2048  func (d *docUnmarshalTOML) UnmarshalTOML(i interface{}) error {
  2049  	if iMap, ok := i.(map[string]interface{}); !ok {
  2050  		return fmt.Errorf("type assertion error: wants %T, have %T", map[string]interface{}{}, i)
  2051  	} else if key, ok := iMap["key"]; !ok {
  2052  		return fmt.Errorf("key '%s' not in map", "key")
  2053  	} else if keyString, ok := key.(string); !ok {
  2054  		return fmt.Errorf("type assertion error: wants %T, have %T", "", key)
  2055  	} else {
  2056  		d.Decoded.Key = keyString
  2057  	}
  2058  	return nil
  2059  }
  2060  
  2061  func TestDecoderStrictCustomUnmarshal(t *testing.T) {
  2062  	t.Skip()
  2063  	//input := `key = "ok"`
  2064  	//var doc docUnmarshalTOML
  2065  	//err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
  2066  	//if err != nil {
  2067  	//	t.Fatal("unexpected error:", err)
  2068  	//}
  2069  	//if doc.Decoded.Key != "ok" {
  2070  	//	t.Errorf("Bad unmarshal: expected ok, got %v", doc.Decoded.Key)
  2071  	//}
  2072  }
  2073  
  2074  type parent struct {
  2075  	Doc        docUnmarshalTOML
  2076  	DocPointer *docUnmarshalTOML
  2077  }
  2078  
  2079  func TestCustomUnmarshal(t *testing.T) {
  2080  	t.Skip("not sure if UnmarshalTOML is a good idea")
  2081  	input := `
  2082  [Doc]
  2083      key = "ok1"
  2084  [DocPointer]
  2085      key = "ok2"
  2086  `
  2087  
  2088  	var d parent
  2089  	err := toml.Unmarshal([]byte(input), &d)
  2090  	require.NoError(t, err)
  2091  	assert.Equal(t, "ok1", d.Doc.Decoded.Key)
  2092  	assert.Equal(t, "ok2", d.DocPointer.Decoded.Key)
  2093  }
  2094  
  2095  func TestCustomUnmarshalError(t *testing.T) {
  2096  	t.Skip("not sure if UnmarshalTOML is a good idea")
  2097  
  2098  	input := `
  2099  [Doc]
  2100      key = 1
  2101  [DocPointer]
  2102      key = "ok2"
  2103  `
  2104  
  2105  	expected := "(2, 1): unmarshal toml: type assertion error: wants string, have int64"
  2106  
  2107  	var d parent
  2108  	err := toml.Unmarshal([]byte(input), &d)
  2109  	if err == nil {
  2110  		t.Error("expected error, got none")
  2111  	} else if err.Error() != expected {
  2112  		t.Errorf("expect err: %s, got: %s", expected, err.Error())
  2113  	}
  2114  }
  2115  
  2116  type intWrapper struct {
  2117  	Value int
  2118  }
  2119  
  2120  func (w *intWrapper) UnmarshalText(text []byte) error {
  2121  	var err error
  2122  	if w.Value, err = strconv.Atoi(string(text)); err == nil {
  2123  		return nil
  2124  	}
  2125  	if b, err := strconv.ParseBool(string(text)); err == nil {
  2126  		if b {
  2127  			w.Value = 1
  2128  		}
  2129  		return nil
  2130  	}
  2131  	if f, err := strconv.ParseFloat(string(text), 32); err == nil {
  2132  		w.Value = int(f)
  2133  		return nil
  2134  	}
  2135  	return fmt.Errorf("unsupported: %s", text)
  2136  }
  2137  
  2138  func TestTextUnmarshal(t *testing.T) {
  2139  	var doc struct {
  2140  		UnixTime intWrapper
  2141  		Version  *intWrapper
  2142  
  2143  		Bool  intWrapper
  2144  		Int   intWrapper
  2145  		Float intWrapper
  2146  	}
  2147  
  2148  	input := `
  2149  UnixTime = "12"
  2150  Version = "42"
  2151  Bool = true
  2152  Int = 21
  2153  Float = 2.0
  2154  `
  2155  	err := toml.Unmarshal([]byte(input), &doc)
  2156  	require.NoError(t, err)
  2157  	assert.Equal(t, 12, doc.UnixTime.Value)
  2158  	assert.Equal(t, 42, doc.Version.Value)
  2159  	assert.Equal(t, 1, doc.Bool.Value)
  2160  	assert.Equal(t, 21, doc.Int.Value)
  2161  	assert.Equal(t, 2, doc.Float.Value)
  2162  }
  2163  
  2164  func TestTextUnmarshalError(t *testing.T) {
  2165  	var doc struct {
  2166  		Failer intWrapper
  2167  	}
  2168  
  2169  	input := `Failer = "hello"`
  2170  	if err := toml.Unmarshal([]byte(input), &doc); err == nil {
  2171  		t.Fatalf("expected err, got none")
  2172  	}
  2173  }
  2174  
  2175  // issue406
  2176  func TestPreserveNotEmptyField(t *testing.T) {
  2177  	doc := []byte(`Field1 = "ccc"`)
  2178  	type Inner struct {
  2179  		InnerField1 string
  2180  		InnerField2 int
  2181  	}
  2182  	type TestStruct struct {
  2183  		Field1 string
  2184  		Field2 int
  2185  		Field3 Inner
  2186  	}
  2187  
  2188  	actual := TestStruct{
  2189  		"aaa",
  2190  		100,
  2191  		Inner{
  2192  			"bbb",
  2193  			200,
  2194  		},
  2195  	}
  2196  
  2197  	expected := TestStruct{
  2198  		"ccc",
  2199  		100,
  2200  		Inner{
  2201  			"bbb",
  2202  			200,
  2203  		},
  2204  	}
  2205  
  2206  	err := toml.Unmarshal(doc, &actual)
  2207  	if err != nil {
  2208  		t.Fatal(err)
  2209  	}
  2210  
  2211  	if !reflect.DeepEqual(actual, expected) {
  2212  		t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
  2213  	}
  2214  }
  2215  
  2216  // github issue 432
  2217  func TestUnmarshalEmptyInterface(t *testing.T) {
  2218  	doc := []byte(`User = "pelletier"`)
  2219  
  2220  	var v interface{}
  2221  
  2222  	err := toml.Unmarshal(doc, &v)
  2223  	if err != nil {
  2224  		t.Fatal(err)
  2225  	}
  2226  	require.IsType(t, map[string]interface{}{}, v)
  2227  
  2228  	x := v.(map[string]interface{})
  2229  	assert.Equal(t, "pelletier", x["User"])
  2230  }
  2231  
  2232  func TestUnmarshalEmptyInterfaceDeep(t *testing.T) {
  2233  	t.Skipf("TODO")
  2234  	doc := []byte(`
  2235  User = "pelletier"
  2236  Age = 99
  2237  
  2238  [foo]
  2239  bar = 42
  2240  `)
  2241  
  2242  	var v interface{}
  2243  
  2244  	err := toml.Unmarshal(doc, &v)
  2245  	if err != nil {
  2246  		t.Fatal(err)
  2247  	}
  2248  
  2249  	x, ok := v.(map[string]interface{})
  2250  	if !ok {
  2251  		t.Fatal(err)
  2252  	}
  2253  
  2254  	expected := map[string]interface{}{
  2255  		"User": "pelletier",
  2256  		"Age":  99,
  2257  		"foo": map[string]interface{}{
  2258  			"bar": 42,
  2259  		},
  2260  	}
  2261  
  2262  	reflect.DeepEqual(x, expected)
  2263  }
  2264  
  2265  type Config struct {
  2266  	Key string `toml:"key"`
  2267  	Obj Custom `toml:"obj"`
  2268  }
  2269  
  2270  type Custom struct {
  2271  	v string
  2272  }
  2273  
  2274  func (c *Custom) UnmarshalTOML(v interface{}) error {
  2275  	c.v = "called"
  2276  	return nil
  2277  }
  2278  
  2279  func TestGithubIssue431(t *testing.T) {
  2280  	doc := `key = "value"`
  2281  	var c Config
  2282  	if err := toml.Unmarshal([]byte(doc), &c); err != nil {
  2283  		t.Fatalf("unexpected error: %s", err)
  2284  	}
  2285  
  2286  	if c.Key != "value" {
  2287  		t.Errorf("expected c.Key='value', not '%s'", c.Key)
  2288  	}
  2289  
  2290  	if c.Obj.v == "called" {
  2291  		t.Errorf("UnmarshalTOML should not have been called")
  2292  	}
  2293  }
  2294  
  2295  type durationString struct {
  2296  	time.Duration
  2297  }
  2298  
  2299  func (d *durationString) UnmarshalTOML(v interface{}) error {
  2300  	d.Duration = 10 * time.Second
  2301  	return nil
  2302  }
  2303  
  2304  type config437Error struct{}
  2305  
  2306  func (e *config437Error) UnmarshalTOML(v interface{}) error {
  2307  	return errors.New("expected")
  2308  }
  2309  
  2310  type config437 struct {
  2311  	HTTP struct {
  2312  		PingTimeout durationString `toml:"PingTimeout"`
  2313  		ErrorField  config437Error
  2314  	} `toml:"HTTP"`
  2315  }
  2316  
  2317  func TestGithubIssue437(t *testing.T) {
  2318  	t.Skipf("unmarshalTOML not implemented")
  2319  	src := `
  2320  [HTTP]
  2321  PingTimeout = "32m"
  2322  `
  2323  	cfg := &config437{}
  2324  	cfg.HTTP.PingTimeout = durationString{time.Second}
  2325  
  2326  	err := toml.Unmarshal([]byte(src), cfg)
  2327  	if err != nil {
  2328  		t.Fatalf("unexpected errors %s", err)
  2329  	}
  2330  	expected := durationString{10 * time.Second}
  2331  	if cfg.HTTP.PingTimeout != expected {
  2332  		t.Fatalf("expected '%s', got '%s'", expected, cfg.HTTP.PingTimeout)
  2333  	}
  2334  }
  2335  
  2336  func TestLeafUnmarshalerError(t *testing.T) {
  2337  	src := `
  2338  [HTTP]
  2339  ErrorField = "foo"
  2340  `
  2341  	cfg := &config437{}
  2342  
  2343  	err := toml.Unmarshal([]byte(src), cfg)
  2344  	if err == nil {
  2345  		t.Fatalf("error was expected")
  2346  	}
  2347  }
  2348  

View as plain text