slice_eface_test.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package tests
  2. import (
  3. "github.com/modern-go/reflect2"
  4. "github.com/modern-go/test"
  5. "testing"
  6. "context"
  7. "github.com/modern-go/test/must"
  8. "github.com/modern-go/test/should"
  9. "unsafe"
  10. )
  11. func Test_slice_eface(t *testing.T) {
  12. t.Run("MakeSlice", testOp(func(api reflect2.API) interface{} {
  13. valType := api.TypeOf([]interface{}{}).(reflect2.SliceType)
  14. obj := valType.MakeSlice(5, 10)
  15. (*obj.(*[]interface{}))[0] = 100
  16. (*obj.(*[]interface{}))[4] = 20
  17. return obj
  18. }))
  19. t.Run("SetIndex", testOp(func(api reflect2.API) interface{} {
  20. obj := []interface{}{1, nil}
  21. valType := api.TypeOf(obj).(reflect2.SliceType)
  22. elem0 := interface{}(100)
  23. valType.SetIndex(&obj, 0, &elem0)
  24. elem1 := interface{}(20)
  25. valType.SetIndex(&obj, 1, &elem1)
  26. return obj
  27. }))
  28. t.Run("UnsafeSetIndex", test.Case(func(ctx context.Context) {
  29. obj := []interface{}{1, 2}
  30. valType := reflect2.TypeOf(obj).(reflect2.SliceType)
  31. var elem0 interface{} = 100
  32. valType.UnsafeSetIndex(reflect2.PtrOf(obj), 0, unsafe.Pointer(&elem0))
  33. var elem1 interface{} = 10
  34. valType.UnsafeSetIndex(reflect2.PtrOf(obj), 1, unsafe.Pointer(&elem1))
  35. must.Equal([]interface{}{100, 10}, obj)
  36. }))
  37. t.Run("GetIndex", testOp(func(api reflect2.API) interface{} {
  38. obj := []interface{}{1, nil}
  39. valType := api.TypeOf(obj).(reflect2.SliceType)
  40. return []interface{}{
  41. valType.GetIndex(&obj, 0),
  42. valType.GetIndex(&obj, 1),
  43. }
  44. }))
  45. t.Run("UnsafeGetIndex", test.Case(func(ctx context.Context) {
  46. obj := []interface{}{1, nil}
  47. valType := reflect2.TypeOf(obj).(reflect2.SliceType)
  48. elem0 := valType.UnsafeGetIndex(unsafe.Pointer(&obj), 0)
  49. must.Equal(1, *(*interface{})(elem0))
  50. }))
  51. t.Run("Append", testOp(func(api reflect2.API) interface{} {
  52. obj := make([]interface{}, 2, 3)
  53. obj[0] = 1
  54. obj[1] = 2
  55. valType := api.TypeOf(obj).(reflect2.SliceType)
  56. elem1 := interface{}(3)
  57. valType.Append(&obj, &elem1)
  58. // will trigger grow
  59. elem2 := interface{}(4)
  60. valType.Append(&obj, &elem2)
  61. return obj
  62. }))
  63. t.Run("UnsafeAppend", test.Case(func(ctx context.Context) {
  64. obj := make([]interface{}, 2, 3)
  65. obj[0] = 1
  66. obj[1] = 2
  67. valType := reflect2.TypeOf(obj).(reflect2.SliceType)
  68. var elem2 interface{} = 3
  69. valType.UnsafeAppend(unsafe.Pointer(&obj), unsafe.Pointer(&elem2))
  70. var elem3 interface{} = 4
  71. valType.UnsafeAppend(unsafe.Pointer(&obj), unsafe.Pointer(&elem3))
  72. should.Equal([]interface{}{1, 2, 3, 4}, valType.UnsafeIndirect(unsafe.Pointer(&obj)))
  73. }))
  74. }