github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/reflector/reflector_test.go (about) 1 package reflector 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "sort" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 ) 12 13 // TestStruct ... 14 type TestStruct struct { 15 _ int `bu:"ba"` 16 Exported string 17 unexported int `aaa:"bbb" ccc:"ddd"` 18 } 19 20 func init() { 21 var ts TestStruct 22 _ = ts.unexported 23 } 24 25 type Address struct { 26 Street string `tag:"be" tag2:"1,2,3"` 27 Number int `tag:"bi"` 28 } 29 30 type Person struct { 31 Name string `tag:"bu"` 32 Address 33 } 34 35 func (p Person) Add(a, b, c int) int { return a + b + c } 36 func (p *Person) Subtract(a, b int) int { return a - b } 37 func (p Person) ReturnsError(err bool) (string, *int, error) { 38 i := 2 39 if err { 40 return "", nil, errors.New("error here") 41 } 42 return "jen", &i, nil 43 } 44 45 type CustomType int 46 47 func (ct CustomType) Method1() string { return "yep" } 48 func (ct *CustomType) Method2() int { return 7 } 49 50 func (p Person) Hi(name string) string { 51 return fmt.Sprintf("Hi %s my name is %s", name, p.Name) 52 } 53 54 type Company struct { 55 Address 56 Number int `tag:"bi"` 57 } 58 59 // TestDoubleFields checks that there are no "double" fields (or fields shadowing) 60 func TestDoubleFields(t *testing.T) { 61 t.Parallel() 62 structs := []interface{}{ 63 Obj{}, 64 ObjField{}, 65 ObjMethod{}, 66 ObjMetadata{}, 67 ObjFieldMetadata{}, 68 ObjMethodMetadata{}, 69 } 70 for _, s := range structs { 71 double := New(s).FindDoubleFields() 72 assert.Equal(t, 0, len(double)) 73 } 74 } 75 76 func TestString(t *testing.T) { 77 t.Parallel() 78 assert.Equal(t, "reflector.Person", New(Person{}).String()) 79 assert.Equal(t, "*reflector.Person", New(&Person{}).String()) 80 assert.Equal(t, "nil", New(nil).String()) 81 assert.Equal(t, "int", New(1).String()) 82 var i int 83 assert.Equal(t, "*int", New(&i).String()) 84 85 // Check that when we twice get a field, the metadata field is cached only once: 86 assert.Equal(t, New(Person{}).Field("bu").ObjFieldMetadata, New(Person{}).Field("bu").ObjFieldMetadata) 87 assert.Equal(t, New(&Person{}).Field("bu").ObjFieldMetadata, New(&Person{}).Field("bu").ObjFieldMetadata) 88 assert.Equal(t, New(Person{}).Field("Address").ObjFieldMetadata, New(Person{}).Field("Address").ObjFieldMetadata) 89 assert.Equal(t, New(&Person{}).Field("bu").ObjFieldMetadata, New(&Person{}).Field("bu").ObjFieldMetadata) 90 } 91 92 func TestNilStringPtr(t *testing.T) { 93 t.Parallel() 94 assert.Equal(t, "*string", New((*string)(nil)).String()) 95 assert.Equal(t, 0, len(New((*string)(nil)).Fields())) 96 assert.Equal(t, 0, len(New((*string)(nil)).Methods())) 97 98 v, err := New((*string)(nil)).Field("Bu").Get() 99 assert.Nil(t, v) 100 assert.NotNil(t, err) 101 } 102 103 func TestNilStructPtr(t *testing.T) { 104 t.Parallel() 105 assert.Equal(t, "*reflector.Person", New((*Person)(nil)).String()) 106 assert.Equal(t, 2, len(New((*Person)(nil)).Fields())) 107 assert.Equal(t, 4, len(New((*Person)(nil)).Methods())) 108 109 err := New((*Person)(nil)).Field("Number").Set(17) 110 assert.NotNil(t, err) 111 112 v, err := New((*Person)(nil)).Field("Bu").Get() 113 assert.Nil(t, v) 114 assert.NotNil(t, err) 115 } 116 117 func TestListFieldsFlattened(t *testing.T) { 118 t.Parallel() 119 p := Person{} 120 obj := New(p) 121 122 assert.True(t, obj.IsValid()) 123 assert.False(t, obj.IsPtr()) 124 assert.True(t, obj.IsStructOrPtrToStruct()) 125 126 fields := obj.FieldsFlattened() 127 assert.Equal(t, 3, len(fields)) 128 assert.Equal(t, fields[0].Name(), "Name") 129 assert.Equal(t, fields[1].Name(), "Street") 130 assert.Equal(t, fields[2].Name(), "Number") 131 132 assert.True(t, obj.Field("Name").IsValid()) 133 134 kind := obj.Field("Name").Kind() 135 assert.Equal(t, reflect.String, kind) 136 137 kind = obj.Field("BuName").Kind() 138 assert.Equal(t, reflect.Invalid, kind) 139 140 ty := obj.Field("Number").Type() 141 assert.Equal(t, reflect.TypeOf(1), ty) 142 143 ty = obj.Field("Istra").Type() 144 assert.Nil(t, ty) 145 } 146 147 func TestListFields(t *testing.T) { 148 t.Parallel() 149 p := Person{} 150 obj := New(p) 151 152 fields := obj.Fields() 153 assert.Equal(t, len(fields), 2) 154 assert.Equal(t, fields[0].Name(), "Name") 155 assert.Equal(t, fields[1].Name(), "Address") 156 } 157 158 func TestListFieldsAll(t *testing.T) { 159 t.Parallel() 160 p := Person{} 161 obj := New(p) 162 163 fields := obj.FieldsAll() 164 assert.Equal(t, len(fields), 4) 165 assert.Equal(t, fields[0].Name(), "Name") 166 assert.Equal(t, fields[1].Name(), "Address") 167 assert.Equal(t, fields[2].Name(), "Street") 168 assert.Equal(t, fields[3].Name(), "Number") 169 } 170 171 func TestListFieldsAnonymous(t *testing.T) { 172 t.Parallel() 173 p := Person{} 174 obj := New(p) 175 176 fields := obj.FieldsAnonymous() 177 assert.Equal(t, 1, len(fields)) 178 assert.Equal(t, fields[0].Name(), "Address") 179 } 180 181 func TestListFieldsAllWithDoubleFields(t *testing.T) { 182 t.Parallel() 183 obj := New(Company{}) 184 185 fields := obj.FieldsAll() 186 assert.Equal(t, len(fields), 4) 187 assert.Equal(t, fields[0].Name(), "Address") 188 assert.Equal(t, fields[1].Name(), "Street") 189 // Number is declared both in Company and in Address, so listed twice here: 190 assert.Equal(t, fields[2].Name(), "Number") 191 assert.Equal(t, fields[3].Name(), "Number") 192 } 193 194 func TestFindDoubleFields(t *testing.T) { 195 t.Parallel() 196 obj := New(Company{}) 197 198 fields := obj.FindDoubleFields() 199 assert.Equal(t, 1, len(fields)) 200 assert.Equal(t, fields[0], "Number") 201 } 202 203 func TestListFieldsOnPointer(t *testing.T) { 204 t.Parallel() 205 p := &Person{} 206 obj := New(p) 207 208 assert.True(t, obj.IsPtr()) 209 assert.True(t, obj.IsStructOrPtrToStruct()) 210 211 fields := obj.Fields() 212 assert.Equal(t, len(fields), 2) 213 assert.Equal(t, fields[0].Name(), "Name") 214 assert.Equal(t, fields[1].Name(), "Address") 215 216 kind := obj.Field("Name").Kind() 217 assert.Equal(t, reflect.String, kind) 218 219 kind = obj.Field("BuName").Kind() 220 assert.Equal(t, reflect.Invalid, kind) 221 222 ty := obj.Field("Number").Type() 223 assert.Equal(t, reflect.TypeOf(1), ty) 224 225 ty = obj.Field("Istra").Type() 226 assert.Nil(t, ty) 227 } 228 229 func TestListFieldsFlattenedOnPointer(t *testing.T) { 230 t.Parallel() 231 p := &Person{} 232 obj := New(p) 233 234 fields := obj.FieldsFlattened() 235 assert.Equal(t, len(fields), 3) 236 assert.Equal(t, fields[0].Name(), "Name") 237 assert.Equal(t, fields[1].Name(), "Street") 238 assert.Equal(t, fields[2].Name(), "Number") 239 } 240 241 func TestNoFieldsNoCustomType(t *testing.T) { 242 t.Parallel() 243 assert.Equal(t, len(New(CustomType(1)).Fields()), 0) 244 ct := CustomType(2) 245 assert.Equal(t, len(New(&ct).Fields()), 0) 246 } 247 248 func TestIsStructForCustomTypes(t *testing.T) { 249 t.Parallel() 250 ct := CustomType(2) 251 assert.False(t, New(CustomType(1)).IsPtr()) 252 assert.True(t, New(&ct).IsPtr()) 253 assert.False(t, New(CustomType(1)).IsStructOrPtrToStruct()) 254 assert.False(t, New(&ct).IsStructOrPtrToStruct()) 255 } 256 257 func TestFieldValidity(t *testing.T) { 258 t.Parallel() 259 assert.False(t, New(CustomType(1)).Field("jkljkl").IsValid()) 260 assert.True(t, New(Person{}).Field("street").IsValid()) 261 assert.True(t, New(Person{}).Field("Street").IsValid()) 262 assert.True(t, New(Person{}).Field("Number").IsValid()) 263 assert.True(t, New(Person{}).Field("Name").IsValid()) 264 } 265 266 func TestSetFieldNonPointer(t *testing.T) { 267 t.Parallel() 268 p := Person{} 269 obj := New(p) 270 assert.False(t, obj.IsPtr()) 271 272 field := obj.Field("Street") 273 assert.False(t, field.IsSettable()) 274 275 err := field.Set("ulica") 276 assert.Error(t, err) 277 278 value, err := field.Get() 279 assert.Nil(t, err) 280 assert.Equal(t, "", value) 281 282 assert.Equal(t, "", p.Street) 283 284 street, err := obj.Field("Street").Get() 285 assert.Nil(t, err) 286 287 // This actually don't work because p is a struct and reflector is working on it's own copy: 288 assert.Equal(t, "", street) 289 } 290 291 func TestSetField(t *testing.T) { 292 t.Parallel() 293 p := Person{} 294 obj := New(&p) 295 assert.True(t, obj.IsPtr()) 296 297 field := obj.Field("Street") 298 assert.True(t, field.IsSettable()) 299 300 err := field.Set("ulica") 301 assert.Nil(t, err) 302 303 value, err := field.Get() 304 assert.Nil(t, err) 305 assert.Equal(t, "ulica", value) 306 307 assert.Equal(t, "ulica", p.Street) 308 } 309 310 func TestCustomTypeMethods(t *testing.T) { 311 t.Parallel() 312 assert.Equal(t, len(New(CustomType(1)).Methods()), 1) 313 ct := CustomType(1) 314 assert.Equal(t, len(New(&ct).Methods()), 2) 315 } 316 317 func TestMethods(t *testing.T) { 318 t.Parallel() 319 assert.Equal(t, len(New(Person{}).Methods()), 3) 320 assert.Equal(t, len(New(&Person{}).Methods()), 4) 321 322 // Check that when we twice get a field, the metadata field is cached only once: 323 assert.Equal(t, New(Person{}).Method("Add").ObjMethodMetadata, New(Person{}).Method("Add").ObjMethodMetadata) 324 assert.Equal(t, New(&Person{}).Method("Add").ObjMethodMetadata, New(&Person{}).Method("Add").ObjMethodMetadata) 325 } 326 327 func TestCallMethod(t *testing.T) { 328 t.Parallel() 329 obj := New(&Person{}) 330 method := obj.Method("Add") 331 res, err := method.Call(2, 3, 6) 332 assert.Nil(t, err) 333 assert.False(t, res.IsError()) 334 assert.Equal(t, len(res.Result), 1) 335 assert.Equal(t, res.Result[0], 11) 336 337 assert.True(t, method.IsValid()) 338 assert.Equal(t, len(method.InTypes()), 3) 339 assert.Equal(t, len(method.OutTypes()), 1) 340 341 sub, err := obj.Method("Subtract").Call(5, 6) 342 assert.Nil(t, err) 343 assert.Equal(t, sub.Result, []interface{}{-1}) 344 } 345 346 func TestCallInvalidMethod(t *testing.T) { 347 t.Parallel() 348 obj := New(&Person{}) 349 method := obj.Method("AddAdddd") 350 res, err := method.Call([]interface{}{2, 3, 6}) 351 assert.NotNil(t, err) 352 assert.Nil(t, res) 353 354 assert.Equal(t, len(method.InTypes()), 0) 355 assert.Equal(t, len(method.OutTypes()), 0) 356 } 357 358 func TestMethodsValidityOnPtr(t *testing.T) { 359 t.Parallel() 360 ct := CustomType(1) 361 obj := New(&ct) 362 363 assert.True(t, obj.IsPtr()) 364 365 assert.True(t, obj.Method("Method1").IsValid()) 366 assert.True(t, obj.Method("Method2").IsValid()) 367 368 { 369 res, err := obj.Method("Method1").Call() 370 assert.Nil(t, err) 371 assert.Equal(t, res.Result, []interface{}{"yep"}) 372 } 373 { 374 res, err := obj.Method("Method2").Call() 375 assert.Nil(t, err) 376 assert.Equal(t, res.Result, []interface{}{7}) 377 } 378 } 379 380 func TestMethodsValidityOnNonPtr(t *testing.T) { 381 t.Parallel() 382 obj := New(CustomType(1)) 383 384 assert.False(t, obj.IsPtr()) 385 386 assert.True(t, obj.Method("Method1").IsValid()) 387 // False because it's not a pointer 388 assert.False(t, obj.Method("Method2").IsValid()) 389 390 { 391 res, err := obj.Method("Method1").Call() 392 assert.Nil(t, err) 393 assert.Equal(t, res.Result, []interface{}{"yep"}) 394 } 395 { 396 _, err := obj.Method("Method2").Call() 397 assert.NotNil(t, err) 398 } 399 } 400 401 func testCallMethod(t *testing.T, callValue bool, lenResult int) bool { 402 obj := New(&Person{}) 403 res, err := obj.Method("ReturnsError").Call(callValue) 404 assert.Nil(t, err) 405 assert.Equal(t, len(res.Result), lenResult) 406 return res.IsError() 407 } 408 409 func TestCallMethodWithoutErrResult(t *testing.T) { 410 t.Parallel() 411 isErr := testCallMethod(t, true, 3) 412 assert.True(t, isErr) 413 } 414 415 func TestCallMethodWithErrResult(t *testing.T) { 416 t.Parallel() 417 isErr := testCallMethod(t, false, 3) 418 assert.False(t, isErr) 419 } 420 421 func TestTag(t *testing.T) { 422 t.Parallel() 423 obj := New(&Person{}) 424 tag, err := obj.Field("Street").Tag("invalid") 425 assert.Nil(t, err) 426 assert.Equal(t, len(tag), 0) 427 } 428 429 func TestInvalidTag(t *testing.T) { 430 t.Parallel() 431 obj := New(&Person{}) 432 tag, err := obj.Field("HahaStreet").Tag("invalid") 433 assert.NotNil(t, err) 434 assert.Equal(t, "invalid field HahaStreet", err.Error()) 435 assert.Equal(t, len(tag), 0) 436 } 437 438 func TestValidTag(t *testing.T) { 439 t.Parallel() 440 obj := New(&Person{}) 441 tag, err := obj.Field("Street").Tag("tag") 442 assert.Nil(t, err) 443 assert.Equal(t, tag, "be") 444 } 445 446 func TestValidTags(t *testing.T) { 447 t.Parallel() 448 obj := New(&Person{}) 449 450 tags, err := obj.Field("Street").TagExpanded("tag") 451 assert.Nil(t, err) 452 assert.Equal(t, tags, []string{"be"}) 453 454 tags2, err := obj.Field("Street").TagExpanded("tag2") 455 assert.Nil(t, err) 456 assert.Equal(t, tags2, []string{"1", "2", "3"}) 457 } 458 459 func TestAllTags(t *testing.T) { 460 t.Parallel() 461 obj := New(&Person{}) 462 463 tags, err := obj.Field("Street").Tags() 464 assert.Nil(t, err) 465 assert.Equal(t, len(tags), 2) 466 assert.Equal(t, tags["tag"].Value, "be") 467 assert.Equal(t, tags["tag2"].Value, "1,2,3") 468 } 469 470 func TestNewFromType(t *testing.T) { 471 t.Parallel() 472 obj1 := NewFromType(reflect.TypeOf(Person{})) 473 obj2 := New(&Person{}) 474 475 assert.Equal(t, obj1.objType.String(), obj2.objType.String()) 476 assert.Equal(t, obj1.objKind.String(), obj2.objKind.String()) 477 assert.Equal(t, obj1.underlyingType.String(), obj2.underlyingType.String()) 478 } 479 480 func TestAnonymousFields(t *testing.T) { 481 t.Parallel() 482 obj := New(&Person{}) 483 484 assert.True(t, obj.Field("Address").IsAnonymous()) 485 assert.False(t, obj.Field("Name").IsAnonymous()) 486 } 487 488 func TestNil(t *testing.T) { 489 t.Parallel() 490 obj := New(nil) 491 assert.Equal(t, 0, len(obj.Fields())) 492 assert.Equal(t, 0, len(obj.Methods())) 493 494 res, err := obj.Field("Aaa").Get() 495 assert.Nil(t, res) 496 assert.NotNil(t, err) 497 498 err = obj.Field("Aaa").Set(1) 499 assert.NotNil(t, err) 500 } 501 502 func TestNilType(t *testing.T) { 503 t.Parallel() 504 obj := NewFromType(nil) 505 assert.Equal(t, 0, len(obj.Fields())) 506 assert.Equal(t, 0, len(obj.Methods())) 507 508 res, err := obj.Field("Aaa").Get() 509 assert.Nil(t, res) 510 assert.NotNil(t, err) 511 512 err = obj.Field("Aaa").Set(1) 513 assert.NotNil(t, err) 514 515 _, err = obj.Method("aaa").Call("bu") 516 assert.NotNil(t, err) 517 } 518 519 func TestStringObj(t *testing.T) { 520 t.Parallel() 521 obj := New("") 522 assert.Equal(t, 0, len(obj.Fields())) 523 assert.Equal(t, 0, len(obj.Methods())) 524 525 res, err := obj.Field("Aaa").Get() 526 assert.Nil(t, res) 527 assert.NotNil(t, err) 528 529 err = obj.Field("Aaa").Set(1) 530 assert.NotNil(t, err) 531 532 _, err = obj.Method("aaa").Call("bu") 533 assert.NotNil(t, err) 534 } 535 536 type TestWithInnerStruct struct { 537 Aaa string 538 Bbb struct { 539 Ccc int 540 Ddd float64 541 } 542 } 543 544 func TestInnerStruct(t *testing.T) { 545 t.Parallel() 546 obj := New(TestWithInnerStruct{}) 547 fields := obj.Fields() 548 assert.Equal(t, 2, len(fields)) 549 550 assert.Equal(t, "Aaa", fields[0].Name()) 551 assert.Equal(t, "string", fields[0].Type().String()) 552 assert.Equal(t, "string", fields[0].Kind().String()) 553 554 assert.Equal(t, "Bbb", fields[1].Name()) 555 assert.Equal(t, "struct { Ccc int; Ddd float64 }", fields[1].Type().String()) 556 assert.Equal(t, "struct", fields[1].Kind().String()) 557 558 // This is not an anonymous struct, so fields are always the same: 559 assert.Equal(t, 2, len(obj.FieldsAll())) 560 assert.Equal(t, 2, len(obj.FieldsFlattened())) 561 } 562 563 func TestExportedUnexported(t *testing.T) { 564 t.Parallel() 565 obj := New(&TestStruct{}) 566 assert.Equal(t, "_", obj.Fields()[0].Name()) 567 assert.False(t, obj.Fields()[0].IsExported()) 568 569 assert.Equal(t, "Exported", obj.Fields()[1].Name()) 570 assert.True(t, obj.Fields()[1].IsExported()) 571 572 assert.Equal(t, "unexported", obj.Fields()[2].Name()) 573 assert.False(t, obj.Fields()[2].IsExported()) 574 575 err := obj.Field("Exported").Set("aaa") 576 assert.Nil(t, err) 577 578 err = obj.Field("unexported").Set(1777) 579 assert.NotNil(t, err) 580 assert.Contains(t, err.Error(), "not settable") 581 582 value, err := obj.Field("unexported").Get() 583 assert.NotNil(t, err) 584 assert.Nil(t, value) 585 assert.Contains(t, err.Error(), "cannot read unexported field") 586 587 // But tags on unexported fields are still readable: 588 { 589 tags, err := obj.Field("_").Tags() 590 assert.Nil(t, err) 591 assert.Equal(t, 1, len(tags)) 592 assert.Equal(t, "ba", tags["bu"].Value) 593 } 594 { 595 tags, err := obj.Field("unexported").Tags() 596 assert.Nil(t, err) 597 assert.Equal(t, 2, len(tags)) 598 } 599 } 600 601 func TestStringLen(t *testing.T) { 602 s := "jkljk" 603 assert.Equal(t, len(s), New(s).Len()) 604 assert.Equal(t, len(s), New(&s).Len()) 605 } 606 607 func TestLenOfInvalidTypes(t *testing.T) { 608 assert.Equal(t, 0, New(&TestStruct{}).Len()) 609 assert.Equal(t, 0, New(TestStruct{}).Len()) 610 611 { 612 val, found := New(TestStruct{}).GetByIndex(20) 613 assert.False(t, found) 614 assert.Nil(t, val) 615 } 616 { 617 val, found := New(TestStruct{}).GetByKey("nothing") 618 assert.False(t, found) 619 assert.Equal(t, nil, val) 620 } 621 { 622 keys, err := New(TestStruct{}).Keys() 623 assert.Nil(t, keys) 624 assert.NotNil(t, err) 625 } 626 } 627 628 func TestSlice(t *testing.T) { 629 { 630 a := []int{1, 2, 3, 4, 8, 7, 6, 5} 631 assert.Equal(t, len(a), New(a).Len()) 632 assert.Equal(t, len(a), New(&a).Len()) 633 { 634 o := New(&a) 635 assert.Nil(t, o.SetByIndex(1, 1000)) 636 assert.Equal(t, []int{1, 1000, 3, 4, 8, 7, 6, 5}, a) 637 } 638 { 639 o := New(&a) 640 assert.NotNil(t, o.SetByIndex(-1, 1000)) 641 assert.NotNil(t, o.SetByIndex(700, 1000)) 642 } 643 { 644 o := New(a) 645 assert.Nil(t, o.SetByIndex(1, 1000)) 646 assert.Equal(t, []int{1, 1000, 3, 4, 8, 7, 6, 5}, a) 647 } 648 { 649 val, found := New(a).GetByIndex(2) 650 assert.True(t, found) 651 assert.Equal(t, val, 3) 652 } 653 { 654 val, found := New(a).GetByIndex(20) 655 assert.False(t, found) 656 assert.Nil(t, val) 657 } 658 { 659 val, found := New(a).GetByIndex(-20) 660 assert.False(t, found) 661 assert.Nil(t, val) 662 } 663 } 664 } 665 666 func TestMapLenGetSet(t *testing.T) { 667 m := map[string]interface{}{"jkljk": 8, "11": 13, "12": nil} 668 assert.Equal(t, len(m), New(m).Len()) 669 assert.Equal(t, len(m), New(&m).Len()) 670 { 671 keys, err := New(&m).Keys() 672 assert.Nil(t, err) 673 assert.Equal(t, 3, len(keys)) 674 keysStrings := make([]string, len(keys)) 675 for n := range keys { 676 keysStrings[n] = keys[n].(string) 677 } 678 sort.Strings(keysStrings) 679 assert.Equal(t, []string{"11", "12", "jkljk"}, keysStrings) 680 } 681 { 682 val, found := New(&m).GetByKey("11") 683 assert.True(t, found) 684 assert.Equal(t, 13, val) 685 } 686 { 687 val, found := New(m).GetByKey("11") 688 assert.True(t, found) 689 assert.Equal(t, 13, val) 690 } 691 { 692 val, found := New(m).GetByKey("12") 693 assert.True(t, found) 694 assert.Equal(t, nil, val) 695 } 696 { 697 val, found := New(m).GetByKey("nothing") 698 assert.False(t, found) 699 assert.Equal(t, nil, val) 700 } 701 { 702 val, found := New(m).GetByKey(17) 703 assert.False(t, found) 704 assert.Equal(t, nil, val) 705 } 706 } 707 708 func TestMapSet(t *testing.T) { 709 m := map[string]interface{}{"jkljk": 8, "11": 13, "12": nil} 710 o := New(&m) 711 assert.Nil(t, o.SetByKey("17", 71)) 712 val, found := m["17"] 713 assert.True(t, found) 714 assert.Equal(t, 71, val) 715 } 716 717 func TestSetStringByIndex(t *testing.T) { 718 s := "jkljkl" 719 o := New(&s) 720 assert.NotNil(t, o.SetByIndex(0, 'a')) 721 }