| OLD | NEW |
| 1 // Copyright 2015 Google Inc. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package render | 5 package render |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "fmt" | 9 "fmt" |
| 10 "reflect" |
| 10 "regexp" | 11 "regexp" |
| 11 "runtime" | 12 "runtime" |
| 12 "testing" | 13 "testing" |
| 13 ) | 14 ) |
| 14 | 15 |
| 15 func init() { | 16 func init() { |
| 16 // For testing purposes, pointers will render as "PTR" so that they are | 17 // For testing purposes, pointers will render as "PTR" so that they are |
| 17 // deterministic. | 18 // deterministic. |
| 18 renderPointer = func(buf *bytes.Buffer, p uintptr) { | 19 renderPointer = func(buf *bytes.Buffer, p uintptr) { |
| 19 buf.WriteString("PTR") | 20 buf.WriteString("PTR") |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 }, `[]*render.testStruct{(*render.testStruct){Name:"foo", I:inte
rface{}(nil), m:""}, ` + | 75 }, `[]*render.testStruct{(*render.testStruct){Name:"foo", I:inte
rface{}(nil), m:""}, ` + |
| 75 `(*render.testStruct){Name:"bar", I:interface{}(nil), m:
""}}`}, | 76 `(*render.testStruct){Name:"bar", I:interface{}(nil), m:
""}}`}, |
| 76 {myStringSlice{"foo", "bar"}, `render.myStringSlice{"foo", "bar"
}`}, | 77 {myStringSlice{"foo", "bar"}, `render.myStringSlice{"foo", "bar"
}`}, |
| 77 {myStringMap{"foo": "bar"}, `render.myStringMap{"foo":"bar"}`}, | 78 {myStringMap{"foo": "bar"}, `render.myStringMap{"foo":"bar"}`}, |
| 78 {myIntType(12), `render.myIntType(12)`}, | 79 {myIntType(12), `render.myIntType(12)`}, |
| 79 {&mit, `(*render.myIntType)(42)`}, | 80 {&mit, `(*render.myIntType)(42)`}, |
| 80 {myStringType("foo"), `render.myStringType("foo")`}, | 81 {myStringType("foo"), `render.myStringType("foo")`}, |
| 81 {struct { | 82 {struct { |
| 82 a int | 83 a int |
| 83 b string | 84 b string |
| 84 » » }{123, "foo"}, `struct { a int; b string }{a:123, b:"foo"}`}, | 85 » » }{123, "foo"}, `struct { a int; b string }{123, "foo"}`}, |
| 85 {[]string{"foo", "foo", "bar", "baz", "qux", "qux"}, | 86 {[]string{"foo", "foo", "bar", "baz", "qux", "qux"}, |
| 86 `[]string{"foo", "foo", "bar", "baz", "qux", "qux"}`}, | 87 `[]string{"foo", "foo", "bar", "baz", "qux", "qux"}`}, |
| 87 {[...]int{1, 2, 3}, `[3]int{1, 2, 3}`}, | 88 {[...]int{1, 2, 3}, `[3]int{1, 2, 3}`}, |
| 88 {map[string]bool{ | 89 {map[string]bool{ |
| 89 "foo": true, | 90 "foo": true, |
| 90 "bar": false, | 91 "bar": false, |
| 91 }, `map[string]bool{"bar":false, "foo":true}`}, | 92 }, `map[string]bool{"bar":false, "foo":true}`}, |
| 92 {map[int]string{1: "foo", 2: "bar"}, `map[int]string{1:"foo", 2:
"bar"}`}, | 93 {map[int]string{1: "foo", 2: "bar"}, `map[int]string{1:"foo", 2:
"bar"}`}, |
| 93 {uint32(1337), `1337`}, | 94 {uint32(1337), `1337`}, |
| 94 {3.14, `3.14`}, | 95 {3.14, `3.14`}, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 } | 127 } |
| 127 | 128 |
| 128 func TestRenderRecursiveMap(t *testing.T) { | 129 func TestRenderRecursiveMap(t *testing.T) { |
| 129 m := map[string]interface{}{} | 130 m := map[string]interface{}{} |
| 130 foo := "foo" | 131 foo := "foo" |
| 131 m["foo"] = m | 132 m["foo"] = m |
| 132 m["bar"] = [](*string){&foo, &foo} | 133 m["bar"] = [](*string){&foo, &foo} |
| 133 v := []map[string]interface{}{m, m} | 134 v := []map[string]interface{}{m, m} |
| 134 | 135 |
| 135 assertRendersLike(t, "Recursive map", v, | 136 assertRendersLike(t, "Recursive map", v, |
| 136 » » `[]map[string]interface{}{map[string]interface{}{`+ | 137 » » `[]map[string]interface{}{{`+ |
| 137 `"bar":[]*string{(*string)("foo"), (*string)("foo")}, `+ | 138 `"bar":[]*string{(*string)("foo"), (*string)("foo")}, `+ |
| 138 » » » `"foo":<REC(map[string]interface{})>}, `+ | 139 » » » `"foo":<REC(map[string]interface{})>}, {`+ |
| 139 » » » `map[string]interface{}{`+ | |
| 140 `"bar":[]*string{(*string)("foo"), (*string)("foo")}, `+ | 140 `"bar":[]*string{(*string)("foo"), (*string)("foo")}, `+ |
| 141 `"foo":<REC(map[string]interface{})>}}`) | 141 `"foo":<REC(map[string]interface{})>}}`) |
| 142 } | 142 } |
| 143 | 143 |
| 144 func TestRenderImplicitType(t *testing.T) { |
| 145 type namedStruct struct{ a, b int } |
| 146 type namedInt int |
| 147 |
| 148 tcs := []struct { |
| 149 in interface{} |
| 150 expect string |
| 151 }{ |
| 152 { |
| 153 []struct{ a, b int }{{1, 2}}, |
| 154 "[]struct { a int; b int }{{1, 2}}", |
| 155 }, |
| 156 { |
| 157 map[string]struct{ a, b int }{"hi": {1, 2}}, |
| 158 `map[string]struct { a int; b int }{"hi":{1, 2}}`, |
| 159 }, |
| 160 { |
| 161 map[namedInt]struct{}{10: {}}, |
| 162 `map[render.namedInt]struct {}{10:{}}`, |
| 163 }, |
| 164 { |
| 165 struct{ a, b int }{1, 2}, |
| 166 `struct { a int; b int }{1, 2}`, |
| 167 }, |
| 168 { |
| 169 namedStruct{1, 2}, |
| 170 "render.namedStruct{a:1, b:2}", |
| 171 }, |
| 172 } |
| 173 |
| 174 for _, tc := range tcs { |
| 175 assertRendersLike(t, reflect.TypeOf(tc.in).String(), tc.in, tc.e
xpect) |
| 176 } |
| 177 } |
| 178 |
| 144 func ExampleInReadme() { | 179 func ExampleInReadme() { |
| 145 type customType int | 180 type customType int |
| 146 type testStruct struct { | 181 type testStruct struct { |
| 147 S string | 182 S string |
| 148 V *map[string]int | 183 V *map[string]int |
| 149 I interface{} | 184 I interface{} |
| 150 } | 185 } |
| 151 | 186 |
| 152 a := testStruct{ | 187 a := testStruct{ |
| 153 S: "hello", | 188 S: "hello", |
| 154 V: &map[string]int{"foo": 0, "bar": 1}, | 189 V: &map[string]int{"foo": 0, "bar": 1}, |
| 155 I: customType(42), | 190 I: customType(42), |
| 156 } | 191 } |
| 157 | 192 |
| 158 fmt.Println("Render test:") | 193 fmt.Println("Render test:") |
| 159 fmt.Printf("fmt.Printf: %s\n", sanitizePointer(fmt.Sprintf("%#v", a))
) | 194 fmt.Printf("fmt.Printf: %s\n", sanitizePointer(fmt.Sprintf("%#v", a))
) |
| 160 fmt.Printf("render.Render: %s\n", Render(a)) | 195 fmt.Printf("render.Render: %s\n", Render(a)) |
| 161 // Output: Render test: | 196 // Output: Render test: |
| 162 // fmt.Printf: render.testStruct{S:"hello", V:(*map[string]int)(0x600
dd065), I:42} | 197 // fmt.Printf: render.testStruct{S:"hello", V:(*map[string]int)(0x600
dd065), I:42} |
| 163 // render.Render: render.testStruct{S:"hello", V:(*map[string]int){"bar"
:1, "foo":0}, I:render.customType(42)} | 198 // render.Render: render.testStruct{S:"hello", V:(*map[string]int){"bar"
:1, "foo":0}, I:render.customType(42)} |
| 164 } | 199 } |
| 165 | 200 |
| 166 var pointerRE = regexp.MustCompile(`\(0x[a-f0-9]+\)`) | 201 var pointerRE = regexp.MustCompile(`\(0x[a-f0-9]+\)`) |
| 167 | 202 |
| 168 func sanitizePointer(s string) string { | 203 func sanitizePointer(s string) string { |
| 169 return pointerRE.ReplaceAllString(s, "(0x600dd065)") | 204 return pointerRE.ReplaceAllString(s, "(0x600dd065)") |
| 170 } | 205 } |
| OLD | NEW |