cuelang.org/go@v0.13.0/internal/encoding/yaml/decode_test.go (about)

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