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