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