| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | package yaml_test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2019-10-23 21:00:00 +09:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2019-10-26 18:39:15 +09:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/goccy/go-yaml" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestEncoder(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		source string | 
					
						
							|  |  |  | 		value  interface{} | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"null\n", | 
					
						
							|  |  |  | 			(*struct{})(nil), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: hi\n", | 
					
						
							|  |  |  | 			map[string]string{"v": "hi"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: \"true\"\n", | 
					
						
							|  |  |  | 			map[string]string{"v": "true"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: \"false\"\n", | 
					
						
							|  |  |  | 			map[string]string{"v": "false"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: true\n", | 
					
						
							|  |  |  | 			map[string]interface{}{"v": true}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: false\n", | 
					
						
							|  |  |  | 			map[string]bool{"v": false}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: 10\n", | 
					
						
							|  |  |  | 			map[string]int{"v": 10}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: -10\n", | 
					
						
							|  |  |  | 			map[string]int{"v": -10}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: 4294967296\n", | 
					
						
							|  |  |  | 			map[string]int{"v": 4294967296}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: 0.1\n", | 
					
						
							|  |  |  | 			map[string]interface{}{"v": 0.1}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: 0.99\n", | 
					
						
							|  |  |  | 			map[string]float32{"v": 0.99}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: -0.1\n", | 
					
						
							|  |  |  | 			map[string]float64{"v": -0.1}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: 1.0\n", | 
					
						
							|  |  |  | 			map[string]float64{"v": 1.0}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: .inf\n", | 
					
						
							|  |  |  | 			map[string]interface{}{"v": math.Inf(0)}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: -.inf\n", | 
					
						
							|  |  |  | 			map[string]interface{}{"v": math.Inf(-1)}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: .nan\n", | 
					
						
							|  |  |  | 			map[string]interface{}{"v": math.NaN()}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: null\n", | 
					
						
							|  |  |  | 			map[string]interface{}{"v": nil}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: \"\"\n", | 
					
						
							|  |  |  | 			map[string]string{"v": ""}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v:\n- A\n- B\n", | 
					
						
							| 
									
										
										
										
											2019-10-21 01:28:48 +09:00
										 |  |  | 			map[string][]string{"v": {"A", "B"}}, | 
					
						
							| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: -\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "-"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"123\n", | 
					
						
							|  |  |  | 			123, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"hello: world\n", | 
					
						
							|  |  |  | 			map[string]string{"hello": "world"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v:\n- A\n- 1\n- B:\n  - 2\n  - 3\n", | 
					
						
							|  |  |  | 			map[string]interface{}{ | 
					
						
							|  |  |  | 				"v": []interface{}{ | 
					
						
							|  |  |  | 					"A", | 
					
						
							|  |  |  | 					1, | 
					
						
							|  |  |  | 					map[string][]int{ | 
					
						
							| 
									
										
										
										
											2019-10-21 01:28:48 +09:00
										 |  |  | 						"B": {2, 3}, | 
					
						
							| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a:\n  b: c\n", | 
					
						
							|  |  |  | 			map[string]interface{}{ | 
					
						
							|  |  |  | 				"a": map[string]string{ | 
					
						
							|  |  |  | 					"b": "c", | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n", | 
					
						
							|  |  |  | 			map[string]string{ | 
					
						
							|  |  |  | 				"t2": "2018-01-09T10:40:47Z", | 
					
						
							|  |  |  | 				"t4": "2098-01-09T10:40:47Z", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a:\n  b: c\n  d: e\n", | 
					
						
							|  |  |  | 			map[string]interface{}{ | 
					
						
							|  |  |  | 				"a": map[string]string{ | 
					
						
							|  |  |  | 					"b": "c", | 
					
						
							|  |  |  | 					"d": "e", | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 3s\n", | 
					
						
							|  |  |  | 			map[string]string{ | 
					
						
							|  |  |  | 				"a": "3s", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: <foo>\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "<foo>"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: \"1:1\"\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "1:1"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 1.2.3.4\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "1.2.3.4"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: \"b: c\"\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "b: c"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: \"Hello #comment\"\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "Hello #comment"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 100.5\n", | 
					
						
							|  |  |  | 			map[string]interface{}{ | 
					
						
							|  |  |  | 				"a": 100.5, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: \"\\\\0\"\n", | 
					
						
							|  |  |  | 			map[string]string{"a": "\\0"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 1\nb: 2\nc: 3\nd: 4\nsub:\n  e: 5\n", | 
					
						
							|  |  |  | 			map[string]interface{}{ | 
					
						
							|  |  |  | 				"a": 1, | 
					
						
							|  |  |  | 				"b": 2, | 
					
						
							|  |  |  | 				"c": 3, | 
					
						
							|  |  |  | 				"d": 4, | 
					
						
							|  |  |  | 				"sub": map[string]int{ | 
					
						
							|  |  |  | 					"e": 5, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: b\nc: d\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A string | 
					
						
							|  |  |  | 				C string `yaml:"c"` | 
					
						
							|  |  |  | 			}{ | 
					
						
							|  |  |  | 				"b", "d", | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 1\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A int | 
					
						
							|  |  |  | 				B int `yaml:"-"` | 
					
						
							|  |  |  | 			}{ | 
					
						
							|  |  |  | 				1, 0, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-10-31 13:08:11 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Conditional flag | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 1\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A int "a,omitempty" | 
					
						
							|  |  |  | 				B int "b,omitempty" | 
					
						
							|  |  |  | 			}{1, 0}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"{}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A int "a,omitempty" | 
					
						
							|  |  |  | 				B int "b,omitempty" | 
					
						
							|  |  |  | 			}{0, 0}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: {x: 1}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A *struct{ X, y int } "a,omitempty,flow" | 
					
						
							|  |  |  | 			}{&struct{ X, y int }{1, 2}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"{}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A *struct{ X, y int } "a,omitempty,flow" | 
					
						
							|  |  |  | 			}{nil}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: {x: 0}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A *struct{ X, y int } "a,omitempty,flow" | 
					
						
							|  |  |  | 			}{&struct{ X, y int }{}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: {x: 1}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A struct{ X, y int } "a,omitempty,flow" | 
					
						
							|  |  |  | 			}{struct{ X, y int }{1, 2}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"{}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A struct{ X, y int } "a,omitempty,flow" | 
					
						
							|  |  |  | 			}{struct{ X, y int }{0, 1}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: 1.0\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A float64 "a,omitempty" | 
					
						
							|  |  |  | 				B float64 "b,omitempty" | 
					
						
							|  |  |  | 			}{1, 0}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Flow flag | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: [1, 2]\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A []int "a,flow" | 
					
						
							|  |  |  | 			}{[]int{1, 2}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: {b: c, d: e}\n", | 
					
						
							|  |  |  | 			&struct { | 
					
						
							|  |  |  | 				A map[string]string "a,flow" | 
					
						
							|  |  |  | 			}{map[string]string{"b": "c", "d": "e"}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"a: {b: c, d: e}\n", | 
					
						
							|  |  |  | 			struct { | 
					
						
							|  |  |  | 				A struct { | 
					
						
							|  |  |  | 					B, D string | 
					
						
							|  |  |  | 				} "a,flow" | 
					
						
							|  |  |  | 			}{struct{ B, D string }{"c", "e"}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-11-07 17:18:17 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Multi bytes | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"v: あいうえお\n", | 
					
						
							|  |  |  | 			map[string]string{"v": "あいうえお"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-10-19 18:28:36 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for _, test := range tests { | 
					
						
							|  |  |  | 		var buf bytes.Buffer | 
					
						
							|  |  |  | 		enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 		if err := enc.Encode(test.value); err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if test.source != buf.String() { | 
					
						
							|  |  |  | 			t.Fatalf("expect = [%s], actual = [%s]", test.source, buf.String()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-19 22:01:36 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestEncodeWithAnchorAndAlias(t *testing.T) { | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 	type T struct { | 
					
						
							|  |  |  | 		A int | 
					
						
							|  |  |  | 		B string | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var v struct { | 
					
						
							|  |  |  | 		A *T `yaml:"a,anchor=c"` | 
					
						
							|  |  |  | 		B *T `yaml:"b,alias=c"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.A = &T{A: 1, B: "hello"} | 
					
						
							|  |  |  | 	v.B = v.A | 
					
						
							|  |  |  | 	if err := enc.Encode(v); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := "a: &c\n  a: 1\n  b: hello\nb: *c\n" | 
					
						
							|  |  |  | 	if expect != buf.String() { | 
					
						
							|  |  |  | 		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-20 13:05:03 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestEncodeWithAutoAlias(t *testing.T) { | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 	type T struct { | 
					
						
							|  |  |  | 		I int | 
					
						
							|  |  |  | 		S string | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var v struct { | 
					
						
							|  |  |  | 		A *T `yaml:"a,anchor=a"` | 
					
						
							|  |  |  | 		B *T `yaml:"b,anchor=b"` | 
					
						
							|  |  |  | 		C *T `yaml:"c,alias"` | 
					
						
							|  |  |  | 		D *T `yaml:"d,alias"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.A = &T{I: 1, S: "hello"} | 
					
						
							|  |  |  | 	v.B = &T{I: 2, S: "world"} | 
					
						
							|  |  |  | 	v.C = v.A | 
					
						
							|  |  |  | 	v.D = v.B | 
					
						
							|  |  |  | 	if err := enc.Encode(v); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := `a: &a | 
					
						
							|  |  |  |   i: 1 | 
					
						
							|  |  |  |   s: hello | 
					
						
							|  |  |  | b: &b | 
					
						
							|  |  |  |   i: 2 | 
					
						
							|  |  |  |   s: world | 
					
						
							|  |  |  | c: *a | 
					
						
							|  |  |  | d: *b | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	if expect != buf.String() { | 
					
						
							|  |  |  | 		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-20 13:31:29 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestEncodeWithImplicitAnchorAndAlias(t *testing.T) { | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 	type T struct { | 
					
						
							|  |  |  | 		I int | 
					
						
							|  |  |  | 		S string | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var v struct { | 
					
						
							|  |  |  | 		A *T `yaml:"a,anchor"` | 
					
						
							|  |  |  | 		B *T `yaml:"b,anchor"` | 
					
						
							|  |  |  | 		C *T `yaml:"c,alias"` | 
					
						
							|  |  |  | 		D *T `yaml:"d,alias"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.A = &T{I: 1, S: "hello"} | 
					
						
							|  |  |  | 	v.B = &T{I: 2, S: "world"} | 
					
						
							|  |  |  | 	v.C = v.A | 
					
						
							|  |  |  | 	v.D = v.B | 
					
						
							|  |  |  | 	if err := enc.Encode(v); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := `a: &a | 
					
						
							|  |  |  |   i: 1 | 
					
						
							|  |  |  |   s: hello | 
					
						
							|  |  |  | b: &b | 
					
						
							|  |  |  |   i: 2 | 
					
						
							|  |  |  |   s: world | 
					
						
							|  |  |  | c: *a | 
					
						
							|  |  |  | d: *b | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	if expect != buf.String() { | 
					
						
							|  |  |  | 		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-20 21:47:06 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestEncodeWithMerge(t *testing.T) { | 
					
						
							|  |  |  | 	type Person struct { | 
					
						
							|  |  |  | 		*Person `yaml:",omitempty,inline,alias"` | 
					
						
							|  |  |  | 		Name    string `yaml:",omitempty"` | 
					
						
							|  |  |  | 		Age     int    `yaml:",omitempty"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defaultPerson := &Person{ | 
					
						
							|  |  |  | 		Name: "John Smith", | 
					
						
							|  |  |  | 		Age:  20, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	people := []*Person{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Person: defaultPerson, | 
					
						
							|  |  |  | 			Name:   "Ken", | 
					
						
							|  |  |  | 			Age:    10, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Person: defaultPerson, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var doc struct { | 
					
						
							|  |  |  | 		Default *Person   `yaml:"default,anchor"` | 
					
						
							|  |  |  | 		People  []*Person `yaml:"people"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	doc.Default = defaultPerson | 
					
						
							|  |  |  | 	doc.People = people | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 	if err := enc.Encode(doc); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := `default: &default | 
					
						
							|  |  |  |   name: John Smith | 
					
						
							|  |  |  |   age: 20 | 
					
						
							|  |  |  | people: | 
					
						
							|  |  |  | - <<: *default | 
					
						
							|  |  |  |   name: Ken | 
					
						
							|  |  |  |   age: 10 | 
					
						
							|  |  |  | - <<: *default | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	if expect != buf.String() { | 
					
						
							|  |  |  | 		t.Fatalf("expect = [%s], actual = [%s]", expect, buf.String()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-23 21:00:00 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-28 22:13:03 +09:00
										 |  |  | func TestEncoder_Inline(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-10-28 21:37:12 +09:00
										 |  |  | 	type base struct { | 
					
						
							|  |  |  | 		A int | 
					
						
							|  |  |  | 		B string | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-28 22:13:03 +09:00
										 |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 	if err := enc.Encode(struct { | 
					
						
							| 
									
										
										
										
											2019-10-28 21:37:12 +09:00
										 |  |  | 		*base `yaml:",inline"` | 
					
						
							|  |  |  | 		C     bool | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		base: &base{ | 
					
						
							|  |  |  | 			A: 1, | 
					
						
							|  |  |  | 			B: "hello", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		C: true, | 
					
						
							| 
									
										
										
										
											2019-10-28 22:13:03 +09:00
										 |  |  | 	}); err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-28 21:37:12 +09:00
										 |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := ` | 
					
						
							|  |  |  | a: 1 | 
					
						
							|  |  |  | b: hello | 
					
						
							|  |  |  | c: true | 
					
						
							|  |  |  | ` | 
					
						
							| 
									
										
										
										
											2019-10-28 22:13:03 +09:00
										 |  |  | 	actual := "\n" + buf.String() | 
					
						
							| 
									
										
										
										
											2019-10-28 21:37:12 +09:00
										 |  |  | 	if expect != actual { | 
					
						
							|  |  |  | 		t.Fatalf("inline marshal error: expect=[%s] actual=[%s]", expect, actual) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-28 22:25:00 +09:00
										 |  |  | func TestEncoder_InlineAndConflictKey(t *testing.T) { | 
					
						
							|  |  |  | 	type base struct { | 
					
						
							|  |  |  | 		A int | 
					
						
							|  |  |  | 		B string | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf) | 
					
						
							|  |  |  | 	if err := enc.Encode(struct { | 
					
						
							|  |  |  | 		*base `yaml:",inline"` | 
					
						
							|  |  |  | 		A     int // conflict | 
					
						
							|  |  |  | 		C     bool | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		base: &base{ | 
					
						
							|  |  |  | 			A: 1, | 
					
						
							|  |  |  | 			B: "hello", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		A: 0, // default value | 
					
						
							|  |  |  | 		C: true, | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := ` | 
					
						
							|  |  |  | b: hello | 
					
						
							|  |  |  | a: 0 | 
					
						
							|  |  |  | c: true | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	actual := "\n" + buf.String() | 
					
						
							|  |  |  | 	if expect != actual { | 
					
						
							|  |  |  | 		t.Fatalf("inline marshal error: expect=[%s] actual=[%s]", expect, actual) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 13:29:43 +09:00
										 |  |  | func TestEncoder_Flow(t *testing.T) { | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	enc := yaml.NewEncoder(&buf, yaml.Flow(true)) | 
					
						
							|  |  |  | 	var v struct { | 
					
						
							|  |  |  | 		A int | 
					
						
							|  |  |  | 		B string | 
					
						
							|  |  |  | 		C struct { | 
					
						
							|  |  |  | 			D int | 
					
						
							|  |  |  | 			E string | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		F []int | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.A = 1 | 
					
						
							|  |  |  | 	v.B = "hello" | 
					
						
							|  |  |  | 	v.C.D = 3 | 
					
						
							|  |  |  | 	v.C.E = "world" | 
					
						
							|  |  |  | 	v.F = []int{1, 2} | 
					
						
							|  |  |  | 	if err := enc.Encode(v); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("%+v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	expect := ` | 
					
						
							|  |  |  | {a: 1, b: hello, c: {d: 3, e: world}, f: [1, 2]} | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 	actual := "\n" + buf.String() | 
					
						
							|  |  |  | 	if expect != actual { | 
					
						
							|  |  |  | 		t.Fatalf("flow style marshal error: expect=[%s] actual=[%s]", expect, actual) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 21:00:00 +09:00
										 |  |  | func Example_Marshal_ExplicitAnchorAlias() { | 
					
						
							|  |  |  | 	type T struct { | 
					
						
							|  |  |  | 		A int | 
					
						
							|  |  |  | 		B string | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var v struct { | 
					
						
							|  |  |  | 		C *T `yaml:"c,anchor=x"` | 
					
						
							|  |  |  | 		D *T `yaml:"d,alias=x"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.C = &T{A: 1, B: "hello"} | 
					
						
							|  |  |  | 	v.D = v.C | 
					
						
							|  |  |  | 	bytes, err := yaml.Marshal(v) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fmt.Println(string(bytes)) | 
					
						
							|  |  |  | 	// OUTPUT: | 
					
						
							|  |  |  | 	//c: &x | 
					
						
							|  |  |  | 	//   a: 1 | 
					
						
							|  |  |  | 	//   b: hello | 
					
						
							|  |  |  | 	//d: *x | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func Example_Marshal_ImplicitAnchorAlias() { | 
					
						
							|  |  |  | 	type T struct { | 
					
						
							|  |  |  | 		I int | 
					
						
							|  |  |  | 		S string | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var v struct { | 
					
						
							|  |  |  | 		A *T `yaml:"a,anchor"` | 
					
						
							|  |  |  | 		B *T `yaml:"b,anchor"` | 
					
						
							|  |  |  | 		C *T `yaml:"c,alias"` | 
					
						
							|  |  |  | 		D *T `yaml:"d,alias"` | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.A = &T{I: 1, S: "hello"} | 
					
						
							|  |  |  | 	v.B = &T{I: 2, S: "world"} | 
					
						
							|  |  |  | 	v.C = v.A // C has same pointer address to A | 
					
						
							|  |  |  | 	v.D = v.B // D has same pointer address to B | 
					
						
							|  |  |  | 	bytes, err := yaml.Marshal(v) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fmt.Println(string(bytes)) | 
					
						
							|  |  |  | 	// OUTPUT: | 
					
						
							| 
									
										
										
										
											2019-10-23 21:05:41 +09:00
										 |  |  | 	// a: &a | 
					
						
							|  |  |  | 	//   i: 1 | 
					
						
							|  |  |  | 	//   s: hello | 
					
						
							|  |  |  | 	// b: &b | 
					
						
							|  |  |  | 	//   i: 2 | 
					
						
							|  |  |  | 	//   s: world | 
					
						
							|  |  |  | 	// c: *a | 
					
						
							|  |  |  | 	// d: *b | 
					
						
							| 
									
										
										
										
											2019-10-23 21:00:00 +09:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-26 18:39:15 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | type tMarshal []string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (t *tMarshal) MarshalYAML() ([]byte, error) { | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	buf.WriteString("tags:\n") | 
					
						
							|  |  |  | 	for i, v := range *t { | 
					
						
							|  |  |  | 		if i == 0 { | 
					
						
							|  |  |  | 			fmt.Fprintf(&buf, "- %s\n", v) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			fmt.Fprintf(&buf, "  %s\n", v) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return buf.Bytes(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func Test_Marshaler(t *testing.T) { | 
					
						
							|  |  |  | 	const expected = `- hello-world | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// sanity check | 
					
						
							|  |  |  | 	var l []string | 
					
						
							|  |  |  | 	if err := yaml.Unmarshal([]byte(expected), &l); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to parse string: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf, err := yaml.Marshal(tMarshal{"hello-world"}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to marshal: %s", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if string(buf) != expected { | 
					
						
							|  |  |  | 		t.Fatalf("expected '%s', got '%s'", expected, buf) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Logf("%s", buf) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type SlowMarshaler struct { | 
					
						
							|  |  |  | 	A string | 
					
						
							|  |  |  | 	B int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | type FastMarshaler struct { | 
					
						
							|  |  |  | 	A string | 
					
						
							|  |  |  | 	B int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (v SlowMarshaler) MarshalYAML() ([]byte, error) { | 
					
						
							|  |  |  | 	var buf bytes.Buffer | 
					
						
							|  |  |  | 	buf.WriteString("tags:\n") | 
					
						
							|  |  |  | 	buf.WriteString("- slow-marshaler\n") | 
					
						
							|  |  |  | 	buf.WriteString("a: " + v.A + "\n") | 
					
						
							|  |  |  | 	buf.WriteString("b: " + strconv.FormatInt(int64(v.B), 10) + "\n") | 
					
						
							|  |  |  | 	return buf.Bytes(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (v FastMarshaler) MarshalYAML() (interface{}, error) { | 
					
						
							|  |  |  | 	return yaml.MapSlice{ | 
					
						
							|  |  |  | 		{"tags", []string{"fast-marshaler"}}, | 
					
						
							|  |  |  | 		{"a", v.A}, | 
					
						
							|  |  |  | 		{"b", v.B}, | 
					
						
							|  |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func Example_MarshalYAML() { | 
					
						
							|  |  |  | 	var slow SlowMarshaler | 
					
						
							|  |  |  | 	slow.A = "Hello slow poke" | 
					
						
							|  |  |  | 	slow.B = 100 | 
					
						
							|  |  |  | 	buf, err := yaml.Marshal(slow) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Println(string(buf)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var fast FastMarshaler | 
					
						
							|  |  |  | 	fast.A = "Hello speed demon" | 
					
						
							|  |  |  | 	fast.B = 100 | 
					
						
							|  |  |  | 	buf, err = yaml.Marshal(fast) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Println(string(buf)) | 
					
						
							|  |  |  | 	// OUTPUT: | 
					
						
							|  |  |  | 	// tags: | 
					
						
							|  |  |  | 	// - slow-marshaler | 
					
						
							|  |  |  | 	// a: Hello slow poke | 
					
						
							|  |  |  | 	// b: 100 | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// tags: | 
					
						
							|  |  |  | 	// - fast-marshaler | 
					
						
							|  |  |  | 	// a: Hello speed demon | 
					
						
							|  |  |  | 	// b: 100 | 
					
						
							|  |  |  | } |