...

Source file src/github.com/pelletier/go-toml/v2/unmarshaler_test.go

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

     1  package toml_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"math"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/pelletier/go-toml/v2"
    15  	"github.com/pelletier/go-toml/v2/unstable"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  type unmarshalTextKey struct {
    21  	A string
    22  	B string
    23  }
    24  
    25  func (k *unmarshalTextKey) UnmarshalText(text []byte) error {
    26  	parts := strings.Split(string(text), "-")
    27  	if len(parts) != 2 {
    28  		return fmt.Errorf("invalid text key: %s", text)
    29  	}
    30  	k.A = parts[0]
    31  	k.B = parts[1]
    32  	return nil
    33  }
    34  
    35  type unmarshalBadTextKey struct{}
    36  
    37  func (k *unmarshalBadTextKey) UnmarshalText(text []byte) error {
    38  	return fmt.Errorf("error")
    39  }
    40  
    41  func ExampleDecoder_DisallowUnknownFields() {
    42  	type S struct {
    43  		Key1 string
    44  		Key3 string
    45  	}
    46  	doc := `
    47  key1 = "value1"
    48  key2 = "value2"
    49  key3 = "value3"
    50  `
    51  	r := strings.NewReader(doc)
    52  	d := toml.NewDecoder(r)
    53  	d.DisallowUnknownFields()
    54  	s := S{}
    55  	err := d.Decode(&s)
    56  
    57  	fmt.Println(err.Error())
    58  
    59  	var details *toml.StrictMissingError
    60  	if !errors.As(err, &details) {
    61  		panic(fmt.Sprintf("err should have been a *toml.StrictMissingError, but got %s (%T)", err, err))
    62  	}
    63  
    64  	fmt.Println(details.String())
    65  	// Output:
    66  	// strict mode: fields in the document are missing in the target struct
    67  	// 2| key1 = "value1"
    68  	// 3| key2 = "value2"
    69  	//  | ~~~~ missing field
    70  	// 4| key3 = "value3"
    71  }
    72  
    73  func ExampleUnmarshal() {
    74  	type MyConfig struct {
    75  		Version int
    76  		Name    string
    77  		Tags    []string
    78  	}
    79  
    80  	doc := `
    81  	version = 2
    82  	name = "go-toml"
    83  	tags = ["go", "toml"]
    84  	`
    85  
    86  	var cfg MyConfig
    87  	err := toml.Unmarshal([]byte(doc), &cfg)
    88  	if err != nil {
    89  		panic(err)
    90  	}
    91  	fmt.Println("version:", cfg.Version)
    92  	fmt.Println("name:", cfg.Name)
    93  	fmt.Println("tags:", cfg.Tags)
    94  	// Output:
    95  	// version: 2
    96  	// name: go-toml
    97  	// tags: [go toml]
    98  }
    99  
   100  type badReader struct{}
   101  
   102  func (r *badReader) Read([]byte) (int, error) {
   103  	return 0, fmt.Errorf("testing error")
   104  }
   105  
   106  func TestDecodeReaderError(t *testing.T) {
   107  	r := &badReader{}
   108  
   109  	dec := toml.NewDecoder(r)
   110  	m := map[string]interface{}{}
   111  	err := dec.Decode(&m)
   112  	require.Error(t, err)
   113  }
   114  
   115  // nolint:funlen
   116  func TestUnmarshal_Integers(t *testing.T) {
   117  	examples := []struct {
   118  		desc     string
   119  		input    string
   120  		expected int64
   121  		err      bool
   122  	}{
   123  		{
   124  			desc:     "integer just digits",
   125  			input:    `1234`,
   126  			expected: 1234,
   127  		},
   128  		{
   129  			desc:     "integer zero",
   130  			input:    `0`,
   131  			expected: 0,
   132  		},
   133  		{
   134  			desc:     "integer sign",
   135  			input:    `+99`,
   136  			expected: 99,
   137  		},
   138  		{
   139  			desc:     "integer decimal underscore",
   140  			input:    `123_456`,
   141  			expected: 123456,
   142  		},
   143  		{
   144  			desc:     "integer hex uppercase",
   145  			input:    `0xDEADBEEF`,
   146  			expected: 0xDEADBEEF,
   147  		},
   148  		{
   149  			desc:     "integer hex lowercase",
   150  			input:    `0xdead_beef`,
   151  			expected: 0xDEADBEEF,
   152  		},
   153  		{
   154  			desc:     "integer octal",
   155  			input:    `0o01234567`,
   156  			expected: 0o01234567,
   157  		},
   158  		{
   159  			desc:     "integer binary",
   160  			input:    `0b11010110`,
   161  			expected: 0b11010110,
   162  		},
   163  		{
   164  			desc:  "double underscore",
   165  			input: "12__3",
   166  			err:   true,
   167  		},
   168  		{
   169  			desc:  "starts with underscore",
   170  			input: "_1",
   171  			err:   true,
   172  		},
   173  		{
   174  			desc:  "ends with underscore",
   175  			input: "1_",
   176  			err:   true,
   177  		},
   178  	}
   179  
   180  	type doc struct {
   181  		A int64
   182  	}
   183  
   184  	for _, e := range examples {
   185  		e := e
   186  		t.Run(e.desc, func(t *testing.T) {
   187  			doc := doc{}
   188  			err := toml.Unmarshal([]byte(`A = `+e.input), &doc)
   189  			if e.err {
   190  				require.Error(t, err)
   191  			} else {
   192  				require.NoError(t, err)
   193  				assert.Equal(t, e.expected, doc.A)
   194  			}
   195  		})
   196  	}
   197  }
   198  
   199  //nolint:funlen
   200  func TestUnmarshal_Floats(t *testing.T) {
   201  	examples := []struct {
   202  		desc     string
   203  		input    string
   204  		expected float64
   205  		testFn   func(t *testing.T, v float64)
   206  		err      bool
   207  	}{
   208  
   209  		{
   210  			desc:     "float pi",
   211  			input:    `3.1415`,
   212  			expected: 3.1415,
   213  		},
   214  		{
   215  			desc:     "float negative",
   216  			input:    `-0.01`,
   217  			expected: -0.01,
   218  		},
   219  		{
   220  			desc:     "float signed exponent",
   221  			input:    `5e+22`,
   222  			expected: 5e+22,
   223  		},
   224  		{
   225  			desc:     "float exponent lowercase",
   226  			input:    `1e06`,
   227  			expected: 1e06,
   228  		},
   229  		{
   230  			desc:     "float exponent uppercase",
   231  			input:    `-2E-2`,
   232  			expected: -2e-2,
   233  		},
   234  		{
   235  			desc:     "float exponent zero",
   236  			input:    `0e0`,
   237  			expected: 0.0,
   238  		},
   239  		{
   240  			desc:     "float upper exponent zero",
   241  			input:    `0E0`,
   242  			expected: 0.0,
   243  		},
   244  		{
   245  			desc:     "float zero without decimals",
   246  			input:    `0`,
   247  			expected: 0.0,
   248  		},
   249  		{
   250  			desc:     "float fractional with exponent",
   251  			input:    `6.626e-34`,
   252  			expected: 6.626e-34,
   253  		},
   254  		{
   255  			desc:     "float underscores",
   256  			input:    `224_617.445_991_228`,
   257  			expected: 224_617.445_991_228,
   258  		},
   259  		{
   260  			desc:     "inf",
   261  			input:    `inf`,
   262  			expected: math.Inf(+1),
   263  		},
   264  		{
   265  			desc:     "inf negative",
   266  			input:    `-inf`,
   267  			expected: math.Inf(-1),
   268  		},
   269  		{
   270  			desc:     "inf positive",
   271  			input:    `+inf`,
   272  			expected: math.Inf(+1),
   273  		},
   274  		{
   275  			desc:  "nan",
   276  			input: `nan`,
   277  			testFn: func(t *testing.T, v float64) {
   278  				t.Helper()
   279  				assert.True(t, math.IsNaN(v))
   280  			},
   281  		},
   282  		{
   283  			desc:  "nan negative",
   284  			input: `-nan`,
   285  			testFn: func(t *testing.T, v float64) {
   286  				t.Helper()
   287  				assert.True(t, math.IsNaN(v))
   288  			},
   289  		},
   290  		{
   291  			desc:  "nan positive",
   292  			input: `+nan`,
   293  			testFn: func(t *testing.T, v float64) {
   294  				t.Helper()
   295  				assert.True(t, math.IsNaN(v))
   296  			},
   297  		},
   298  		{
   299  			desc:  "underscore after integer part",
   300  			input: `1_e2`,
   301  			err:   true,
   302  		},
   303  		{
   304  			desc:  "underscore after integer part",
   305  			input: `1.0_e2`,
   306  			err:   true,
   307  		},
   308  		{
   309  			desc:  "leading zero in positive float",
   310  			input: `+0_0.0`,
   311  			err:   true,
   312  		},
   313  	}
   314  
   315  	type doc struct {
   316  		A float64
   317  	}
   318  
   319  	for _, e := range examples {
   320  		e := e
   321  		t.Run(e.desc, func(t *testing.T) {
   322  			doc := doc{}
   323  			err := toml.Unmarshal([]byte(`A = `+e.input), &doc)
   324  			if e.err {
   325  				require.Error(t, err)
   326  			} else {
   327  				require.NoError(t, err)
   328  				if e.testFn != nil {
   329  					e.testFn(t, doc.A)
   330  				} else {
   331  					assert.Equal(t, e.expected, doc.A)
   332  				}
   333  			}
   334  		})
   335  	}
   336  }
   337  
   338  //nolint:funlen
   339  func TestUnmarshal(t *testing.T) {
   340  	type test struct {
   341  		target   interface{}
   342  		expected interface{}
   343  		err      bool
   344  		assert   func(t *testing.T, test test)
   345  	}
   346  	examples := []struct {
   347  		skip  bool
   348  		desc  string
   349  		input string
   350  		gen   func() test
   351  	}{
   352  		{
   353  			desc:  "kv string",
   354  			input: `A = "foo"`,
   355  			gen: func() test {
   356  				type doc struct {
   357  					A string
   358  				}
   359  
   360  				return test{
   361  					target:   &doc{},
   362  					expected: &doc{A: "foo"},
   363  				}
   364  			},
   365  		},
   366  		{
   367  			desc:  "kv literal string",
   368  			input: `A = 'foo 🙂 '`,
   369  			gen: func() test {
   370  				type doc struct {
   371  					A string
   372  				}
   373  
   374  				return test{
   375  					target:   &doc{},
   376  					expected: &doc{A: "foo 🙂 "},
   377  				}
   378  			},
   379  		},
   380  		{
   381  			desc:  "kv text key",
   382  			input: `a-1 = "foo"`,
   383  			gen: func() test {
   384  				type doc = map[unmarshalTextKey]string
   385  
   386  				return test{
   387  					target:   &doc{},
   388  					expected: &doc{{A: "a", B: "1"}: "foo"},
   389  				}
   390  			},
   391  		},
   392  		{
   393  			desc: "table text key",
   394  			input: `["a-1"]
   395  foo = "bar"`,
   396  			gen: func() test {
   397  				type doc = map[unmarshalTextKey]map[string]string
   398  
   399  				return test{
   400  					target:   &doc{},
   401  					expected: &doc{{A: "a", B: "1"}: map[string]string{"foo": "bar"}},
   402  				}
   403  			},
   404  		},
   405  		{
   406  			desc:  "kv ptr text key",
   407  			input: `a-1 = "foo"`,
   408  			gen: func() test {
   409  				type doc = map[*unmarshalTextKey]string
   410  
   411  				return test{
   412  					target:   &doc{},
   413  					expected: &doc{{A: "a", B: "1"}: "foo"},
   414  					assert: func(t *testing.T, test test) {
   415  						// Despite the documentation:
   416  						//     Pointer variable equality is determined based on the equality of the
   417  						// 		 referenced values (as opposed to the memory addresses).
   418  						// assert.Equal does not work properly with maps with pointer keys
   419  						// https://github.com/stretchr/testify/issues/1143
   420  						expected := make(map[unmarshalTextKey]string)
   421  						for k, v := range *(test.expected.(*doc)) {
   422  							expected[*k] = v
   423  						}
   424  						got := make(map[unmarshalTextKey]string)
   425  						for k, v := range *(test.target.(*doc)) {
   426  							got[*k] = v
   427  						}
   428  						assert.Equal(t, expected, got)
   429  					},
   430  				}
   431  			},
   432  		},
   433  		{
   434  			desc:  "kv bad text key",
   435  			input: `a-1 = "foo"`,
   436  			gen: func() test {
   437  				type doc = map[unmarshalBadTextKey]string
   438  
   439  				return test{
   440  					target: &doc{},
   441  					err:    true,
   442  				}
   443  			},
   444  		},
   445  		{
   446  			desc:  "kv bad ptr text key",
   447  			input: `a-1 = "foo"`,
   448  			gen: func() test {
   449  				type doc = map[*unmarshalBadTextKey]string
   450  
   451  				return test{
   452  					target: &doc{},
   453  					err:    true,
   454  				}
   455  			},
   456  		},
   457  		{
   458  			desc: "table bad text key",
   459  			input: `["a-1"]
   460  foo = "bar"`,
   461  			gen: func() test {
   462  				type doc = map[unmarshalBadTextKey]map[string]string
   463  
   464  				return test{
   465  					target: &doc{},
   466  					err:    true,
   467  				}
   468  			},
   469  		},
   470  		{
   471  			desc:  "time.time with negative zone",
   472  			input: `a = 1979-05-27T00:32:00-07:00 `, // space intentional
   473  			gen: func() test {
   474  				var v map[string]time.Time
   475  
   476  				return test{
   477  					target: &v,
   478  					expected: &map[string]time.Time{
   479  						"a": time.Date(1979, 5, 27, 0, 32, 0, 0, time.FixedZone("", -7*3600)),
   480  					},
   481  				}
   482  			},
   483  		},
   484  		{
   485  			desc:  "time.time with positive zone",
   486  			input: `a = 1979-05-27T00:32:00+07:00`,
   487  			gen: func() test {
   488  				var v map[string]time.Time
   489  
   490  				return test{
   491  					target: &v,
   492  					expected: &map[string]time.Time{
   493  						"a": time.Date(1979, 5, 27, 0, 32, 0, 0, time.FixedZone("", 7*3600)),
   494  					},
   495  				}
   496  			},
   497  		},
   498  		{
   499  			desc:  "time.time with zone and fractional",
   500  			input: `a = 1979-05-27T00:32:00.999999-07:00`,
   501  			gen: func() test {
   502  				var v map[string]time.Time
   503  
   504  				return test{
   505  					target: &v,
   506  					expected: &map[string]time.Time{
   507  						"a": time.Date(1979, 5, 27, 0, 32, 0, 999999000, time.FixedZone("", -7*3600)),
   508  					},
   509  				}
   510  			},
   511  		},
   512  		{
   513  			desc:  "local datetime into time.Time",
   514  			input: `a = 1979-05-27T00:32:00`,
   515  			gen: func() test {
   516  				type doc struct {
   517  					A time.Time
   518  				}
   519  
   520  				return test{
   521  					target: &doc{},
   522  					expected: &doc{
   523  						A: time.Date(1979, 5, 27, 0, 32, 0, 0, time.Local),
   524  					},
   525  				}
   526  			},
   527  		},
   528  		{
   529  			desc:  "local datetime into interface",
   530  			input: `a = 1979-05-27T00:32:00`,
   531  			gen: func() test {
   532  				type doc struct {
   533  					A interface{}
   534  				}
   535  
   536  				return test{
   537  					target: &doc{},
   538  					expected: &doc{
   539  						A: toml.LocalDateTime{
   540  							toml.LocalDate{1979, 5, 27},
   541  							toml.LocalTime{0, 32, 0, 0, 0},
   542  						},
   543  					},
   544  				}
   545  			},
   546  		},
   547  		{
   548  			desc:  "local date into interface",
   549  			input: `a = 1979-05-27`,
   550  			gen: func() test {
   551  				type doc struct {
   552  					A interface{}
   553  				}
   554  
   555  				return test{
   556  					target: &doc{},
   557  					expected: &doc{
   558  						A: toml.LocalDate{1979, 5, 27},
   559  					},
   560  				}
   561  			},
   562  		},
   563  		{
   564  			desc:  "local leap-day date into interface",
   565  			input: `a = 2020-02-29`,
   566  			gen: func() test {
   567  				type doc struct {
   568  					A interface{}
   569  				}
   570  
   571  				return test{
   572  					target: &doc{},
   573  					expected: &doc{
   574  						A: toml.LocalDate{2020, 2, 29},
   575  					},
   576  				}
   577  			},
   578  		},
   579  		{
   580  			desc:  "local-time with nano second",
   581  			input: `a = 12:08:05.666666666`,
   582  			gen: func() test {
   583  				var v map[string]interface{}
   584  
   585  				return test{
   586  					target: &v,
   587  					expected: &map[string]interface{}{
   588  						"a": toml.LocalTime{Hour: 12, Minute: 8, Second: 5, Nanosecond: 666666666, Precision: 9},
   589  					},
   590  				}
   591  			},
   592  		},
   593  		{
   594  			desc:  "local-time",
   595  			input: `a = 12:08:05`,
   596  			gen: func() test {
   597  				var v map[string]interface{}
   598  
   599  				return test{
   600  					target: &v,
   601  					expected: &map[string]interface{}{
   602  						"a": toml.LocalTime{Hour: 12, Minute: 8, Second: 5},
   603  					},
   604  				}
   605  			},
   606  		},
   607  		{
   608  			desc:  "local-time missing digit",
   609  			input: `a = 12:08:0`,
   610  			gen: func() test {
   611  				var v map[string]interface{}
   612  
   613  				return test{
   614  					target: &v,
   615  					err:    true,
   616  				}
   617  			},
   618  		},
   619  		{
   620  			desc:  "local-time extra digit",
   621  			input: `a = 12:08:000`,
   622  			gen: func() test {
   623  				var v map[string]interface{}
   624  
   625  				return test{
   626  					target: &v,
   627  					err:    true,
   628  				}
   629  			},
   630  		},
   631  		{
   632  			desc: "issue 475 - space between dots in key",
   633  			input: `fruit. color = "yellow"
   634  					fruit . flavor = "banana"`,
   635  			gen: func() test {
   636  				m := map[string]interface{}{}
   637  
   638  				return test{
   639  					target: &m,
   640  					expected: &map[string]interface{}{
   641  						"fruit": map[string]interface{}{
   642  							"color":  "yellow",
   643  							"flavor": "banana",
   644  						},
   645  					},
   646  				}
   647  			},
   648  		},
   649  		{
   650  			desc: "issue 427 - quotation marks in key",
   651  			input: `'"a"' = 1
   652  					"\"b\"" = 2`,
   653  			gen: func() test {
   654  				m := map[string]interface{}{}
   655  
   656  				return test{
   657  					target: &m,
   658  					expected: &map[string]interface{}{
   659  						`"a"`: int64(1),
   660  						`"b"`: int64(2),
   661  					},
   662  				}
   663  			},
   664  		},
   665  		{
   666  			desc: "issue 739 - table redefinition",
   667  			input: `
   668  [foo.bar.baz]
   669  wibble = 'wobble'
   670  
   671  [foo]
   672  
   673  [foo.bar]
   674  huey = 'dewey'
   675  			`,
   676  			gen: func() test {
   677  				m := map[string]interface{}{}
   678  
   679  				return test{
   680  					target: &m,
   681  					expected: &map[string]interface{}{
   682  						`foo`: map[string]interface{}{
   683  							"bar": map[string]interface{}{
   684  								"huey": "dewey",
   685  								"baz": map[string]interface{}{
   686  									"wibble": "wobble",
   687  								},
   688  							},
   689  						},
   690  					},
   691  				}
   692  			},
   693  		},
   694  		{
   695  			desc: "multiline basic string",
   696  			input: `A = """\
   697  					Test"""`,
   698  			gen: func() test {
   699  				type doc struct {
   700  					A string
   701  				}
   702  
   703  				return test{
   704  					target:   &doc{},
   705  					expected: &doc{A: "Test"},
   706  				}
   707  			},
   708  		},
   709  		{
   710  			desc:  "multiline literal string with windows newline",
   711  			input: "A = '''\r\nTest'''",
   712  			gen: func() test {
   713  				type doc struct {
   714  					A string
   715  				}
   716  
   717  				return test{
   718  					target:   &doc{},
   719  					expected: &doc{A: "Test"},
   720  				}
   721  			},
   722  		},
   723  		{
   724  			desc:  "multiline basic string with windows newline",
   725  			input: "A = \"\"\"\r\nTe\r\nst\"\"\"",
   726  			gen: func() test {
   727  				type doc struct {
   728  					A string
   729  				}
   730  
   731  				return test{
   732  					target:   &doc{},
   733  					expected: &doc{A: "Te\r\nst"},
   734  				}
   735  			},
   736  		},
   737  		{
   738  			desc: "multiline basic string escapes",
   739  			input: `A = """
   740  \\\b\f\n\r\t\uffff\U0001D11E"""`,
   741  			gen: func() test {
   742  				type doc struct {
   743  					A string
   744  				}
   745  
   746  				return test{
   747  					target:   &doc{},
   748  					expected: &doc{A: "\\\b\f\n\r\t\uffff\U0001D11E"},
   749  				}
   750  			},
   751  		},
   752  		{
   753  			desc:  "basic string escapes",
   754  			input: `A = "\\\b\f\n\r\t\uffff\U0001D11E"`,
   755  			gen: func() test {
   756  				type doc struct {
   757  					A string
   758  				}
   759  
   760  				return test{
   761  					target:   &doc{},
   762  					expected: &doc{A: "\\\b\f\n\r\t\uffff\U0001D11E"},
   763  				}
   764  			},
   765  		},
   766  		{
   767  			desc:  "spaces around dotted keys",
   768  			input: "a . b = 1",
   769  			gen: func() test {
   770  				return test{
   771  					target:   &map[string]map[string]interface{}{},
   772  					expected: &map[string]map[string]interface{}{"a": {"b": int64(1)}},
   773  				}
   774  			},
   775  		},
   776  		{
   777  			desc:  "kv bool true",
   778  			input: `A = true`,
   779  			gen: func() test {
   780  				type doc struct {
   781  					A bool
   782  				}
   783  
   784  				return test{
   785  					target:   &doc{},
   786  					expected: &doc{A: true},
   787  				}
   788  			},
   789  		},
   790  		{
   791  			desc:  "kv bool false",
   792  			input: `A = false`,
   793  			gen: func() test {
   794  				type doc struct {
   795  					A bool
   796  				}
   797  
   798  				return test{
   799  					target:   &doc{A: true},
   800  					expected: &doc{A: false},
   801  				}
   802  			},
   803  		},
   804  		{
   805  			desc:  "string array",
   806  			input: `A = ["foo", "bar"]`,
   807  			gen: func() test {
   808  				type doc struct {
   809  					A []string
   810  				}
   811  
   812  				return test{
   813  					target:   &doc{},
   814  					expected: &doc{A: []string{"foo", "bar"}},
   815  				}
   816  			},
   817  		},
   818  		{
   819  			desc:  "long string array into []string",
   820  			input: `A = ["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17"]`,
   821  			gen: func() test {
   822  				type doc struct {
   823  					A []string
   824  				}
   825  
   826  				return test{
   827  					target:   &doc{},
   828  					expected: &doc{A: []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17"}},
   829  				}
   830  			},
   831  		},
   832  		{
   833  			desc: "long string array into []interface{}",
   834  			input: `A = ["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14",
   835  "15","16","17"]`,
   836  			gen: func() test {
   837  				type doc struct {
   838  					A []interface{}
   839  				}
   840  
   841  				return test{
   842  					target: &doc{},
   843  					expected: &doc{A: []interface{}{"0", "1", "2", "3", "4", "5", "6",
   844  						"7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17"}},
   845  				}
   846  			},
   847  		},
   848  		{
   849  			desc: "standard table",
   850  			input: `[A]
   851  B = "data"`,
   852  			gen: func() test {
   853  				type A struct {
   854  					B string
   855  				}
   856  				type doc struct {
   857  					A A
   858  				}
   859  
   860  				return test{
   861  					target:   &doc{},
   862  					expected: &doc{A: A{B: "data"}},
   863  				}
   864  			},
   865  		},
   866  		{
   867  			desc:  "standard empty table",
   868  			input: `[A]`,
   869  			gen: func() test {
   870  				var v map[string]interface{}
   871  
   872  				return test{
   873  					target:   &v,
   874  					expected: &map[string]interface{}{`A`: map[string]interface{}{}},
   875  				}
   876  			},
   877  		},
   878  		{
   879  			desc:  "inline table",
   880  			input: `Name = {First = "hello", Last = "world"}`,
   881  			gen: func() test {
   882  				type name struct {
   883  					First string
   884  					Last  string
   885  				}
   886  				type doc struct {
   887  					Name name
   888  				}
   889  
   890  				return test{
   891  					target: &doc{},
   892  					expected: &doc{Name: name{
   893  						First: "hello",
   894  						Last:  "world",
   895  					}},
   896  				}
   897  			},
   898  		},
   899  		{
   900  			desc:  "inline empty table",
   901  			input: `A = {}`,
   902  			gen: func() test {
   903  				var v map[string]interface{}
   904  
   905  				return test{
   906  					target:   &v,
   907  					expected: &map[string]interface{}{`A`: map[string]interface{}{}},
   908  				}
   909  			},
   910  		},
   911  		{
   912  			desc:  "inline table inside array",
   913  			input: `Names = [{First = "hello", Last = "world"}, {First = "ab", Last = "cd"}]`,
   914  			gen: func() test {
   915  				type name struct {
   916  					First string
   917  					Last  string
   918  				}
   919  				type doc struct {
   920  					Names []name
   921  				}
   922  
   923  				return test{
   924  					target: &doc{},
   925  					expected: &doc{
   926  						Names: []name{
   927  							{
   928  								First: "hello",
   929  								Last:  "world",
   930  							},
   931  							{
   932  								First: "ab",
   933  								Last:  "cd",
   934  							},
   935  						},
   936  					},
   937  				}
   938  			},
   939  		},
   940  		{
   941  			desc:  "into map[string]interface{}",
   942  			input: `A = "foo"`,
   943  			gen: func() test {
   944  				doc := map[string]interface{}{}
   945  
   946  				return test{
   947  					target: &doc,
   948  					expected: &map[string]interface{}{
   949  						"A": "foo",
   950  					},
   951  				}
   952  			},
   953  		},
   954  		{
   955  			desc: "multi keys of different types into map[string]interface{}",
   956  			input: `A = "foo"
   957  					B = 42`,
   958  			gen: func() test {
   959  				doc := map[string]interface{}{}
   960  
   961  				return test{
   962  					target: &doc,
   963  					expected: &map[string]interface{}{
   964  						"A": "foo",
   965  						"B": int64(42),
   966  					},
   967  				}
   968  			},
   969  		},
   970  		{
   971  			desc:  "slice in a map[string]interface{}",
   972  			input: `A = ["foo", "bar"]`,
   973  			gen: func() test {
   974  				doc := map[string]interface{}{}
   975  
   976  				return test{
   977  					target: &doc,
   978  					expected: &map[string]interface{}{
   979  						"A": []interface{}{"foo", "bar"},
   980  					},
   981  				}
   982  			},
   983  		},
   984  		{
   985  			desc:  "string into map[string]string",
   986  			input: `A = "foo"`,
   987  			gen: func() test {
   988  				doc := map[string]string{}
   989  
   990  				return test{
   991  					target: &doc,
   992  					expected: &map[string]string{
   993  						"A": "foo",
   994  					},
   995  				}
   996  			},
   997  		},
   998  		{
   999  			desc:  "float64 into map[string]string",
  1000  			input: `A = 42.0`,
  1001  			gen: func() test {
  1002  				doc := map[string]string{}
  1003  
  1004  				return test{
  1005  					target: &doc,
  1006  					err:    true,
  1007  				}
  1008  			},
  1009  		},
  1010  		{
  1011  			desc: "one-level one-element array table",
  1012  			input: `[[First]]
  1013  					Second = "hello"`,
  1014  			gen: func() test {
  1015  				type First struct {
  1016  					Second string
  1017  				}
  1018  				type Doc struct {
  1019  					First []First
  1020  				}
  1021  
  1022  				return test{
  1023  					target: &Doc{},
  1024  					expected: &Doc{
  1025  						First: []First{
  1026  							{
  1027  								Second: "hello",
  1028  							},
  1029  						},
  1030  					},
  1031  				}
  1032  			},
  1033  		},
  1034  		{
  1035  			desc: "one-level multi-element array table",
  1036  			input: `[[Products]]
  1037  					Name = "Hammer"
  1038  					Sku = 738594937
  1039  
  1040  					[[Products]]  # empty table within the array
  1041  
  1042  					[[Products]]
  1043  					Name = "Nail"
  1044  					Sku = 284758393
  1045  
  1046  					Color = "gray"`,
  1047  			gen: func() test {
  1048  				type Product struct {
  1049  					Name  string
  1050  					Sku   int64
  1051  					Color string
  1052  				}
  1053  				type Doc struct {
  1054  					Products []Product
  1055  				}
  1056  
  1057  				return test{
  1058  					target: &Doc{},
  1059  					expected: &Doc{
  1060  						Products: []Product{
  1061  							{Name: "Hammer", Sku: 738594937},
  1062  							{},
  1063  							{Name: "Nail", Sku: 284758393, Color: "gray"},
  1064  						},
  1065  					},
  1066  				}
  1067  			},
  1068  		},
  1069  		{
  1070  			desc: "one-level multi-element array table to map",
  1071  			input: `[[Products]]
  1072  					Name = "Hammer"
  1073  					Sku = 738594937
  1074  
  1075  					[[Products]]  # empty table within the array
  1076  
  1077  					[[Products]]
  1078  					Name = "Nail"
  1079  					Sku = 284758393
  1080  
  1081  					Color = "gray"`,
  1082  			gen: func() test {
  1083  				return test{
  1084  					target: &map[string]interface{}{},
  1085  					expected: &map[string]interface{}{
  1086  						"Products": []interface{}{
  1087  							map[string]interface{}{
  1088  								"Name": "Hammer",
  1089  								"Sku":  int64(738594937),
  1090  							},
  1091  							map[string]interface{}{},
  1092  							map[string]interface{}{
  1093  								"Name":  "Nail",
  1094  								"Sku":   int64(284758393),
  1095  								"Color": "gray",
  1096  							},
  1097  						},
  1098  					},
  1099  				}
  1100  			},
  1101  		},
  1102  		{
  1103  			desc: "sub-table in array table",
  1104  			input: `[[Fruits]]
  1105  					Name = "apple"
  1106  
  1107  					[Fruits.Physical]  # subtable
  1108  					Color = "red"
  1109  					Shape = "round"`,
  1110  			gen: func() test {
  1111  				return test{
  1112  					target: &map[string]interface{}{},
  1113  					expected: &map[string]interface{}{
  1114  						"Fruits": []interface{}{
  1115  							map[string]interface{}{
  1116  								"Name": "apple",
  1117  								"Physical": map[string]interface{}{
  1118  									"Color": "red",
  1119  									"Shape": "round",
  1120  								},
  1121  							},
  1122  						},
  1123  					},
  1124  				}
  1125  			},
  1126  		},
  1127  		{
  1128  			desc: "multiple sub-table in array tables",
  1129  			input: `[[Fruits]]
  1130  					Name = "apple"
  1131  
  1132  					[[Fruits.Varieties]]  # nested array of tables
  1133  					Name = "red delicious"
  1134  
  1135  					[[Fruits.Varieties]]
  1136  					Name = "granny smith"
  1137  
  1138  					[[Fruits]]
  1139  					Name = "banana"
  1140  
  1141  					[[Fruits.Varieties]]
  1142  					Name = "plantain"`,
  1143  			gen: func() test {
  1144  				return test{
  1145  					target: &map[string]interface{}{},
  1146  					expected: &map[string]interface{}{
  1147  						"Fruits": []interface{}{
  1148  							map[string]interface{}{
  1149  								"Name": "apple",
  1150  								"Varieties": []interface{}{
  1151  									map[string]interface{}{
  1152  										"Name": "red delicious",
  1153  									},
  1154  									map[string]interface{}{
  1155  										"Name": "granny smith",
  1156  									},
  1157  								},
  1158  							},
  1159  							map[string]interface{}{
  1160  								"Name": "banana",
  1161  								"Varieties": []interface{}{
  1162  									map[string]interface{}{
  1163  										"Name": "plantain",
  1164  									},
  1165  								},
  1166  							},
  1167  						},
  1168  					},
  1169  				}
  1170  			},
  1171  		},
  1172  		{
  1173  			desc: "multiple sub-table in array tables into structs",
  1174  			input: `[[Fruits]]
  1175  					Name = "apple"
  1176  
  1177  					[[Fruits.Varieties]]  # nested array of tables
  1178  					Name = "red delicious"
  1179  
  1180  					[[Fruits.Varieties]]
  1181  					Name = "granny smith"
  1182  
  1183  					[[Fruits]]
  1184  					Name = "banana"
  1185  
  1186  					[[Fruits.Varieties]]
  1187  					Name = "plantain"`,
  1188  			gen: func() test {
  1189  				type Variety struct {
  1190  					Name string
  1191  				}
  1192  				type Fruit struct {
  1193  					Name      string
  1194  					Varieties []Variety
  1195  				}
  1196  				type doc struct {
  1197  					Fruits []Fruit
  1198  				}
  1199  
  1200  				return test{
  1201  					target: &doc{},
  1202  					expected: &doc{
  1203  						Fruits: []Fruit{
  1204  							{
  1205  								Name: "apple",
  1206  								Varieties: []Variety{
  1207  									{Name: "red delicious"},
  1208  									{Name: "granny smith"},
  1209  								},
  1210  							},
  1211  							{
  1212  								Name: "banana",
  1213  								Varieties: []Variety{
  1214  									{Name: "plantain"},
  1215  								},
  1216  							},
  1217  						},
  1218  					},
  1219  				}
  1220  			},
  1221  		},
  1222  		{
  1223  			desc: "array table into interface in struct",
  1224  			input: `[[foo]]
  1225  			bar = "hello"`,
  1226  			gen: func() test {
  1227  				type doc struct {
  1228  					Foo interface{}
  1229  				}
  1230  				return test{
  1231  					target: &doc{},
  1232  					expected: &doc{
  1233  						Foo: []interface{}{
  1234  							map[string]interface{}{
  1235  								"bar": "hello",
  1236  							},
  1237  						},
  1238  					},
  1239  				}
  1240  			},
  1241  		},
  1242  		{
  1243  			desc: "array table into interface in struct already initialized with right type",
  1244  			input: `[[foo]]
  1245  			bar = "hello"`,
  1246  			gen: func() test {
  1247  				type doc struct {
  1248  					Foo interface{}
  1249  				}
  1250  				return test{
  1251  					target: &doc{
  1252  						Foo: []interface{}{},
  1253  					},
  1254  					expected: &doc{
  1255  						Foo: []interface{}{
  1256  							map[string]interface{}{
  1257  								"bar": "hello",
  1258  							},
  1259  						},
  1260  					},
  1261  				}
  1262  			},
  1263  		},
  1264  		{
  1265  			desc: "array table into interface in struct already initialized with wrong type",
  1266  			input: `[[foo]]
  1267  			bar = "hello"`,
  1268  			gen: func() test {
  1269  				type doc struct {
  1270  					Foo interface{}
  1271  				}
  1272  				return test{
  1273  					target: &doc{
  1274  						Foo: []string{},
  1275  					},
  1276  					expected: &doc{
  1277  						Foo: []interface{}{
  1278  							map[string]interface{}{
  1279  								"bar": "hello",
  1280  							},
  1281  						},
  1282  					},
  1283  				}
  1284  			},
  1285  		},
  1286  		{
  1287  			desc: "array table into maps with pointer on last key",
  1288  			input: `[[foo]]
  1289  			bar = "hello"`,
  1290  			gen: func() test {
  1291  				type doc struct {
  1292  					Foo **[]interface{}
  1293  				}
  1294  				x := &[]interface{}{
  1295  					map[string]interface{}{
  1296  						"bar": "hello",
  1297  					},
  1298  				}
  1299  				return test{
  1300  					target: &doc{},
  1301  					expected: &doc{
  1302  						Foo: &x,
  1303  					},
  1304  				}
  1305  			},
  1306  		},
  1307  		{
  1308  			desc: "array table into maps with pointer on intermediate key",
  1309  			input: `[[foo.foo2]]
  1310  			bar = "hello"`,
  1311  			gen: func() test {
  1312  				type doc struct {
  1313  					Foo **map[string]interface{}
  1314  				}
  1315  				x := &map[string]interface{}{
  1316  					"foo2": []interface{}{
  1317  						map[string]interface{}{
  1318  							"bar": "hello",
  1319  						},
  1320  					},
  1321  				}
  1322  				return test{
  1323  					target: &doc{},
  1324  					expected: &doc{
  1325  						Foo: &x,
  1326  					},
  1327  				}
  1328  			},
  1329  		},
  1330  		{
  1331  			desc: "array table into maps with pointer on last key with invalid leaf type",
  1332  			input: `[[foo]]
  1333  			bar = "hello"`,
  1334  			gen: func() test {
  1335  				type doc struct {
  1336  					Foo **[]map[string]int
  1337  				}
  1338  				return test{
  1339  					target: &doc{},
  1340  					err:    true,
  1341  				}
  1342  			},
  1343  		},
  1344  		{
  1345  			desc:  "unexported struct fields are ignored",
  1346  			input: `foo = "bar"`,
  1347  			gen: func() test {
  1348  				type doc struct {
  1349  					foo string
  1350  				}
  1351  				return test{
  1352  					target:   &doc{},
  1353  					expected: &doc{},
  1354  				}
  1355  			},
  1356  		},
  1357  		{
  1358  			desc: "array table into nil ptr",
  1359  			input: `[[foo]]
  1360  			bar = "hello"`,
  1361  			gen: func() test {
  1362  				type doc struct {
  1363  					Foo *[]interface{}
  1364  				}
  1365  				return test{
  1366  					target: &doc{},
  1367  					expected: &doc{
  1368  						Foo: &[]interface{}{
  1369  							map[string]interface{}{
  1370  								"bar": "hello",
  1371  							},
  1372  						},
  1373  					},
  1374  				}
  1375  			},
  1376  		},
  1377  		{
  1378  			desc: "array table into nil ptr of invalid type",
  1379  			input: `[[foo]]
  1380  			bar = "hello"`,
  1381  			gen: func() test {
  1382  				type doc struct {
  1383  					Foo *string
  1384  				}
  1385  				return test{
  1386  					target: &doc{},
  1387  					err:    true,
  1388  				}
  1389  			},
  1390  		},
  1391  		{
  1392  			desc: "array table with intermediate ptr",
  1393  			input: `[[foo.bar]]
  1394  			bar = "hello"`,
  1395  			gen: func() test {
  1396  				type doc struct {
  1397  					Foo *map[string]interface{}
  1398  				}
  1399  				return test{
  1400  					target: &doc{},
  1401  					expected: &doc{
  1402  						Foo: &map[string]interface{}{
  1403  							"bar": []interface{}{
  1404  								map[string]interface{}{
  1405  									"bar": "hello",
  1406  								},
  1407  							},
  1408  						},
  1409  					},
  1410  				}
  1411  			},
  1412  		},
  1413  		{
  1414  			desc:  "unmarshal array into interface that contains a slice",
  1415  			input: `a = [1,2,3]`,
  1416  			gen: func() test {
  1417  				type doc struct {
  1418  					A interface{}
  1419  				}
  1420  				return test{
  1421  					target: &doc{
  1422  						A: []string{},
  1423  					},
  1424  					expected: &doc{
  1425  						A: []interface{}{
  1426  							int64(1),
  1427  							int64(2),
  1428  							int64(3),
  1429  						},
  1430  					},
  1431  				}
  1432  			},
  1433  		},
  1434  		{
  1435  			desc:  "unmarshal array into interface that contains a []interface{}",
  1436  			input: `a = [1,2,3]`,
  1437  			gen: func() test {
  1438  				type doc struct {
  1439  					A interface{}
  1440  				}
  1441  				return test{
  1442  					target: &doc{
  1443  						A: []interface{}{},
  1444  					},
  1445  					expected: &doc{
  1446  						A: []interface{}{
  1447  							int64(1),
  1448  							int64(2),
  1449  							int64(3),
  1450  						},
  1451  					},
  1452  				}
  1453  			},
  1454  		},
  1455  		{
  1456  			desc:  "unmarshal key into map with existing value",
  1457  			input: `a = "new"`,
  1458  			gen: func() test {
  1459  				return test{
  1460  					target:   &map[string]interface{}{"a": "old"},
  1461  					expected: &map[string]interface{}{"a": "new"},
  1462  				}
  1463  			},
  1464  		},
  1465  		{
  1466  			desc:  "unmarshal key into map with existing value",
  1467  			input: `a.b = "new"`,
  1468  			gen: func() test {
  1469  				type doc struct {
  1470  					A interface{}
  1471  				}
  1472  				return test{
  1473  					target: &doc{},
  1474  					expected: &doc{
  1475  						A: map[string]interface{}{
  1476  							"b": "new",
  1477  						},
  1478  					},
  1479  				}
  1480  			},
  1481  		},
  1482  		{
  1483  			desc:  "unmarshal array into struct field with existing array",
  1484  			input: `a = [1,2]`,
  1485  			gen: func() test {
  1486  				type doc struct {
  1487  					A []int
  1488  				}
  1489  				return test{
  1490  					target: &doc{},
  1491  					expected: &doc{
  1492  						A: []int{1, 2},
  1493  					},
  1494  				}
  1495  			},
  1496  		},
  1497  		{
  1498  			desc:  "unmarshal inline table into map",
  1499  			input: `a = {b="hello"}`,
  1500  			gen: func() test {
  1501  				type doc struct {
  1502  					A map[string]interface{}
  1503  				}
  1504  				return test{
  1505  					target: &doc{},
  1506  					expected: &doc{
  1507  						A: map[string]interface{}{
  1508  							"b": "hello",
  1509  						},
  1510  					},
  1511  				}
  1512  			},
  1513  		},
  1514  		{
  1515  			desc:  "unmarshal inline table into map of incorrect type",
  1516  			input: `a = {b="hello"}`,
  1517  			gen: func() test {
  1518  				type doc struct {
  1519  					A map[string]int
  1520  				}
  1521  				return test{
  1522  					target: &doc{},
  1523  					err:    true,
  1524  				}
  1525  			},
  1526  		},
  1527  		{
  1528  			desc:  "slice pointer in slice pointer",
  1529  			input: `A = ["Hello"]`,
  1530  			gen: func() test {
  1531  				type doc struct {
  1532  					A *[]*string
  1533  				}
  1534  				hello := "Hello"
  1535  
  1536  				return test{
  1537  					target: &doc{},
  1538  					expected: &doc{
  1539  						A: &[]*string{&hello},
  1540  					},
  1541  				}
  1542  			},
  1543  		},
  1544  		{
  1545  			desc:  "interface holding a string",
  1546  			input: `A = "Hello"`,
  1547  			gen: func() test {
  1548  				type doc struct {
  1549  					A interface{}
  1550  				}
  1551  				return test{
  1552  					target: &doc{},
  1553  					expected: &doc{
  1554  						A: "Hello",
  1555  					},
  1556  				}
  1557  			},
  1558  		},
  1559  		{
  1560  			desc:  "map of bools",
  1561  			input: `A = true`,
  1562  			gen: func() test {
  1563  				return test{
  1564  					target:   &map[string]bool{},
  1565  					expected: &map[string]bool{"A": true},
  1566  				}
  1567  			},
  1568  		},
  1569  		{
  1570  			desc:  "map of int64",
  1571  			input: `A = 42`,
  1572  			gen: func() test {
  1573  				return test{
  1574  					target:   &map[string]int64{},
  1575  					expected: &map[string]int64{"A": 42},
  1576  				}
  1577  			},
  1578  		},
  1579  		{
  1580  			desc:  "map of float64",
  1581  			input: `A = 4.2`,
  1582  			gen: func() test {
  1583  				return test{
  1584  					target:   &map[string]float64{},
  1585  					expected: &map[string]float64{"A": 4.2},
  1586  				}
  1587  			},
  1588  		},
  1589  		{
  1590  			desc:  "array of int in map",
  1591  			input: `A = [1,2,3]`,
  1592  			gen: func() test {
  1593  				return test{
  1594  					target:   &map[string][3]int{},
  1595  					expected: &map[string][3]int{"A": {1, 2, 3}},
  1596  				}
  1597  			},
  1598  		},
  1599  		{
  1600  			desc:  "array of int in map with too many elements",
  1601  			input: `A = [1,2,3,4,5]`,
  1602  			gen: func() test {
  1603  				return test{
  1604  					target:   &map[string][3]int{},
  1605  					expected: &map[string][3]int{"A": {1, 2, 3}},
  1606  				}
  1607  			},
  1608  		},
  1609  		{
  1610  			desc:  "array of int in map with invalid element",
  1611  			input: `A = [1,2,false]`,
  1612  			gen: func() test {
  1613  				return test{
  1614  					target: &map[string][3]int{},
  1615  					err:    true,
  1616  				}
  1617  			},
  1618  		},
  1619  		{
  1620  			desc: "nested arrays",
  1621  			input: `
  1622  			[[A]]
  1623  			[[A.B]]
  1624  			C = 1
  1625  			[[A]]
  1626  			[[A.B]]
  1627  			C = 2`,
  1628  			gen: func() test {
  1629  				type leaf struct {
  1630  					C int
  1631  				}
  1632  				type inner struct {
  1633  					B [2]leaf
  1634  				}
  1635  				type s struct {
  1636  					A [2]inner
  1637  				}
  1638  				return test{
  1639  					target: &s{},
  1640  					expected: &s{A: [2]inner{
  1641  						{B: [2]leaf{
  1642  							{C: 1},
  1643  						}},
  1644  						{B: [2]leaf{
  1645  							{C: 2},
  1646  						}},
  1647  					}},
  1648  				}
  1649  			},
  1650  		},
  1651  		{
  1652  			desc: "nested arrays too many",
  1653  			input: `
  1654  			[[A]]
  1655  			[[A.B]]
  1656  			C = 1
  1657  			[[A.B]]
  1658  			C = 2`,
  1659  			gen: func() test {
  1660  				type leaf struct {
  1661  					C int
  1662  				}
  1663  				type inner struct {
  1664  					B [1]leaf
  1665  				}
  1666  				type s struct {
  1667  					A [1]inner
  1668  				}
  1669  				return test{
  1670  					target: &s{},
  1671  					err:    true,
  1672  				}
  1673  			},
  1674  		},
  1675  		{
  1676  			desc:  "empty array table in interface{}",
  1677  			input: `[[products]]`,
  1678  			gen: func() test {
  1679  				return test{
  1680  					target: &map[string]interface{}{},
  1681  					expected: &map[string]interface{}{
  1682  						"products": []interface{}{
  1683  							map[string]interface{}{},
  1684  						},
  1685  					},
  1686  				}
  1687  			},
  1688  		},
  1689  		{
  1690  			desc:  "into map with invalid key type",
  1691  			input: `A = "hello"`,
  1692  			gen: func() test {
  1693  				return test{
  1694  					target: &map[int]string{},
  1695  					err:    true,
  1696  				}
  1697  			},
  1698  		},
  1699  		{
  1700  			desc:  "empty map into map with invalid key type",
  1701  			input: ``,
  1702  			gen: func() test {
  1703  				return test{
  1704  					target:   &map[int]string{},
  1705  					expected: &map[int]string{},
  1706  				}
  1707  			},
  1708  		},
  1709  		{
  1710  			desc:  "into map with convertible key type",
  1711  			input: `A = "hello"`,
  1712  			gen: func() test {
  1713  				type foo string
  1714  				return test{
  1715  					target: &map[foo]string{},
  1716  					expected: &map[foo]string{
  1717  						"A": "hello",
  1718  					},
  1719  				}
  1720  			},
  1721  		},
  1722  		{
  1723  			desc:  "array of int in struct",
  1724  			input: `A = [1,2,3]`,
  1725  			gen: func() test {
  1726  				type s struct {
  1727  					A [3]int
  1728  				}
  1729  				return test{
  1730  					target:   &s{},
  1731  					expected: &s{A: [3]int{1, 2, 3}},
  1732  				}
  1733  			},
  1734  		},
  1735  		{
  1736  			desc: "array of int in struct",
  1737  			input: `[A]
  1738  			b = 42`,
  1739  			gen: func() test {
  1740  				type s struct {
  1741  					A *map[string]interface{}
  1742  				}
  1743  				return test{
  1744  					target:   &s{},
  1745  					expected: &s{A: &map[string]interface{}{"b": int64(42)}},
  1746  				}
  1747  			},
  1748  		},
  1749  		{
  1750  			desc:  "assign bool to float",
  1751  			input: `A = true`,
  1752  			gen: func() test {
  1753  				return test{
  1754  					target: &map[string]float64{},
  1755  					err:    true,
  1756  				}
  1757  			},
  1758  		},
  1759  		{
  1760  			desc: "interface holding a struct",
  1761  			input: `[A]
  1762  					B = "After"`,
  1763  			gen: func() test {
  1764  				type inner struct {
  1765  					B interface{}
  1766  				}
  1767  				type doc struct {
  1768  					A interface{}
  1769  				}
  1770  
  1771  				return test{
  1772  					target: &doc{
  1773  						A: inner{
  1774  							B: "Before",
  1775  						},
  1776  					},
  1777  					expected: &doc{
  1778  						A: map[string]interface{}{
  1779  							"B": "After",
  1780  						},
  1781  					},
  1782  				}
  1783  			},
  1784  		},
  1785  		{
  1786  			desc: "array of structs with table arrays",
  1787  			input: `[[A]]
  1788  			B = "one"
  1789  			[[A]]
  1790  			B = "two"`,
  1791  			gen: func() test {
  1792  				type inner struct {
  1793  					B string
  1794  				}
  1795  				type doc struct {
  1796  					A [4]inner
  1797  				}
  1798  
  1799  				return test{
  1800  					target: &doc{},
  1801  					expected: &doc{
  1802  						A: [4]inner{
  1803  							{B: "one"},
  1804  							{B: "two"},
  1805  						},
  1806  					},
  1807  				}
  1808  			},
  1809  		},
  1810  		{
  1811  			desc:  "windows line endings",
  1812  			input: "A = 1\r\n\r\nB = 2",
  1813  			gen: func() test {
  1814  				doc := map[string]interface{}{}
  1815  
  1816  				return test{
  1817  					target: &doc,
  1818  					expected: &map[string]interface{}{
  1819  						"A": int64(1),
  1820  						"B": int64(2),
  1821  					},
  1822  				}
  1823  			},
  1824  		},
  1825  		{
  1826  			desc:  "dangling CR",
  1827  			input: "A = 1\r",
  1828  			gen: func() test {
  1829  				doc := map[string]interface{}{}
  1830  
  1831  				return test{
  1832  					target: &doc,
  1833  					err:    true,
  1834  				}
  1835  			},
  1836  		},
  1837  		{
  1838  			desc:  "missing NL after CR",
  1839  			input: "A = 1\rB = 2",
  1840  			gen: func() test {
  1841  				doc := map[string]interface{}{}
  1842  
  1843  				return test{
  1844  					target: &doc,
  1845  					err:    true,
  1846  				}
  1847  			},
  1848  		},
  1849  		{
  1850  			desc:  "no newline (#526)",
  1851  			input: `a = 1z = 2`,
  1852  			gen: func() test {
  1853  				m := map[string]interface{}{}
  1854  
  1855  				return test{
  1856  					target: &m,
  1857  					err:    true,
  1858  				}
  1859  			},
  1860  		},
  1861  		{
  1862  			desc:  "mismatch types int to string",
  1863  			input: `A = 42`,
  1864  			gen: func() test {
  1865  				type S struct {
  1866  					A string
  1867  				}
  1868  				return test{
  1869  					target: &S{},
  1870  					err:    true,
  1871  				}
  1872  			},
  1873  		},
  1874  		{
  1875  			desc:  "mismatch types array of int to interface with non-slice",
  1876  			input: `A = [42]`,
  1877  			gen: func() test {
  1878  				type S struct {
  1879  					A string
  1880  				}
  1881  				return test{
  1882  					target: &S{},
  1883  					err:    true,
  1884  				}
  1885  			},
  1886  		},
  1887  		{
  1888  			desc:  "comment with CRLF",
  1889  			input: "# foo\r\na=2",
  1890  			gen: func() test {
  1891  				doc := map[string]interface{}{}
  1892  
  1893  				return test{
  1894  					target:   &doc,
  1895  					expected: &map[string]interface{}{"a": int64(2)},
  1896  				}
  1897  			},
  1898  		},
  1899  		{
  1900  			desc:  "comment that looks like a date",
  1901  			input: "a=19#9-",
  1902  			gen: func() test {
  1903  				doc := map[string]interface{}{}
  1904  
  1905  				return test{
  1906  					target:   &doc,
  1907  					expected: &map[string]interface{}{"a": int64(19)},
  1908  				}
  1909  			},
  1910  		},
  1911  		{
  1912  			desc:  "comment that looks like a date",
  1913  			input: "a=199#-",
  1914  			gen: func() test {
  1915  				doc := map[string]interface{}{}
  1916  
  1917  				return test{
  1918  					target:   &doc,
  1919  					expected: &map[string]interface{}{"a": int64(199)},
  1920  				}
  1921  			},
  1922  		},
  1923  		{
  1924  			desc:  "kv that points to a slice",
  1925  			input: "a.b.c = 'foo'",
  1926  			gen: func() test {
  1927  				doc := map[string][]string{}
  1928  				return test{
  1929  					target: &doc,
  1930  					err:    true,
  1931  				}
  1932  			},
  1933  		},
  1934  		{
  1935  			desc:  "kv that points to a pointer to a slice",
  1936  			input: "a.b.c = 'foo'",
  1937  			gen: func() test {
  1938  				doc := map[string]*[]string{}
  1939  				return test{
  1940  					target: &doc,
  1941  					err:    true,
  1942  				}
  1943  			},
  1944  		},
  1945  	}
  1946  
  1947  	for _, e := range examples {
  1948  		e := e
  1949  		t.Run(e.desc, func(t *testing.T) {
  1950  			if e.skip {
  1951  				t.Skip()
  1952  			}
  1953  			test := e.gen()
  1954  			if test.err && test.expected != nil {
  1955  				panic("invalid test: cannot expect both an error and a value")
  1956  			}
  1957  			err := toml.Unmarshal([]byte(e.input), test.target)
  1958  			if test.err {
  1959  				if err == nil {
  1960  					t.Log("=>", test.target)
  1961  				}
  1962  				require.Error(t, err)
  1963  			} else {
  1964  				require.NoError(t, err)
  1965  				if test.assert != nil {
  1966  					test.assert(t, test)
  1967  				} else {
  1968  					assert.Equal(t, test.expected, test.target)
  1969  				}
  1970  			}
  1971  		})
  1972  	}
  1973  }
  1974  
  1975  func TestUnmarshalOverflows(t *testing.T) {
  1976  	examples := []struct {
  1977  		t      interface{}
  1978  		errors []string
  1979  	}{
  1980  		{
  1981  			t:      &map[string]int32{},
  1982  			errors: []string{`-2147483649`, `2147483649`},
  1983  		},
  1984  		{
  1985  			t:      &map[string]int16{},
  1986  			errors: []string{`-2147483649`, `2147483649`},
  1987  		},
  1988  		{
  1989  			t:      &map[string]int8{},
  1990  			errors: []string{`-2147483649`, `2147483649`},
  1991  		},
  1992  		{
  1993  			t:      &map[string]int{},
  1994  			errors: []string{`-19223372036854775808`, `9223372036854775808`},
  1995  		},
  1996  		{
  1997  			t:      &map[string]uint64{},
  1998  			errors: []string{`-1`, `18446744073709551616`},
  1999  		},
  2000  		{
  2001  			t:      &map[string]uint32{},
  2002  			errors: []string{`-1`, `18446744073709551616`},
  2003  		},
  2004  		{
  2005  			t:      &map[string]uint16{},
  2006  			errors: []string{`-1`, `18446744073709551616`},
  2007  		},
  2008  		{
  2009  			t:      &map[string]uint8{},
  2010  			errors: []string{`-1`, `18446744073709551616`},
  2011  		},
  2012  		{
  2013  			t:      &map[string]uint{},
  2014  			errors: []string{`-1`, `18446744073709551616`},
  2015  		},
  2016  	}
  2017  
  2018  	for _, e := range examples {
  2019  		e := e
  2020  		for _, v := range e.errors {
  2021  			v := v
  2022  			t.Run(fmt.Sprintf("%T %s", e.t, v), func(t *testing.T) {
  2023  				doc := "A = " + v
  2024  				err := toml.Unmarshal([]byte(doc), e.t)
  2025  				t.Log("input:", doc)
  2026  				require.Error(t, err)
  2027  			})
  2028  		}
  2029  		t.Run(fmt.Sprintf("%T ok", e.t), func(t *testing.T) {
  2030  			doc := "A = 1"
  2031  			err := toml.Unmarshal([]byte(doc), e.t)
  2032  			t.Log("input:", doc)
  2033  			require.NoError(t, err)
  2034  		})
  2035  	}
  2036  }
  2037  
  2038  func TestUnmarshalErrors(t *testing.T) {
  2039  	type mystruct struct {
  2040  		Bar string
  2041  	}
  2042  
  2043  	data := `bar = 42`
  2044  
  2045  	s := mystruct{}
  2046  	err := toml.Unmarshal([]byte(data), &s)
  2047  	require.Error(t, err)
  2048  
  2049  	require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.mystruct.Bar of type string", err.Error())
  2050  }
  2051  
  2052  func TestUnmarshalStringInvalidStructField(t *testing.T) {
  2053  	type Server struct {
  2054  		Path string
  2055  		Port int
  2056  	}
  2057  
  2058  	type Cfg struct {
  2059  		Server Server
  2060  	}
  2061  
  2062  	var cfg Cfg
  2063  
  2064  	data := `[server]
  2065  path = "/my/path"
  2066  port = "bad"
  2067  `
  2068  
  2069  	file := strings.NewReader(data)
  2070  	err := toml.NewDecoder(file).Decode(&cfg)
  2071  	require.Error(t, err)
  2072  
  2073  	x := err.(*toml.DecodeError)
  2074  	require.Equal(t, "toml: cannot decode TOML string into struct field toml_test.Server.Port of type int", x.Error())
  2075  	expected := `1| [server]
  2076  2| path = "/my/path"
  2077  3| port = "bad"
  2078   |        ~~~~~ cannot decode TOML string into struct field toml_test.Server.Port of type int`
  2079  
  2080  	require.Equal(t, expected, x.String())
  2081  }
  2082  
  2083  func TestUnmarshalIntegerInvalidStructField(t *testing.T) {
  2084  	type Server struct {
  2085  		Path string
  2086  		Port int
  2087  	}
  2088  
  2089  	type Cfg struct {
  2090  		Server Server
  2091  	}
  2092  
  2093  	var cfg Cfg
  2094  
  2095  	data := `[server]
  2096  path = 100
  2097  port = 50
  2098  `
  2099  
  2100  	file := strings.NewReader(data)
  2101  	err := toml.NewDecoder(file).Decode(&cfg)
  2102  	require.Error(t, err)
  2103  
  2104  	x := err.(*toml.DecodeError)
  2105  	require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.Server.Path of type string", x.Error())
  2106  	expected := `1| [server]
  2107  2| path = 100
  2108   |        ~~~ cannot decode TOML integer into struct field toml_test.Server.Path of type string
  2109  3| port = 50`
  2110  
  2111  	require.Equal(t, expected, x.String())
  2112  }
  2113  
  2114  func TestUnmarshalInvalidTarget(t *testing.T) {
  2115  	x := "foo"
  2116  	err := toml.Unmarshal([]byte{}, x)
  2117  	require.Error(t, err)
  2118  
  2119  	var m *map[string]interface{}
  2120  	err = toml.Unmarshal([]byte{}, m)
  2121  	require.Error(t, err)
  2122  }
  2123  
  2124  func TestUnmarshalFloat32(t *testing.T) {
  2125  	t.Run("fits", func(t *testing.T) {
  2126  		doc := "A = 1.2"
  2127  		err := toml.Unmarshal([]byte(doc), &map[string]float32{})
  2128  		require.NoError(t, err)
  2129  	})
  2130  	t.Run("overflows", func(t *testing.T) {
  2131  		doc := "A = 4.40282346638528859811704183484516925440e+38"
  2132  		err := toml.Unmarshal([]byte(doc), &map[string]float32{})
  2133  		require.Error(t, err)
  2134  	})
  2135  }
  2136  
  2137  func TestDecoderStrict(t *testing.T) {
  2138  	examples := []struct {
  2139  		desc     string
  2140  		input    string
  2141  		expected string
  2142  		target   interface{}
  2143  	}{
  2144  		{
  2145  			desc: "multiple missing root keys",
  2146  			input: `
  2147  key1 = "value1"
  2148  key2 = "missing2"
  2149  key3 = "missing3"
  2150  key4 = "value4"
  2151  `,
  2152  			expected: `2| key1 = "value1"
  2153  3| key2 = "missing2"
  2154   | ~~~~ missing field
  2155  4| key3 = "missing3"
  2156  5| key4 = "value4"
  2157  ---
  2158  2| key1 = "value1"
  2159  3| key2 = "missing2"
  2160  4| key3 = "missing3"
  2161   | ~~~~ missing field
  2162  5| key4 = "value4"`,
  2163  			target: &struct {
  2164  				Key1 string
  2165  				Key4 string
  2166  			}{},
  2167  		},
  2168  		{
  2169  			desc:  "multi-part key",
  2170  			input: `a.short.key="foo"`,
  2171  			expected: `1| a.short.key="foo"
  2172   | ~~~~~~~~~~~ missing field`,
  2173  		},
  2174  		{
  2175  			desc: "missing table",
  2176  			input: `
  2177  [foo]
  2178  bar = 42
  2179  `,
  2180  			expected: `2| [foo]
  2181   |  ~~~ missing table
  2182  3| bar = 42`,
  2183  		},
  2184  
  2185  		{
  2186  			desc: "missing array table",
  2187  			input: `
  2188  [[foo]]
  2189  bar = 42`,
  2190  			expected: `2| [[foo]]
  2191   |   ~~~ missing table
  2192  3| bar = 42`,
  2193  		},
  2194  	}
  2195  
  2196  	for _, e := range examples {
  2197  		e := e
  2198  		t.Run(e.desc, func(t *testing.T) {
  2199  			t.Run("strict", func(t *testing.T) {
  2200  				r := strings.NewReader(e.input)
  2201  				d := toml.NewDecoder(r)
  2202  				d.DisallowUnknownFields()
  2203  				x := e.target
  2204  				if x == nil {
  2205  					x = &struct{}{}
  2206  				}
  2207  				err := d.Decode(x)
  2208  
  2209  				var tsm *toml.StrictMissingError
  2210  				if errors.As(err, &tsm) {
  2211  					assert.Equal(t, e.expected, tsm.String())
  2212  				} else {
  2213  					t.Fatalf("err should have been a *toml.StrictMissingError, but got %s (%T)", err, err)
  2214  				}
  2215  			})
  2216  
  2217  			t.Run("default", func(t *testing.T) {
  2218  				r := strings.NewReader(e.input)
  2219  				d := toml.NewDecoder(r)
  2220  				x := e.target
  2221  				if x == nil {
  2222  					x = &struct{}{}
  2223  				}
  2224  				err := d.Decode(x)
  2225  				require.NoError(t, err)
  2226  			})
  2227  		})
  2228  	}
  2229  }
  2230  
  2231  func TestIssue252(t *testing.T) {
  2232  	type config struct {
  2233  		Val1 string `toml:"val1"`
  2234  		Val2 string `toml:"val2"`
  2235  	}
  2236  
  2237  	configFile := []byte(
  2238  		`
  2239  val1 = "test1"
  2240  `)
  2241  
  2242  	cfg := &config{
  2243  		Val2: "test2",
  2244  	}
  2245  
  2246  	err := toml.Unmarshal(configFile, cfg)
  2247  	require.NoError(t, err)
  2248  	require.Equal(t, "test2", cfg.Val2)
  2249  }
  2250  
  2251  func TestIssue287(t *testing.T) {
  2252  	b := `y=[[{}]]`
  2253  	v := map[string]interface{}{}
  2254  	err := toml.Unmarshal([]byte(b), &v)
  2255  	require.NoError(t, err)
  2256  
  2257  	expected := map[string]interface{}{
  2258  		"y": []interface{}{
  2259  			[]interface{}{
  2260  				map[string]interface{}{},
  2261  			},
  2262  		},
  2263  	}
  2264  	require.Equal(t, expected, v)
  2265  }
  2266  
  2267  type (
  2268  	Map458   map[string]interface{}
  2269  	Slice458 []interface{}
  2270  )
  2271  
  2272  func (m Map458) A(s string) Slice458 {
  2273  	return m[s].([]interface{})
  2274  }
  2275  
  2276  func TestIssue458(t *testing.T) {
  2277  	s := []byte(`[[package]]
  2278  dependencies = ["regex"]
  2279  name = "decode"
  2280  version = "0.1.0"`)
  2281  	m := Map458{}
  2282  	err := toml.Unmarshal(s, &m)
  2283  	require.NoError(t, err)
  2284  	a := m.A("package")
  2285  	expected := Slice458{
  2286  		map[string]interface{}{
  2287  			"dependencies": []interface{}{"regex"},
  2288  			"name":         "decode",
  2289  			"version":      "0.1.0",
  2290  		},
  2291  	}
  2292  	assert.Equal(t, expected, a)
  2293  }
  2294  
  2295  type Integer484 struct {
  2296  	Value int
  2297  }
  2298  
  2299  func (i Integer484) MarshalText() ([]byte, error) {
  2300  	return []byte(strconv.Itoa(i.Value)), nil
  2301  }
  2302  
  2303  func (i *Integer484) UnmarshalText(data []byte) error {
  2304  	conv, err := strconv.Atoi(string(data))
  2305  	if err != nil {
  2306  		return fmt.Errorf("UnmarshalText: %w", err)
  2307  	}
  2308  	i.Value = conv
  2309  
  2310  	return nil
  2311  }
  2312  
  2313  type Config484 struct {
  2314  	Integers []Integer484 `toml:"integers"`
  2315  }
  2316  
  2317  func TestIssue484(t *testing.T) {
  2318  	raw := []byte(`integers = ["1","2","3","100"]`)
  2319  
  2320  	var cfg Config484
  2321  	err := toml.Unmarshal(raw, &cfg)
  2322  	require.NoError(t, err)
  2323  	assert.Equal(t, Config484{
  2324  		Integers: []Integer484{{1}, {2}, {3}, {100}},
  2325  	}, cfg)
  2326  }
  2327  
  2328  func TestIssue494(t *testing.T) {
  2329  	data := `
  2330  foo = 2021-04-08
  2331  bar = 2021-04-08
  2332  `
  2333  
  2334  	type s struct {
  2335  		Foo time.Time `toml:"foo"`
  2336  		Bar time.Time `toml:"bar"`
  2337  	}
  2338  	ss := new(s)
  2339  	err := toml.Unmarshal([]byte(data), ss)
  2340  	require.NoError(t, err)
  2341  }
  2342  
  2343  func TestIssue508(t *testing.T) {
  2344  	type head struct {
  2345  		Title string `toml:"title"`
  2346  	}
  2347  
  2348  	type text struct {
  2349  		head
  2350  	}
  2351  
  2352  	b := []byte(`title = "This is a title"`)
  2353  
  2354  	t1 := text{}
  2355  	err := toml.Unmarshal(b, &t1)
  2356  	require.NoError(t, err)
  2357  	require.Equal(t, "This is a title", t1.head.Title)
  2358  }
  2359  
  2360  func TestIssue507(t *testing.T) {
  2361  	data := []byte{'0', '=', '\n', '0', 'a', 'm', 'e'}
  2362  	m := map[string]interface{}{}
  2363  	err := toml.Unmarshal(data, &m)
  2364  	require.Error(t, err)
  2365  }
  2366  
  2367  type uuid [16]byte
  2368  
  2369  func (u *uuid) UnmarshalText(text []byte) (err error) {
  2370  	// Note: the original reported issue had a more complex implementation
  2371  	// of this function. But the important part is to verify that a
  2372  	// non-struct type implementing UnmarshalText works with the unmarshal
  2373  	// process.
  2374  	placeholder := bytes.Repeat([]byte{0xAA}, 16)
  2375  	copy(u[:], placeholder)
  2376  	return nil
  2377  }
  2378  
  2379  func TestIssue564(t *testing.T) {
  2380  	type Config struct {
  2381  		ID uuid
  2382  	}
  2383  
  2384  	var config Config
  2385  
  2386  	err := toml.Unmarshal([]byte(`id = "0818a52b97b94768941ba1172c76cf6c"`), &config)
  2387  	require.NoError(t, err)
  2388  	require.Equal(t, uuid{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, config.ID)
  2389  }
  2390  
  2391  func TestIssue575(t *testing.T) {
  2392  	b := []byte(`
  2393  [pkg.cargo]
  2394  version = "0.55.0 (5ae8d74b3 2021-06-22)"
  2395  git_commit_hash = "a178d0322ce20e33eac124758e837cbd80a6f633"
  2396  [pkg.cargo.target.aarch64-apple-darwin]
  2397  available = true
  2398  url = "https://static.rust-lang.org/dist/2021-07-29/cargo-1.54.0-aarch64-apple-darwin.tar.gz"
  2399  hash = "7bac3901d8eb6a4191ffeebe75b29c78bcb270158ec901addb31f588d965d35d"
  2400  xz_url = "https://static.rust-lang.org/dist/2021-07-29/cargo-1.54.0-aarch64-apple-darwin.tar.xz"
  2401  xz_hash = "5207644fd6379f3e5b8ae60016b854efa55a381b0c363bff7f9b2f25bfccc430"
  2402  
  2403  [pkg.cargo.target.aarch64-pc-windows-msvc]
  2404  available = true
  2405  url = "https://static.rust-lang.org/dist/2021-07-29/cargo-1.54.0-aarch64-pc-windows-msvc.tar.gz"
  2406  hash = "eb8ccd9b1f6312b06dc749c17896fa4e9c163661c273dcb61cd7a48376227f6d"
  2407  xz_url = "https://static.rust-lang.org/dist/2021-07-29/cargo-1.54.0-aarch64-pc-windows-msvc.tar.xz"
  2408  xz_hash = "1a48f723fea1f17d786ce6eadd9d00914d38062d28fd9c455ed3c3801905b388"
  2409  `)
  2410  
  2411  	type target struct {
  2412  		XZ_URL string
  2413  	}
  2414  
  2415  	type pkg struct {
  2416  		Target map[string]target
  2417  	}
  2418  
  2419  	type doc struct {
  2420  		Pkg map[string]pkg
  2421  	}
  2422  
  2423  	var dist doc
  2424  	err := toml.Unmarshal(b, &dist)
  2425  	require.NoError(t, err)
  2426  
  2427  	expected := doc{
  2428  		Pkg: map[string]pkg{
  2429  			"cargo": {
  2430  				Target: map[string]target{
  2431  					"aarch64-apple-darwin": {
  2432  						XZ_URL: "https://static.rust-lang.org/dist/2021-07-29/cargo-1.54.0-aarch64-apple-darwin.tar.xz",
  2433  					},
  2434  					"aarch64-pc-windows-msvc": {
  2435  						XZ_URL: "https://static.rust-lang.org/dist/2021-07-29/cargo-1.54.0-aarch64-pc-windows-msvc.tar.xz",
  2436  					},
  2437  				},
  2438  			},
  2439  		},
  2440  	}
  2441  
  2442  	require.Equal(t, expected, dist)
  2443  }
  2444  
  2445  func TestIssue579(t *testing.T) {
  2446  	var v interface{}
  2447  	err := toml.Unmarshal([]byte(`[foo`), &v)
  2448  	require.Error(t, err)
  2449  }
  2450  
  2451  func TestIssue581(t *testing.T) {
  2452  	var v interface{}
  2453  	err := toml.Unmarshal([]byte(`P=[#`), &v)
  2454  	require.Error(t, err)
  2455  }
  2456  
  2457  func TestIssue585(t *testing.T) {
  2458  	var v interface{}
  2459  	err := toml.Unmarshal([]byte(`a=1979-05127T 0`), &v)
  2460  	require.Error(t, err)
  2461  }
  2462  
  2463  func TestIssue586(t *testing.T) {
  2464  	var v interface{}
  2465  	err := toml.Unmarshal([]byte(`a={ `), &v)
  2466  	require.Error(t, err)
  2467  }
  2468  
  2469  func TestIssue588(t *testing.T) {
  2470  	var v interface{}
  2471  	err := toml.Unmarshal([]byte(`a=[1#`), &v)
  2472  	require.Error(t, err)
  2473  }
  2474  
  2475  // Support lowercase 'T' and 'Z'
  2476  func TestIssue600(t *testing.T) {
  2477  	var v interface{}
  2478  	err := toml.Unmarshal([]byte(`a=1979-05-27t00:32:00z`), &v)
  2479  	require.NoError(t, err)
  2480  }
  2481  
  2482  func TestIssue596(t *testing.T) {
  2483  	var v interface{}
  2484  	err := toml.Unmarshal([]byte(`a=1979-05-27T90:+2:99`), &v)
  2485  	require.Error(t, err)
  2486  }
  2487  
  2488  func TestIssue602(t *testing.T) {
  2489  	var v interface{}
  2490  	err := toml.Unmarshal([]byte(""), &v)
  2491  	require.NoError(t, err)
  2492  
  2493  	var expected interface{} = map[string]interface{}{}
  2494  
  2495  	require.Equal(t, expected, v)
  2496  }
  2497  
  2498  func TestIssue623(t *testing.T) {
  2499  	definition := struct {
  2500  		Things []string
  2501  	}{}
  2502  
  2503  	values := `[things]
  2504  foo = "bar"`
  2505  
  2506  	err := toml.Unmarshal([]byte(values), &definition)
  2507  	require.Error(t, err)
  2508  }
  2509  
  2510  func TestIssue631(t *testing.T) {
  2511  	v := map[string]interface{}{}
  2512  	err := toml.Unmarshal([]byte("\"\\b\u007f\"= 2"), &v)
  2513  	require.Error(t, err)
  2514  }
  2515  
  2516  func TestIssue658(t *testing.T) {
  2517  	var v map[string]interface{}
  2518  	err := toml.Unmarshal([]byte("e={b=1,b=4}"), &v)
  2519  	require.Error(t, err)
  2520  }
  2521  
  2522  func TestIssue662(t *testing.T) {
  2523  	var v map[string]interface{}
  2524  	err := toml.Unmarshal([]byte("a=[{b=1,b=2}]"), &v)
  2525  	require.Error(t, err)
  2526  }
  2527  
  2528  func TestIssue666(t *testing.T) {
  2529  	var v map[string]interface{}
  2530  	err := toml.Unmarshal([]byte("a={}\na={}"), &v)
  2531  	require.Error(t, err)
  2532  }
  2533  
  2534  func TestIssue677(t *testing.T) {
  2535  	doc := `
  2536  [Build]
  2537  Name = "publication build"
  2538  
  2539  [[Build.Dependencies]]
  2540  Name = "command"
  2541  Program = "hugo"
  2542  `
  2543  
  2544  	type _tomlJob struct {
  2545  		Dependencies []map[string]interface{}
  2546  	}
  2547  
  2548  	type tomlParser struct {
  2549  		Build *_tomlJob
  2550  	}
  2551  
  2552  	p := tomlParser{}
  2553  
  2554  	err := toml.Unmarshal([]byte(doc), &p)
  2555  	require.NoError(t, err)
  2556  
  2557  	expected := tomlParser{
  2558  		Build: &_tomlJob{
  2559  			Dependencies: []map[string]interface{}{
  2560  				{
  2561  					"Name":    "command",
  2562  					"Program": "hugo",
  2563  				},
  2564  			},
  2565  		},
  2566  	}
  2567  	require.Equal(t, expected, p)
  2568  }
  2569  
  2570  func TestIssue701(t *testing.T) {
  2571  	// Expected behavior:
  2572  	// Return an error since a cannot be modified. From the TOML spec:
  2573  	//
  2574  	// > Inline tables are fully self-contained and define all
  2575  	// keys and sub-tables within them. Keys and sub-tables cannot
  2576  	// be added outside the braces.
  2577  
  2578  	docs := []string{
  2579  		`
  2580  a={}
  2581  [a.b]
  2582  z=0
  2583  `,
  2584  		`
  2585  a={}
  2586  [[a.b]]
  2587  z=0
  2588  `,
  2589  	}
  2590  
  2591  	for _, doc := range docs {
  2592  		var v interface{}
  2593  		err := toml.Unmarshal([]byte(doc), &v)
  2594  		assert.Error(t, err)
  2595  	}
  2596  }
  2597  
  2598  func TestIssue703(t *testing.T) {
  2599  	var v interface{}
  2600  	err := toml.Unmarshal([]byte("[a]\nx.y=0\n[a.x]"), &v)
  2601  	require.Error(t, err)
  2602  }
  2603  
  2604  func TestIssue708(t *testing.T) {
  2605  	v := map[string]string{}
  2606  	err := toml.Unmarshal([]byte("0=\"\"\"\\\r\n\"\"\""), &v)
  2607  	require.NoError(t, err)
  2608  	require.Equal(t, map[string]string{"0": ""}, v)
  2609  }
  2610  
  2611  func TestIssue710(t *testing.T) {
  2612  	v := map[string]toml.LocalTime{}
  2613  	err := toml.Unmarshal([]byte(`0=00:00:00.0000000000`), &v)
  2614  	require.NoError(t, err)
  2615  	require.Equal(t, map[string]toml.LocalTime{"0": {Precision: 9}}, v)
  2616  	v1 := map[string]toml.LocalTime{}
  2617  	err = toml.Unmarshal([]byte(`0=00:00:00.0000000001`), &v1)
  2618  	require.NoError(t, err)
  2619  	require.Equal(t, map[string]toml.LocalTime{"0": {Precision: 9}}, v1)
  2620  	v2 := map[string]toml.LocalTime{}
  2621  	err = toml.Unmarshal([]byte(`0=00:00:00.1111111119`), &v2)
  2622  	require.NoError(t, err)
  2623  	require.Equal(t, map[string]toml.LocalTime{"0": {Nanosecond: 111111111, Precision: 9}}, v2)
  2624  }
  2625  
  2626  func TestIssue715(t *testing.T) {
  2627  	var v interface{}
  2628  	err := toml.Unmarshal([]byte("0=+"), &v)
  2629  	require.Error(t, err)
  2630  
  2631  	err = toml.Unmarshal([]byte("0=-"), &v)
  2632  	require.Error(t, err)
  2633  
  2634  	err = toml.Unmarshal([]byte("0=+A"), &v)
  2635  	require.Error(t, err)
  2636  }
  2637  
  2638  func TestIssue714(t *testing.T) {
  2639  	var v interface{}
  2640  	err := toml.Unmarshal([]byte("0."), &v)
  2641  	require.Error(t, err)
  2642  
  2643  	err = toml.Unmarshal([]byte("0={0=0,"), &v)
  2644  	require.Error(t, err)
  2645  }
  2646  
  2647  func TestIssue772(t *testing.T) {
  2648  	type FileHandling struct {
  2649  		FilePattern string `toml:"pattern"`
  2650  	}
  2651  
  2652  	type Config struct {
  2653  		FileHandling `toml:"filehandling"`
  2654  	}
  2655  
  2656  	var defaultConfigFile = []byte(`
  2657  		[filehandling]
  2658  		pattern = "reach-masterdev-"`)
  2659  
  2660  	config := Config{}
  2661  	err := toml.Unmarshal(defaultConfigFile, &config)
  2662  	require.NoError(t, err)
  2663  	require.Equal(t, "reach-masterdev-", config.FileHandling.FilePattern)
  2664  }
  2665  
  2666  func TestIssue774(t *testing.T) {
  2667  	type ScpData struct {
  2668  		Host string `json:"host"`
  2669  	}
  2670  
  2671  	type GenConfig struct {
  2672  		SCP []ScpData `toml:"scp" comment:"Array of Secure Copy Configurations"`
  2673  	}
  2674  
  2675  	c := &GenConfig{}
  2676  	c.SCP = []ScpData{{Host: "main.domain.com"}}
  2677  
  2678  	b, err := toml.Marshal(c)
  2679  	require.NoError(t, err)
  2680  
  2681  	expected := `# Array of Secure Copy Configurations
  2682  [[scp]]
  2683  Host = 'main.domain.com'
  2684  `
  2685  
  2686  	require.Equal(t, expected, string(b))
  2687  }
  2688  
  2689  func TestIssue799(t *testing.T) {
  2690  	const testTOML = `
  2691  # notice the double brackets
  2692  [[test]]
  2693  answer = 42
  2694  `
  2695  
  2696  	var s struct {
  2697  		// should be []map[string]int
  2698  		Test map[string]int `toml:"test"`
  2699  	}
  2700  
  2701  	err := toml.Unmarshal([]byte(testTOML), &s)
  2702  	require.Error(t, err)
  2703  }
  2704  
  2705  func TestIssue807(t *testing.T) {
  2706  	type A struct {
  2707  		Name string `toml:"name"`
  2708  	}
  2709  
  2710  	type M struct {
  2711  		*A
  2712  	}
  2713  
  2714  	var m M
  2715  	err := toml.Unmarshal([]byte(`name = 'foo'`), &m)
  2716  	require.NoError(t, err)
  2717  	require.Equal(t, "foo", m.Name)
  2718  }
  2719  
  2720  func TestIssue850(t *testing.T) {
  2721  	data := make(map[string]string)
  2722  	err := toml.Unmarshal([]byte("foo = {}"), &data)
  2723  	require.Error(t, err)
  2724  }
  2725  
  2726  func TestIssue851(t *testing.T) {
  2727  	type Target struct {
  2728  		Params map[string]string `toml:"params"`
  2729  	}
  2730  
  2731  	content := "params = {a=\"1\",b=\"2\"}"
  2732  	var target Target
  2733  	err := toml.Unmarshal([]byte(content), &target)
  2734  	require.NoError(t, err)
  2735  	require.Equal(t, map[string]string{"a": "1", "b": "2"}, target.Params)
  2736  	err = toml.Unmarshal([]byte(content), &target)
  2737  	require.NoError(t, err)
  2738  	require.Equal(t, map[string]string{"a": "1", "b": "2"}, target.Params)
  2739  }
  2740  
  2741  func TestIssue866(t *testing.T) {
  2742  	type Pipeline struct {
  2743  		Mapping map[string]struct {
  2744  			Req [][]string `toml:"req"`
  2745  			Res [][]string `toml:"res"`
  2746  		} `toml:"mapping"`
  2747  	}
  2748  
  2749  	type Pipelines struct {
  2750  		PipelineMapping map[string]*Pipeline `toml:"pipelines"`
  2751  	}
  2752  
  2753  	var badToml = `
  2754  [pipelines.register]
  2755  mapping.inst.req = [
  2756      ["param1", "value1"],
  2757  ]
  2758  mapping.inst.res = [
  2759      ["param2", "value2"],
  2760  ]
  2761  `
  2762  
  2763  	pipelines := new(Pipelines)
  2764  	if err := toml.NewDecoder(bytes.NewBufferString(badToml)).DisallowUnknownFields().Decode(pipelines); err != nil {
  2765  		t.Fatal(err)
  2766  	}
  2767  	if pipelines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
  2768  		t.Fatal("unmarshal failed with mismatch value")
  2769  	}
  2770  
  2771  	var goodTooToml = `
  2772  [pipelines.register]
  2773  mapping.inst.req = [
  2774      ["param1", "value1"],
  2775  ]
  2776  `
  2777  
  2778  	pipelines = new(Pipelines)
  2779  	if err := toml.NewDecoder(bytes.NewBufferString(goodTooToml)).DisallowUnknownFields().Decode(pipelines); err != nil {
  2780  		t.Fatal(err)
  2781  	}
  2782  	if pipelines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
  2783  		t.Fatal("unmarshal failed with mismatch value")
  2784  	}
  2785  
  2786  	var goodToml = `
  2787  [pipelines.register.mapping.inst]
  2788  req = [
  2789      ["param1", "value1"],
  2790  ]
  2791  res = [
  2792      ["param2", "value2"],
  2793  ]
  2794  `
  2795  
  2796  	pipelines = new(Pipelines)
  2797  	if err := toml.NewDecoder(bytes.NewBufferString(goodToml)).DisallowUnknownFields().Decode(pipelines); err != nil {
  2798  		t.Fatal(err)
  2799  	}
  2800  	if pipelines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
  2801  		t.Fatal("unmarshal failed with mismatch value")
  2802  	}
  2803  }
  2804  
  2805  func TestIssue915(t *testing.T) {
  2806  	type blah struct {
  2807  		A string `toml:"a"`
  2808  	}
  2809  
  2810  	type config struct {
  2811  		Fizz string `toml:"fizz"`
  2812  		blah `toml:"blah"`
  2813  	}
  2814  
  2815  	b := []byte(`
  2816  fizz = "abc"
  2817  blah.a = "def"`)
  2818  	var cfg config
  2819  	err := toml.Unmarshal(b, &cfg)
  2820  	require.NoError(t, err)
  2821  
  2822  	require.Equal(t, "abc", cfg.Fizz)
  2823  	require.Equal(t, "def", cfg.blah.A)
  2824  	require.Equal(t, "def", cfg.A)
  2825  }
  2826  
  2827  func TestIssue931(t *testing.T) {
  2828  	type item struct {
  2829  		Name string
  2830  	}
  2831  
  2832  	type items struct {
  2833  		Slice []item
  2834  	}
  2835  
  2836  	its := items{[]item{{"a"}, {"b"}}}
  2837  
  2838  	b := []byte(`
  2839  	[[Slice]]
  2840    Name = 'c'
  2841  
  2842  [[Slice]]
  2843    Name = 'd'
  2844  	`)
  2845  
  2846  	toml.Unmarshal(b, &its)
  2847  	require.Equal(t, items{[]item{{"c"}, {"d"}}}, its)
  2848  }
  2849  
  2850  func TestIssue931Interface(t *testing.T) {
  2851  	type items struct {
  2852  		Slice interface{}
  2853  	}
  2854  
  2855  	type item = map[string]interface{}
  2856  
  2857  	its := items{[]interface{}{item{"Name": "a"}, item{"Name": "b"}}}
  2858  
  2859  	b := []byte(`
  2860  	[[Slice]]
  2861    Name = 'c'
  2862  
  2863  [[Slice]]
  2864    Name = 'd'
  2865  	`)
  2866  
  2867  	toml.Unmarshal(b, &its)
  2868  	require.Equal(t, items{[]interface{}{item{"Name": "c"}, item{"Name": "d"}}}, its)
  2869  }
  2870  
  2871  func TestIssue931SliceInterface(t *testing.T) {
  2872  	type items struct {
  2873  		Slice []interface{}
  2874  	}
  2875  
  2876  	type item = map[string]interface{}
  2877  
  2878  	its := items{
  2879  		[]interface{}{
  2880  			item{"Name": "a"},
  2881  			item{"Name": "b"},
  2882  		},
  2883  	}
  2884  
  2885  	b := []byte(`
  2886  	[[Slice]]
  2887    Name = 'c'
  2888  
  2889  [[Slice]]
  2890    Name = 'd'
  2891  	`)
  2892  
  2893  	toml.Unmarshal(b, &its)
  2894  	require.Equal(t, items{[]interface{}{item{"Name": "c"}, item{"Name": "d"}}}, its)
  2895  }
  2896  
  2897  func TestUnmarshalDecodeErrors(t *testing.T) {
  2898  	examples := []struct {
  2899  		desc string
  2900  		data string
  2901  		msg  string
  2902  	}{
  2903  		{
  2904  			desc: "local date with invalid digit",
  2905  			data: `a = 20x1-05-21`,
  2906  		},
  2907  		{
  2908  			desc: "local time with fractional",
  2909  			data: `a = 11:22:33.x`,
  2910  		},
  2911  		{
  2912  			desc: "wrong time offset separator",
  2913  			data: `a = 1979-05-27T00:32:00.-07:00`,
  2914  		},
  2915  		{
  2916  			desc: "wrong time offset separator",
  2917  			data: `a = 1979-05-27T00:32:00Z07:00`,
  2918  		},
  2919  		{
  2920  			desc: "float with double _",
  2921  			data: `flt8 = 224_617.445_991__228`,
  2922  		},
  2923  		{
  2924  			desc: "float with double .",
  2925  			data: `flt8 = 1..2`,
  2926  		},
  2927  		{
  2928  			desc: "number with plus sign and leading underscore",
  2929  			data: `a = +_0`,
  2930  		},
  2931  		{
  2932  			desc: "number with negative sign and leading underscore",
  2933  			data: `a = -_0`,
  2934  		},
  2935  		{
  2936  			desc: "exponent with plus sign and leading underscore",
  2937  			data: `a = 0e+_0`,
  2938  		},
  2939  		{
  2940  			desc: "exponent with negative sign and leading underscore",
  2941  			data: `a = 0e-_0`,
  2942  		},
  2943  		{
  2944  			desc: "int with wrong base",
  2945  			data: `a = 0f2`,
  2946  		},
  2947  		{
  2948  			desc: "int hex with double underscore",
  2949  			data: `a = 0xFFF__FFF`,
  2950  		},
  2951  		{
  2952  			desc: "int hex very large",
  2953  			data: `a = 0xFFFFFFFFFFFFFFFFF`,
  2954  		},
  2955  		{
  2956  			desc: "int oct with double underscore",
  2957  			data: `a = 0o777__77`,
  2958  		},
  2959  		{
  2960  			desc: "int oct very large",
  2961  			data: `a = 0o77777777777777777777777`,
  2962  		},
  2963  		{
  2964  			desc: "int bin with double underscore",
  2965  			data: `a = 0b111__111`,
  2966  		},
  2967  		{
  2968  			desc: "int bin very large",
  2969  			data: `a = 0b11111111111111111111111111111111111111111111111111111111111111111111111111111`,
  2970  		},
  2971  		{
  2972  			desc: "int dec very large",
  2973  			data: `a = 999999999999999999999999`,
  2974  		},
  2975  		{
  2976  			desc: "literal string with new lines",
  2977  			data: `a = 'hello
  2978  world'`,
  2979  			msg: `literal strings cannot have new lines`,
  2980  		},
  2981  		{
  2982  			desc: "unterminated literal string",
  2983  			data: `a = 'hello`,
  2984  			msg:  `unterminated literal string`,
  2985  		},
  2986  		{
  2987  			desc: "unterminated multiline literal string",
  2988  			data: `a = '''hello`,
  2989  			msg:  `multiline literal string not terminated by '''`,
  2990  		},
  2991  		{
  2992  			desc: "basic string with new lines",
  2993  			data: `a = "hello
  2994  "`,
  2995  			msg: `basic strings cannot have new lines`,
  2996  		},
  2997  		{
  2998  			desc: "basic string with unfinished escape",
  2999  			data: `a = "hello \`,
  3000  			msg:  `need a character after \`,
  3001  		},
  3002  		{
  3003  			desc: "basic unfinished multiline string",
  3004  			data: `a = """hello`,
  3005  			msg:  `multiline basic string not terminated by """`,
  3006  		},
  3007  		{
  3008  			desc: "basic unfinished escape in multiline string",
  3009  			data: `a = """hello \`,
  3010  			msg:  `need a character after \`,
  3011  		},
  3012  		{
  3013  			desc: "malformed local date",
  3014  			data: `a = 2021-033-0`,
  3015  			msg:  `dates are expected to have the format YYYY-MM-DD`,
  3016  		},
  3017  		{
  3018  			desc: "malformed tz",
  3019  			data: `a = 2021-03-30 21:31:00+1`,
  3020  			msg:  `invalid date-time timezone`,
  3021  		},
  3022  		{
  3023  			desc: "malformed tz first char",
  3024  			data: `a = 2021-03-30 21:31:00:1`,
  3025  			msg:  `extra characters at the end of a local date time`,
  3026  		},
  3027  		{
  3028  			desc: "bad char between hours and minutes",
  3029  			data: `a = 2021-03-30 213:1:00`,
  3030  			msg:  `expecting colon between hours and minutes`,
  3031  		},
  3032  		{
  3033  			desc: "bad char between minutes and seconds",
  3034  			data: `a = 2021-03-30 21:312:0`,
  3035  			msg:  `expecting colon between minutes and seconds`,
  3036  		},
  3037  		{
  3038  			desc: "invalid hour value",
  3039  			data: `a=1979-05-27T90:+2:99`,
  3040  			msg:  `hour cannot be greater 23`,
  3041  		},
  3042  		{
  3043  			desc: "invalid minutes value",
  3044  			data: `a=1979-05-27T23:+2:99`,
  3045  			msg:  `expected digit (0-9)`,
  3046  		},
  3047  		{
  3048  			desc: "invalid seconds value",
  3049  			data: `a=1979-05-27T12:45:99`,
  3050  			msg:  `seconds cannot be greater 60`,
  3051  		},
  3052  		{
  3053  			desc: `binary with invalid digit`,
  3054  			data: `a = 0bf`,
  3055  		},
  3056  		{
  3057  			desc: `invalid i in dec`,
  3058  			data: `a = 0i`,
  3059  		},
  3060  		{
  3061  			desc: `invalid n in dec`,
  3062  			data: `a = 0n`,
  3063  		},
  3064  		{
  3065  			desc: `invalid unquoted key`,
  3066  			data: `a`,
  3067  		},
  3068  		{
  3069  			desc: "dt with tz has no time",
  3070  			data: `a = 2021-03-30TZ`,
  3071  		},
  3072  		{
  3073  			desc: "invalid end of array table",
  3074  			data: `[[a}`,
  3075  		},
  3076  		{
  3077  			desc: "invalid end of array table two",
  3078  			data: `[[a]}`,
  3079  		},
  3080  		{
  3081  			desc: "eof after equal",
  3082  			data: `a =`,
  3083  		},
  3084  		{
  3085  			desc: "invalid true boolean",
  3086  			data: `a = trois`,
  3087  		},
  3088  		{
  3089  			desc: "invalid false boolean",
  3090  			data: `a = faux`,
  3091  		},
  3092  		{
  3093  			desc: "inline table with incorrect separator",
  3094  			data: `a = {b=1;}`,
  3095  		},
  3096  		{
  3097  			desc: "inline table with invalid value",
  3098  			data: `a = {b=faux}`,
  3099  		},
  3100  		{
  3101  			desc: `incomplete array after whitespace`,
  3102  			data: `a = [ `,
  3103  		},
  3104  		{
  3105  			desc: `array with comma first`,
  3106  			data: `a = [ ,]`,
  3107  		},
  3108  		{
  3109  			desc: `array staring with incomplete newline`,
  3110  			data: "a = [\r]",
  3111  		},
  3112  		{
  3113  			desc: `array with incomplete newline after comma`,
  3114  			data: "a = [1,\r]",
  3115  		},
  3116  		{
  3117  			desc: `array with incomplete newline after value`,
  3118  			data: "a = [1\r]",
  3119  		},
  3120  		{
  3121  			desc: `invalid unicode in basic multiline string`,
  3122  			data: `A = """\u123"""`,
  3123  		},
  3124  		{
  3125  			desc: `invalid long unicode in basic multiline string`,
  3126  			data: `A = """\U0001D11"""`,
  3127  		},
  3128  		{
  3129  			desc: `invalid unicode in basic string`,
  3130  			data: `A = "\u123"`,
  3131  		},
  3132  		{
  3133  			desc: `invalid long unicode in basic string`,
  3134  			data: `A = "\U0001D11"`,
  3135  		},
  3136  		{
  3137  			desc: `invalid escape char basic multiline string`,
  3138  			data: `A = """\z"""`,
  3139  		},
  3140  		{
  3141  			desc: `invalid inf`,
  3142  			data: `A = ick`,
  3143  		},
  3144  		{
  3145  			desc: `invalid nan`,
  3146  			data: `A = non`,
  3147  		},
  3148  		{
  3149  			desc: `invalid character in comment in array`,
  3150  			data: "A = [#\x00\n]",
  3151  		},
  3152  		{
  3153  			desc: "invalid utf8 character in long string with no escape sequence",
  3154  			data: "a = \"aaaa\x80aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
  3155  		},
  3156  		{
  3157  			desc: "invalid ascii character in long string with no escape sequence",
  3158  			data: "a = \"aaaa\x00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"",
  3159  		},
  3160  		{
  3161  			desc: "unfinished 2-byte utf8 character in string with no escape sequence",
  3162  			data: "a = \"aaaa\xC2\"",
  3163  		},
  3164  		{
  3165  			desc: "unfinished 3-byte utf8 character in string with no escape sequence",
  3166  			data: "a = \"aaaa\xE2\x00\x00\"",
  3167  		},
  3168  		{
  3169  			desc: "invalid 3rd byte of 3-byte utf8 character in string with no escape sequence",
  3170  			data: "a = \"aaaa\xE2\x80\x00\"",
  3171  		},
  3172  		{
  3173  			desc: "invalid 4th byte of 4-byte utf8 character in string with no escape sequence",
  3174  			data: "a = \"aaaa\xF2\x81\x81\x00\"",
  3175  		},
  3176  		{
  3177  			desc: "unfinished 2-byte utf8 character in literal string",
  3178  			data: "a = 'aaa\xC2'",
  3179  		},
  3180  		{
  3181  			desc: "unfinished 3-byte utf8 character in literal string",
  3182  			data: "a = 'aaaa\xE2\x00\x00'",
  3183  		},
  3184  		{
  3185  			desc: "invalid 3rd byte of 3-byte utf8 character in literal string",
  3186  			data: "a = 'aaaa\xE2\x80\x00'",
  3187  		},
  3188  		{
  3189  			desc: "invalid 4th byte of 4-byte utf8 character in literal string",
  3190  			data: "a = 'aaaa\xF2\x81\x81\x00'",
  3191  		},
  3192  		{
  3193  			desc: "invalid start utf8 character in literal string",
  3194  			data: "a = '\x80'",
  3195  		},
  3196  		{
  3197  			desc: "utf8 character with not enough bytes before end in literal string",
  3198  			data: "a = '\xEF'",
  3199  		},
  3200  		{
  3201  			desc: "basic string with newline after the first escape code",
  3202  			data: "a = \"\\t\n\"",
  3203  		},
  3204  		{
  3205  			desc: "basic string with unfinished escape sequence after the first escape code",
  3206  			data: "a = \"\\t\\",
  3207  		},
  3208  		{
  3209  			desc: "basic string with unfinished after the first escape code",
  3210  			data: "a = \"\\t",
  3211  		},
  3212  		{
  3213  			desc: "multiline basic string with unfinished escape sequence after the first escape code",
  3214  			data: "a = \"\"\"\\t\\",
  3215  		},
  3216  		{
  3217  			desc: `impossible date-day`,
  3218  			data: `A = 2021-03-40T23:59:00`,
  3219  			msg:  `impossible date`,
  3220  		},
  3221  		{
  3222  			desc: `leap day in non-leap year`,
  3223  			data: `A = 2021-02-29T23:59:00`,
  3224  			msg:  `impossible date`,
  3225  		},
  3226  		{
  3227  			desc: `missing minute digit`,
  3228  			data: `a=17:4::01`,
  3229  		},
  3230  		{
  3231  			desc: `invalid space in year`,
  3232  			data: `i=19 7-12-21T10:32:00`,
  3233  		},
  3234  		{
  3235  			desc: `missing nanoseconds digits`,
  3236  			data: `a=17:45:56.`,
  3237  		},
  3238  		{
  3239  			desc: `minutes over 60`,
  3240  			data: `a=17:99:00`,
  3241  		},
  3242  		{
  3243  			desc: `invalid second`,
  3244  			data: `a=17:00::0`,
  3245  		},
  3246  		{
  3247  			desc: `invalid hour`,
  3248  			data: `a=1::00:00`,
  3249  		},
  3250  		{
  3251  			desc: `invalid month`,
  3252  			data: `a=2021-0--29`,
  3253  		},
  3254  		{
  3255  			desc: `zero is an invalid day`,
  3256  			data: `a=2021-11-00`,
  3257  		},
  3258  		{
  3259  			desc: `zero is an invalid month`,
  3260  			data: `a=2021-00-11`,
  3261  		},
  3262  		{
  3263  			desc: `invalid number of seconds digits with trailing digit`,
  3264  			data: `a=0000-01-01 00:00:000000Z3`,
  3265  		},
  3266  		{
  3267  			desc: `invalid zone offset hours`,
  3268  			data: `a=0000-01-01 00:00:00+24:00`,
  3269  		},
  3270  		{
  3271  			desc: `invalid zone offset minutes`,
  3272  			data: `a=0000-01-01 00:00:00+00:60`,
  3273  		},
  3274  		{
  3275  			desc: `invalid character in zone offset hours`,
  3276  			data: `a=0000-01-01 00:00:00+0Z:00`,
  3277  		},
  3278  		{
  3279  			desc: `invalid character in zone offset minutes`,
  3280  			data: `a=0000-01-01 00:00:00+00:0Z`,
  3281  		},
  3282  		{
  3283  			desc: `invalid number of seconds`,
  3284  			data: `a=0000-01-01 00:00:00+27000`,
  3285  		},
  3286  		{
  3287  			desc: `carriage return inside basic key`,
  3288  			data: "\"\r\"=42",
  3289  		},
  3290  		{
  3291  			desc: `carriage return inside literal key`,
  3292  			data: "'\r'=42",
  3293  		},
  3294  		{
  3295  			desc: `carriage return inside basic string`,
  3296  			data: "A = \"\r\"",
  3297  		},
  3298  		{
  3299  			desc: `carriage return inside basic multiline string`,
  3300  			data: "a=\"\"\"\r\"\"\"",
  3301  		},
  3302  		{
  3303  			desc: `carriage return at the trail of basic multiline string`,
  3304  			data: "a=\"\"\"\r",
  3305  		},
  3306  		{
  3307  			desc: `carriage return inside literal string`,
  3308  			data: "A = '\r'",
  3309  		},
  3310  		{
  3311  			desc: `carriage return inside multiline literal string`,
  3312  			data: "a='''\r'''",
  3313  		},
  3314  		{
  3315  			desc: `carriage return at trail of multiline literal string`,
  3316  			data: "a='''\r",
  3317  		},
  3318  		{
  3319  			desc: `carriage return in comment`,
  3320  			data: "# this is a test\ra=1",
  3321  		},
  3322  		{
  3323  			desc: `backspace in comment`,
  3324  			data: "# this is a test\ba=1",
  3325  		},
  3326  	}
  3327  
  3328  	for _, e := range examples {
  3329  		e := e
  3330  		t.Run(e.desc, func(t *testing.T) {
  3331  			m := map[string]interface{}{}
  3332  			err := toml.Unmarshal([]byte(e.data), &m)
  3333  			require.Error(t, err)
  3334  
  3335  			var de *toml.DecodeError
  3336  			if !errors.As(err, &de) {
  3337  				t.Fatalf("err should have been a *toml.DecodeError, but got %s (%T)", err, err)
  3338  			}
  3339  
  3340  			if e.msg != "" {
  3341  				t.Log("\n" + de.String())
  3342  				require.Equal(t, "toml: "+e.msg, de.Error())
  3343  			}
  3344  		})
  3345  	}
  3346  }
  3347  
  3348  func TestOmitEmpty(t *testing.T) {
  3349  	type inner struct {
  3350  		private string
  3351  		Skip    string `toml:"-"`
  3352  		V       string
  3353  	}
  3354  
  3355  	type elem struct {
  3356  		Foo   string `toml:",omitempty"`
  3357  		Bar   string `toml:",omitempty"`
  3358  		Inner inner  `toml:",omitempty"`
  3359  	}
  3360  
  3361  	type doc struct {
  3362  		X []elem `toml:",inline"`
  3363  	}
  3364  
  3365  	d := doc{X: []elem{elem{
  3366  		Foo: "test",
  3367  		Inner: inner{
  3368  			V: "alue",
  3369  		},
  3370  	}}}
  3371  
  3372  	b, err := toml.Marshal(d)
  3373  	require.NoError(t, err)
  3374  
  3375  	require.Equal(t, "X = [{Foo = 'test', Inner = {V = 'alue'}}]\n", string(b))
  3376  }
  3377  
  3378  func TestUnmarshalTags(t *testing.T) {
  3379  	type doc struct {
  3380  		Dash   string `toml:"-,"`
  3381  		Ignore string `toml:"-"`
  3382  		A      string `toml:"hello"`
  3383  		B      string `toml:"comma,omitempty"`
  3384  	}
  3385  
  3386  	data := `
  3387  '-' = "dash"
  3388  Ignore = 'me'
  3389  hello = 'content'
  3390  comma = 'ok'
  3391  `
  3392  
  3393  	d := doc{}
  3394  	expected := doc{
  3395  		Dash:   "dash",
  3396  		Ignore: "",
  3397  		A:      "content",
  3398  		B:      "ok",
  3399  	}
  3400  
  3401  	err := toml.Unmarshal([]byte(data), &d)
  3402  	require.NoError(t, err)
  3403  	require.Equal(t, expected, d)
  3404  }
  3405  
  3406  func TestASCIIControlCharacters(t *testing.T) {
  3407  	invalidCharacters := []byte{0x7F}
  3408  	for c := byte(0x0); c <= 0x08; c++ {
  3409  		invalidCharacters = append(invalidCharacters, c)
  3410  	}
  3411  	for c := byte(0x0B); c <= 0x0C; c++ {
  3412  		invalidCharacters = append(invalidCharacters, c)
  3413  	}
  3414  	for c := byte(0x0E); c <= 0x1F; c++ {
  3415  		invalidCharacters = append(invalidCharacters, c)
  3416  	}
  3417  
  3418  	type stringType struct {
  3419  		Delimiter string
  3420  		CanEscape bool
  3421  	}
  3422  
  3423  	stringTypes := map[string]stringType{
  3424  		"basic":            {Delimiter: "\"", CanEscape: true},
  3425  		"basicMultiline":   {Delimiter: "\"\"\"", CanEscape: true},
  3426  		"literal":          {Delimiter: "'", CanEscape: false},
  3427  		"literalMultiline": {Delimiter: "'''", CanEscape: false},
  3428  	}
  3429  
  3430  	checkError := func(t *testing.T, input []byte) {
  3431  		t.Helper()
  3432  		m := map[string]interface{}{}
  3433  		err := toml.Unmarshal(input, &m)
  3434  		require.Error(t, err)
  3435  
  3436  		var de *toml.DecodeError
  3437  		if !errors.As(err, &de) {
  3438  			t.Fatalf("err should have been a *toml.DecodeError, but got %s (%T)", err, err)
  3439  		}
  3440  	}
  3441  
  3442  	for name, st := range stringTypes {
  3443  		t.Run(name, func(t *testing.T) {
  3444  			for _, c := range invalidCharacters {
  3445  				name := fmt.Sprintf("%2X", c)
  3446  				t.Run(name, func(t *testing.T) {
  3447  					data := []byte("A = " + st.Delimiter + string(c) + st.Delimiter)
  3448  					checkError(t, data)
  3449  
  3450  					if st.CanEscape {
  3451  						t.Run("withEscapeBefore", func(t *testing.T) {
  3452  							data := []byte("A = " + st.Delimiter + "\\t" + string(c) + st.Delimiter)
  3453  							checkError(t, data)
  3454  						})
  3455  						t.Run("withEscapeAfter", func(t *testing.T) {
  3456  							data := []byte("A = " + st.Delimiter + string(c) + "\\t" + st.Delimiter)
  3457  							checkError(t, data)
  3458  						})
  3459  					}
  3460  				})
  3461  			}
  3462  		})
  3463  	}
  3464  }
  3465  
  3466  //nolint:funlen
  3467  func TestLocalDateTime(t *testing.T) {
  3468  	examples := []struct {
  3469  		desc  string
  3470  		input string
  3471  		prec  int
  3472  	}{
  3473  		{
  3474  			desc:  "9 digits zero nanoseconds",
  3475  			input: "2006-01-02T15:04:05.000000000",
  3476  			prec:  9,
  3477  		},
  3478  		{
  3479  			desc:  "9 digits",
  3480  			input: "2006-01-02T15:04:05.123456789",
  3481  			prec:  9,
  3482  		},
  3483  		{
  3484  			desc:  "8 digits",
  3485  			input: "2006-01-02T15:04:05.12345678",
  3486  			prec:  8,
  3487  		},
  3488  		{
  3489  			desc:  "7 digits",
  3490  			input: "2006-01-02T15:04:05.1234567",
  3491  			prec:  7,
  3492  		},
  3493  		{
  3494  			desc:  "6 digits",
  3495  			input: "2006-01-02T15:04:05.123456",
  3496  			prec:  6,
  3497  		},
  3498  		{
  3499  			desc:  "5 digits",
  3500  			input: "2006-01-02T15:04:05.12345",
  3501  			prec:  5,
  3502  		},
  3503  		{
  3504  			desc:  "4 digits",
  3505  			input: "2006-01-02T15:04:05.1234",
  3506  			prec:  4,
  3507  		},
  3508  		{
  3509  			desc:  "3 digits",
  3510  			input: "2006-01-02T15:04:05.123",
  3511  			prec:  3,
  3512  		},
  3513  		{
  3514  			desc:  "2 digits",
  3515  			input: "2006-01-02T15:04:05.12",
  3516  			prec:  2,
  3517  		},
  3518  		{
  3519  			desc:  "1 digit",
  3520  			input: "2006-01-02T15:04:05.1",
  3521  			prec:  1,
  3522  		},
  3523  		{
  3524  			desc:  "0 digit",
  3525  			input: "2006-01-02T15:04:05",
  3526  		},
  3527  	}
  3528  
  3529  	for _, e := range examples {
  3530  		e := e
  3531  		t.Run(e.desc, func(t *testing.T) {
  3532  			t.Log("input:", e.input)
  3533  			doc := `a = ` + e.input
  3534  			m := map[string]toml.LocalDateTime{}
  3535  			err := toml.Unmarshal([]byte(doc), &m)
  3536  			require.NoError(t, err)
  3537  			actual := m["a"]
  3538  			golang, err := time.Parse("2006-01-02T15:04:05.999999999", e.input)
  3539  			require.NoError(t, err)
  3540  			expected := toml.LocalDateTime{
  3541  				toml.LocalDate{golang.Year(), int(golang.Month()), golang.Day()},
  3542  				toml.LocalTime{golang.Hour(), golang.Minute(), golang.Second(), golang.Nanosecond(), e.prec},
  3543  			}
  3544  			require.Equal(t, expected, actual)
  3545  		})
  3546  	}
  3547  }
  3548  
  3549  func TestUnmarshal_RecursiveTable(t *testing.T) {
  3550  	type Foo struct {
  3551  		I int
  3552  		F *Foo
  3553  	}
  3554  
  3555  	examples := []struct {
  3556  		desc     string
  3557  		input    string
  3558  		expected string
  3559  		err      bool
  3560  	}{
  3561  		{
  3562  			desc: "simplest",
  3563  			input: `
  3564  				I=1
  3565  			`,
  3566  			expected: `{"I":1,"F":null}`,
  3567  		},
  3568  		{
  3569  			desc: "depth 1",
  3570  			input: `
  3571  				I=1
  3572  				[F]
  3573  				I=2
  3574  			`,
  3575  			expected: `{"I":1,"F":{"I":2,"F":null}}`,
  3576  		},
  3577  		{
  3578  			desc: "depth 3",
  3579  			input: `
  3580  				I=1
  3581  				[F]
  3582  				I=2
  3583  				[F.F]
  3584  				I=3
  3585  			`,
  3586  			expected: `{"I":1,"F":{"I":2,"F":{"I":3,"F":null}}}`,
  3587  		},
  3588  		{
  3589  			desc: "depth 4",
  3590  			input: `
  3591  				I=1
  3592  				[F]
  3593  				I=2
  3594  				[F.F]
  3595  				I=3
  3596  				[F.F.F]
  3597  				I=4
  3598  			`,
  3599  			expected: `{"I":1,"F":{"I":2,"F":{"I":3,"F":{"I":4,"F":null}}}}`,
  3600  		},
  3601  		{
  3602  			desc: "skip mid step",
  3603  			input: `
  3604  				I=1
  3605  				[F.F]
  3606  				I=7
  3607  			`,
  3608  			expected: `{"I":1,"F":{"I":0,"F":{"I":7,"F":null}}}`,
  3609  		},
  3610  	}
  3611  
  3612  	for _, ex := range examples {
  3613  		e := ex
  3614  		t.Run(e.desc, func(t *testing.T) {
  3615  			foo := Foo{}
  3616  			err := toml.Unmarshal([]byte(e.input), &foo)
  3617  			if e.err {
  3618  				require.Error(t, err)
  3619  			} else {
  3620  				require.NoError(t, err)
  3621  				j, err := json.Marshal(foo)
  3622  				require.NoError(t, err)
  3623  				assert.Equal(t, e.expected, string(j))
  3624  			}
  3625  		})
  3626  	}
  3627  }
  3628  
  3629  func TestUnmarshal_RecursiveTableArray(t *testing.T) {
  3630  	type Foo struct {
  3631  		I int
  3632  		F []*Foo
  3633  	}
  3634  
  3635  	examples := []struct {
  3636  		desc     string
  3637  		input    string
  3638  		expected string
  3639  		err      bool
  3640  	}{
  3641  		{
  3642  			desc: "simplest",
  3643  			input: `
  3644  				I=1
  3645  				F=[]
  3646  			`,
  3647  			expected: `{"I":1,"F":[]}`,
  3648  		},
  3649  		{
  3650  			desc: "depth 1",
  3651  			input: `
  3652  				I=1
  3653  				[[F]]
  3654  				I=2
  3655  				F=[]
  3656  			`,
  3657  			expected: `{"I":1,"F":[{"I":2,"F":[]}]}`,
  3658  		},
  3659  		{
  3660  			desc: "depth 2",
  3661  			input: `
  3662  				I=1
  3663  				[[F]]
  3664  				I=2
  3665  				[[F.F]]
  3666  				I=3
  3667  				F=[]
  3668  			`,
  3669  			expected: `{"I":1,"F":[{"I":2,"F":[{"I":3,"F":[]}]}]}`,
  3670  		},
  3671  		{
  3672  			desc: "depth 3",
  3673  			input: `
  3674  				I=1
  3675  				[[F]]
  3676  				I=2
  3677  				[[F.F]]
  3678  				I=3
  3679  				[[F.F.F]]
  3680  				I=4
  3681  				F=[]
  3682  			`,
  3683  			expected: `{"I":1,"F":[{"I":2,"F":[{"I":3,"F":[{"I":4,"F":[]}]}]}]}`,
  3684  		},
  3685  		{
  3686  			desc: "depth 4",
  3687  			input: `
  3688  				I=1
  3689  				[[F]]
  3690  				I=2
  3691  				[[F.F]]
  3692  				I=3
  3693  				[[F.F.F]]
  3694  				I=4
  3695  				[[F.F.F.F]]
  3696  				I=5
  3697  				F=[]
  3698  			`,
  3699  			expected: `{"I":1,"F":[{"I":2,"F":[{"I":3,"F":[{"I":4,"F":[{"I":5,"F":[]}]}]}]}]}`,
  3700  		},
  3701  	}
  3702  
  3703  	for _, ex := range examples {
  3704  		e := ex
  3705  		t.Run(e.desc, func(t *testing.T) {
  3706  			foo := Foo{}
  3707  			err := toml.Unmarshal([]byte(e.input), &foo)
  3708  			if e.err {
  3709  				require.Error(t, err)
  3710  			} else {
  3711  				require.NoError(t, err)
  3712  				j, err := json.Marshal(foo)
  3713  				require.NoError(t, err)
  3714  				assert.Equal(t, e.expected, string(j))
  3715  			}
  3716  		})
  3717  	}
  3718  }
  3719  
  3720  func TestUnmarshalEmbedNonString(t *testing.T) {
  3721  	type Foo []byte
  3722  	type doc struct {
  3723  		Foo
  3724  	}
  3725  
  3726  	d := doc{}
  3727  
  3728  	err := toml.Unmarshal([]byte(`foo = 'bar'`), &d)
  3729  	require.NoError(t, err)
  3730  	require.Nil(t, d.Foo)
  3731  }
  3732  
  3733  func TestUnmarshal_Nil(t *testing.T) {
  3734  	type Foo struct {
  3735  		Foo *Foo `toml:"foo,omitempty"`
  3736  		Bar *Foo `toml:"bar,omitempty"`
  3737  	}
  3738  
  3739  	examples := []struct {
  3740  		desc     string
  3741  		input    string
  3742  		expected string
  3743  		err      bool
  3744  	}{
  3745  		{
  3746  			desc:     "empty",
  3747  			input:    ``,
  3748  			expected: ``,
  3749  		},
  3750  		{
  3751  			desc: "simplest",
  3752  			input: `
  3753              [foo]
  3754              [foo.foo]
  3755              `,
  3756  			expected: "[foo]\n[foo.foo]\n",
  3757  		},
  3758  	}
  3759  
  3760  	for _, ex := range examples {
  3761  		e := ex
  3762  		t.Run(e.desc, func(t *testing.T) {
  3763  			foo := Foo{}
  3764  			err := toml.Unmarshal([]byte(e.input), &foo)
  3765  			if e.err {
  3766  				require.Error(t, err)
  3767  			} else {
  3768  				require.NoError(t, err)
  3769  				j, err := toml.Marshal(foo)
  3770  				require.NoError(t, err)
  3771  				assert.Equal(t, e.expected, string(j))
  3772  			}
  3773  		})
  3774  	}
  3775  }
  3776  
  3777  type CustomUnmarshalerKey struct {
  3778  	A int64
  3779  }
  3780  
  3781  func (k *CustomUnmarshalerKey) UnmarshalTOML(value *unstable.Node) error {
  3782  	item, err := strconv.ParseInt(string(value.Data), 10, 64)
  3783  	if err != nil {
  3784  		return fmt.Errorf("error converting to int64, %v", err)
  3785  	}
  3786  	k.A = item
  3787  	return nil
  3788  
  3789  }
  3790  
  3791  func TestUnmarshal_CustomUnmarshaler(t *testing.T) {
  3792  	type MyConfig struct {
  3793  		Unmarshalers []CustomUnmarshalerKey `toml:"unmarshalers"`
  3794  		Foo          *string                `toml:"foo,omitempty"`
  3795  	}
  3796  
  3797  	examples := []struct {
  3798  		desc                        string
  3799  		disableUnmarshalerInterface bool
  3800  		input                       string
  3801  		expected                    MyConfig
  3802  		err                         bool
  3803  	}{
  3804  		{
  3805  			desc:     "empty",
  3806  			input:    ``,
  3807  			expected: MyConfig{Unmarshalers: []CustomUnmarshalerKey{}, Foo: nil},
  3808  		},
  3809  		{
  3810  			desc:  "simple",
  3811  			input: `unmarshalers = [1,2,3]`,
  3812  			expected: MyConfig{
  3813  				Unmarshalers: []CustomUnmarshalerKey{
  3814  					{A: 1},
  3815  					{A: 2},
  3816  					{A: 3},
  3817  				},
  3818  				Foo: nil,
  3819  			},
  3820  		},
  3821  		{
  3822  			desc: "unmarshal string and custom unmarshaler",
  3823  			input: `unmarshalers = [1,2,3]
  3824  foo = "bar"`,
  3825  			expected: MyConfig{
  3826  				Unmarshalers: []CustomUnmarshalerKey{
  3827  					{A: 1},
  3828  					{A: 2},
  3829  					{A: 3},
  3830  				},
  3831  				Foo: func(v string) *string {
  3832  					return &v
  3833  				}("bar"),
  3834  			},
  3835  		},
  3836  		{
  3837  			desc:                        "simple example, but unmarshaler interface disabled",
  3838  			disableUnmarshalerInterface: true,
  3839  			input:                       `unmarshalers = [1,2,3]`,
  3840  			err:                         true,
  3841  		},
  3842  	}
  3843  
  3844  	for _, ex := range examples {
  3845  		e := ex
  3846  		t.Run(e.desc, func(t *testing.T) {
  3847  			foo := MyConfig{}
  3848  
  3849  			decoder := toml.NewDecoder(bytes.NewReader([]byte(e.input)))
  3850  			if !ex.disableUnmarshalerInterface {
  3851  				decoder.EnableUnmarshalerInterface()
  3852  			}
  3853  			err := decoder.Decode(&foo)
  3854  
  3855  			if e.err {
  3856  				require.Error(t, err)
  3857  			} else {
  3858  				require.NoError(t, err)
  3859  				require.Equal(t, len(foo.Unmarshalers), len(e.expected.Unmarshalers))
  3860  				for i := 0; i < len(foo.Unmarshalers); i++ {
  3861  					require.Equal(t, foo.Unmarshalers[i], e.expected.Unmarshalers[i])
  3862  				}
  3863  				require.Equal(t, foo.Foo, e.expected.Foo)
  3864  			}
  3865  		})
  3866  	}
  3867  }
  3868  

View as plain text