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 |