github.com/solo-io/cue@v0.4.7/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/solo-io/cue/cue/ast"
    13  	"github.com/solo-io/cue/cue/format"
    14  	"github.com/solo-io/cue/internal/cuetest"
    15  	"github.com/solo-io/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 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  	// Some cross type conversions
   266  	{
   267  		"v: 42",
   268  		"v: 42",
   269  	}, {
   270  		"v: -42",
   271  		"v: -42",
   272  	}, {
   273  		"v: 4294967296",
   274  		"v: 4294967296",
   275  	}, {
   276  		"v: -4294967296",
   277  		"v: -4294967296",
   278  	},
   279  
   280  	// int
   281  	{
   282  		"int_max: 2147483647",
   283  		"int_max: 2147483647",
   284  	},
   285  	{
   286  		"int_min: -2147483648",
   287  		"int_min: -2147483648",
   288  	},
   289  	{
   290  		"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
   291  		"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
   292  	},
   293  
   294  	// int64
   295  	{
   296  		"int64_max: 9223372036854775807",
   297  		"int64_max: 9223372036854775807",
   298  	},
   299  	{
   300  		"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
   301  		"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
   302  	},
   303  	{
   304  		"int64_min: -9223372036854775808",
   305  		"int64_min: -9223372036854775808",
   306  	},
   307  	{
   308  		"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
   309  		"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
   310  	},
   311  	{
   312  		"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
   313  		"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
   314  	},
   315  
   316  	// uint
   317  	{
   318  		"uint_max: 4294967295",
   319  		"uint_max: 4294967295",
   320  	},
   321  
   322  	// uint64
   323  	{
   324  		"uint64_max: 18446744073709551615",
   325  		"uint64_max: 18446744073709551615",
   326  	},
   327  	{
   328  		"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
   329  		"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
   330  	},
   331  	{
   332  		"uint64_maxint64: 9223372036854775807",
   333  		"uint64_maxint64: 9223372036854775807",
   334  	},
   335  
   336  	// float32
   337  	{
   338  		"float32_max: 3.40282346638528859811704183484516925440e+38",
   339  		"float32_max: 3.40282346638528859811704183484516925440e+38",
   340  	},
   341  	{
   342  		"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
   343  		"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
   344  	},
   345  	{
   346  		"float32_maxuint64: 18446744073709551615",
   347  		"float32_maxuint64: 18446744073709551615",
   348  	},
   349  	{
   350  		"float32_maxuint64+1: 18446744073709551616",
   351  		`"float32_maxuint64+1": 18446744073709551616`,
   352  	},
   353  
   354  	// float64
   355  	{
   356  		"float64_max: 1.797693134862315708145274237317043567981e+308",
   357  		"float64_max: 1.797693134862315708145274237317043567981e+308",
   358  	},
   359  	{
   360  		"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
   361  		"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
   362  	},
   363  	{
   364  		"float64_maxuint64: 18446744073709551615",
   365  		"float64_maxuint64: 18446744073709551615",
   366  	},
   367  	{
   368  		"float64_maxuint64+1: 18446744073709551616",
   369  		`"float64_maxuint64+1": 18446744073709551616`,
   370  	},
   371  
   372  	// Overflow cases.
   373  	{
   374  		"v: 4294967297",
   375  		"v: 4294967297",
   376  	}, {
   377  		"v: 128",
   378  		"v: 128",
   379  	},
   380  
   381  	// Quoted values.
   382  	{
   383  		"'1': '\"2\"'",
   384  		`"1": "\"2\""`,
   385  	}, {
   386  		"v:\n- A\n- 'B\n\n  C'\n",
   387  		`v: [
   388  	"A",
   389  	"""
   390  		B
   391  		C
   392  		""",
   393  ]`,
   394  	}, {
   395  		`"\0"`,
   396  		`"\u0000"`,
   397  	},
   398  
   399  	// Explicit tags.
   400  	{
   401  		"v: !!float '1.1'",
   402  		"v: 1.1",
   403  	}, {
   404  		"v: !!float 0",
   405  		"v: float & 0", // Should this be 0.0?
   406  	}, {
   407  		"v: !!float -1",
   408  		"v: float & -1", // Should this be -1.0?
   409  	}, {
   410  		"v: !!null ''",
   411  		"v: null",
   412  	}, {
   413  		"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
   414  		"v: 1",
   415  	},
   416  
   417  	// Non-specific tag (Issue #75)
   418  	{
   419  		"v: ! test",
   420  		// TODO: map[string]interface{}{"v": "test"},
   421  		"",
   422  	},
   423  
   424  	// Anchors and aliases.
   425  	{
   426  		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
   427  		`a: 1
   428  b: 2
   429  c: 1
   430  d: 2`,
   431  	}, {
   432  		"a: &a {c: 1}\nb: *a",
   433  		`a: {c: 1}
   434  b: {
   435  	c: 1
   436  }`,
   437  	}, {
   438  		"a: &a [1, 2]\nb: *a",
   439  		"a: [1, 2]\nb: [1, 2]", // TODO: a: [1, 2], b: a
   440  	},
   441  
   442  	{
   443  		"foo: ''",
   444  		`foo: ""`,
   445  	}, {
   446  		"foo: null",
   447  		"foo: null",
   448  	},
   449  
   450  	// Support for ~
   451  	{
   452  		"foo: ~",
   453  		"foo: null",
   454  	},
   455  
   456  	// Bug #1191981
   457  	{
   458  		"" +
   459  			"%YAML 1.1\n" +
   460  			"--- !!str\n" +
   461  			`"Generic line break (no glyph)\n\` + "\n" +
   462  			` Generic line break (glyphed)\n\` + "\n" +
   463  			` Line separator\u2028\` + "\n" +
   464  			` Paragraph separator\u2029"` + "\n",
   465  		`"""
   466  	Generic line break (no glyph)
   467  	Generic line break (glyphed)
   468  	Line separator\u2028Paragraph separator\u2029
   469  	"""`,
   470  	},
   471  
   472  	// bug 1243827
   473  	{
   474  		"a: -b_c",
   475  		`a: "-b_c"`,
   476  	},
   477  	{
   478  		"a: +b_c",
   479  		`a: "+b_c"`,
   480  	},
   481  	{
   482  		"a: 50cent_of_dollar",
   483  		`a: "50cent_of_dollar"`,
   484  	},
   485  
   486  	// issue #295 (allow scalars with colons in flow mappings and sequences)
   487  	{
   488  		"a: {b: https://github.com/go-yaml/yaml}",
   489  		`a: {b: "https://github.com/go-yaml/yaml"}`,
   490  	},
   491  	{
   492  		"a: [https://github.com/go-yaml/yaml]",
   493  		`a: ["https://github.com/go-yaml/yaml"]`,
   494  	},
   495  
   496  	// Duration
   497  	{
   498  		"a: 3s",
   499  		`a: "3s"`, // for now
   500  	},
   501  
   502  	// Issue #24.
   503  	{
   504  		"a: <foo>",
   505  		`a: "<foo>"`,
   506  	},
   507  
   508  	// Base 60 floats are obsolete and unsupported.
   509  	{
   510  		"a: 1:1\n",
   511  		`a: "1:1"`,
   512  	},
   513  
   514  	// Binary data.
   515  	{
   516  		"a: !!binary gIGC\n",
   517  		`a: '\x80\x81\x82'`,
   518  	}, {
   519  		"a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
   520  		"a: '" + strings.Repeat(`\x90`, 54) + "'",
   521  	}, {
   522  		"a: !!binary |\n  " + strings.Repeat("A", 70) + "\n  ==\n",
   523  		"a: '" + strings.Repeat(`\x00`, 52) + "'",
   524  	},
   525  
   526  	// Ordered maps.
   527  	{
   528  		"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
   529  		`b: 2, a: 1, d: 4, c: 3, sub: {e: 5}`,
   530  	},
   531  
   532  	// Spacing
   533  	{
   534  		`
   535  a: {}
   536  c: 1
   537  d: [
   538  ]
   539  e: []
   540  `,
   541  		`a: {}
   542  c: 1
   543  d: [
   544  ]
   545  e: []`,
   546  	},
   547  
   548  	{
   549  		`
   550  a:
   551    - { "a": 1, "b": 2 }
   552    - { "c": 1, "d": 2 }
   553  `,
   554  		`a: [{
   555  	a: 1, b: 2
   556  }, {
   557  	c: 1, d: 2
   558  }]`,
   559  	},
   560  
   561  	{
   562  		"a:\n b:\n  c: d\n  e: f\n",
   563  		`a: {
   564  	b: {
   565  		c: "d"
   566  		e: "f"
   567  	}
   568  }`,
   569  	},
   570  
   571  	// Issue #39.
   572  	{
   573  		"a:\n b:\n  c: d\n",
   574  		`a: {
   575  	b: {
   576  		c: "d"
   577  	}
   578  }`,
   579  	},
   580  
   581  	// Timestamps
   582  	{
   583  		// Date only.
   584  		"a: 2015-01-01\n",
   585  		`a: "2015-01-01"`,
   586  	},
   587  	{
   588  		// RFC3339
   589  		"a: 2015-02-24T18:19:39.12Z\n",
   590  		`a: "2015-02-24T18:19:39.12Z"`,
   591  	},
   592  	{
   593  		// RFC3339 with short dates.
   594  		"a: 2015-2-3T3:4:5Z",
   595  		`a: "2015-2-3T3:4:5Z"`,
   596  	},
   597  	{
   598  		// ISO8601 lower case t
   599  		"a: 2015-02-24t18:19:39Z\n",
   600  		`a: "2015-02-24t18:19:39Z"`,
   601  	},
   602  	{
   603  		// space separate, no time zone
   604  		"a: 2015-02-24 18:19:39\n",
   605  		`a: "2015-02-24 18:19:39"`,
   606  	},
   607  	// Some cases not currently handled. Uncomment these when
   608  	// the code is fixed.
   609  	//	{
   610  	//		// space separated with time zone
   611  	//		"a: 2001-12-14 21:59:43.10 -5",
   612  	//		map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
   613  	//	},
   614  	//	{
   615  	//		// arbitrary whitespace between fields
   616  	//		"a: 2001-12-14 \t\t \t21:59:43.10 \t Z",
   617  	//		map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
   618  	//	},
   619  	{
   620  		// explicit string tag
   621  		"a: !!str 2015-01-01",
   622  		`a: "2015-01-01"`,
   623  	},
   624  	{
   625  		// explicit timestamp tag on quoted string
   626  		"a: !!timestamp \"2015-01-01\"",
   627  		`a: "2015-01-01"`,
   628  	},
   629  	{
   630  		// explicit timestamp tag on unquoted string
   631  		"a: !!timestamp 2015-01-01",
   632  		`a: "2015-01-01"`,
   633  	},
   634  	{
   635  		// quoted string that's a valid timestamp
   636  		"a: \"2015-01-01\"",
   637  		"a: \"2015-01-01\"",
   638  	},
   639  
   640  	// Empty list
   641  	{
   642  		"a: []",
   643  		"a: []",
   644  	},
   645  
   646  	// UTF-16-LE
   647  	{
   648  		"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
   649  		`ñoño: "very yes"`,
   650  	},
   651  	// UTF-16-LE with surrogate.
   652  	{
   653  		"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
   654  		`ñoño: "very yes 🟔"`,
   655  	},
   656  
   657  	// UTF-16-BE
   658  	{
   659  		"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
   660  		`ñoño: "very yes"`,
   661  	},
   662  	// UTF-16-BE with surrogate.
   663  	{
   664  		"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
   665  		`ñoño: "very yes 🟔"`,
   666  	},
   667  
   668  	// YAML Float regex shouldn't match this
   669  	{
   670  		"a: 123456e1\n",
   671  		`a: "123456e1"`,
   672  	}, {
   673  		"a: 123456E1\n",
   674  		`a: "123456E1"`,
   675  	},
   676  	// yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
   677  	{
   678  		"First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
   679  		`"First occurrence":  "Foo"
   680  "Second occurrence": "Foo"
   681  "Override anchor":   "Bar"
   682  "Reuse anchor":      "Bar"`,
   683  	},
   684  	// Single document with garbage following it.
   685  	{
   686  		"---\nhello\n...\n}not yaml",
   687  		`"hello"`,
   688  	},
   689  }
   690  
   691  type M map[interface{}]interface{}
   692  
   693  type inlineB struct {
   694  	B       int
   695  	inlineC `yaml:",inline"`
   696  }
   697  
   698  type inlineC struct {
   699  	C int
   700  }
   701  
   702  func cueStr(node ast.Node) string {
   703  	if s, ok := node.(*ast.StructLit); ok {
   704  		node = &ast.File{
   705  			Decls: s.Elts,
   706  		}
   707  	}
   708  	b, _ := format.Node(node)
   709  	return strings.TrimSpace(string(b))
   710  }
   711  
   712  func newDecoder(t *testing.T, data string) *yaml.Decoder {
   713  	dec, err := yaml.NewDecoder("test.yaml", strings.NewReader(data))
   714  	if err != nil {
   715  		t.Fatal(err)
   716  	}
   717  	return dec
   718  }
   719  
   720  func callUnmarshal(t *testing.T, data string) (ast.Expr, error) {
   721  	return yaml.Unmarshal("test.yaml", []byte(data))
   722  }
   723  
   724  func TestUnmarshal(t *testing.T) {
   725  	for i, item := range unmarshalTests {
   726  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   727  			t.Logf("test %d: %q", i, item.data)
   728  			expr, err := callUnmarshal(t, item.data)
   729  			if _, ok := err.(*yaml.TypeError); !ok && err != nil {
   730  				t.Fatal("expected error to be nil")
   731  			}
   732  			if got := cueStr(expr); got != item.want {
   733  				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
   734  			}
   735  		})
   736  	}
   737  }
   738  
   739  // // TODO(v3): This test should also work when unmarshaling onto an interface{}.
   740  // func (s *S) TestUnmarshalFullTimestamp(c *C) {
   741  // 	// Full timestamp in same format as encoded. This is confirmed to be
   742  // 	// properly decoded by Python as a timestamp as well.
   743  // 	var str = "2015-02-24T18:19:39.123456789-03:00"
   744  // 	expr, err := yaml.Unmarshal([]byte(str))
   745  // 	c.Assert(err, IsNil)
   746  // 	c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location()))
   747  // 	c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
   748  // }
   749  
   750  func TestDecoderSingleDocument(t *testing.T) {
   751  	// Test that Decoder.Decode works as expected on
   752  	// all the unmarshal tests.
   753  	for i, item := range unmarshalTests {
   754  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   755  			if item.data == "" {
   756  				// Behaviour differs when there's no YAML.
   757  				return
   758  			}
   759  			expr, err := newDecoder(t, item.data).Decode()
   760  			if _, ok := err.(*yaml.TypeError); !ok && err != nil {
   761  				t.Errorf("err should be nil, was %v", err)
   762  			}
   763  			if got := cueStr(expr); got != item.want {
   764  				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
   765  			}
   766  		})
   767  	}
   768  }
   769  
   770  var decoderTests = []struct {
   771  	data string
   772  	want string
   773  }{{
   774  	"",
   775  	"",
   776  }, {
   777  	"a: b",
   778  	`a: "b"`,
   779  }, {
   780  	"---\na: b\n...\n",
   781  	`a: "b"`,
   782  }, {
   783  	"---\n'hello'\n...\n---\ngoodbye\n...\n",
   784  	`"hello"` + "\n" + `"goodbye"`,
   785  }}
   786  
   787  func TestDecoder(t *testing.T) {
   788  	for i, item := range decoderTests {
   789  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   790  			var values []string
   791  			dec := newDecoder(t, item.data)
   792  			for {
   793  				expr, err := dec.Decode()
   794  				if err == io.EOF {
   795  					break
   796  				}
   797  				if err != nil {
   798  					t.Errorf("err should be nil, was %v", err)
   799  				}
   800  				values = append(values, cueStr(expr))
   801  			}
   802  			got := strings.Join(values, "\n")
   803  			if got != item.want {
   804  				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
   805  			}
   806  		})
   807  	}
   808  }
   809  
   810  type errReader struct{}
   811  
   812  func (errReader) Read([]byte) (int, error) {
   813  	return 0, errors.New("some read error")
   814  }
   815  
   816  func TestUnmarshalNaN(t *testing.T) {
   817  	expr, err := callUnmarshal(t, "notanum: .NaN")
   818  	if err != nil {
   819  		t.Fatal("unexpected error", err)
   820  	}
   821  	got := cueStr(expr)
   822  	want := "notanum: NaN"
   823  	if got != want {
   824  		t.Errorf("got %v; want %v", got, want)
   825  	}
   826  }
   827  
   828  var unmarshalErrorTests = []struct {
   829  	data, error string
   830  }{
   831  	{"\nv: !!float 'error'", "test.yaml:2: cannot decode !!str `error` as a !!float"},
   832  	{"v: [A,", "test.yaml:1: did not find expected node content"},
   833  	{"v:\n- [A,", "test.yaml:2: did not find expected node content"},
   834  	{"a:\n- b: *,", "test.yaml:2: did not find expected alphabetic or numeric character"},
   835  	{"a: *b\n", "test.yaml:1: unknown anchor 'b' referenced"},
   836  	{"a: &a\n  b: *a\n", "test.yaml:2: anchor 'a' value contains itself"},
   837  	{"value: -", "test.yaml:1: block sequence entries are not allowed in this context"},
   838  	{"a: !!binary ==", "test.yaml:1: !!binary value contains invalid base64 data"},
   839  	{"{[.]}", `test.yaml:1: invalid map key: sequence`},
   840  	{"{{.}}", `test.yaml:1: invalid map key: map`},
   841  	{"b: *a\na: &a {c: 1}", `test.yaml:1: unknown anchor 'a' referenced`},
   842  	{"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "test.yaml:1: did not find expected whitespace"},
   843  }
   844  
   845  func TestUnmarshalErrors(t *testing.T) {
   846  	for i, item := range unmarshalErrorTests {
   847  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   848  			expr, err := callUnmarshal(t, item.data)
   849  			val := ""
   850  			if expr != nil {
   851  				val = cueStr(expr)
   852  			}
   853  			if err == nil || err.Error() != item.error {
   854  				t.Errorf("got %v; want %v; (value %v)", err, item.error, val)
   855  			}
   856  		})
   857  	}
   858  }
   859  
   860  func TestDecoderErrors(t *testing.T) {
   861  	for i, item := range unmarshalErrorTests {
   862  		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
   863  			_, err := newDecoder(t, item.data).Decode()
   864  			if err == nil || err.Error() != item.error {
   865  				t.Errorf("got %v; want %v", err, item.error)
   866  			}
   867  		})
   868  	}
   869  }
   870  
   871  func TestFiles(t *testing.T) {
   872  	files := []string{"merge"}
   873  	for _, test := range files {
   874  		t.Run(test, func(t *testing.T) {
   875  			testname := fmt.Sprintf("testdata/%s.test", test)
   876  			filename := fmt.Sprintf("testdata/%s.out", test)
   877  			mergeTests, err := ioutil.ReadFile(testname)
   878  			if err != nil {
   879  				t.Fatal(err)
   880  			}
   881  			expr, err := yaml.Unmarshal("test.yaml", mergeTests)
   882  			if err != nil {
   883  				t.Fatal(err)
   884  			}
   885  			got := cueStr(expr)
   886  			if cuetest.UpdateGoldenFiles {
   887  				ioutil.WriteFile(filename, []byte(got), 0644)
   888  				return
   889  			}
   890  			b, err := ioutil.ReadFile(filename)
   891  			if err != nil {
   892  				t.Fatal(err)
   893  			}
   894  			if want := string(b); got != want {
   895  				t.Errorf("\n got: %v;\nwant: %v", got, want)
   896  			}
   897  		})
   898  	}
   899  }
   900  
   901  func TestFuzzCrashers(t *testing.T) {
   902  	cases := []string{
   903  		// runtime error: index out of range
   904  		"\"\\0\\\r\n",
   905  
   906  		// should not happen
   907  		"  0: [\n] 0",
   908  		"? ? \"\n\" 0",
   909  		"    - {\n000}0",
   910  		"0:\n  0: [0\n] 0",
   911  		"    - \"\n000\"0",
   912  		"    - \"\n000\"\"",
   913  		"0:\n    - {\n000}0",
   914  		"0:\n    - \"\n000\"0",
   915  		"0:\n    - \"\n000\"\"",
   916  
   917  		// runtime error: index out of range
   918  		" \ufeff\n",
   919  		"? \ufeff\n",
   920  		"? \ufeff:\n",
   921  		"0: \ufeff\n",
   922  		"? \ufeff: \ufeff\n",
   923  	}
   924  	for _, data := range cases {
   925  		_, _ = callUnmarshal(t, data)
   926  	}
   927  }
   928  
   929  //var data []byte
   930  //func init() {
   931  //	var err error
   932  //	data, err = ioutil.ReadFile("/tmp/file.yaml")
   933  //	if err != nil {
   934  //		panic(err)
   935  //	}
   936  //}
   937  //
   938  //func (s *S) BenchmarkUnmarshal(c *C) {
   939  //	var err error
   940  //	for i := 0; i < c.N; i++ {
   941  //		var v map[string]interface{}
   942  //		err = yaml.Unmarshal(data, &v)
   943  //	}
   944  //	if err != nil {
   945  //		panic(err)
   946  //	}
   947  //}
   948  //
   949  //func (s *S) BenchmarkMarshal(c *C) {
   950  //	var v map[string]interface{}
   951  //	yaml.Unmarshal(data, &v)
   952  //	c.ResetTimer()
   953  //	for i := 0; i < c.N; i++ {
   954  //		yaml.Marshal(&v)
   955  //	}
   956  //}