github.com/searKing/golang/go@v1.2.117/reflect/reflect_test.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package reflect_test 6 7 import ( 8 "reflect" 9 "strings" 10 "testing" 11 12 reflect_ "github.com/searKing/golang/go/reflect" 13 ) 14 15 func TestParseStructTag(t *testing.T) { 16 test := []struct { 17 name string 18 tag string 19 exp []reflect_.SubStructTag 20 invalid bool 21 }{ 22 { 23 name: "empty tag", 24 tag: "", 25 }, 26 { 27 name: "tag with one key (invalid)", 28 tag: "json", 29 invalid: true, 30 }, 31 { 32 name: "tag with one key (valid)", 33 tag: `json:""`, 34 exp: []reflect_.SubStructTag{ 35 { 36 Key: "json", 37 }, 38 }, 39 }, 40 { 41 name: "tag with one key and dash name", 42 tag: `json:"-"`, 43 exp: []reflect_.SubStructTag{ 44 { 45 Key: "json", Name: "-", 46 }, 47 }, 48 }, 49 { 50 name: "tag with key and name", 51 tag: `json:"foo"`, 52 exp: []reflect_.SubStructTag{ 53 { 54 Key: "json", Name: "foo", 55 }, 56 }, 57 }, 58 { 59 name: "tag with key, name and option", 60 tag: `json:"foo,omitempty"`, 61 exp: []reflect_.SubStructTag{ 62 { 63 Key: "json", Name: "foo", Options: []string{"omitempty"}, 64 }, 65 }, 66 }, 67 { 68 name: "tag with multiple keys", 69 tag: `json:"" yaml:""`, 70 exp: []reflect_.SubStructTag{ 71 {Key: "json"}, 72 {Key: "yaml"}, 73 }, 74 }, 75 { 76 name: "tag with multiple keys and names", 77 tag: `json:"foo" yaml:"bar"`, 78 exp: []reflect_.SubStructTag{ 79 {Key: "json", Name: "foo"}, 80 {Key: "yaml", Name: "bar"}, 81 }, 82 }, 83 { 84 name: "tag with multiple keys, different names and options", 85 tag: `json:"foo,omitempty" yaml:"bar,omitempty"`, 86 exp: []reflect_.SubStructTag{ 87 {Key: "json", Name: "foo", Options: []string{"omitempty"}}, 88 {Key: "yaml", Name: "bar", Options: []string{"omitempty"}}, 89 }, 90 }, 91 { 92 name: "tag with multiple keys, different names and options", 93 tag: `json:"foo" yaml:"bar,omitempty" xml:"-"`, 94 exp: []reflect_.SubStructTag{ 95 {Key: "json", Name: "foo"}, 96 {Key: "yaml", Name: "bar", Options: []string{"omitempty"}}, 97 {Key: "xml", Name: "-"}, 98 }, 99 }, 100 { 101 name: "tag with quoted name", 102 tag: `json:"foo,bar:\"baz\""`, 103 exp: []reflect_.SubStructTag{ 104 { 105 Key: "json", Name: "foo", Options: []string{`bar:"baz"`}, 106 }, 107 }, 108 }, 109 { 110 name: "tag with trailing space", 111 tag: `json:"foo " `, 112 invalid: true, 113 }, 114 { 115 name: "json tag value with space", 116 tag: `json:"oneof=http https"`, 117 invalid: true, 118 }, 119 { 120 name: "tag[^json|xml|asn1] value with space", 121 tag: `validate:"oneof=http https"`, 122 }, 123 } 124 125 for i, ts := range test { 126 t.Run(ts.name, func(t *testing.T) { 127 tags, err := reflect_.ParseStructTag(ts.tag) 128 invalid := err != nil 129 130 if invalid != ts.invalid { 131 t.Errorf("#%d, invalid case\n\twant: %+v\n\tgot : %+v\n\terr : %s", i, ts.invalid, invalid, err) 132 } 133 134 if invalid { 135 return 136 } 137 138 for _, tag := range ts.exp { 139 got, _ := tags.Get(tag.Key) 140 if !reflect.DeepEqual(tag, got) { 141 t.Errorf("#%d, parse\n\twant: %#v\n\tgot : %#v", i, tag, got) 142 } 143 } 144 145 trimmedInput := strings.TrimSpace(ts.tag) 146 got := tags.String() 147 148 if len(trimmedInput) != len(got) { 149 t.Errorf("#%d, parse string\n\twant: %#v\n\tgot : %#v", i, trimmedInput, got) 150 } 151 }) 152 } 153 } 154 155 func TestTags_Get(t *testing.T) { 156 tag := `json:"foo,omitempty" yaml:"bar,omitempty"` 157 158 tags, err := reflect_.ParseStructTag(tag) 159 if err != nil { 160 t.Fatal(err) 161 } 162 163 found, ok := tags.Get("json") 164 if !ok { 165 t.Fatalf("expect %q, go %q", "json", "") 166 } 167 168 t.Run("String", func(t *testing.T) { 169 want := `json:"foo,omitempty"` 170 if found.String() != want { 171 t.Errorf("get\n\twant: %#v\n\tgot : %#v", want, found.String()) 172 } 173 }) 174 t.Run("Value", func(t *testing.T) { 175 want := `foo,omitempty` 176 if found.Value() != want { 177 t.Errorf("get\n\twant: %#v\n\tgot : %#v", want, found.Value()) 178 } 179 }) 180 } 181 182 func TestTags_Set(t *testing.T) { 183 tag := `json:"foo,omitempty" yaml:"bar,omitempty"` 184 185 tags, err := reflect_.ParseStructTag(tag) 186 if err != nil { 187 t.Fatal(err) 188 } 189 err = tags.Set(reflect_.SubStructTag{ 190 Key: "json", 191 Name: "bar", 192 Options: []string{}, 193 }) 194 if err != nil { 195 t.Fatal(err) 196 } 197 198 found, ok := tags.Get("json") 199 if !ok { 200 t.Fatalf("expect %q, go %q", "json", "") 201 } 202 203 want := `json:"bar"` 204 if found.String() != want { 205 t.Errorf("set\n\twant: %#v\n\tgot : %#v", want, found.String()) 206 } 207 } 208 209 func TestTags_Set_Append(t *testing.T) { 210 tag := `json:"foo,omitempty"` 211 212 tags, err := reflect_.ParseStructTag(tag) 213 if err != nil { 214 t.Fatal(err) 215 } 216 217 err = tags.Set(reflect_.SubStructTag{ 218 Key: "yaml", 219 Name: "bar", 220 Options: []string{"omitempty"}, 221 }) 222 if err != nil { 223 t.Fatal(err) 224 } 225 226 found, ok := tags.Get("yaml") 227 if !ok { 228 t.Fatalf("expect %q, go %q", "json", "") 229 } 230 231 want := `yaml:"bar,omitempty"` 232 if found.String() != want { 233 t.Errorf("set append\n\twant: %#v\n\tgot : %#v", want, found.String()) 234 } 235 236 wantFull := `json:"foo,omitempty" yaml:"bar,omitempty"` 237 got := tags.String() 238 if len(got) != len(wantFull) { 239 t.Errorf("set append\n\twant: %#v\n\tgot : %#v", wantFull, got) 240 } 241 } 242 243 func TestTags_Set_KeyDoesNotExist(t *testing.T) { 244 tag := `json:"foo,omitempty" yaml:"bar,omitempty"` 245 246 tags, err := reflect_.ParseStructTag(tag) 247 if err != nil { 248 t.Fatal(err) 249 } 250 251 err = tags.Set(reflect_.SubStructTag{ 252 Key: "", 253 Name: "bar", 254 Options: []string{}, 255 }) 256 if err == nil { 257 t.Fatal("setting tag with a nonexisting key should error") 258 } 259 } 260 261 func TestTags_Delete(t *testing.T) { 262 tag := `json:"foo,omitempty" yaml:"bar,omitempty" xml:"-"` 263 264 tags, err := reflect_.ParseStructTag(tag) 265 if err != nil { 266 t.Fatal(err) 267 } 268 269 tags.Delete("xml") 270 if len(tags.Keys()) != 2 { 271 t.Fatalf("tag length should be 2, have %d", len(tags.Keys())) 272 } 273 274 found, ok := tags.Get("json") 275 if !ok { 276 t.Fatalf("expect %q, go %q", "json", "") 277 } 278 279 want := `json:"foo,omitempty"` 280 if found.String() != want { 281 t.Errorf("delete\n\twant: %#v\n\tgot : %#v", want, found.String()) 282 } 283 284 wantFull := `json:"foo,omitempty" yaml:"bar,omitempty"` 285 if len(tags.String()) != len(wantFull) { 286 t.Errorf("delete\n\twant: %#v\n\tgot : %#v", wantFull, tags.String()) 287 } 288 } 289 290 func TestTags_DeleteOptions(t *testing.T) { 291 tag := `json:"foo,omitempty" yaml:"bar,omitempty,omitempty" xml:"-"` 292 293 tags, err := reflect_.ParseStructTag(tag) 294 if err != nil { 295 t.Fatal(err) 296 } 297 298 tags.DeleteOptions("json", "omitempty") 299 300 want := `json:"foo" yaml:"bar,omitempty,omitempty" xml:"-"` 301 if len(tags.String()) != len(want) { 302 t.Errorf("delete option\n\twant: %#v\n\tgot : %#v", want, tags.String()) 303 } 304 305 tags.DeleteOptions("yaml", "omitempty") 306 want = `json:"foo" yaml:"bar" xml:"-"` 307 if len(tags.String()) != len(want) { 308 t.Errorf("delete option\n\twant: %#v\n\tgot : %#v", want, tags.String()) 309 } 310 } 311 312 func TestTags_AddOption(t *testing.T) { 313 tag := `json:"foo" yaml:"bar,omitempty" xml:"-"` 314 315 tags, err := reflect_.ParseStructTag(tag) 316 if err != nil { 317 t.Fatal(err) 318 } 319 320 tags.AddOptions("json", "omitempty") 321 322 want := `json:"foo,omitempty" yaml:"bar,omitempty" xml:"-"` 323 if len(tags.String()) != len(want) { 324 t.Errorf("add options\n\twant: %#v\n\tgot : %#v", want, tags.String()) 325 } 326 327 // this shouldn't change anything 328 tags.AddOptions("yaml", "omitempty") 329 330 want = `json:"foo,omitempty" yaml:"bar,omitempty" xml:"-"` 331 if len(tags.String()) != len(want) { 332 t.Errorf("add options\n\twant: %#v\n\tgot : %#v", want, tags.String()) 333 } 334 335 // this should append to the existing 336 tags.AddOptions("yaml", "omitempty", "flatten") 337 want = `json:"foo,omitempty" yaml:"bar,omitempty,flatten" xml:"-"` 338 if len(tags.String()) != len(want) { 339 t.Errorf("add options\n\twant: %#v\n\tgot : %#v", want, tags.String()) 340 } 341 } 342 343 func TestTags_String(t *testing.T) { 344 tag := `json:"foo" yaml:"bar,omitempty" xml:"-"` 345 346 tags, err := reflect_.ParseStructTag(tag) 347 if err != nil { 348 t.Fatal(err) 349 } 350 351 got := tags.String() 352 if len(got) != len(tag) { 353 t.Errorf("string\n\twant: %#v\n\tgot : %#v", tag, got) 354 } 355 } 356 357 func TestTags_OrderedString(t *testing.T) { 358 tag := `json:"foo" yaml:"bar,omitempty" xml:"-"` 359 360 tags, err := reflect_.ParseStructTag(tag) 361 if err != nil { 362 t.Fatal(err) 363 } 364 365 got := tags.OrderedString() 366 want := `json:"foo" yaml:"bar,omitempty" xml:"-"` 367 368 if got != want { 369 t.Errorf("string\n\twant: %#v\n\tgot : %#v", want, got) 370 } 371 } 372 373 func TestTags_SortedString(t *testing.T) { 374 tag := `json:"foo" yaml:"bar,omitempty" xml:"-"` 375 376 tags, err := reflect_.ParseStructTag(tag) 377 if err != nil { 378 t.Fatal(err) 379 } 380 381 got := tags.SortedString() 382 want := `json:"foo" xml:"-" yaml:"bar,omitempty"` 383 384 if got != want { 385 t.Errorf("string\n\twant: %#v\n\tgot : %#v", want, got) 386 } 387 } 388 389 func TestTags_AstString(t *testing.T) { 390 tag := `json:"foo" yaml:"bar,omitempty" xml:"-"` 391 392 tags, err := reflect_.ParseStructTag(tag) 393 if err != nil { 394 t.Fatal(err) 395 } 396 397 got := tags.AstString() 398 want := "`json:\"foo\" yaml:\"bar,omitempty\" xml:\"-\"`" 399 if len(got) != len(want) { 400 t.Errorf("string\n\twant: %#v\n\tgot : %#v", want, got) 401 } 402 }