github.com/goki/ki@v1.1.11/kit/ptrs_test.go (about) 1 // Copyright (c) 2018, The GoKi Authors. 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 kit 6 7 import ( 8 "reflect" 9 "testing" 10 "unsafe" 11 ) 12 13 // structs are in embeds_test.go 14 15 type PtrTstSub struct { 16 Mbr1 string 17 Mbr2 int 18 Enum TestFlags 19 } 20 21 type PtrTst struct { 22 Mbr1 string 23 Mbr2 int 24 Enum TestFlags 25 SubField PtrTstSub 26 } 27 28 var pt = PtrTst{} 29 30 func InitPtrTst() { 31 pt.Mbr1 = "mbr1 string" 32 pt.Mbr2 = 2 33 pt.Enum = TestFlag2 34 } 35 36 func FieldValue(obj interface{}, fld reflect.StructField) reflect.Value { 37 ov := reflect.ValueOf(obj) 38 f := unsafe.Pointer(ov.Pointer() + fld.Offset) 39 nw := reflect.NewAt(fld.Type, f) 40 return UnhideIfaceValue(nw).Elem() 41 } 42 43 func SubFieldValue(obj interface{}, fld reflect.StructField, sub reflect.StructField) reflect.Value { 44 ov := reflect.ValueOf(obj) 45 f := unsafe.Pointer(ov.Pointer() + fld.Offset + sub.Offset) 46 nw := reflect.NewAt(sub.Type, f) 47 return UnhideIfaceValue(nw).Elem() 48 } 49 50 // test ability to create an addressable pointer value to fields of a struct 51 func TestNewAt(t *testing.T) { 52 InitPtrTst() 53 typ := reflect.TypeOf(pt) 54 fld, _ := typ.FieldByName("Mbr2") 55 vf := FieldValue(&pt, fld) 56 57 // fmt.Printf("Fld: %v Typ: %v vf: %v vfi: %v vfT: %v vfp: %v canaddr: %v canset: %v caninterface: %v\n", fld.Name, vf.Type().String(), vf.String(), vf.Interface(), vf.Interface(), vf.Interface(), vf.CanAddr(), vf.CanSet(), vf.CanInterface()) 58 59 vf.Elem().Set(reflect.ValueOf(int(10))) 60 61 if pt.Mbr2 != 10 { 62 t.Errorf("Mbr2 should be 10, is: %v\n", pt.Mbr2) 63 } 64 65 fld, _ = typ.FieldByName("Mbr1") 66 vf = FieldValue(&pt, fld) 67 68 // fmt.Printf("Fld: %v Typ: %v vf: %v vfi: %v vfT: %v vfp: %v canaddr: %v canset: %v caninterface: %v\n", fld.Name, vf.Type().String(), vf.String(), vf.Interface(), vf.Interface(), vf.Interface(), vf.CanAddr(), vf.CanSet(), vf.CanInterface()) 69 70 vf.Elem().Set(reflect.ValueOf("this is a new string")) 71 72 if pt.Mbr1 != "this is a new string" { 73 t.Errorf("Mbr1 should be 'this is a new string': %v\n", pt.Mbr1) 74 } 75 76 fld, _ = typ.FieldByName("Enum") 77 vf = FieldValue(&pt, fld) 78 79 // fmt.Printf("Fld: %v Typ: %v vf: %v vfi: %v vfT: %v vfp: %v canaddr: %v canset: %v caninterface: %v\n", fld.Name, vf.Type().String(), vf.String(), vf.Interface(), vf.Interface(), vf.Interface(), vf.CanAddr(), vf.CanSet(), vf.CanInterface()) 80 81 vf.Elem().Set(reflect.ValueOf(TestFlag1)) 82 83 if pt.Enum != TestFlag1 { 84 t.Errorf("Enum should be TestFlag1: %v\n", pt.Enum) 85 } 86 87 err := SetEnumValueFromString(vf, "TestFlag2") 88 if err != nil { 89 t.Errorf("%v", err) 90 } 91 92 if pt.Enum != TestFlag2 { 93 t.Errorf("Enum should be TestFlag2: %v\n", pt.Enum) 94 } 95 96 err = Enums.SetEnumValueFromAltString(vf, "flag1") 97 if err != nil { 98 t.Errorf("%v", err) 99 } 100 101 if pt.Enum != TestFlag1 { 102 t.Errorf("Enum should be TestFlag1: %v\n", pt.Enum) 103 } 104 } 105 106 func TestNewAtSub(t *testing.T) { 107 InitPtrTst() 108 typ := reflect.TypeOf(pt) 109 subtyp := reflect.TypeOf(pt.SubField) 110 111 fld, _ := typ.FieldByName("SubField") 112 sub, _ := subtyp.FieldByName("Enum") 113 vf := SubFieldValue(&pt, fld, sub) 114 115 // fmt.Printf("Fld: %v Typ: %v vf: %v vfi: %v vfT: %v vfp: %v canaddr: %v canset: %v caninterface: %v\n", fld.Name, vf.Type().String(), vf.String(), vf.Interface(), vf.Interface(), vf.Interface(), vf.CanAddr(), vf.CanSet(), vf.CanInterface()) 116 117 pt.SubField.Enum = TestFlag2 118 vf.Elem().Set(reflect.ValueOf(TestFlag1)) 119 120 if pt.SubField.Enum != TestFlag1 { 121 t.Errorf("Enum should be TestFlag1: %v\n", pt.SubField.Enum) 122 } 123 124 err := SetEnumValueFromString(vf, "TestFlag2") 125 if err != nil { 126 t.Errorf("%v", err) 127 } 128 129 if pt.SubField.Enum != TestFlag2 { 130 t.Errorf("Enum should be TestFlag2: %v\n", pt.SubField.Enum) 131 } 132 133 err = Enums.SetEnumValueFromAltString(vf, "flag1") 134 if err != nil { 135 t.Errorf("%v", err) 136 } 137 138 if pt.SubField.Enum != TestFlag1 { 139 t.Errorf("Enum should be TestFlag1: %v\n", pt.SubField.Enum) 140 } 141 142 }