github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/internal/third_party/yaml/decode_test.go (about)

     1  package yaml_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/joomcode/cue/cue/ast"
    13  	"github.com/joomcode/cue/cue/format"
    14  	"github.com/joomcode/cue/internal/cuetest"
    15  	"github.com/joomcode/cue/internal/third_party/yaml"
    16  )
    17  
    18  var unmarshalIntTest = 123
    19  
    20  var unmarshalTests = []struct {
    21  	data string
    22  	want string
    23  }{
    24  	{
    25  		"",
    26  		"",
    27  	},
    28  	{
    29  		"{}",
    30  		"",
    31  	}, {
    32  		"v: hi",
    33  		`v: "hi"`,
    34  	}, {
    35  		"v: hi",
    36  		`v: "hi"`,
    37  	}, {
    38  		"v: true",
    39  		"v: true",
    40  	}, {
    41  		"v: 10",
    42  		"v: 10",
    43  	}, {
    44  		"v: 0b10",
    45  		"v: 0b10",
    46  	}, {
    47  		"v: 0xA",
    48  		"v: 0xA",
    49  	}, {
    50  		"v: 4294967296",
    51  		"v: 4294967296",
    52  	}, {
    53  		"v: 0.1",
    54  		"v: 0.1",
    55  	}, {
    56  		"v: .1",
    57  		"v: 0.1",
    58  	}, {
    59  		"v: .Inf",
    60  		"v: +Inf",
    61  	}, {
    62  		"v: -.Inf",
    63  		"v: -Inf",
    64  	}, {
    65  		"v: -10",
    66  		"v: -10",
    67  	}, {
    68  		"v: -.1",
    69  		"v: -0.1",
    70  	},
    71  
    72  	// Simple values.
    73  	{
    74  		"123",
    75  		"123",
    76  	},
    77  
    78  	// Floats from spec
    79  	{
    80  		"canonical: 6.8523e+5",
    81  		"canonical: 6.8523e+5",
    82  	}, {
    83  		"expo: 685.230_15e+03",
    84  		"expo: 685.230_15e+03",
    85  	}, {
    86  		"fixed: 685_230.15",
    87  		"fixed: 685_230.15",
    88  	}, {
    89  		"neginf: -.inf",
    90  		"neginf: -Inf",
    91  	}, {
    92  		"fixed: 685_230.15",
    93  		"fixed: 685_230.15",
    94  	},
    95  	//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
    96  	//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
    97  
    98  	// Bools from spec
    99  	{
   100  		"canonical: y",
   101  		`canonical: "y"`,
   102  	}, {
   103  		"answer: n",
   104  		`answer: "n"`,
   105  	}, {
   106  		"answer: NO",
   107  		`answer: "NO"`,
   108  	}, {
   109  		"logical: True",
   110  		"logical: true",
   111  	}, {
   112  		"option: on",
   113  		`option: "on"`,
   114  	}, {
   115  		"answer: off",
   116  		`answer: "off"`,
   117  	},
   118  	// Ints from spec
   119  	{
   120  		"canonical: 685230",
   121  		"canonical: 685230",
   122  	}, {
   123  		"decimal: +685_230",
   124  		"decimal: +685_230",
   125  	}, {
   126  		"octal: 02472256",
   127  		"octal: 0o2472256",
   128  	}, {
   129  		"hexa: 0x_0A_74_AE",
   130  		"hexa: 0x_0A_74_AE",
   131  	}, {
   132  		"bin: 0b1010_0111_0100_1010_1110",
   133  		"bin: 0b1010_0111_0100_1010_1110",
   134  	}, {
   135  		"bin: -0b101010",
   136  		"bin: -0b101010",
   137  	}, {
   138  		"bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
   139  		"bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
   140  	}, {
   141  		"decimal: +685_230",
   142  		"decimal: +685_230",
   143  	},
   144  
   145  	//{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
   146  
   147  	// Nulls from spec
   148  	{
   149  		"empty:",
   150  		"empty: null",
   151  	}, {
   152  		"canonical: ~",
   153  		"canonical: null",
   154  	}, {
   155  		"english: null",
   156  		"english: null",
   157  	}, {
   158  		"_foo: 1",
   159  		`"_foo": 1`,
   160  	}, {
   161  		`"#foo": 1`,
   162  		`"#foo": 1`,
   163  	}, {
   164  		"_#foo: 1",
   165  		`"_#foo": 1`,
   166  	}, {
   167  		"~: null key",
   168  		`"null": "null key"`,
   169  	}, {
   170  		`empty:
   171  apple: "newline"`,
   172  		`empty: null
   173  apple: "newline"`,
   174  	},
   175  
   176  	// Flow sequence
   177  	{
   178  		"seq: [A,B]",
   179  		`seq: ["A", "B"]`,
   180  	}, {
   181  		"seq: [A,B,C,]",
   182  		`seq: ["A", "B", "C"]`,
   183  	}, {
   184  		"seq: [A,1,C]",
   185  		`seq: ["A", 1, "C"]`,
   186  	},
   187  	// Block sequence
   188  	{
   189  		"seq:\n - A\n - B",
   190  		`seq: [
   191  	"A",
   192  	"B",
   193  ]`,
   194  	}, {
   195  		"seq:\n - A\n - B\n - C",
   196  		`seq: [
   197  	"A",
   198  	"B",
   199  	"C",
   200  ]`,
   201  	}, {
   202  		"seq:\n - A\n - 1\n - C",
   203  		`seq: [
   204  	"A",
   205  	1,
   206  	"C",
   207  ]`,
   208  	},
   209  
   210  	// Literal block scalar
   211  	{
   212  		"scalar: | # Comment\n\n literal\n\n \ttext\n\n",
   213  		`scalar: """
   214  
   215  	literal
   216  
   217  	\ttext
   218  
   219  	"""`,
   220  	},
   221  
   222  	// Folded block scalar
   223  	{
   224  		"scalar: > # Comment\n\n folded\n line\n \n next\n line\n  * one\n  * two\n\n last\n line\n\n",
   225  		`scalar: """
   226  
   227  	folded line
   228  	next line
   229  	 * one
   230  	 * two
   231  
   232  	last line
   233  
   234  	"""`,
   235  	},
   236  
   237  	// Structs
   238  	{
   239  		"a: {b: c}",
   240  		`a: {b: "c"}`,
   241  	},
   242  	{
   243  		"hello: world",
   244  		`hello: "world"`,
   245  	}, {
   246  		"a:",
   247  		"a: null",
   248  	}, {
   249  		"a: 1",
   250  		"a: 1",
   251  	}, {
   252  		"a: 1.0",
   253  		"a: 1.0",
   254  	}, {
   255  		"a: [1, 2]",
   256  		"a: [1, 2]",
   257  	}, {
   258  		"a: y",
   259  		`a: "y"`,
   260  	}, {
   261  		"{ a: 1, b: {c: 1} }",
   262  		`a: 1, b: {c: 1}`,
   263  	}, {
   264  		`
   265  True: 1
   266  Null: 1
   267  .Inf: 2
   268  `,
   269  		`"true": 1
   270  "null": 1
   271  "+Inf": 2`,
   272  	},
   273  
   274  	// Some cross type conversions
   275  	{
   276  		"v: 42",
   277  		"v: 42",
   278  	}, {
   279  		"v: -42",
   280  		"v: -42",
   281  	}, {
   282  		"v: 4294967296",
   283  		"v: 4294967296",
   284  	}, {
   285  		"v: -4294967296",
   286  		"v: -4294967296",
   287  	},
   288  
   289  	// int
   290  	{
   291  		"int_max: 2147483647",
   292  		"int_max: 2147483647",
   293  	},
   294  	{
   295  		"int_min: -2147483648",
   296  		"int_min: -2147483648",
   297  	},
   298  	{
   299  		"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
   300  		"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
   301  	},
   302  
   303  	// int64
   304  	{
   305  		"int64_max: 9223372036854775807",
   306  		"int64_max: 9223372036854775807",
   307  	},
   308  	{
   309  		"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
   310  		"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
   311  	},
   312  	{
   313  		"int64_min: -9223372036854775808",
   314  		"int64_min: -9223372036854775808",
   315  	},
   316  	{
   317  		"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
   318  		"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
   319  	},
   320  	{
   321  		"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
   322  		"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
   323  	},
   324  
   325  	// uint
   326  	{
   327  		"uint_max: 4294967295",
   328  		"uint_max: 4294967295",
   329  	},
   330  
   331  	// uint64
   332  	{
   333  		"uint64_max: 18446744073709551615",
   334  		"uint64_max: 18446744073709551615",
   335  	},
   336  	{
   337  		"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
   338  		"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
   339  	},
   340  	{
   341  		"uint64_maxint64: 9223372036854775807",
   342  		"uint64_maxint64: 9223372036854775807",
   343  	},
   344  
   345  	// float32
   346  	{
   347  		"float32_max: 3.40282346638528859811704183484516925440e+38",
   348  		"float32_max: 3.40282346638528859811704183484516925440e+38",
   349  	},
   350  	{
   351  		"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
   352  		"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
   353  	},
   354  	{
   355  		"float32_maxuint64: 18446744073709551615",
   356  		"float32_maxuint64: 18446744073709551615",
   357  	},
   358  	{
   359  		"float32_maxuint64+1: 18446744073709551616",
   360  		`"float32_maxuint64+1": 18446744073709551616`,
   361  	},
   362  
   363  	// float64
   364  	{
   365  		"float64_max: 1.797693134862315708145274237317043567981e+308",
   366  		"float64_max: 1.797693134862315708145274237317043567981e+308",
   367  	},
   368  	{
   369  		"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
   370  		"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
   371  	},
   372  	{
   373  		"float64_maxuint64: 18446744073709551615",
   374  		"float64_maxuint64: 18446744073709551615",
   375  	},
   376  	{
   377  		"float64_maxuint64+1: 18446744073709551616",
   378  		`"float64_maxuint64+1": 18446744073709551616`,
   379  	},
   380  
   381  	// Overflow cases.
   382  	{
   383  		"v: 4294967297",
   384  		"v: 4294967297",
   385  	}, {
   386  		"v: 128",
   387  		"v: 128",
   388  	},
   389  
   390  	// Quoted values.
   391  	{
   392  		"'1': '\"2\"'",
   393  		`"1": "\"2\""`,
   394  	}, {
   395  		"v:\n- A\n- 'B\n\n  C'\n",
   396  		`v: [
   397  	"A",
   398  	"""
   399  		B
   400  		C
   401  		""",
   402  ]`,
   403  	}, {
   404  		`"\0"`,
   405  		`"\u0000"`,
   406  	},
   407  
   408  	// Explicit tags.
   409  	{
   410  		"v: !!float '1.1'",
   411  		"v: 1.1",
   412  	}, {
   413  		"v: !!float 0",
   414  		"v: float & 0", // Should this be 0.0?
   415  	}, {
   416  		"v: !!float -1",
   417  		"v: float & -1", // Should this be -1.0?
   418  	}, {
   419  		"v: !!null ''",
   420  		"v: null",
   421  	}, {
   422  		"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
   423  		"v: 1",
   424  	},
   425  
   426  	// Non-specific tag (Issue #75)
   427  	{
   428  		"v: ! test",
   429  		// TODO: map[string]interface{}{"v": "test"},
   430  		"",
   431  	},
   432  
   433  	// Anchors and aliases.
   434  	{
   435  		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
   436  		`a: 1
   437  b: 2
   438  c: 1
   439  d: 2`,
   440  	}, {
   441  		"a: &a {c: 1}\nb: *a",
   442  		`a: {c: 1}
   443  b: {
   444  	c: 1
   445  }`,
   446  	}, {
   447  		"a: &a [1, 2]\nb: *a",
   448  		"a: [1, 2]\nb: [1, 2]", // TODO: a: [1, 2], b: a
   449  	},
   450  
   451  	{
   452  		"foo: ''",
   453  		`foo: ""`,
   454  	}, {
   455  		"foo: null",
   456  		"foo: null",
   457  	},
   458  
   459  	// Support for ~
   460  	{
   461  		"foo: ~",
   462  		"foo: null",
   463  	},
   464  
   465  	// Bug #1191981
   466  	{
   467  		"" +
   468  			"%YAML 1.1\n" +
   469  			"--- !!str\n" +
   470  			`"Generic line break (no glyph)\n\` + "\n" +
   471  			` Generic line break (glyphed)\n\` + "\n" +
   472  			` Line separator\u2028\` + "\n" +
   473  			` Paragraph separator\u2029"` + "\n",
   474  		`"""
   475  	Generic line break (no glyph)
   476  	Generic line break (glyphed)
   477  	Line separator\u2028Paragraph separator\u2029
   478  	"""`,
   479  	},
   480  
   481  	// bug 1243827
   482  	{
   483  		"a: -b_c",
   484  		`a: "-b_c"`,
   485  	},
   486  	{
   487  		"a: +b_c",
   488  		`a: "+b_c"`,
   489  	},
   490  	{
   491  		"a: 50cent_of_dollar",
   492  		`a: "50cent_of_dollar"`,
   493  	},
   494  
   495  	// issue #295 (allow scalars with colons in flow mappings and sequences)
   496  	{
   497  		"a: {b: https://github.com/go-yaml/yaml}",
   498  		`a: {b: "https://github.com/go-yaml/yaml"}`,
   499  	},
   500  	{
   501  		"a: [https://github.com/go-yaml/yaml]",
   502  		`a: ["https://github.com/go-yaml/yaml"]`,
   503  	},
   504  
   505  	// Duration
   506  	{
   507  		"a: 3s",
   508  		`a: "3s"`, // for now
   509  	},
   510  
   511  	// Issue #24.
   512  	{
   513  		"a: <foo>",
   514  		`a: "<foo>"`,
   515  	},
   516  
   517  	// Base 60 floats are obsolete and unsupported.
   518  	{
   519  		"a: 1:1\n",
   520  		`a: "1:1"`,
   521  	},
   522  
   523  	// Binary data.
   524  	{
   525  		"a: !!binary gIGC\n",
   526  		`a: '\x80\x81\x82'`,
   527  	}, {
   528  		"a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
   529  		"a: '" + strings.Repeat(`\x90`, 54) + "'",
   530  	}, {
   531  		"a: !!binary |\n  " + strings.Repeat("A", 70) + "\n  ==\n",
   532  		"a: '" + strings.Repeat(`\x00`, 52) + "'",
   533  	},
   534  
   535  	// Ordered maps.
   536  	{
   537  		"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
   538  		`b: 2, a: 1, d: 4, c: 3, sub: {e: 5}`,
   539  	},
   540  
   541  	// Spacing
   542  	{
   543  		`
   544  a: {}
   545  c: 1
   546  d: [
   547  ]
   548  e: []
   549  `,
   550  		`a: {}
   551  c: 1
   552  d: [
   553  ]
   554  e: []`,
   555  	},
   556  
   557  	{
   558  		`
   559  a:
   560    - { "a": 1, "b": 2 }
   561    - { "c": 1, "d": 2 }
   562  `,
   563  		`a: [{
   564  	a: 1, b: 2
   565  }, {
   566  	c: 1, d: 2
   567  }]`,
   568  	},
   569  
   570  	{
   571  		"a:\n b:\n  c: d\n  e: f\n",
   572  		`a: {
   573  	b: {
   574  		c: "d"
   575  		e: "f"
   576  	}
   577  }`,
   578  	},
   579  
   580  	// Issue #39.
   581  	{
   582  		"a:\n b:\n  c: d\n",
   583  		`a: {
   584  	b: {
   585  		c: "d"
   586  	}
   587  }`,
   588  	},
   589  
   590  	// Timestamps
   591  	{
   592  		// Date only.
   593  		"a: 2015-01-01\n",
   594  		`a: "2015-01-01"`,
   595  	},
   596  	{
   597  		// RFC3339
   598  		"a: 2015-02-24T18:19:39.12Z\n",
   599  		`a: "2015-02-24T18:19:39.12Z"`,
   600  	},
   601  	{
   602  		// RFC3339 with short dates.
   603  		"a: 2015-2-3T3:4:5Z",
   604  		`a: "2015-2-3T3:4:5Z"`,
   605  	},
   606  	{
   607  		// ISO8601 lower case t
   608  		"a: 2015-02-24t18:19:39Z\n",
   609  		`a: "2015-02-24t18:19:39Z"`,
   610  	},
   611  	{
   612  		// space separate, no time zone
   613  		"a: 2015-02-24 18:19:39\n",
   614  		`a: "2015-02-24 18:19:39"`,
   615  	},
   616  	// Some cases not currently handled. Uncomment these when
   617  	// the code is fixed.
   618  	//	{
   619  	//		// space separated with time zone
   620  	//		"a: 2001-12-14 21:59:43.10 -5",
   621  	//		map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
   622  	//	},
   623  	//	{
   624  	//		// arbitrary whitespace between fields
   625  	//		"a: 2001-12-14 \t\t \t21:59:43.10 \t Z",
   626  	//		map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
   627  	//	},
   628  	{
   629  		// explicit string tag
   630  		"a: !!str 2015-01-01",
   631  		`a: "2015-01-01"`,
   632  	},
   633  	{
   634  		// explicit timestamp tag on quoted string
   635  		"a: !!timestamp \"2015-01-01\"",
   636  		`a: "2015-01-01"`,
   637  	},
   638  	{
   639  		// explicit timestamp tag on unquoted string
   640  		"a: !!timestamp 2015-01-01",
   641  		`a: "2015-01-01"`,
   642  	},
   643  	{
   644  		// quoted string that's a valid timestamp
   645  		"a: \"2015-01-01\"",
   646  		"a: \"2015-01-01\"",
   647  	},
   648  
   649  	// Empty list
   650  	{
   651  		"a: []",
   652  		"a: []",
   653  	},
   654  
   655  	// UTF-16-LE
   656  	{
   657  		"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
   658  		`ñoño: "very yes"`,
   659  	},
   660  	// UTF-16-LE with surrogate.
   661  	{
   662  		"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
   663  		`ñoño: "very yes 🟔"`,
   664  	},
   665  
   666  	// UTF-16-BE
   667  	{
   668  		"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
   669  		`ñoño: "very yes"`,
   670  	},
   671  	// UTF-16-BE with surrogate.
   672  	{
   673  		"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
   674  		`ñoño: "very yes 🟔"`,
   675  	},
   676  
   677  	// YAML Float regex shouldn't match this
   678  	{
   679  		"a: 123456e1\n",
   680  		`a: "123456e1"`,
   681  	}, {
   682  		"a: 123456E1\n",
   683  		`a: "123456E1"`,
   684  	},
   685  	// yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
   686  	{
   687  		"First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
   688  		`"First occurrence":  "Foo"
   689  "Second occurrence": "Foo"
   690  "Override anchor":   "Bar"
   691  "Reuse anchor":      "Bar"`,
   692  	},
   693  	// Single document with garbage following it.
   694  	{
   695  		"---\nhello\n...\n}not yaml",
   696  		`"hello"`,
   697  	},
   698  }
   699  
   700  type M map[interface{}]interface{}
   701  
   702  type inlineB struct {
   703  	B       int
   704  	inlineC `yaml:",inline"`
   705  }
   706  
   707  type inlineC struct {
   708  	C int
   709  }
   710  
   711  func cueStr(node ast.Node) string {
   712  	if s, ok := node.(*ast.StructLit); ok {
   713  		node = &ast.File{
   714  			Decls: s.Elts,
   715  		}
   716  	}
   717  	b, _ := format.Node(node)
   718  	return strings.TrimSpace(string(b))
   719  }
   720  
   721  func newDecoder(t *testing.T, data string) *yaml.Decoder {
   722  	dec, err := yaml.NewDecoder("test.yaml", strings.NewReader(data))
   723  	if err != nil {
   724  		t.Fatal(err)
   725  	}
   726  	return dec
   727  }
   728  
   729  func callUnmarshal(t *testing.T, data string) (ast.Expr, error) {
   730  	return yaml.Unmarshal("test.yaml", []byte(data))
   731  }
   732  
   733  func TestUnmarshal(t *testing.T) {
   734  	for i, item := range unmarshalTests {
   735  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   736  			t.Logf("test %d: %q", i, item.data)
   737  			expr, err := callUnmarshal(t, item.data)
   738  			if _, ok := err.(*yaml.TypeError); !ok && err != nil {
   739  				t.Fatal("expected error to be nil")
   740  			}
   741  			if got := cueStr(expr); got != item.want {
   742  				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
   743  			}
   744  		})
   745  	}
   746  }
   747  
   748  // For debug purposes: do not delete.
   749  func TestX(t *testing.T) {
   750  	y := `
   751  `
   752  	y = strings.TrimSpace(y)
   753  	if len(y) == 0 {
   754  		t.Skip()
   755  	}
   756  
   757  	expr, err := callUnmarshal(t, y)
   758  	if _, ok := err.(*yaml.TypeError); !ok && err != nil {
   759  		t.Fatal(err)
   760  	}
   761  	t.Error(cueStr(expr))
   762  }
   763  
   764  // // TODO(v3): This test should also work when unmarshaling onto an interface{}.
   765  // func (s *S) TestUnmarshalFullTimestamp(c *C) {
   766  // 	// Full timestamp in same format as encoded. This is confirmed to be
   767  // 	// properly decoded by Python as a timestamp as well.
   768  // 	var str = "2015-02-24T18:19:39.123456789-03:00"
   769  // 	expr, err := yaml.Unmarshal([]byte(str))
   770  // 	c.Assert(err, IsNil)
   771  // 	c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location()))
   772  // 	c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
   773  // }
   774  
   775  func TestDecoderSingleDocument(t *testing.T) {
   776  	// Test that Decoder.Decode works as expected on
   777  	// all the unmarshal tests.
   778  	for i, item := range unmarshalTests {
   779  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   780  			if item.data == "" {
   781  				// Behaviour differs when there's no YAML.
   782  				return
   783  			}
   784  			expr, err := newDecoder(t, item.data).Decode()
   785  			if _, ok := err.(*yaml.TypeError); !ok && err != nil {
   786  				t.Errorf("err should be nil, was %v", err)
   787  			}
   788  			if got := cueStr(expr); got != item.want {
   789  				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
   790  			}
   791  		})
   792  	}
   793  }
   794  
   795  var decoderTests = []struct {
   796  	data string
   797  	want string
   798  }{{
   799  	"",
   800  	"",
   801  }, {
   802  	"a: b",
   803  	`a: "b"`,
   804  }, {
   805  	"---\na: b\n...\n",
   806  	`a: "b"`,
   807  }, {
   808  	"---\n'hello'\n...\n---\ngoodbye\n...\n",
   809  	`"hello"` + "\n" + `"goodbye"`,
   810  }}
   811  
   812  func TestDecoder(t *testing.T) {
   813  	for i, item := range decoderTests {
   814  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   815  			var values []string
   816  			dec := newDecoder(t, item.data)
   817  			for {
   818  				expr, err := dec.Decode()
   819  				if err == io.EOF {
   820  					break
   821  				}
   822  				if err != nil {
   823  					t.Errorf("err should be nil, was %v", err)
   824  				}
   825  				values = append(values, cueStr(expr))
   826  			}
   827  			got := strings.Join(values, "\n")
   828  			if got != item.want {
   829  				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
   830  			}
   831  		})
   832  	}
   833  }
   834  
   835  type errReader struct{}
   836  
   837  func (errReader) Read([]byte) (int, error) {
   838  	return 0, errors.New("some read error")
   839  }
   840  
   841  func TestUnmarshalNaN(t *testing.T) {
   842  	expr, err := callUnmarshal(t, "notanum: .NaN")
   843  	if err != nil {
   844  		t.Fatal("unexpected error", err)
   845  	}
   846  	got := cueStr(expr)
   847  	want := "notanum: NaN"
   848  	if got != want {
   849  		t.Errorf("got %v; want %v", got, want)
   850  	}
   851  }
   852  
   853  var unmarshalErrorTests = []struct {
   854  	data, error string
   855  }{
   856  	{"\nv: !!float 'error'", "test.yaml:2: cannot decode !!str `error` as a !!float"},
   857  	{"v: [A,", "test.yaml:1: did not find expected node content"},
   858  	{"v:\n- [A,", "test.yaml:2: did not find expected node content"},
   859  	{"a:\n- b: *,", "test.yaml:2: did not find expected alphabetic or numeric character"},
   860  	{"a: *b\n", "test.yaml:1: unknown anchor 'b' referenced"},
   861  	{"a: &a\n  b: *a\n", "test.yaml:2: anchor 'a' value contains itself"},
   862  	{"value: -", "test.yaml:1: block sequence entries are not allowed in this context"},
   863  	{"a: !!binary ==", "test.yaml:1: !!binary value contains invalid base64 data"},
   864  	{"{[.]}", `test.yaml:1: invalid map key: sequence`},
   865  	{"{{.}}", `test.yaml:1: invalid map key: map`},
   866  	{"b: *a\na: &a {c: 1}", `test.yaml:1: unknown anchor 'a' referenced`},
   867  	{"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "test.yaml:1: did not find expected whitespace"},
   868  }
   869  
   870  func TestUnmarshalErrors(t *testing.T) {
   871  	for i, item := range unmarshalErrorTests {
   872  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   873  			expr, err := callUnmarshal(t, item.data)
   874  			val := ""
   875  			if expr != nil {
   876  				val = cueStr(expr)
   877  			}
   878  			if err == nil || err.Error() != item.error {
   879  				t.Errorf("got %v; want %v; (value %v)", err, item.error, val)
   880  			}
   881  		})
   882  	}
   883  }
   884  
   885  func TestDecoderErrors(t *testing.T) {
   886  	for i, item := range unmarshalErrorTests {
   887  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   888  			_, err := newDecoder(t, item.data).Decode()
   889  			if err == nil || err.Error() != item.error {
   890  				t.Errorf("got %v; want %v", err, item.error)
   891  			}
   892  		})
   893  	}
   894  }
   895  
   896  func TestFiles(t *testing.T) {
   897  	files := []string{"merge"}
   898  	for _, test := range files {
   899  		t.Run(test, func(t *testing.T) {
   900  			testname := fmt.Sprintf("testdata/%s.test", test)
   901  			filename := fmt.Sprintf("testdata/%s.out", test)
   902  			mergeTests, err := ioutil.ReadFile(testname)
   903  			if err != nil {
   904  				t.Fatal(err)
   905  			}
   906  			expr, err := yaml.Unmarshal("test.yaml", mergeTests)
   907  			if err != nil {
   908  				t.Fatal(err)
   909  			}
   910  			got := cueStr(expr)
   911  			if cuetest.UpdateGoldenFiles {
   912  				ioutil.WriteFile(filename, []byte(got), 0644)
   913  				return
   914  			}
   915  			b, err := ioutil.ReadFile(filename)
   916  			if err != nil {
   917  				t.Fatal(err)
   918  			}
   919  			if want := string(b); got != want {
   920  				t.Errorf("\n got: %v;\nwant: %v", got, want)
   921  			}
   922  		})
   923  	}
   924  }
   925  
   926  func TestFuzzCrashers(t *testing.T) {
   927  	cases := []string{
   928  		// runtime error: index out of range
   929  		"\"\\0\\\r\n",
   930  
   931  		// should not happen
   932  		"  0: [\n] 0",
   933  		"? ? \"\n\" 0",
   934  		"    - {\n000}0",
   935  		"0:\n  0: [0\n] 0",
   936  		"    - \"\n000\"0",
   937  		"    - \"\n000\"\"",
   938  		"0:\n    - {\n000}0",
   939  		"0:\n    - \"\n000\"0",
   940  		"0:\n    - \"\n000\"\"",
   941  
   942  		// runtime error: index out of range
   943  		" \ufeff\n",
   944  		"? \ufeff\n",
   945  		"? \ufeff:\n",
   946  		"0: \ufeff\n",
   947  		"? \ufeff: \ufeff\n",
   948  	}
   949  	for _, data := range cases {
   950  		_, _ = callUnmarshal(t, data)
   951  	}
   952  }
   953  
   954  //var data []byte
   955  //func init() {
   956  //	var err error
   957  //	data, err = ioutil.ReadFile("/tmp/file.yaml")
   958  //	if err != nil {
   959  //		panic(err)
   960  //	}
   961  //}
   962  //
   963  //func (s *S) BenchmarkUnmarshal(c *C) {
   964  //	var err error
   965  //	for i := 0; i < c.N; i++ {
   966  //		var v map[string]interface{}
   967  //		err = yaml.Unmarshal(data, &v)
   968  //	}
   969  //	if err != nil {
   970  //		panic(err)
   971  //	}
   972  //}
   973  //
   974  //func (s *S) BenchmarkMarshal(c *C) {
   975  //	var v map[string]interface{}
   976  //	yaml.Unmarshal(data, &v)
   977  //	c.ResetTimer()
   978  //	for i := 0; i < c.N; i++ {
   979  //		yaml.Marshal(&v)
   980  //	}
   981  //}