github.com/trevoraustin/hub@v2.2.0-preview1.0.20141105230840-96d8bfc654cc+incompatible/Godeps/_workspace/src/gopkg.in/yaml.v1/decode_test.go (about)

     1  package yaml_test
     2  
     3  import (
     4  	. "gopkg.in/check.v1"
     5  	"gopkg.in/yaml.v1"
     6  	"math"
     7  	"reflect"
     8  	"time"
     9  )
    10  
    11  var unmarshalIntTest = 123
    12  
    13  var unmarshalTests = []struct {
    14  	data  string
    15  	value interface{}
    16  }{
    17  	{
    18  		"",
    19  		&struct{}{},
    20  	}, {
    21  		"{}", &struct{}{},
    22  	}, {
    23  		"v: hi",
    24  		map[string]string{"v": "hi"},
    25  	}, {
    26  		"v: hi", map[string]interface{}{"v": "hi"},
    27  	}, {
    28  		"v: true",
    29  		map[string]string{"v": "true"},
    30  	}, {
    31  		"v: true",
    32  		map[string]interface{}{"v": true},
    33  	}, {
    34  		"v: 10",
    35  		map[string]interface{}{"v": 10},
    36  	}, {
    37  		"v: 0b10",
    38  		map[string]interface{}{"v": 2},
    39  	}, {
    40  		"v: 0xA",
    41  		map[string]interface{}{"v": 10},
    42  	}, {
    43  		"v: 4294967296",
    44  		map[string]int64{"v": 4294967296},
    45  	}, {
    46  		"v: 0.1",
    47  		map[string]interface{}{"v": 0.1},
    48  	}, {
    49  		"v: .1",
    50  		map[string]interface{}{"v": 0.1},
    51  	}, {
    52  		"v: .Inf",
    53  		map[string]interface{}{"v": math.Inf(+1)},
    54  	}, {
    55  		"v: -.Inf",
    56  		map[string]interface{}{"v": math.Inf(-1)},
    57  	}, {
    58  		"v: -10",
    59  		map[string]interface{}{"v": -10},
    60  	}, {
    61  		"v: -.1",
    62  		map[string]interface{}{"v": -0.1},
    63  	},
    64  
    65  	// Simple values.
    66  	{
    67  		"123",
    68  		&unmarshalIntTest,
    69  	},
    70  
    71  	// Floats from spec
    72  	{
    73  		"canonical: 6.8523e+5",
    74  		map[string]interface{}{"canonical": 6.8523e+5},
    75  	}, {
    76  		"expo: 685.230_15e+03",
    77  		map[string]interface{}{"expo": 685.23015e+03},
    78  	}, {
    79  		"fixed: 685_230.15",
    80  		map[string]interface{}{"fixed": 685230.15},
    81  	}, {
    82  		"neginf: -.inf",
    83  		map[string]interface{}{"neginf": math.Inf(-1)},
    84  	}, {
    85  		"fixed: 685_230.15",
    86  		map[string]float64{"fixed": 685230.15},
    87  	},
    88  	//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
    89  	//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
    90  
    91  	// Bools from spec
    92  	{
    93  		"canonical: y",
    94  		map[string]interface{}{"canonical": true},
    95  	}, {
    96  		"answer: NO",
    97  		map[string]interface{}{"answer": false},
    98  	}, {
    99  		"logical: True",
   100  		map[string]interface{}{"logical": true},
   101  	}, {
   102  		"option: on",
   103  		map[string]interface{}{"option": true},
   104  	}, {
   105  		"option: on",
   106  		map[string]bool{"option": true},
   107  	},
   108  	// Ints from spec
   109  	{
   110  		"canonical: 685230",
   111  		map[string]interface{}{"canonical": 685230},
   112  	}, {
   113  		"decimal: +685_230",
   114  		map[string]interface{}{"decimal": 685230},
   115  	}, {
   116  		"octal: 02472256",
   117  		map[string]interface{}{"octal": 685230},
   118  	}, {
   119  		"hexa: 0x_0A_74_AE",
   120  		map[string]interface{}{"hexa": 685230},
   121  	}, {
   122  		"bin: 0b1010_0111_0100_1010_1110",
   123  		map[string]interface{}{"bin": 685230},
   124  	}, {
   125  		"bin: -0b101010",
   126  		map[string]interface{}{"bin": -42},
   127  	}, {
   128  		"decimal: +685_230",
   129  		map[string]int{"decimal": 685230},
   130  	},
   131  
   132  	//{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
   133  
   134  	// Nulls from spec
   135  	{
   136  		"empty:",
   137  		map[string]interface{}{"empty": nil},
   138  	}, {
   139  		"canonical: ~",
   140  		map[string]interface{}{"canonical": nil},
   141  	}, {
   142  		"english: null",
   143  		map[string]interface{}{"english": nil},
   144  	}, {
   145  		"~: null key",
   146  		map[interface{}]string{nil: "null key"},
   147  	}, {
   148  		"empty:",
   149  		map[string]*bool{"empty": nil},
   150  	},
   151  
   152  	// Flow sequence
   153  	{
   154  		"seq: [A,B]",
   155  		map[string]interface{}{"seq": []interface{}{"A", "B"}},
   156  	}, {
   157  		"seq: [A,B,C,]",
   158  		map[string][]string{"seq": []string{"A", "B", "C"}},
   159  	}, {
   160  		"seq: [A,1,C]",
   161  		map[string][]string{"seq": []string{"A", "1", "C"}},
   162  	}, {
   163  		"seq: [A,1,C]",
   164  		map[string][]int{"seq": []int{1}},
   165  	}, {
   166  		"seq: [A,1,C]",
   167  		map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
   168  	},
   169  	// Block sequence
   170  	{
   171  		"seq:\n - A\n - B",
   172  		map[string]interface{}{"seq": []interface{}{"A", "B"}},
   173  	}, {
   174  		"seq:\n - A\n - B\n - C",
   175  		map[string][]string{"seq": []string{"A", "B", "C"}},
   176  	}, {
   177  		"seq:\n - A\n - 1\n - C",
   178  		map[string][]string{"seq": []string{"A", "1", "C"}},
   179  	}, {
   180  		"seq:\n - A\n - 1\n - C",
   181  		map[string][]int{"seq": []int{1}},
   182  	}, {
   183  		"seq:\n - A\n - 1\n - C",
   184  		map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
   185  	},
   186  
   187  	// Literal block scalar
   188  	{
   189  		"scalar: | # Comment\n\n literal\n\n \ttext\n\n",
   190  		map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
   191  	},
   192  
   193  	// Folded block scalar
   194  	{
   195  		"scalar: > # Comment\n\n folded\n line\n \n next\n line\n  * one\n  * two\n\n last\n line\n\n",
   196  		map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
   197  	},
   198  
   199  	// Map inside interface with no type hints.
   200  	{
   201  		"a: {b: c}",
   202  		map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
   203  	},
   204  
   205  	// Structs and type conversions.
   206  	{
   207  		"hello: world",
   208  		&struct{ Hello string }{"world"},
   209  	}, {
   210  		"a: {b: c}",
   211  		&struct{ A struct{ B string } }{struct{ B string }{"c"}},
   212  	}, {
   213  		"a: {b: c}",
   214  		&struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
   215  	}, {
   216  		"a: {b: c}",
   217  		&struct{ A map[string]string }{map[string]string{"b": "c"}},
   218  	}, {
   219  		"a: {b: c}",
   220  		&struct{ A *map[string]string }{&map[string]string{"b": "c"}},
   221  	}, {
   222  		"a:",
   223  		&struct{ A map[string]string }{},
   224  	}, {
   225  		"a: 1",
   226  		&struct{ A int }{1},
   227  	}, {
   228  		"a: 1",
   229  		&struct{ A float64 }{1},
   230  	}, {
   231  		"a: 1.0",
   232  		&struct{ A int }{1},
   233  	}, {
   234  		"a: 1.0",
   235  		&struct{ A uint }{1},
   236  	}, {
   237  		"a: [1, 2]",
   238  		&struct{ A []int }{[]int{1, 2}},
   239  	}, {
   240  		"a: 1",
   241  		&struct{ B int }{0},
   242  	}, {
   243  		"a: 1",
   244  		&struct {
   245  			B int "a"
   246  		}{1},
   247  	}, {
   248  		"a: y",
   249  		&struct{ A bool }{true},
   250  	},
   251  
   252  	// Some cross type conversions
   253  	{
   254  		"v: 42",
   255  		map[string]uint{"v": 42},
   256  	}, {
   257  		"v: -42",
   258  		map[string]uint{},
   259  	}, {
   260  		"v: 4294967296",
   261  		map[string]uint64{"v": 4294967296},
   262  	}, {
   263  		"v: -4294967296",
   264  		map[string]uint64{},
   265  	},
   266  
   267  	// Overflow cases.
   268  	{
   269  		"v: 4294967297",
   270  		map[string]int32{},
   271  	}, {
   272  		"v: 128",
   273  		map[string]int8{},
   274  	},
   275  
   276  	// Quoted values.
   277  	{
   278  		"'1': '\"2\"'",
   279  		map[interface{}]interface{}{"1": "\"2\""},
   280  	}, {
   281  		"v:\n- A\n- 'B\n\n  C'\n",
   282  		map[string][]string{"v": []string{"A", "B\nC"}},
   283  	},
   284  
   285  	// Explicit tags.
   286  	{
   287  		"v: !!float '1.1'",
   288  		map[string]interface{}{"v": 1.1},
   289  	}, {
   290  		"v: !!null ''",
   291  		map[string]interface{}{"v": nil},
   292  	}, {
   293  		"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
   294  		map[string]interface{}{"v": 1},
   295  	},
   296  
   297  	// Anchors and aliases.
   298  	{
   299  		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
   300  		&struct{ A, B, C, D int }{1, 2, 1, 2},
   301  	}, {
   302  		"a: &a {c: 1}\nb: *a",
   303  		&struct {
   304  			A, B struct {
   305  				C int
   306  			}
   307  		}{struct{ C int }{1}, struct{ C int }{1}},
   308  	}, {
   309  		"a: &a [1, 2]\nb: *a",
   310  		&struct{ B []int }{[]int{1, 2}},
   311  	},
   312  
   313  	// Bug #1133337
   314  	{
   315  		"foo: ''",
   316  		map[string]*string{"foo": new(string)},
   317  	}, {
   318  		"foo: null",
   319  		map[string]string{},
   320  	},
   321  
   322  	// Ignored field
   323  	{
   324  		"a: 1\nb: 2\n",
   325  		&struct {
   326  			A int
   327  			B int "-"
   328  		}{1, 0},
   329  	},
   330  
   331  	// Bug #1191981
   332  	{
   333  		"" +
   334  			"%YAML 1.1\n" +
   335  			"--- !!str\n" +
   336  			`"Generic line break (no glyph)\n\` + "\n" +
   337  			` Generic line break (glyphed)\n\` + "\n" +
   338  			` Line separator\u2028\` + "\n" +
   339  			` Paragraph separator\u2029"` + "\n",
   340  		"" +
   341  			"Generic line break (no glyph)\n" +
   342  			"Generic line break (glyphed)\n" +
   343  			"Line separator\u2028Paragraph separator\u2029",
   344  	},
   345  
   346  	// Struct inlining
   347  	{
   348  		"a: 1\nb: 2\nc: 3\n",
   349  		&struct {
   350  			A int
   351  			C inlineB `yaml:",inline"`
   352  		}{1, inlineB{2, inlineC{3}}},
   353  	},
   354  
   355  	// bug 1243827
   356  	{
   357  		"a: -b_c",
   358  		map[string]interface{}{"a": "-b_c"},
   359  	},
   360  	{
   361  		"a: +b_c",
   362  		map[string]interface{}{"a": "+b_c"},
   363  	},
   364  	{
   365  		"a: 50cent_of_dollar",
   366  		map[string]interface{}{"a": "50cent_of_dollar"},
   367  	},
   368  
   369  	// Duration
   370  	{
   371  		"a: 3s",
   372  		map[string]time.Duration{"a": 3 * time.Second},
   373  	},
   374  
   375  	// Issue #24. 
   376  	{
   377  		"a: <foo>",
   378  		map[string]string{"a": "<foo>"},
   379  	},
   380  }
   381  
   382  type inlineB struct {
   383  	B       int
   384  	inlineC `yaml:",inline"`
   385  }
   386  
   387  type inlineC struct {
   388  	C int
   389  }
   390  
   391  func (s *S) TestUnmarshal(c *C) {
   392  	for i, item := range unmarshalTests {
   393  		t := reflect.ValueOf(item.value).Type()
   394  		var value interface{}
   395  		switch t.Kind() {
   396  		case reflect.Map:
   397  			value = reflect.MakeMap(t).Interface()
   398  		case reflect.String:
   399  			t := reflect.ValueOf(item.value).Type()
   400  			v := reflect.New(t)
   401  			value = v.Interface()
   402  		default:
   403  			pt := reflect.ValueOf(item.value).Type()
   404  			pv := reflect.New(pt.Elem())
   405  			value = pv.Interface()
   406  		}
   407  		err := yaml.Unmarshal([]byte(item.data), value)
   408  		c.Assert(err, IsNil, Commentf("Item #%d", i))
   409  		if t.Kind() == reflect.String {
   410  			c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i))
   411  		} else {
   412  			c.Assert(value, DeepEquals, item.value, Commentf("Item #%d", i))
   413  		}
   414  	}
   415  }
   416  
   417  func (s *S) TestUnmarshalNaN(c *C) {
   418  	value := map[string]interface{}{}
   419  	err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
   420  	c.Assert(err, IsNil)
   421  	c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
   422  }
   423  
   424  var unmarshalErrorTests = []struct {
   425  	data, error string
   426  }{
   427  	{"v: !!float 'error'", "YAML error: Can't decode !!str 'error' as a !!float"},
   428  	{"v: [A,", "YAML error: line 1: did not find expected node content"},
   429  	{"v:\n- [A,", "YAML error: line 2: did not find expected node content"},
   430  	{"a: *b\n", "YAML error: Unknown anchor 'b' referenced"},
   431  	{"a: &a\n  b: *a\n", "YAML error: Anchor 'a' value contains itself"},
   432  	{"value: -", "YAML error: block sequence entries are not allowed in this context"},
   433  }
   434  
   435  func (s *S) TestUnmarshalErrors(c *C) {
   436  	for _, item := range unmarshalErrorTests {
   437  		var value interface{}
   438  		err := yaml.Unmarshal([]byte(item.data), &value)
   439  		c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
   440  	}
   441  }
   442  
   443  var setterTests = []struct {
   444  	data, tag string
   445  	value     interface{}
   446  }{
   447  	{"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
   448  	{"_: [1,A]", "!!seq", []interface{}{1, "A"}},
   449  	{"_: 10", "!!int", 10},
   450  	{"_: null", "!!null", nil},
   451  	{`_: BAR!`, "!!str", "BAR!"},
   452  	{`_: "BAR!"`, "!!str", "BAR!"},
   453  	{"_: !!foo 'BAR!'", "!!foo", "BAR!"},
   454  }
   455  
   456  var setterResult = map[int]bool{}
   457  
   458  type typeWithSetter struct {
   459  	tag   string
   460  	value interface{}
   461  }
   462  
   463  func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) {
   464  	o.tag = tag
   465  	o.value = value
   466  	if i, ok := value.(int); ok {
   467  		if result, ok := setterResult[i]; ok {
   468  			return result
   469  		}
   470  	}
   471  	return true
   472  }
   473  
   474  type setterPointerType struct {
   475  	Field *typeWithSetter "_"
   476  }
   477  
   478  type setterValueType struct {
   479  	Field typeWithSetter "_"
   480  }
   481  
   482  func (s *S) TestUnmarshalWithPointerSetter(c *C) {
   483  	for _, item := range setterTests {
   484  		obj := &setterPointerType{}
   485  		err := yaml.Unmarshal([]byte(item.data), obj)
   486  		c.Assert(err, IsNil)
   487  		c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
   488  		c.Assert(obj.Field.tag, Equals, item.tag)
   489  		c.Assert(obj.Field.value, DeepEquals, item.value)
   490  	}
   491  }
   492  
   493  func (s *S) TestUnmarshalWithValueSetter(c *C) {
   494  	for _, item := range setterTests {
   495  		obj := &setterValueType{}
   496  		err := yaml.Unmarshal([]byte(item.data), obj)
   497  		c.Assert(err, IsNil)
   498  		c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
   499  		c.Assert(obj.Field.tag, Equals, item.tag)
   500  		c.Assert(obj.Field.value, DeepEquals, item.value)
   501  	}
   502  }
   503  
   504  func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
   505  	obj := &typeWithSetter{}
   506  	err := yaml.Unmarshal([]byte(setterTests[0].data), obj)
   507  	c.Assert(err, IsNil)
   508  	c.Assert(obj.tag, Equals, setterTests[0].tag)
   509  	value, ok := obj.value.(map[interface{}]interface{})
   510  	c.Assert(ok, Equals, true)
   511  	c.Assert(value["_"], DeepEquals, setterTests[0].value)
   512  }
   513  
   514  func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
   515  	setterResult[2] = false
   516  	setterResult[4] = false
   517  	defer func() {
   518  		delete(setterResult, 2)
   519  		delete(setterResult, 4)
   520  	}()
   521  
   522  	m := map[string]*typeWithSetter{}
   523  	data := `{abc: 1, def: 2, ghi: 3, jkl: 4}`
   524  	err := yaml.Unmarshal([]byte(data), m)
   525  	c.Assert(err, IsNil)
   526  	c.Assert(m["abc"], NotNil)
   527  	c.Assert(m["def"], IsNil)
   528  	c.Assert(m["ghi"], NotNil)
   529  	c.Assert(m["jkl"], IsNil)
   530  
   531  	c.Assert(m["abc"].value, Equals, 1)
   532  	c.Assert(m["ghi"].value, Equals, 3)
   533  }
   534  
   535  // From http://yaml.org/type/merge.html
   536  var mergeTests = `
   537  anchors:
   538    - &CENTER { "x": 1, "y": 2 }
   539    - &LEFT   { "x": 0, "y": 2 }
   540    - &BIG    { "r": 10 }
   541    - &SMALL  { "r": 1 }
   542  
   543  # All the following maps are equal:
   544  
   545  plain:
   546    # Explicit keys
   547    "x": 1
   548    "y": 2
   549    "r": 10
   550    label: center/big
   551  
   552  mergeOne:
   553    # Merge one map
   554    << : *CENTER
   555    "r": 10
   556    label: center/big
   557  
   558  mergeMultiple:
   559    # Merge multiple maps
   560    << : [ *CENTER, *BIG ]
   561    label: center/big
   562  
   563  override:
   564    # Override
   565    << : [ *BIG, *LEFT, *SMALL ]
   566    "x": 1
   567    label: center/big
   568  
   569  shortTag:
   570    # Explicit short merge tag
   571    !!merge "<<" : [ *CENTER, *BIG ]
   572    label: center/big
   573  
   574  longTag:
   575    # Explicit merge long tag
   576    !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
   577    label: center/big
   578  
   579  inlineMap:
   580    # Inlined map 
   581    << : {"x": 1, "y": 2, "r": 10}
   582    label: center/big
   583  
   584  inlineSequenceMap:
   585    # Inlined map in sequence
   586    << : [ *CENTER, {"r": 10} ]
   587    label: center/big
   588  `
   589  
   590  func (s *S) TestMerge(c *C) {
   591  	var want = map[interface{}]interface{}{
   592  		"x":     1,
   593  		"y":     2,
   594  		"r":     10,
   595  		"label": "center/big",
   596  	}
   597  
   598  	var m map[string]interface{}
   599  	err := yaml.Unmarshal([]byte(mergeTests), &m)
   600  	c.Assert(err, IsNil)
   601  	for name, test := range m {
   602  		if name == "anchors" {
   603  			continue
   604  		}
   605  		c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
   606  	}
   607  }
   608  
   609  func (s *S) TestMergeStruct(c *C) {
   610  	type Data struct {
   611  		X, Y, R int
   612  		Label   string
   613  	}
   614  	want := Data{1, 2, 10, "center/big"}
   615  
   616  	var m map[string]Data
   617  	err := yaml.Unmarshal([]byte(mergeTests), &m)
   618  	c.Assert(err, IsNil)
   619  	for name, test := range m {
   620  		if name == "anchors" {
   621  			continue
   622  		}
   623  		c.Assert(test, Equals, want, Commentf("test %q failed", name))
   624  	}
   625  }
   626  
   627  //var data []byte
   628  //func init() {
   629  //	var err error
   630  //	data, err = ioutil.ReadFile("/tmp/file.yaml")
   631  //	if err != nil {
   632  //		panic(err)
   633  //	}
   634  //}
   635  //
   636  //func (s *S) BenchmarkUnmarshal(c *C) {
   637  //	var err error
   638  //	for i := 0; i < c.N; i++ {
   639  //		var v map[string]interface{}
   640  //		err = yaml.Unmarshal(data, &v)
   641  //	}
   642  //	if err != nil {
   643  //		panic(err)
   644  //	}
   645  //}
   646  //
   647  //func (s *S) BenchmarkMarshal(c *C) {
   648  //	var v map[string]interface{}
   649  //	yaml.Unmarshal(data, &v)
   650  //	c.ResetTimer()
   651  //	for i := 0; i < c.N; i++ {
   652  //		yaml.Marshal(&v)
   653  //	}
   654  //}