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  }