...

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

View as plain text