github.com/marinho/drone@v0.2.1-0.20140504195434-d3ba962e89a7/Godeps/_workspace/src/launchpad.net/goyaml/decode_test.go (about)

     1  package goyaml_test
     2  
     3  import (
     4  	. "launchpad.net/gocheck"
     5  	"launchpad.net/goyaml"
     6  	"math"
     7  	"reflect"
     8  )
     9  
    10  var unmarshalIntTest = 123
    11  
    12  var unmarshalTests = []struct {
    13  	data  string
    14  	value interface{}
    15  }{
    16  	{
    17  		"",
    18  		&struct{}{},
    19  	}, {
    20  		"{}", &struct{}{},
    21  	}, {
    22  		"v: hi",
    23  		map[string]string{"v": "hi"},
    24  	}, {
    25  		"v: hi", map[string]interface{}{"v": "hi"},
    26  	}, {
    27  		"v: true",
    28  		map[string]string{"v": "true"},
    29  	}, {
    30  		"v: true",
    31  		map[string]interface{}{"v": true},
    32  	}, {
    33  		"v: 10",
    34  		map[string]interface{}{"v": 10},
    35  	}, {
    36  		"v: 0b10",
    37  		map[string]interface{}{"v": 2},
    38  	}, {
    39  		"v: 0xA",
    40  		map[string]interface{}{"v": 10},
    41  	}, {
    42  		"v: 4294967296",
    43  		map[string]int64{"v": 4294967296},
    44  	}, {
    45  		"v: 0.1",
    46  		map[string]interface{}{"v": 0.1},
    47  	}, {
    48  		"v: .1",
    49  		map[string]interface{}{"v": 0.1},
    50  	}, {
    51  		"v: .Inf",
    52  		map[string]interface{}{"v": math.Inf(+1)},
    53  	}, {
    54  		"v: -.Inf",
    55  		map[string]interface{}{"v": math.Inf(-1)},
    56  	}, {
    57  		"v: -10",
    58  		map[string]interface{}{"v": -10},
    59  	}, {
    60  		"v: -.1",
    61  		map[string]interface{}{"v": -0.1},
    62  	},
    63  
    64  	// Simple values.
    65  	{
    66  		"123",
    67  		&unmarshalIntTest,
    68  	},
    69  
    70  	// Floats from spec
    71  	{
    72  		"canonical: 6.8523e+5",
    73  		map[string]interface{}{"canonical": 6.8523e+5},
    74  	}, {
    75  		"expo: 685.230_15e+03",
    76  		map[string]interface{}{"expo": 685.23015e+03},
    77  	}, {
    78  		"fixed: 685_230.15",
    79  		map[string]interface{}{"fixed": 685230.15},
    80  	}, {
    81  		"neginf: -.inf",
    82  		map[string]interface{}{"neginf": math.Inf(-1)},
    83  	}, {
    84  		"fixed: 685_230.15",
    85  		map[string]float64{"fixed": 685230.15},
    86  	},
    87  	//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
    88  	//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
    89  
    90  	// Bools from spec
    91  	{
    92  		"canonical: y",
    93  		map[string]interface{}{"canonical": true},
    94  	}, {
    95  		"answer: NO",
    96  		map[string]interface{}{"answer": false},
    97  	}, {
    98  		"logical: True",
    99  		map[string]interface{}{"logical": true},
   100  	}, {
   101  		"option: on",
   102  		map[string]interface{}{"option": true},
   103  	}, {
   104  		"option: on",
   105  		map[string]bool{"option": true},
   106  	},
   107  	// Ints from spec
   108  	{
   109  		"canonical: 685230",
   110  		map[string]interface{}{"canonical": 685230},
   111  	}, {
   112  		"decimal: +685_230",
   113  		map[string]interface{}{"decimal": 685230},
   114  	}, {
   115  		"octal: 02472256",
   116  		map[string]interface{}{"octal": 685230},
   117  	}, {
   118  		"hexa: 0x_0A_74_AE",
   119  		map[string]interface{}{"hexa": 685230},
   120  	}, {
   121  		"bin: 0b1010_0111_0100_1010_1110",
   122  		map[string]interface{}{"bin": 685230},
   123  	}, {
   124  		"bin: -0b101010",
   125  		map[string]interface{}{"bin": -42},
   126  	}, {
   127  		"decimal: +685_230",
   128  		map[string]int{"decimal": 685230},
   129  	},
   130  
   131  	//{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
   132  
   133  	// Nulls from spec
   134  	{
   135  		"empty:",
   136  		map[string]interface{}{"empty": nil},
   137  	}, {
   138  		"canonical: ~",
   139  		map[string]interface{}{"canonical": nil},
   140  	}, {
   141  		"english: null",
   142  		map[string]interface{}{"english": nil},
   143  	}, {
   144  		"~: null key",
   145  		map[interface{}]string{nil: "null key"},
   146  	}, {
   147  		"empty:",
   148  		map[string]*bool{"empty": nil},
   149  	},
   150  
   151  	// Flow sequence
   152  	{
   153  		"seq: [A,B]",
   154  		map[string]interface{}{"seq": []interface{}{"A", "B"}},
   155  	}, {
   156  		"seq: [A,B,C,]",
   157  		map[string][]string{"seq": []string{"A", "B", "C"}},
   158  	}, {
   159  		"seq: [A,1,C]",
   160  		map[string][]string{"seq": []string{"A", "1", "C"}},
   161  	}, {
   162  		"seq: [A,1,C]",
   163  		map[string][]int{"seq": []int{1}},
   164  	}, {
   165  		"seq: [A,1,C]",
   166  		map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
   167  	},
   168  	// Block sequence
   169  	{
   170  		"seq:\n - A\n - B",
   171  		map[string]interface{}{"seq": []interface{}{"A", "B"}},
   172  	}, {
   173  		"seq:\n - A\n - B\n - C",
   174  		map[string][]string{"seq": []string{"A", "B", "C"}},
   175  	}, {
   176  		"seq:\n - A\n - 1\n - C",
   177  		map[string][]string{"seq": []string{"A", "1", "C"}},
   178  	}, {
   179  		"seq:\n - A\n - 1\n - C",
   180  		map[string][]int{"seq": []int{1}},
   181  	}, {
   182  		"seq:\n - A\n - 1\n - C",
   183  		map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
   184  	},
   185  
   186  	// Literal block scalar
   187  	{
   188  		"scalar: | # Comment\n\n literal\n\n \ttext\n\n",
   189  		map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
   190  	},
   191  
   192  	// Folded block scalar
   193  	{
   194  		"scalar: > # Comment\n\n folded\n line\n \n next\n line\n  * one\n  * two\n\n last\n line\n\n",
   195  		map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
   196  	},
   197  
   198  	// Map inside interface with no type hints.
   199  	{
   200  		"a: {b: c}",
   201  		map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
   202  	},
   203  
   204  	// Structs and type conversions.
   205  	{
   206  		"hello: world",
   207  		&struct{ Hello string }{"world"},
   208  	}, {
   209  		"a: {b: c}",
   210  		&struct{ A struct{ B string } }{struct{ B string }{"c"}},
   211  	}, {
   212  		"a: {b: c}",
   213  		&struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
   214  	}, {
   215  		"a: {b: c}",
   216  		&struct{ A map[string]string }{map[string]string{"b": "c"}},
   217  	}, {
   218  		"a: {b: c}",
   219  		&struct{ A *map[string]string }{&map[string]string{"b": "c"}},
   220  	}, {
   221  		"a:",
   222  		&struct{ A map[string]string }{},
   223  	}, {
   224  		"a: 1",
   225  		&struct{ A int }{1},
   226  	}, {
   227  		"a: 1",
   228  		&struct{ A float64 }{1},
   229  	}, {
   230  		"a: 1.0",
   231  		&struct{ A int }{1},
   232  	}, {
   233  		"a: 1.0",
   234  		&struct{ A uint }{1},
   235  	}, {
   236  		"a: [1, 2]",
   237  		&struct{ A []int }{[]int{1, 2}},
   238  	}, {
   239  		"a: 1",
   240  		&struct{ B int }{0},
   241  	}, {
   242  		"a: 1",
   243  		&struct {
   244  			B int "a"
   245  		}{1},
   246  	}, {
   247  		"a: y",
   248  		&struct{ A bool }{true},
   249  	},
   250  
   251  	// Some cross type conversions
   252  	{
   253  		"v: 42",
   254  		map[string]uint{"v": 42},
   255  	}, {
   256  		"v: -42",
   257  		map[string]uint{},
   258  	}, {
   259  		"v: 4294967296",
   260  		map[string]uint64{"v": 4294967296},
   261  	}, {
   262  		"v: -4294967296",
   263  		map[string]uint64{},
   264  	},
   265  
   266  	// Overflow cases.
   267  	{
   268  		"v: 4294967297",
   269  		map[string]int32{},
   270  	}, {
   271  		"v: 128",
   272  		map[string]int8{},
   273  	},
   274  
   275  	// Quoted values.
   276  	{
   277  		"'1': '\"2\"'",
   278  		map[interface{}]interface{}{"1": "\"2\""},
   279  	}, {
   280  		"v:\n- A\n- 'B\n\n  C'\n",
   281  		map[string][]string{"v": []string{"A", "B\nC"}},
   282  	},
   283  
   284  	// Explicit tags.
   285  	{
   286  		"v: !!float '1.1'",
   287  		map[string]interface{}{"v": 1.1},
   288  	}, {
   289  		"v: !!null ''",
   290  		map[string]interface{}{"v": nil},
   291  	}, {
   292  		"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
   293  		map[string]interface{}{"v": 1},
   294  	},
   295  
   296  	// Anchors and aliases.
   297  	{
   298  		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
   299  		&struct{ A, B, C, D int }{1, 2, 1, 2},
   300  	}, {
   301  		"a: &a {c: 1}\nb: *a",
   302  		&struct {
   303  			A, B struct {
   304  				C int
   305  			}
   306  		}{struct{ C int }{1}, struct{ C int }{1}},
   307  	}, {
   308  		"a: &a [1, 2]\nb: *a",
   309  		&struct{ B []int }{[]int{1, 2}},
   310  	},
   311  
   312  	// Bug #1133337
   313  	{
   314  		"foo: ''",
   315  		map[string]*string{"foo": new(string)},
   316  	}, {
   317  		"foo: null",
   318  		map[string]string{},
   319  	},
   320  
   321  	// Ignored field
   322  	{
   323  		"a: 1\nb: 2\n",
   324  		&struct {
   325  			A int
   326  			B int "-"
   327  		}{1, 0},
   328  	},
   329  
   330  	// Bug #1191981
   331  	{
   332  		"" +
   333  			"%YAML 1.1\n" +
   334  			"--- !!str\n" +
   335  			`"Generic line break (no glyph)\n\` + "\n" +
   336  			` Generic line break (glyphed)\n\` + "\n" +
   337  			` Line separator\u2028\` + "\n" +
   338  			` Paragraph separator\u2029"` + "\n",
   339  		"" +
   340  			"Generic line break (no glyph)\n" +
   341  			"Generic line break (glyphed)\n" +
   342  			"Line separator\u2028Paragraph separator\u2029",
   343  	},
   344  
   345  	// Struct inlining
   346  	{
   347  		"a: 1\nb: 2\nc: 3\n",
   348  		&struct {
   349  			A int
   350  			C inlineB `yaml:",inline"`
   351  		}{1, inlineB{2, inlineC{3}}},
   352  	},
   353  }
   354  
   355  type inlineB struct {
   356  	B       int
   357  	inlineC `yaml:",inline"`
   358  }
   359  
   360  type inlineC struct {
   361  	C int
   362  }
   363  
   364  func (s *S) TestUnmarshal(c *C) {
   365  	for i, item := range unmarshalTests {
   366  		t := reflect.ValueOf(item.value).Type()
   367  		var value interface{}
   368  		switch t.Kind() {
   369  		case reflect.Map:
   370  			value = reflect.MakeMap(t).Interface()
   371  		case reflect.String:
   372  			t := reflect.ValueOf(item.value).Type()
   373  			v := reflect.New(t)
   374  			value = v.Interface()
   375  		default:
   376  			pt := reflect.ValueOf(item.value).Type()
   377  			pv := reflect.New(pt.Elem())
   378  			value = pv.Interface()
   379  		}
   380  		err := goyaml.Unmarshal([]byte(item.data), value)
   381  		c.Assert(err, IsNil, Commentf("Item #%d", i))
   382  		if t.Kind() == reflect.String {
   383  			c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i))
   384  		} else {
   385  			c.Assert(value, DeepEquals, item.value, Commentf("Item #%d", i))
   386  		}
   387  	}
   388  }
   389  
   390  func (s *S) TestUnmarshalNaN(c *C) {
   391  	value := map[string]interface{}{}
   392  	err := goyaml.Unmarshal([]byte("notanum: .NaN"), &value)
   393  	c.Assert(err, IsNil)
   394  	c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
   395  }
   396  
   397  var unmarshalErrorTests = []struct {
   398  	data, error string
   399  }{
   400  	{"v: !!float 'error'", "YAML error: Can't decode !!str 'error' as a !!float"},
   401  	{"v: [A,", "YAML error: line 1: did not find expected node content"},
   402  	{"v:\n- [A,", "YAML error: line 2: did not find expected node content"},
   403  	{"a: *b\n", "YAML error: Unknown anchor 'b' referenced"},
   404  	{"a: &a\n  b: *a\n", "YAML error: Anchor 'a' value contains itself"},
   405  	{"value: -", "YAML error: block sequence entries are not allowed in this context"},
   406  }
   407  
   408  func (s *S) TestUnmarshalErrors(c *C) {
   409  	for _, item := range unmarshalErrorTests {
   410  		var value interface{}
   411  		err := goyaml.Unmarshal([]byte(item.data), &value)
   412  		c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
   413  	}
   414  }
   415  
   416  var setterTests = []struct {
   417  	data, tag string
   418  	value     interface{}
   419  }{
   420  	{"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
   421  	{"_: [1,A]", "!!seq", []interface{}{1, "A"}},
   422  	{"_: 10", "!!int", 10},
   423  	{"_: null", "!!null", nil},
   424  	{"_: !!foo 'BAR!'", "!!foo", "BAR!"},
   425  }
   426  
   427  var setterResult = map[int]bool{}
   428  
   429  type typeWithSetter struct {
   430  	tag   string
   431  	value interface{}
   432  }
   433  
   434  func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) {
   435  	o.tag = tag
   436  	o.value = value
   437  	if i, ok := value.(int); ok {
   438  		if result, ok := setterResult[i]; ok {
   439  			return result
   440  		}
   441  	}
   442  	return true
   443  }
   444  
   445  type typeWithSetterField struct {
   446  	Field *typeWithSetter "_"
   447  }
   448  
   449  func (s *S) TestUnmarshalWithSetter(c *C) {
   450  	for _, item := range setterTests {
   451  		obj := &typeWithSetterField{}
   452  		err := goyaml.Unmarshal([]byte(item.data), obj)
   453  		c.Assert(err, IsNil)
   454  		c.Assert(obj.Field, NotNil,
   455  			Commentf("Pointer not initialized (%#v)", item.value))
   456  		c.Assert(obj.Field.tag, Equals, item.tag)
   457  		c.Assert(obj.Field.value, DeepEquals, item.value)
   458  	}
   459  }
   460  
   461  func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
   462  	obj := &typeWithSetter{}
   463  	err := goyaml.Unmarshal([]byte(setterTests[0].data), obj)
   464  	c.Assert(err, IsNil)
   465  	c.Assert(obj.tag, Equals, setterTests[0].tag)
   466  	value, ok := obj.value.(map[interface{}]interface{})
   467  	c.Assert(ok, Equals, true)
   468  	c.Assert(value["_"], DeepEquals, setterTests[0].value)
   469  }
   470  
   471  func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
   472  	setterResult[2] = false
   473  	setterResult[4] = false
   474  	defer func() {
   475  		delete(setterResult, 2)
   476  		delete(setterResult, 4)
   477  	}()
   478  
   479  	m := map[string]*typeWithSetter{}
   480  	data := "{abc: 1, def: 2, ghi: 3, jkl: 4}"
   481  	err := goyaml.Unmarshal([]byte(data), m)
   482  	c.Assert(err, IsNil)
   483  	c.Assert(m["abc"], NotNil)
   484  	c.Assert(m["def"], IsNil)
   485  	c.Assert(m["ghi"], NotNil)
   486  	c.Assert(m["jkl"], IsNil)
   487  
   488  	c.Assert(m["abc"].value, Equals, 1)
   489  	c.Assert(m["ghi"].value, Equals, 3)
   490  }
   491  
   492  //var data []byte
   493  //func init() {
   494  //	var err error
   495  //	data, err = ioutil.ReadFile("/tmp/file.yaml")
   496  //	if err != nil {
   497  //		panic(err)
   498  //	}
   499  //}
   500  //
   501  //func (s *S) BenchmarkUnmarshal(c *C) {
   502  //	var err error
   503  //	for i := 0; i < c.N; i++ {
   504  //		var v map[string]interface{}
   505  //		err = goyaml.Unmarshal(data, &v)
   506  //	}
   507  //	if err != nil {
   508  //		panic(err)
   509  //	}
   510  //}
   511  //
   512  //func (s *S) BenchmarkMarshal(c *C) {
   513  //	var v map[string]interface{}
   514  //	goyaml.Unmarshal(data, &v)
   515  //	c.ResetTimer()
   516  //	for i := 0; i < c.N; i++ {
   517  //		goyaml.Marshal(&v)
   518  //	}
   519  //}