github.com/mfpierre/corectl@v0.5.6/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go (about)

     1  package yaml_test
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	. "gopkg.in/check.v1"
    11  	"gopkg.in/yaml.v2"
    12  	"net"
    13  	"os"
    14  )
    15  
    16  var marshalIntTest = 123
    17  
    18  var marshalTests = []struct {
    19  	value interface{}
    20  	data  string
    21  }{
    22  	{
    23  		nil,
    24  		"null\n",
    25  	}, {
    26  		&struct{}{},
    27  		"{}\n",
    28  	}, {
    29  		map[string]string{"v": "hi"},
    30  		"v: hi\n",
    31  	}, {
    32  		map[string]interface{}{"v": "hi"},
    33  		"v: hi\n",
    34  	}, {
    35  		map[string]string{"v": "true"},
    36  		"v: \"true\"\n",
    37  	}, {
    38  		map[string]string{"v": "false"},
    39  		"v: \"false\"\n",
    40  	}, {
    41  		map[string]interface{}{"v": true},
    42  		"v: true\n",
    43  	}, {
    44  		map[string]interface{}{"v": false},
    45  		"v: false\n",
    46  	}, {
    47  		map[string]interface{}{"v": 10},
    48  		"v: 10\n",
    49  	}, {
    50  		map[string]interface{}{"v": -10},
    51  		"v: -10\n",
    52  	}, {
    53  		map[string]uint{"v": 42},
    54  		"v: 42\n",
    55  	}, {
    56  		map[string]interface{}{"v": int64(4294967296)},
    57  		"v: 4294967296\n",
    58  	}, {
    59  		map[string]int64{"v": int64(4294967296)},
    60  		"v: 4294967296\n",
    61  	}, {
    62  		map[string]uint64{"v": 4294967296},
    63  		"v: 4294967296\n",
    64  	}, {
    65  		map[string]interface{}{"v": "10"},
    66  		"v: \"10\"\n",
    67  	}, {
    68  		map[string]interface{}{"v": 0.1},
    69  		"v: 0.1\n",
    70  	}, {
    71  		map[string]interface{}{"v": float64(0.1)},
    72  		"v: 0.1\n",
    73  	}, {
    74  		map[string]interface{}{"v": -0.1},
    75  		"v: -0.1\n",
    76  	}, {
    77  		map[string]interface{}{"v": math.Inf(+1)},
    78  		"v: .inf\n",
    79  	}, {
    80  		map[string]interface{}{"v": math.Inf(-1)},
    81  		"v: -.inf\n",
    82  	}, {
    83  		map[string]interface{}{"v": math.NaN()},
    84  		"v: .nan\n",
    85  	}, {
    86  		map[string]interface{}{"v": nil},
    87  		"v: null\n",
    88  	}, {
    89  		map[string]interface{}{"v": ""},
    90  		"v: \"\"\n",
    91  	}, {
    92  		map[string][]string{"v": []string{"A", "B"}},
    93  		"v:\n- A\n- B\n",
    94  	}, {
    95  		map[string][]string{"v": []string{"A", "B\nC"}},
    96  		"v:\n- A\n- |-\n  B\n  C\n",
    97  	}, {
    98  		map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
    99  		"v:\n- A\n- 1\n- B:\n  - 2\n  - 3\n",
   100  	}, {
   101  		map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
   102  		"a:\n  b: c\n",
   103  	}, {
   104  		map[string]interface{}{"a": "-"},
   105  		"a: '-'\n",
   106  	},
   107  
   108  	// Simple values.
   109  	{
   110  		&marshalIntTest,
   111  		"123\n",
   112  	},
   113  
   114  	// Structures
   115  	{
   116  		&struct{ Hello string }{"world"},
   117  		"hello: world\n",
   118  	}, {
   119  		&struct {
   120  			A struct {
   121  				B string
   122  			}
   123  		}{struct{ B string }{"c"}},
   124  		"a:\n  b: c\n",
   125  	}, {
   126  		&struct {
   127  			A *struct {
   128  				B string
   129  			}
   130  		}{&struct{ B string }{"c"}},
   131  		"a:\n  b: c\n",
   132  	}, {
   133  		&struct {
   134  			A *struct {
   135  				B string
   136  			}
   137  		}{},
   138  		"a: null\n",
   139  	}, {
   140  		&struct{ A int }{1},
   141  		"a: 1\n",
   142  	}, {
   143  		&struct{ A []int }{[]int{1, 2}},
   144  		"a:\n- 1\n- 2\n",
   145  	}, {
   146  		&struct {
   147  			B int "a"
   148  		}{1},
   149  		"a: 1\n",
   150  	}, {
   151  		&struct{ A bool }{true},
   152  		"a: true\n",
   153  	},
   154  
   155  	// Conditional flag
   156  	{
   157  		&struct {
   158  			A int "a,omitempty"
   159  			B int "b,omitempty"
   160  		}{1, 0},
   161  		"a: 1\n",
   162  	}, {
   163  		&struct {
   164  			A int "a,omitempty"
   165  			B int "b,omitempty"
   166  		}{0, 0},
   167  		"{}\n",
   168  	}, {
   169  		&struct {
   170  			A *struct{ X, y int } "a,omitempty,flow"
   171  		}{&struct{ X, y int }{1, 2}},
   172  		"a: {x: 1}\n",
   173  	}, {
   174  		&struct {
   175  			A *struct{ X, y int } "a,omitempty,flow"
   176  		}{nil},
   177  		"{}\n",
   178  	}, {
   179  		&struct {
   180  			A *struct{ X, y int } "a,omitempty,flow"
   181  		}{&struct{ X, y int }{}},
   182  		"a: {x: 0}\n",
   183  	}, {
   184  		&struct {
   185  			A struct{ X, y int } "a,omitempty,flow"
   186  		}{struct{ X, y int }{1, 2}},
   187  		"a: {x: 1}\n",
   188  	}, {
   189  		&struct {
   190  			A struct{ X, y int } "a,omitempty,flow"
   191  		}{struct{ X, y int }{0, 1}},
   192  		"{}\n",
   193  	}, {
   194  		&struct {
   195  			A float64 "a,omitempty"
   196  			B float64 "b,omitempty"
   197  		}{1, 0},
   198  		"a: 1\n",
   199  	},
   200  
   201  	// Flow flag
   202  	{
   203  		&struct {
   204  			A []int "a,flow"
   205  		}{[]int{1, 2}},
   206  		"a: [1, 2]\n",
   207  	}, {
   208  		&struct {
   209  			A map[string]string "a,flow"
   210  		}{map[string]string{"b": "c", "d": "e"}},
   211  		"a: {b: c, d: e}\n",
   212  	}, {
   213  		&struct {
   214  			A struct {
   215  				B, D string
   216  			} "a,flow"
   217  		}{struct{ B, D string }{"c", "e"}},
   218  		"a: {b: c, d: e}\n",
   219  	},
   220  
   221  	// Unexported field
   222  	{
   223  		&struct {
   224  			u int
   225  			A int
   226  		}{0, 1},
   227  		"a: 1\n",
   228  	},
   229  
   230  	// Ignored field
   231  	{
   232  		&struct {
   233  			A int
   234  			B int "-"
   235  		}{1, 2},
   236  		"a: 1\n",
   237  	},
   238  
   239  	// Struct inlining
   240  	{
   241  		&struct {
   242  			A int
   243  			C inlineB `yaml:",inline"`
   244  		}{1, inlineB{2, inlineC{3}}},
   245  		"a: 1\nb: 2\nc: 3\n",
   246  	},
   247  
   248  	// Map inlining
   249  	{
   250  		&struct {
   251  			A int
   252  			C map[string]int `yaml:",inline"`
   253  		}{1, map[string]int{"b": 2, "c": 3}},
   254  		"a: 1\nb: 2\nc: 3\n",
   255  	},
   256  
   257  	// Duration
   258  	{
   259  		map[string]time.Duration{"a": 3 * time.Second},
   260  		"a: 3s\n",
   261  	},
   262  
   263  	// Issue #24: bug in map merging logic.
   264  	{
   265  		map[string]string{"a": "<foo>"},
   266  		"a: <foo>\n",
   267  	},
   268  
   269  	// Issue #34: marshal unsupported base 60 floats quoted for compatibility
   270  	// with old YAML 1.1 parsers.
   271  	{
   272  		map[string]string{"a": "1:1"},
   273  		"a: \"1:1\"\n",
   274  	},
   275  
   276  	// Binary data.
   277  	{
   278  		map[string]string{"a": "\x00"},
   279  		"a: \"\\0\"\n",
   280  	}, {
   281  		map[string]string{"a": "\x80\x81\x82"},
   282  		"a: !!binary gIGC\n",
   283  	}, {
   284  		map[string]string{"a": strings.Repeat("\x90", 54)},
   285  		"a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
   286  	},
   287  
   288  	// Ordered maps.
   289  	{
   290  		&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
   291  		"b: 2\na: 1\nd: 4\nc: 3\nsub:\n  e: 5\n",
   292  	},
   293  
   294  	// Encode unicode as utf-8 rather than in escaped form.
   295  	{
   296  		map[string]string{"a": "你好"},
   297  		"a: 你好\n",
   298  	},
   299  
   300  	// Support encoding.TextMarshaler.
   301  	{
   302  		map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
   303  		"a: 1.2.3.4\n",
   304  	},
   305  	{
   306  		map[string]time.Time{"a": time.Unix(1424801979, 0)},
   307  		"a: 2015-02-24T18:19:39Z\n",
   308  	},
   309  
   310  	// Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible).
   311  	{
   312  		map[string]string{"a": "b: c"},
   313  		"a: 'b: c'\n",
   314  	},
   315  
   316  	// Containing hash mark ('#') in string should be quoted
   317  	{
   318  		map[string]string{"a": "Hello #comment"},
   319  		"a: 'Hello #comment'\n",
   320  	},
   321  	{
   322  		map[string]string{"a": "你好 #comment"},
   323  		"a: '你好 #comment'\n",
   324  	},
   325  }
   326  
   327  func (s *S) TestMarshal(c *C) {
   328  	defer os.Setenv("TZ", os.Getenv("TZ"))
   329  	os.Setenv("TZ", "UTC")
   330  	for _, item := range marshalTests {
   331  		data, err := yaml.Marshal(item.value)
   332  		c.Assert(err, IsNil)
   333  		c.Assert(string(data), Equals, item.data)
   334  	}
   335  }
   336  
   337  var marshalErrorTests = []struct {
   338  	value interface{}
   339  	error string
   340  	panic string
   341  }{{
   342  	value: &struct {
   343  		B       int
   344  		inlineB ",inline"
   345  	}{1, inlineB{2, inlineC{3}}},
   346  	panic: `Duplicated key 'b' in struct struct \{ B int; .*`,
   347  }, {
   348  	value: &struct {
   349  		A int
   350  		B map[string]int ",inline"
   351  	}{1, map[string]int{"a": 2}},
   352  	panic: `Can't have key "a" in inlined map; conflicts with struct field`,
   353  }}
   354  
   355  func (s *S) TestMarshalErrors(c *C) {
   356  	for _, item := range marshalErrorTests {
   357  		if item.panic != "" {
   358  			c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
   359  		} else {
   360  			_, err := yaml.Marshal(item.value)
   361  			c.Assert(err, ErrorMatches, item.error)
   362  		}
   363  	}
   364  }
   365  
   366  func (s *S) TestMarshalTypeCache(c *C) {
   367  	var data []byte
   368  	var err error
   369  	func() {
   370  		type T struct{ A int }
   371  		data, err = yaml.Marshal(&T{})
   372  		c.Assert(err, IsNil)
   373  	}()
   374  	func() {
   375  		type T struct{ B int }
   376  		data, err = yaml.Marshal(&T{})
   377  		c.Assert(err, IsNil)
   378  	}()
   379  	c.Assert(string(data), Equals, "b: 0\n")
   380  }
   381  
   382  var marshalerTests = []struct {
   383  	data  string
   384  	value interface{}
   385  }{
   386  	{"_:\n  hi: there\n", map[interface{}]interface{}{"hi": "there"}},
   387  	{"_:\n- 1\n- A\n", []interface{}{1, "A"}},
   388  	{"_: 10\n", 10},
   389  	{"_: null\n", nil},
   390  	{"_: BAR!\n", "BAR!"},
   391  }
   392  
   393  type marshalerType struct {
   394  	value interface{}
   395  }
   396  
   397  func (o marshalerType) MarshalText() ([]byte, error) {
   398  	panic("MarshalText called on type with MarshalYAML")
   399  }
   400  
   401  func (o marshalerType) MarshalYAML() (interface{}, error) {
   402  	return o.value, nil
   403  }
   404  
   405  type marshalerValue struct {
   406  	Field marshalerType "_"
   407  }
   408  
   409  func (s *S) TestMarshaler(c *C) {
   410  	for _, item := range marshalerTests {
   411  		obj := &marshalerValue{}
   412  		obj.Field.value = item.value
   413  		data, err := yaml.Marshal(obj)
   414  		c.Assert(err, IsNil)
   415  		c.Assert(string(data), Equals, string(item.data))
   416  	}
   417  }
   418  
   419  func (s *S) TestMarshalerWholeDocument(c *C) {
   420  	obj := &marshalerType{}
   421  	obj.value = map[string]string{"hello": "world!"}
   422  	data, err := yaml.Marshal(obj)
   423  	c.Assert(err, IsNil)
   424  	c.Assert(string(data), Equals, "hello: world!\n")
   425  }
   426  
   427  type failingMarshaler struct{}
   428  
   429  func (ft *failingMarshaler) MarshalYAML() (interface{}, error) {
   430  	return nil, failingErr
   431  }
   432  
   433  func (s *S) TestMarshalerError(c *C) {
   434  	_, err := yaml.Marshal(&failingMarshaler{})
   435  	c.Assert(err, Equals, failingErr)
   436  }
   437  
   438  func (s *S) TestSortedOutput(c *C) {
   439  	order := []interface{}{
   440  		false,
   441  		true,
   442  		1,
   443  		uint(1),
   444  		1.0,
   445  		1.1,
   446  		1.2,
   447  		2,
   448  		uint(2),
   449  		2.0,
   450  		2.1,
   451  		"",
   452  		".1",
   453  		".2",
   454  		".a",
   455  		"1",
   456  		"2",
   457  		"a!10",
   458  		"a/2",
   459  		"a/10",
   460  		"a~10",
   461  		"ab/1",
   462  		"b/1",
   463  		"b/01",
   464  		"b/2",
   465  		"b/02",
   466  		"b/3",
   467  		"b/03",
   468  		"b1",
   469  		"b01",
   470  		"b3",
   471  		"c2.10",
   472  		"c10.2",
   473  		"d1",
   474  		"d12",
   475  		"d12a",
   476  	}
   477  	m := make(map[interface{}]int)
   478  	for _, k := range order {
   479  		m[k] = 1
   480  	}
   481  	data, err := yaml.Marshal(m)
   482  	c.Assert(err, IsNil)
   483  	out := "\n" + string(data)
   484  	last := 0
   485  	for i, k := range order {
   486  		repr := fmt.Sprint(k)
   487  		if s, ok := k.(string); ok {
   488  			if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil {
   489  				repr = `"` + repr + `"`
   490  			}
   491  		}
   492  		index := strings.Index(out, "\n"+repr+":")
   493  		if index == -1 {
   494  			c.Fatalf("%#v is not in the output: %#v", k, out)
   495  		}
   496  		if index < last {
   497  			c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out)
   498  		}
   499  		last = index
   500  	}
   501  }