...

Source file src/gopkg.in/yaml.v3/encode_test.go

Documentation: gopkg.in/yaml.v3

     1  //
     2  // Copyright (c) 2011-2019 Canonical Ltd
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package yaml_test
    17  
    18  import (
    19  	"bytes"
    20  	"fmt"
    21  	"math"
    22  	"strconv"
    23  	"strings"
    24  	"time"
    25  
    26  	"net"
    27  	"os"
    28  
    29  	. "gopkg.in/check.v1"
    30  	"gopkg.in/yaml.v3"
    31  )
    32  
    33  var marshalIntTest = 123
    34  
    35  var marshalTests = []struct {
    36  	value interface{}
    37  	data  string
    38  }{
    39  	{
    40  		nil,
    41  		"null\n",
    42  	}, {
    43  		(*marshalerType)(nil),
    44  		"null\n",
    45  	}, {
    46  		&struct{}{},
    47  		"{}\n",
    48  	}, {
    49  		map[string]string{"v": "hi"},
    50  		"v: hi\n",
    51  	}, {
    52  		map[string]interface{}{"v": "hi"},
    53  		"v: hi\n",
    54  	}, {
    55  		map[string]string{"v": "true"},
    56  		"v: \"true\"\n",
    57  	}, {
    58  		map[string]string{"v": "false"},
    59  		"v: \"false\"\n",
    60  	}, {
    61  		map[string]interface{}{"v": true},
    62  		"v: true\n",
    63  	}, {
    64  		map[string]interface{}{"v": false},
    65  		"v: false\n",
    66  	}, {
    67  		map[string]interface{}{"v": 10},
    68  		"v: 10\n",
    69  	}, {
    70  		map[string]interface{}{"v": -10},
    71  		"v: -10\n",
    72  	}, {
    73  		map[string]uint{"v": 42},
    74  		"v: 42\n",
    75  	}, {
    76  		map[string]interface{}{"v": int64(4294967296)},
    77  		"v: 4294967296\n",
    78  	}, {
    79  		map[string]int64{"v": int64(4294967296)},
    80  		"v: 4294967296\n",
    81  	}, {
    82  		map[string]uint64{"v": 4294967296},
    83  		"v: 4294967296\n",
    84  	}, {
    85  		map[string]interface{}{"v": "10"},
    86  		"v: \"10\"\n",
    87  	}, {
    88  		map[string]interface{}{"v": 0.1},
    89  		"v: 0.1\n",
    90  	}, {
    91  		map[string]interface{}{"v": float64(0.1)},
    92  		"v: 0.1\n",
    93  	}, {
    94  		map[string]interface{}{"v": float32(0.99)},
    95  		"v: 0.99\n",
    96  	}, {
    97  		map[string]interface{}{"v": -0.1},
    98  		"v: -0.1\n",
    99  	}, {
   100  		map[string]interface{}{"v": math.Inf(+1)},
   101  		"v: .inf\n",
   102  	}, {
   103  		map[string]interface{}{"v": math.Inf(-1)},
   104  		"v: -.inf\n",
   105  	}, {
   106  		map[string]interface{}{"v": math.NaN()},
   107  		"v: .nan\n",
   108  	}, {
   109  		map[string]interface{}{"v": nil},
   110  		"v: null\n",
   111  	}, {
   112  		map[string]interface{}{"v": ""},
   113  		"v: \"\"\n",
   114  	}, {
   115  		map[string][]string{"v": []string{"A", "B"}},
   116  		"v:\n    - A\n    - B\n",
   117  	}, {
   118  		map[string][]string{"v": []string{"A", "B\nC"}},
   119  		"v:\n    - A\n    - |-\n      B\n      C\n",
   120  	}, {
   121  		map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
   122  		"v:\n    - A\n    - 1\n    - B:\n        - 2\n        - 3\n",
   123  	}, {
   124  		map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
   125  		"a:\n    b: c\n",
   126  	}, {
   127  		map[string]interface{}{"a": "-"},
   128  		"a: '-'\n",
   129  	},
   130  
   131  	// Simple values.
   132  	{
   133  		&marshalIntTest,
   134  		"123\n",
   135  	},
   136  
   137  	// Structures
   138  	{
   139  		&struct{ Hello string }{"world"},
   140  		"hello: world\n",
   141  	}, {
   142  		&struct {
   143  			A struct {
   144  				B string
   145  			}
   146  		}{struct{ B string }{"c"}},
   147  		"a:\n    b: c\n",
   148  	}, {
   149  		&struct {
   150  			A *struct {
   151  				B string
   152  			}
   153  		}{&struct{ B string }{"c"}},
   154  		"a:\n    b: c\n",
   155  	}, {
   156  		&struct {
   157  			A *struct {
   158  				B string
   159  			}
   160  		}{},
   161  		"a: null\n",
   162  	}, {
   163  		&struct{ A int }{1},
   164  		"a: 1\n",
   165  	}, {
   166  		&struct{ A []int }{[]int{1, 2}},
   167  		"a:\n    - 1\n    - 2\n",
   168  	}, {
   169  		&struct{ A [2]int }{[2]int{1, 2}},
   170  		"a:\n    - 1\n    - 2\n",
   171  	}, {
   172  		&struct {
   173  			B int "a"
   174  		}{1},
   175  		"a: 1\n",
   176  	}, {
   177  		&struct{ A bool }{true},
   178  		"a: true\n",
   179  	}, {
   180  		&struct{ A string }{"true"},
   181  		"a: \"true\"\n",
   182  	}, {
   183  		&struct{ A string }{"off"},
   184  		"a: \"off\"\n",
   185  	},
   186  
   187  	// Conditional flag
   188  	{
   189  		&struct {
   190  			A int "a,omitempty"
   191  			B int "b,omitempty"
   192  		}{1, 0},
   193  		"a: 1\n",
   194  	}, {
   195  		&struct {
   196  			A int "a,omitempty"
   197  			B int "b,omitempty"
   198  		}{0, 0},
   199  		"{}\n",
   200  	}, {
   201  		&struct {
   202  			A *struct{ X, y int } "a,omitempty,flow"
   203  		}{&struct{ X, y int }{1, 2}},
   204  		"a: {x: 1}\n",
   205  	}, {
   206  		&struct {
   207  			A *struct{ X, y int } "a,omitempty,flow"
   208  		}{nil},
   209  		"{}\n",
   210  	}, {
   211  		&struct {
   212  			A *struct{ X, y int } "a,omitempty,flow"
   213  		}{&struct{ X, y int }{}},
   214  		"a: {x: 0}\n",
   215  	}, {
   216  		&struct {
   217  			A struct{ X, y int } "a,omitempty,flow"
   218  		}{struct{ X, y int }{1, 2}},
   219  		"a: {x: 1}\n",
   220  	}, {
   221  		&struct {
   222  			A struct{ X, y int } "a,omitempty,flow"
   223  		}{struct{ X, y int }{0, 1}},
   224  		"{}\n",
   225  	}, {
   226  		&struct {
   227  			A float64 "a,omitempty"
   228  			B float64 "b,omitempty"
   229  		}{1, 0},
   230  		"a: 1\n",
   231  	},
   232  	{
   233  		&struct {
   234  			T1 time.Time  "t1,omitempty"
   235  			T2 time.Time  "t2,omitempty"
   236  			T3 *time.Time "t3,omitempty"
   237  			T4 *time.Time "t4,omitempty"
   238  		}{
   239  			T2: time.Date(2018, 1, 9, 10, 40, 47, 0, time.UTC),
   240  			T4: newTime(time.Date(2098, 1, 9, 10, 40, 47, 0, time.UTC)),
   241  		},
   242  		"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
   243  	},
   244  	// Nil interface that implements Marshaler.
   245  	{
   246  		map[string]yaml.Marshaler{
   247  			"a": nil,
   248  		},
   249  		"a: null\n",
   250  	},
   251  
   252  	// Flow flag
   253  	{
   254  		&struct {
   255  			A []int "a,flow"
   256  		}{[]int{1, 2}},
   257  		"a: [1, 2]\n",
   258  	}, {
   259  		&struct {
   260  			A map[string]string "a,flow"
   261  		}{map[string]string{"b": "c", "d": "e"}},
   262  		"a: {b: c, d: e}\n",
   263  	}, {
   264  		&struct {
   265  			A struct {
   266  				B, D string
   267  			} "a,flow"
   268  		}{struct{ B, D string }{"c", "e"}},
   269  		"a: {b: c, d: e}\n",
   270  	}, {
   271  		&struct {
   272  			A string "a,flow"
   273  		}{"b\nc"},
   274  		"a: \"b\\nc\"\n",
   275  	},
   276  
   277  	// Unexported field
   278  	{
   279  		&struct {
   280  			u int
   281  			A int
   282  		}{0, 1},
   283  		"a: 1\n",
   284  	},
   285  
   286  	// Ignored field
   287  	{
   288  		&struct {
   289  			A int
   290  			B int "-"
   291  		}{1, 2},
   292  		"a: 1\n",
   293  	},
   294  
   295  	// Struct inlining
   296  	{
   297  		&struct {
   298  			A int
   299  			C inlineB `yaml:",inline"`
   300  		}{1, inlineB{2, inlineC{3}}},
   301  		"a: 1\nb: 2\nc: 3\n",
   302  	},
   303  	// Struct inlining as a pointer
   304  	{
   305  		&struct {
   306  			A int
   307  			C *inlineB `yaml:",inline"`
   308  		}{1, &inlineB{2, inlineC{3}}},
   309  		"a: 1\nb: 2\nc: 3\n",
   310  	}, {
   311  		&struct {
   312  			A int
   313  			C *inlineB `yaml:",inline"`
   314  		}{1, nil},
   315  		"a: 1\n",
   316  	}, {
   317  		&struct {
   318  			A int
   319  			D *inlineD `yaml:",inline"`
   320  		}{1, &inlineD{&inlineC{3}, 4}},
   321  		"a: 1\nc: 3\nd: 4\n",
   322  	},
   323  
   324  	// Map inlining
   325  	{
   326  		&struct {
   327  			A int
   328  			C map[string]int `yaml:",inline"`
   329  		}{1, map[string]int{"b": 2, "c": 3}},
   330  		"a: 1\nb: 2\nc: 3\n",
   331  	},
   332  
   333  	// Duration
   334  	{
   335  		map[string]time.Duration{"a": 3 * time.Second},
   336  		"a: 3s\n",
   337  	},
   338  
   339  	// Issue #24: bug in map merging logic.
   340  	{
   341  		map[string]string{"a": "<foo>"},
   342  		"a: <foo>\n",
   343  	},
   344  
   345  	// Issue #34: marshal unsupported base 60 floats quoted for compatibility
   346  	// with old YAML 1.1 parsers.
   347  	{
   348  		map[string]string{"a": "1:1"},
   349  		"a: \"1:1\"\n",
   350  	},
   351  
   352  	// Binary data.
   353  	{
   354  		map[string]string{"a": "\x00"},
   355  		"a: \"\\0\"\n",
   356  	}, {
   357  		map[string]string{"a": "\x80\x81\x82"},
   358  		"a: !!binary gIGC\n",
   359  	}, {
   360  		map[string]string{"a": strings.Repeat("\x90", 54)},
   361  		"a: !!binary |\n    " + strings.Repeat("kJCQ", 17) + "kJ\n    CQ\n",
   362  	},
   363  
   364  	// Encode unicode as utf-8 rather than in escaped form.
   365  	{
   366  		map[string]string{"a": "你好"},
   367  		"a: 你好\n",
   368  	},
   369  
   370  	// Support encoding.TextMarshaler.
   371  	{
   372  		map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
   373  		"a: 1.2.3.4\n",
   374  	},
   375  	// time.Time gets a timestamp tag.
   376  	{
   377  		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
   378  		"a: 2015-02-24T18:19:39Z\n",
   379  	},
   380  	{
   381  		map[string]*time.Time{"a": newTime(time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC))},
   382  		"a: 2015-02-24T18:19:39Z\n",
   383  	},
   384  	{
   385  		// This is confirmed to be properly decoded in Python (libyaml) without a timestamp tag.
   386  		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 123456789, time.FixedZone("FOO", -3*60*60))},
   387  		"a: 2015-02-24T18:19:39.123456789-03:00\n",
   388  	},
   389  	// Ensure timestamp-like strings are quoted.
   390  	{
   391  		map[string]string{"a": "2015-02-24T18:19:39Z"},
   392  		"a: \"2015-02-24T18:19:39Z\"\n",
   393  	},
   394  
   395  	// Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible).
   396  	{
   397  		map[string]string{"a": "b: c"},
   398  		"a: 'b: c'\n",
   399  	},
   400  
   401  	// Containing hash mark ('#') in string should be quoted
   402  	{
   403  		map[string]string{"a": "Hello #comment"},
   404  		"a: 'Hello #comment'\n",
   405  	},
   406  	{
   407  		map[string]string{"a": "你好 #comment"},
   408  		"a: '你好 #comment'\n",
   409  	},
   410  
   411  	// Ensure MarshalYAML also gets called on the result of MarshalYAML itself.
   412  	{
   413  		&marshalerType{marshalerType{true}},
   414  		"true\n",
   415  	}, {
   416  		&marshalerType{&marshalerType{true}},
   417  		"true\n",
   418  	},
   419  
   420  	// Check indentation of maps inside sequences inside maps.
   421  	{
   422  		map[string]interface{}{"a": map[string]interface{}{"b": []map[string]int{{"c": 1, "d": 2}}}},
   423  		"a:\n    b:\n        - c: 1\n          d: 2\n",
   424  	},
   425  
   426  	// Strings with tabs were disallowed as literals (issue #471).
   427  	{
   428  		map[string]string{"a": "\tB\n\tC\n"},
   429  		"a: |\n    \tB\n    \tC\n",
   430  	},
   431  
   432  	// Ensure that strings do not wrap
   433  	{
   434  		map[string]string{"a": "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 "},
   435  		"a: 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 '\n",
   436  	},
   437  
   438  	// yaml.Node
   439  	{
   440  		&struct {
   441  			Value yaml.Node
   442  		}{
   443  			yaml.Node{
   444  				Kind:  yaml.ScalarNode,
   445  				Tag:   "!!str",
   446  				Value: "foo",
   447  				Style: yaml.SingleQuotedStyle,
   448  			},
   449  		},
   450  		"value: 'foo'\n",
   451  	}, {
   452  		yaml.Node{
   453  			Kind:  yaml.ScalarNode,
   454  			Tag:   "!!str",
   455  			Value: "foo",
   456  			Style: yaml.SingleQuotedStyle,
   457  		},
   458  		"'foo'\n",
   459  	},
   460  
   461  	// Enforced tagging with shorthand notation (issue #616).
   462  	{
   463  		&struct {
   464  			Value yaml.Node
   465  		}{
   466  			yaml.Node{
   467  				Kind:  yaml.ScalarNode,
   468  				Style: yaml.TaggedStyle,
   469  				Value: "foo",
   470  				Tag:   "!!str",
   471  			},
   472  		},
   473  		"value: !!str foo\n",
   474  	}, {
   475  		&struct {
   476  			Value yaml.Node
   477  		}{
   478  			yaml.Node{
   479  				Kind:  yaml.MappingNode,
   480  				Style: yaml.TaggedStyle,
   481  				Tag:   "!!map",
   482  			},
   483  		},
   484  		"value: !!map {}\n",
   485  	}, {
   486  		&struct {
   487  			Value yaml.Node
   488  		}{
   489  			yaml.Node{
   490  				Kind:  yaml.SequenceNode,
   491  				Style: yaml.TaggedStyle,
   492  				Tag:   "!!seq",
   493  			},
   494  		},
   495  		"value: !!seq []\n",
   496  	},
   497  }
   498  
   499  func (s *S) TestMarshal(c *C) {
   500  	defer os.Setenv("TZ", os.Getenv("TZ"))
   501  	os.Setenv("TZ", "UTC")
   502  	for i, item := range marshalTests {
   503  		c.Logf("test %d: %q", i, item.data)
   504  		data, err := yaml.Marshal(item.value)
   505  		c.Assert(err, IsNil)
   506  		c.Assert(string(data), Equals, item.data)
   507  	}
   508  }
   509  
   510  func (s *S) TestEncoderSingleDocument(c *C) {
   511  	for i, item := range marshalTests {
   512  		c.Logf("test %d. %q", i, item.data)
   513  		var buf bytes.Buffer
   514  		enc := yaml.NewEncoder(&buf)
   515  		err := enc.Encode(item.value)
   516  		c.Assert(err, Equals, nil)
   517  		err = enc.Close()
   518  		c.Assert(err, Equals, nil)
   519  		c.Assert(buf.String(), Equals, item.data)
   520  	}
   521  }
   522  
   523  func (s *S) TestEncoderMultipleDocuments(c *C) {
   524  	var buf bytes.Buffer
   525  	enc := yaml.NewEncoder(&buf)
   526  	err := enc.Encode(map[string]string{"a": "b"})
   527  	c.Assert(err, Equals, nil)
   528  	err = enc.Encode(map[string]string{"c": "d"})
   529  	c.Assert(err, Equals, nil)
   530  	err = enc.Close()
   531  	c.Assert(err, Equals, nil)
   532  	c.Assert(buf.String(), Equals, "a: b\n---\nc: d\n")
   533  }
   534  
   535  func (s *S) TestEncoderWriteError(c *C) {
   536  	enc := yaml.NewEncoder(errorWriter{})
   537  	err := enc.Encode(map[string]string{"a": "b"})
   538  	c.Assert(err, ErrorMatches, `yaml: write error: some write error`) // Data not flushed yet
   539  }
   540  
   541  type errorWriter struct{}
   542  
   543  func (errorWriter) Write([]byte) (int, error) {
   544  	return 0, fmt.Errorf("some write error")
   545  }
   546  
   547  var marshalErrorTests = []struct {
   548  	value interface{}
   549  	error string
   550  	panic string
   551  }{{
   552  	value: &struct {
   553  		B       int
   554  		inlineB ",inline"
   555  	}{1, inlineB{2, inlineC{3}}},
   556  	panic: `duplicated key 'b' in struct struct \{ B int; .*`,
   557  }, {
   558  	value: &struct {
   559  		A int
   560  		B map[string]int ",inline"
   561  	}{1, map[string]int{"a": 2}},
   562  	panic: `cannot have key "a" in inlined map: conflicts with struct field`,
   563  }}
   564  
   565  func (s *S) TestMarshalErrors(c *C) {
   566  	for _, item := range marshalErrorTests {
   567  		if item.panic != "" {
   568  			c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
   569  		} else {
   570  			_, err := yaml.Marshal(item.value)
   571  			c.Assert(err, ErrorMatches, item.error)
   572  		}
   573  	}
   574  }
   575  
   576  func (s *S) TestMarshalTypeCache(c *C) {
   577  	var data []byte
   578  	var err error
   579  	func() {
   580  		type T struct{ A int }
   581  		data, err = yaml.Marshal(&T{})
   582  		c.Assert(err, IsNil)
   583  	}()
   584  	func() {
   585  		type T struct{ B int }
   586  		data, err = yaml.Marshal(&T{})
   587  		c.Assert(err, IsNil)
   588  	}()
   589  	c.Assert(string(data), Equals, "b: 0\n")
   590  }
   591  
   592  var marshalerTests = []struct {
   593  	data  string
   594  	value interface{}
   595  }{
   596  	{"_:\n    hi: there\n", map[interface{}]interface{}{"hi": "there"}},
   597  	{"_:\n    - 1\n    - A\n", []interface{}{1, "A"}},
   598  	{"_: 10\n", 10},
   599  	{"_: null\n", nil},
   600  	{"_: BAR!\n", "BAR!"},
   601  }
   602  
   603  type marshalerType struct {
   604  	value interface{}
   605  }
   606  
   607  func (o marshalerType) MarshalText() ([]byte, error) {
   608  	panic("MarshalText called on type with MarshalYAML")
   609  }
   610  
   611  func (o marshalerType) MarshalYAML() (interface{}, error) {
   612  	return o.value, nil
   613  }
   614  
   615  type marshalerValue struct {
   616  	Field marshalerType "_"
   617  }
   618  
   619  func (s *S) TestMarshaler(c *C) {
   620  	for _, item := range marshalerTests {
   621  		obj := &marshalerValue{}
   622  		obj.Field.value = item.value
   623  		data, err := yaml.Marshal(obj)
   624  		c.Assert(err, IsNil)
   625  		c.Assert(string(data), Equals, string(item.data))
   626  	}
   627  }
   628  
   629  func (s *S) TestMarshalerWholeDocument(c *C) {
   630  	obj := &marshalerType{}
   631  	obj.value = map[string]string{"hello": "world!"}
   632  	data, err := yaml.Marshal(obj)
   633  	c.Assert(err, IsNil)
   634  	c.Assert(string(data), Equals, "hello: world!\n")
   635  }
   636  
   637  type failingMarshaler struct{}
   638  
   639  func (ft *failingMarshaler) MarshalYAML() (interface{}, error) {
   640  	return nil, failingErr
   641  }
   642  
   643  func (s *S) TestMarshalerError(c *C) {
   644  	_, err := yaml.Marshal(&failingMarshaler{})
   645  	c.Assert(err, Equals, failingErr)
   646  }
   647  
   648  func (s *S) TestSetIndent(c *C) {
   649  	var buf bytes.Buffer
   650  	enc := yaml.NewEncoder(&buf)
   651  	enc.SetIndent(8)
   652  	err := enc.Encode(map[string]interface{}{"a": map[string]interface{}{"b": map[string]string{"c": "d"}}})
   653  	c.Assert(err, Equals, nil)
   654  	err = enc.Close()
   655  	c.Assert(err, Equals, nil)
   656  	c.Assert(buf.String(), Equals, "a:\n        b:\n                c: d\n")
   657  }
   658  
   659  func (s *S) TestSortedOutput(c *C) {
   660  	order := []interface{}{
   661  		false,
   662  		true,
   663  		1,
   664  		uint(1),
   665  		1.0,
   666  		1.1,
   667  		1.2,
   668  		2,
   669  		uint(2),
   670  		2.0,
   671  		2.1,
   672  		"",
   673  		".1",
   674  		".2",
   675  		".a",
   676  		"1",
   677  		"2",
   678  		"a!10",
   679  		"a/0001",
   680  		"a/002",
   681  		"a/3",
   682  		"a/10",
   683  		"a/11",
   684  		"a/0012",
   685  		"a/100",
   686  		"a~10",
   687  		"ab/1",
   688  		"b/1",
   689  		"b/01",
   690  		"b/2",
   691  		"b/02",
   692  		"b/3",
   693  		"b/03",
   694  		"b1",
   695  		"b01",
   696  		"b3",
   697  		"c2.10",
   698  		"c10.2",
   699  		"d1",
   700  		"d7",
   701  		"d7abc",
   702  		"d12",
   703  		"d12a",
   704  		"e2b",
   705  		"e4b",
   706  		"e21a",
   707  	}
   708  	m := make(map[interface{}]int)
   709  	for _, k := range order {
   710  		m[k] = 1
   711  	}
   712  	data, err := yaml.Marshal(m)
   713  	c.Assert(err, IsNil)
   714  	out := "\n" + string(data)
   715  	last := 0
   716  	for i, k := range order {
   717  		repr := fmt.Sprint(k)
   718  		if s, ok := k.(string); ok {
   719  			if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil {
   720  				repr = `"` + repr + `"`
   721  			}
   722  		}
   723  		index := strings.Index(out, "\n"+repr+":")
   724  		if index == -1 {
   725  			c.Fatalf("%#v is not in the output: %#v", k, out)
   726  		}
   727  		if index < last {
   728  			c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out)
   729  		}
   730  		last = index
   731  	}
   732  }
   733  
   734  func newTime(t time.Time) *time.Time {
   735  	return &t
   736  }
   737  

View as plain text