github.com/goki/ki@v1.1.11/ki/node_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 ki
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/goki/ki/kit"
    16  )
    17  
    18  type NodeEmbed struct {
    19  	Node
    20  	Mbr1 string
    21  	Mbr2 int
    22  }
    23  
    24  var NodeEmbedProps = Props{
    25  	"intprop":    -17,
    26  	"floatprop":  3.1415,
    27  	"stringprop": "type string",
    28  }
    29  
    30  var KiT_NodeEmbed = kit.Types.AddType(&NodeEmbed{}, NodeEmbedProps)
    31  
    32  type NodeField struct {
    33  	NodeEmbed
    34  	Field1 NodeEmbed
    35  }
    36  
    37  var KiT_NodeField = kit.Types.AddType(&NodeField{}, nil)
    38  
    39  type NodeField2 struct {
    40  	NodeField
    41  	Field2    NodeEmbed
    42  	PtrIgnore *NodeEmbed
    43  }
    44  
    45  var KiT_NodeField2 = kit.Types.AddType(&NodeField2{}, nil)
    46  
    47  func TestNodeAddChild(t *testing.T) {
    48  	parent := NodeEmbed{}
    49  	parent.InitName(&parent, "par1")
    50  	child := NodeEmbed{}
    51  	// Note: must pass child.KiNode as a pointer  -- if it is a plain Node it is ok but
    52  	// as a member of a struct, for somewhat obscure reasons having to do with the
    53  	// fact that an interface is implicitly a pointer, you need to pass as a pointer here
    54  	parent.AddChild(&child)
    55  	child.SetName("child1")
    56  	if len(parent.Kids) != 1 {
    57  		t.Errorf("Children length != 1, was %d", len(parent.Kids))
    58  	}
    59  	if child.Parent() == nil {
    60  		t.Errorf("child parent is nil")
    61  	}
    62  	if child.Path() != "/par1/child1" {
    63  		t.Errorf("child path != correct, was %v", child.Path())
    64  	}
    65  }
    66  
    67  func TestNodeEmbedAddChild(t *testing.T) {
    68  	parent := NodeEmbed{}
    69  	parent.InitName(&parent, "par1")
    70  	child := NodeEmbed{}
    71  	// Note: must pass child as a pointer  -- if it is a plain Node it is ok but
    72  	// as a member of a struct, for somewhat obscure reasons having to do with the
    73  	// fact that an interface is implicitly a pointer, you need to pass as a pointer here
    74  	parent.AddChild(&child)
    75  	child.SetName("child1")
    76  	if len(parent.Kids) != 1 {
    77  		t.Errorf("Children length != 1, was %d", len(parent.Kids))
    78  	}
    79  	if child.Path() != "/par1/child1" {
    80  		t.Errorf("child path != correct, was %v", child.Path())
    81  	}
    82  }
    83  
    84  func TestNodeEmbedAddNewChild(t *testing.T) {
    85  	// nod := Node{}
    86  	parent := NodeEmbed{}
    87  	parent.InitName(&parent, "par1")
    88  	typ := reflect.TypeOf(parent)
    89  	child := parent.AddNewChild(typ, "child1")
    90  	if len(parent.Kids) != 1 {
    91  		t.Errorf("Children length != 1, was %d", len(parent.Kids))
    92  	}
    93  	if child.Path() != "/par1/child1" {
    94  		t.Errorf("child path != correct, was %v", child.Path())
    95  	}
    96  	if reflect.TypeOf(child).Elem() != Type(parent.This()) {
    97  		t.Errorf("child type != correct, was %T", child)
    98  	}
    99  }
   100  
   101  func TestNodeUniqueNames(t *testing.T) {
   102  	parent := NodeEmbed{}
   103  	parent.InitName(&parent, "par1")
   104  	typ := reflect.TypeOf(parent)
   105  	child := parent.AddNewChild(typ, "child1")
   106  	child2 := parent.AddNewChild(typ, "child1")
   107  	child3 := parent.AddNewChild(typ, "child1")
   108  	if len(parent.Kids) != 3 {
   109  		t.Errorf("Children length != 3, was %d", len(parent.Kids))
   110  	}
   111  	UniquifyNamesAll(parent.This())
   112  	if pth := child.Path(); pth != "/par1/child1" {
   113  		t.Errorf("child path != correct, was %v", pth)
   114  	}
   115  	if pth := child2.Path(); pth != "/par1/child1_001" {
   116  		t.Errorf("child2 path != correct, was %v", pth)
   117  	}
   118  	if pth := child3.Path(); pth != "/par1/child1_002" {
   119  		t.Errorf("child3 path != correct, was %v", pth)
   120  	}
   121  
   122  }
   123  
   124  func TestNodeEscapePaths(t *testing.T) {
   125  	parent := NodeEmbed{}
   126  	parent.InitName(&parent, "par1")
   127  	typ := reflect.TypeOf(parent)
   128  	child := parent.AddNewChild(typ, "child1.go")
   129  	child2 := parent.AddNewChild(typ, "child1/child1")
   130  	child3 := parent.AddNewChild(typ, "child1/child1.go")
   131  	schild2 := child2.AddNewChild(typ, "subchild1")
   132  	if len(parent.Kids) != 3 {
   133  		t.Errorf("Children length != 3, was %d", len(parent.Kids))
   134  	}
   135  	if pth := child.Path(); pth != `/par1/child1\,go` {
   136  		t.Errorf("child path != correct, was %v", pth)
   137  	}
   138  	if pth := child2.Path(); pth != `/par1/child1\\child1` {
   139  		t.Errorf("child2 path != correct, was %v", pth)
   140  	}
   141  	if pth := child3.Path(); pth != `/par1/child1\\child1\,go` {
   142  		t.Errorf("child3 path != correct, was %v", pth)
   143  	}
   144  	ch := parent.FindPath(child.Path())
   145  	if ch != child {
   146  		t.Errorf("child path not found in parent")
   147  	}
   148  	ch = parent.FindPath(child3.Path())
   149  	if ch != child3 {
   150  		t.Errorf("child3 path not found in parent")
   151  	}
   152  	ch = parent.FindPath(child3.Path())
   153  	if ch != child3 {
   154  		t.Errorf("child3 path not found in parent")
   155  	}
   156  	ch = parent.FindPath(schild2.Path())
   157  	if ch != schild2 {
   158  		t.Errorf("schild2 path not found in parent")
   159  	}
   160  	ch = child2.FindPath(schild2.Path())
   161  	if ch != schild2 {
   162  		t.Errorf("schild2 path not found in child2")
   163  	}
   164  }
   165  
   166  func TestNodeDeleteChild(t *testing.T) {
   167  	parent := NodeEmbed{}
   168  	parent.InitName(&parent, "par1")
   169  	typ := reflect.TypeOf(parent)
   170  	child := parent.AddNewChild(typ, "child1")
   171  	parent.DeleteChild(child, true)
   172  	if len(parent.Kids) != 0 {
   173  		t.Errorf("Children length != 0, was %d", len(parent.Kids))
   174  	}
   175  	if len(DelMgr.Dels) != 0 { // note: even though using destroy, UpdateEnd does destroy
   176  		t.Errorf("Deleted length != 0, was %d", len(DelMgr.Dels))
   177  	}
   178  }
   179  
   180  func TestNodeDeleteChildName(t *testing.T) {
   181  	parent := NodeEmbed{}
   182  	parent.InitName(&parent, "par1")
   183  	typ := reflect.TypeOf(parent)
   184  	parent.AddNewChild(typ, "child1")
   185  	parent.DeleteChildByName("child1", true)
   186  	if len(parent.Kids) != 0 {
   187  		t.Errorf("Children length != 0, was %d", len(parent.Kids))
   188  	}
   189  	if len(DelMgr.Dels) != 0 { // note: even though using destroy, UpdateEnd does destroy
   190  		t.Errorf("Deleted length != 0, was %d", len(DelMgr.Dels))
   191  	}
   192  }
   193  
   194  func TestNodeFindName(t *testing.T) {
   195  	names := [...]string{"name0", "name1", "name2", "name3", "name4", "name5"}
   196  	parent := Node{}
   197  	parent.InitName(&parent, "par")
   198  	typ := reflect.TypeOf(parent)
   199  	for _, nm := range names {
   200  		parent.AddNewChild(typ, nm)
   201  	}
   202  	if len(parent.Kids) != len(names) {
   203  		t.Errorf("Children length != n, was %d", len(parent.Kids))
   204  	}
   205  	for i, nm := range names {
   206  		for st := range names { // test all starting indexes
   207  			idx, ok := parent.Children().IndexByName(nm, st)
   208  			if !ok || idx != i {
   209  				t.Errorf("find index was not correct val of %d, was %d", i, idx)
   210  			}
   211  		}
   212  	}
   213  }
   214  
   215  func TestNodeFindNameUnique(t *testing.T) {
   216  	names := [...]string{"child", "child_001", "child_002", "child_003", "child_004", "child_005"}
   217  	parent := Node{}
   218  	parent.InitName(&parent, "par")
   219  	typ := reflect.TypeOf(parent)
   220  	for range names {
   221  		parent.AddNewChild(typ, "child")
   222  	}
   223  	if len(parent.Kids) != len(names) {
   224  		t.Errorf("Children length != n, was %d", len(parent.Kids))
   225  	}
   226  	if UniqueNameCheckAll(parent.This()) {
   227  		t.Errorf("UniqeNameCheckAll failed: Children are not unique!")
   228  	}
   229  	UniquifyNamesAll(parent.This())
   230  	for i, nm := range names {
   231  		for st := range names { // test all starting indexes
   232  			idx, ok := parent.Children().IndexByName(nm, st)
   233  			if !ok || idx != i {
   234  				t.Errorf("find index was not correct val of %d, was %d", i, idx)
   235  			}
   236  		}
   237  	}
   238  }
   239  
   240  func TestNodeFindType(t *testing.T) {
   241  	parent := Node{}
   242  	parent.InitName(&parent, "par")
   243  	parent.AddNewChild(KiT_NodeEmbed, "child1")
   244  	parent.AddNewChild(KiT_Node, "child2")
   245  	idx, ok := parent.Children().IndexByType(KiT_NodeEmbed, NoEmbeds, 0)
   246  	if !ok || idx != 0 {
   247  		t.Errorf("find index was not correct val of %d, was %d", 0, idx)
   248  	}
   249  	idx, ok = parent.Children().IndexByType(KiT_Node, NoEmbeds, 0)
   250  	if !ok || idx != 1 {
   251  		t.Errorf("find index was not correct val of %d, was %d", 1, idx)
   252  	}
   253  	_, err := parent.Children().ElemByTypeTry(KiT_Node, NoEmbeds, 0)
   254  	if err != nil {
   255  		t.Error(err)
   256  	}
   257  }
   258  
   259  func TestNodeMove(t *testing.T) {
   260  	parent := NodeEmbed{}
   261  	parent.InitName(&parent, "par1")
   262  	typ := reflect.TypeOf(parent)
   263  	parent.Mbr1 = "bloop"
   264  	parent.Mbr2 = 32
   265  	// child1 :=
   266  	parent.AddNewChild(typ, "child0")
   267  	var child2 = parent.AddNewChild(typ, "child1").(*NodeEmbed)
   268  	// child3 :=
   269  	parent.AddNewChild(typ, "child2")
   270  	//schild2 :=
   271  	child2.AddNewChild(typ, "subchild1")
   272  	// child4 :=
   273  	parent.AddNewChild(typ, "child3")
   274  
   275  	bf := fmt.Sprintf("mv before:\n%v\n", parent.Kids)
   276  	parent.Children().Move(3, 1)
   277  	a31 := fmt.Sprintf("mv 3 -> 1:\n%v\n", parent.Kids)
   278  	parent.Children().Move(0, 3)
   279  	a03 := fmt.Sprintf("mv 0 -> 3:\n%v\n", parent.Kids)
   280  	parent.Children().Move(1, 2)
   281  	a12 := fmt.Sprintf("mv 1 -> 2:\n%v\n", parent.Kids)
   282  
   283  	bft := `mv before:
   284  [/par1/child0 /par1/child1 /par1/child2 /par1/child3]
   285  `
   286  	if bf != bft {
   287  		t.Errorf("move error\n%v !=\n%v", bf, bft)
   288  	}
   289  	a31t := `mv 3 -> 1:
   290  [/par1/child0 /par1/child3 /par1/child1 /par1/child2]
   291  `
   292  	if a31 != a31t {
   293  		t.Errorf("move error\n%v !=\n%v", a31, a31t)
   294  	}
   295  	a03t := `mv 0 -> 3:
   296  [/par1/child3 /par1/child1 /par1/child2 /par1/child0]
   297  `
   298  	if a03 != a03t {
   299  		t.Errorf("move error\n%v !=\n%v", a03, a03t)
   300  	}
   301  	a12t := `mv 1 -> 2:
   302  [/par1/child3 /par1/child2 /par1/child1 /par1/child0]
   303  `
   304  	if a12 != a12t {
   305  		t.Errorf("move error\n%v !=\n%v", a12, a12t)
   306  	}
   307  }
   308  
   309  func TestNodeConfig(t *testing.T) {
   310  	parent := NodeEmbed{}
   311  	parent.InitName(&parent, "par1")
   312  	typ := reflect.TypeOf(parent)
   313  	parent.Mbr1 = "bloop"
   314  	parent.Mbr2 = 32
   315  	// child1 :=
   316  	parent.AddNewChild(typ, "child0")
   317  	var child2 = parent.AddNewChild(typ, "child1").(*NodeEmbed)
   318  	// child3 :=
   319  	parent.AddNewChild(typ, "child2")
   320  	//schild2 :=
   321  	child2.AddNewChild(typ, "subchild1")
   322  	// child4 :=
   323  	parent.AddNewChild(typ, "child3")
   324  
   325  	config1 := kit.TypeAndNameList{
   326  		{Type: KiT_NodeEmbed, Name: "child2"},
   327  		{Type: KiT_NodeEmbed, Name: "child3"},
   328  		{Type: KiT_NodeEmbed, Name: "child1"},
   329  	}
   330  
   331  	// bf := fmt.Sprintf("mv before:\n%v\n", parent.Kids)
   332  
   333  	mods, updt := parent.ConfigChildren(config1)
   334  	if mods {
   335  		parent.UpdateEnd(updt)
   336  	}
   337  
   338  	cf1 := fmt.Sprintf("config1:\n%v\n", parent.Kids)
   339  
   340  	// config2 := kit.TypeAndNameList{
   341  	// 	{KiT_NodeEmbed, "child4"},
   342  	// 	{KiT_Node, "child1"}, // note: changing this to Node type removes child1.subchild1
   343  	// 	{KiT_NodeEmbed, "child5"},
   344  	// 	{KiT_NodeEmbed, "child3"},
   345  	// 	{KiT_NodeEmbed, "child6"},
   346  	// }
   347  
   348  	config3 := kit.TypeAndNameList{}
   349  	// fmt.Printf("NodeEmbed type name: %v\n", kit.FullTypeName(KiT_NodeEmbed))
   350  	netn := kit.Types.TypeName(KiT_NodeEmbed)
   351  	ntn := kit.Types.TypeName(KiT_Node)
   352  	err := config3.SetFromString("{" + netn + ", child4}, {" + ntn + ", child1}, {" + netn + ", child5}, {" + netn + ", child3}, {" + netn + ", child6}")
   353  	if err != nil {
   354  		t.Errorf("%v", err)
   355  	}
   356  
   357  	mods, updt = parent.ConfigChildren(config3)
   358  	if mods {
   359  		parent.UpdateEnd(updt)
   360  	}
   361  
   362  	cf2 := fmt.Sprintf("config2:\n%v\n", parent.Kids)
   363  
   364  	cf1t := `config1:
   365  [/par1/child2 /par1/child3 /par1/child1]
   366  `
   367  	if cf1 != cf1t {
   368  		t.Errorf("config error\n%v !=\n%v", cf1, cf1t)
   369  	}
   370  
   371  	cf2t := `config2:
   372  [/par1/child4 /par1/child1 /par1/child5 /par1/child3 /par1/child6]
   373  `
   374  	if cf2 != cf2t {
   375  		t.Errorf("config error\n%v !=\n%v", cf2, cf2t)
   376  	}
   377  }
   378  
   379  //////////////////////////////////////////
   380  //  JSON I/O
   381  
   382  func TestNodeJSONSave(t *testing.T) {
   383  	parent := NodeEmbed{}
   384  	parent.InitName(&parent, "par1")
   385  	typ := reflect.TypeOf(parent)
   386  	parent.Mbr1 = "bloop"
   387  	parent.Mbr2 = 32
   388  	// child1 :=
   389  	parent.AddNewChild(typ, "child1")
   390  	var child2 = parent.AddNewChild(typ, "child1").(*NodeEmbed)
   391  	// child3 :=
   392  	parent.AddNewChild(typ, "child1")
   393  	child2.AddNewChild(typ, "subchild1")
   394  
   395  	var buf bytes.Buffer
   396  	err := parent.WriteJSON(&buf, true)
   397  	if err != nil {
   398  		t.Error(err)
   399  		// } else {
   400  		// 	fmt.Printf("json output:\n%v\n", string(buf.Bytes()))
   401  	}
   402  	b := buf.Bytes()
   403  
   404  	tstload := NodeEmbed{}
   405  	tstload.InitName(&tstload, "")
   406  	err = tstload.ReadJSON(bytes.NewReader(b))
   407  	if err != nil {
   408  		t.Error(err)
   409  	} else {
   410  		var buf2 bytes.Buffer
   411  		err = tstload.WriteJSON(&buf2, true)
   412  		if err != nil {
   413  			t.Error(err)
   414  		}
   415  		tstb := buf2.Bytes()
   416  		// fmt.Printf("test loaded json output: %v\n", string(tstb))
   417  		if !bytes.Equal(tstb, b) {
   418  			t.Error("original and unmarshal'd json rep are not equivalent")
   419  		}
   420  	}
   421  
   422  	nwnd, err := ReadNewJSON(bytes.NewReader(b))
   423  	if err != nil {
   424  		t.Error(err)
   425  	} else {
   426  		var buf2 bytes.Buffer
   427  		err = nwnd.WriteJSON(&buf2, true)
   428  		if err != nil {
   429  			t.Error(err)
   430  		}
   431  		tstb := buf2.Bytes()
   432  		// fmt.Printf("test loaded json output: %v\n", string(tstb))
   433  		if !bytes.Equal(tstb, b) {
   434  			t.Error("original and unmarshal'd json rep are not equivalent")
   435  		}
   436  	}
   437  }
   438  
   439  func TestNodeXMLSave(t *testing.T) {
   440  	parent := NodeEmbed{}
   441  	parent.InitName(&parent, "par1")
   442  	typ := reflect.TypeOf(parent)
   443  	parent.Mbr1 = "bloop"
   444  	parent.Mbr2 = 32
   445  	// child1 :=
   446  	parent.AddNewChild(typ, "child1")
   447  	var child2 = parent.AddNewChild(typ, "child1").(*NodeEmbed)
   448  	// child3 :=
   449  	parent.AddNewChild(typ, "child1")
   450  	child2.AddNewChild(typ, "subchild1")
   451  
   452  	var buf bytes.Buffer
   453  	err := parent.WriteXML(&buf, true)
   454  	if err != nil {
   455  		t.Error(err)
   456  		// } else {
   457  		// 	fmt.Printf("xml output:\n%v\n", string(buf.Bytes()))
   458  	}
   459  	b := buf.Bytes()
   460  
   461  	tstload := NodeEmbed{}
   462  	tstload.InitName(&tstload, "")
   463  	err = tstload.ReadXML(bytes.NewReader(b))
   464  	if err != nil {
   465  		t.Error(err)
   466  	} else {
   467  		var buf2 bytes.Buffer
   468  		if err != nil {
   469  			t.Error(err)
   470  		}
   471  		err := tstload.WriteXML(&buf2, true)
   472  		if err != nil {
   473  			t.Error(err)
   474  		}
   475  		tstb := buf2.Bytes()
   476  		// fmt.Printf("test loaded json output:\n%v\n", string(tstb))
   477  		if !bytes.Equal(tstb, b) {
   478  			t.Error("original and unmarshal'd XML rep are not equivalent")
   479  		}
   480  	}
   481  }
   482  
   483  //////////////////////////////////////////
   484  //  function calling
   485  
   486  func TestNodeCallFun(t *testing.T) {
   487  	parent := NodeEmbed{}
   488  	parent.InitName(&parent, "par1")
   489  	typ := reflect.TypeOf(parent)
   490  	parent.Mbr1 = "bloop"
   491  	parent.Mbr2 = 32
   492  	// child1 :=
   493  	parent.AddNewChild(typ, "child1")
   494  	child2 := parent.AddNewChild(typ, "child1")
   495  	// child3 :=
   496  	parent.AddNewChild(typ, "child1")
   497  	schild2 := child2.AddNewChild(typ, "subchild1")
   498  	UniquifyNames(parent.This())
   499  
   500  	res := make([]string, 0, 10)
   501  	parent.FuncDownMeFirst(0, "fun_down", func(k Ki, level int, d interface{}) bool {
   502  		res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   503  		return true
   504  	})
   505  
   506  	trg := []string{"[par1, fun_down, lev 0]", "[child1, fun_down, lev 1]", "[child1_001, fun_down, lev 1]", "[subchild1, fun_down, lev 2]", "[child1_002, fun_down, lev 1]"}
   507  	if !reflect.DeepEqual(res, trg) {
   508  		t.Errorf("FuncDown error -- results:\n%v\n != target:\n%v\n", res, trg)
   509  	}
   510  	res = res[:0]
   511  
   512  	// test return = false case
   513  	parent.FuncDownMeFirst(0, "fun_down", func(k Ki, level int, d interface{}) bool {
   514  		res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   515  		if k.Name() == "child1_001" {
   516  			return Break
   517  		}
   518  		return Continue
   519  	})
   520  
   521  	trg = []string{"[par1, fun_down, lev 0]", "[child1, fun_down, lev 1]", "[child1_001, fun_down, lev 1]", "[child1_002, fun_down, lev 1]"}
   522  	if !reflect.DeepEqual(res, trg) {
   523  		t.Errorf("FuncDown return false error -- results:\n%v\n != target:\n%v\n", res, trg)
   524  	}
   525  	res = res[:0]
   526  
   527  	schild2.FuncUp(0, "fun_up", func(k Ki, level int, d interface{}) bool {
   528  		res = append(res, fmt.Sprintf("%v, %v", k.Name(), d))
   529  		return Continue
   530  	})
   531  	//	fmt.Printf("result: %v\n", res)
   532  
   533  	trg = []string{"subchild1, fun_up", "child1_001, fun_up", "par1, fun_up"}
   534  	if !reflect.DeepEqual(res, trg) {
   535  		t.Errorf("FuncUp error -- results: %v != target: %v\n", res, trg)
   536  	}
   537  	res = res[:0]
   538  
   539  	parent.FuncDownMeLast(0, "fun_down_me_last", func(k Ki, level int, d interface{}) bool {
   540  		return Continue
   541  	},
   542  		func(k Ki, level int, d interface{}) bool {
   543  			res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   544  			return Continue
   545  		})
   546  	// fmt.Printf("node field fun result: %v\n", res)
   547  	trg = []string{"[child1, fun_down_me_last, lev 1]", "[subchild1, fun_down_me_last, lev 2]", "[child1_001, fun_down_me_last, lev 1]", "[child1_002, fun_down_me_last, lev 1]", "[par1, fun_down_me_last, lev 0]"}
   548  	if !reflect.DeepEqual(res, trg) {
   549  		t.Errorf("NodeField FuncDownMeLast error -- results:\n%v\n!= target:\n%v\n", res, trg)
   550  	}
   551  	res = res[:0]
   552  
   553  	// test for return = false working
   554  	parent.FuncDownMeLast(0, "fun_down_me_last", func(k Ki, level int, d interface{}) bool {
   555  		if k.Name() == "child1_001" {
   556  			return Break
   557  		}
   558  		return Continue
   559  	},
   560  		func(k Ki, level int, d interface{}) bool {
   561  			if k.Name() == "child1_001" {
   562  				return Break
   563  			}
   564  			res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   565  			return Continue
   566  		})
   567  	// fmt.Printf("node field fun result: %v\n", res)
   568  	trg = []string{"[child1, fun_down_me_last, lev 1]", "[child1_002, fun_down_me_last, lev 1]", "[par1, fun_down_me_last, lev 0]"}
   569  	if !reflect.DeepEqual(res, trg) {
   570  		t.Errorf("NodeField FuncDownMeLast error -- results:\n%v\n!= target:\n%v\n", res, trg)
   571  	}
   572  	res = res[:0]
   573  
   574  	parent.FuncDownBreadthFirst(0, "fun_breadth", func(k Ki, level int, d interface{}) bool {
   575  		res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   576  		return Continue
   577  	})
   578  	// fmt.Printf("node field fun result: %v\n", res)
   579  	trg = []string{"[par1, fun_breadth, lev 0]", "[child1, fun_breadth, lev 1]", "[child1_001, fun_breadth, lev 1]", "[child1_002, fun_breadth, lev 1]", "[subchild1, fun_breadth, lev 2]"}
   580  	if !reflect.DeepEqual(res, trg) {
   581  		t.Errorf("NodeField FuncDownBreadthFirst error -- results:\n%v\n!= target:\n%v\n", res, trg)
   582  	}
   583  	res = res[:0]
   584  
   585  	// test for return false
   586  	parent.FuncDownBreadthFirst(0, "fun_breadth", func(k Ki, level int, d interface{}) bool {
   587  		if k.Name() == "child1_001" {
   588  			return Break
   589  		}
   590  		res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   591  		return Continue
   592  	})
   593  	// fmt.Printf("node field fun result: %v\n", res)
   594  	trg = []string{"[par1, fun_breadth, lev 0]", "[child1, fun_breadth, lev 1]", "[child1_002, fun_breadth, lev 1]"}
   595  	if !reflect.DeepEqual(res, trg) {
   596  		t.Errorf("NodeField FuncDownBreadthFirst error -- results:\n%v\n!= target:\n%v\n", res, trg)
   597  	}
   598  	res = res[:0]
   599  }
   600  
   601  func TestNodeUpdate(t *testing.T) {
   602  	parent := NodeEmbed{}
   603  	parent.InitName(&parent, "par1")
   604  	typ := reflect.TypeOf(parent)
   605  	parent.Mbr1 = "bloop"
   606  	parent.Mbr2 = 32
   607  
   608  	res := make([]string, 0, 10)
   609  	parent.NodeSignal().Connect(&parent, func(r, s Ki, sig int64, d interface{}) {
   610  		res = append(res, fmt.Sprintf("%v sig %v flags %v", s.Name(), NodeSignals(sig),
   611  			kit.BitFlagsToString((s.Flags()), FlagsN)))
   612  	})
   613  	// child1 :=
   614  	updt := parent.UpdateStart()
   615  	parent.SetChildAdded()
   616  	parent.AddNewChild(typ, "child1")
   617  	child2 := parent.AddNewChild(typ, "child1")
   618  	// child3 :=
   619  	parent.UpdateEnd(updt)
   620  	updt = parent.UpdateStart()
   621  	parent.SetChildAdded()
   622  	parent.AddNewChild(typ, "child1")
   623  	parent.UpdateEnd(updt)
   624  	schild2 := child2.AddNewChild(typ, "subchild1")
   625  	child2.SetChildAdded()
   626  	parent.UpdateEnd(updt)
   627  
   628  	for ri := range res {
   629  		res[ri] = strings.Replace(res[ri], "HasNoKiFields|", "", -1)
   630  	}
   631  	// fmt.Printf("res: %v\n", res)
   632  	trg := []string{"par1 sig NodeSignalUpdated flags ChildAdded", "par1 sig NodeSignalUpdated flags ChildAdded", "par1 sig NodeSignalUpdated flags ChildAdded"}
   633  	if !reflect.DeepEqual(res, trg) {
   634  		t.Errorf("Add child sigs error -- results:\n%v\n!= target:\n%v\n", res, trg)
   635  	}
   636  	res = res[:0]
   637  
   638  	child2.NodeSignal().Connect(&parent, func(r, s Ki, sig int64, d interface{}) {
   639  		res = append(res, fmt.Sprintf("%v sig %v", s.Name(), NodeSignals(sig)))
   640  	})
   641  	schild2.NodeSignal().Connect(&parent, func(r, s Ki, sig int64, d interface{}) {
   642  		res = append(res, fmt.Sprintf("%v sig %v", s.Name(), NodeSignals(sig)))
   643  	})
   644  
   645  	// fmt.Print("\nnode update top starting\n")
   646  	updt = child2.UpdateStart()
   647  	updt2 := schild2.UpdateStart()
   648  	schild2.UpdateEnd(updt2)
   649  	child2.UpdateEnd(updt)
   650  
   651  	// fmt.Printf("res: %v\n", res)
   652  	trg = []string{"child1 sig NodeSignalUpdated"}
   653  	if !reflect.DeepEqual(res, trg) {
   654  		t.Errorf("update signal only top error -- results: %v != target: %v\n", res, trg)
   655  	}
   656  	res = res[:0]
   657  
   658  	UniquifyNamesAll(parent.This())
   659  
   660  	parent.FuncDownMeFirst(0, "upcnt", func(n Ki, level int, d interface{}) bool {
   661  		res = append(res, fmt.Sprintf("%v %v", n.Name(), n.IsUpdating()))
   662  		return Continue
   663  	})
   664  	// fmt.Printf("res: %v\n", res)
   665  
   666  	trg = []string{"par1 false", "child1 false", "child1_001 false", "subchild1 false", "child1_002 false"}
   667  	if !reflect.DeepEqual(res, trg) {
   668  		t.Errorf("update counts error -- results: %v != target: %v\n", res, trg)
   669  	}
   670  
   671  }
   672  
   673  func TestProps(t *testing.T) {
   674  	parent := NodeEmbed{}
   675  	parent.InitName(&parent, "par1")
   676  	typ := reflect.TypeOf(parent)
   677  	parent.Mbr1 = "bloop"
   678  	parent.Mbr2 = 32
   679  
   680  	res := make([]string, 0, 10)
   681  	parent.NodeSignal().Connect(&parent, func(r, s Ki, sig int64, d interface{}) {
   682  		res = append(res, fmt.Sprintf("%v sig %v", s.Name(), sig))
   683  	})
   684  	// child1 :=
   685  	parent.AddNewChild(typ, "child1")
   686  	child2 := parent.AddNewChild(typ, "child1")
   687  	// child3 :=
   688  	updt := parent.UpdateStart()
   689  	parent.AddNewChild(typ, "child1")
   690  	parent.UpdateEnd(updt)
   691  	schild2 := child2.AddNewChild(typ, "subchild1")
   692  
   693  	parent.SetProp("intprop", 42)
   694  	pprop, ok := kit.ToInt(parent.Prop("intprop"))
   695  	if !ok || pprop != 42 {
   696  		t.Errorf("TestProps error -- pprop %v != %v\n", pprop, 42)
   697  	}
   698  	sprop, ok := schild2.PropInherit("intprop", Inherit, NoTypeProps)
   699  	if !ok {
   700  		t.Errorf("TestProps error -- intprop inherited not found\n")
   701  	}
   702  	sint, ok := kit.ToInt(sprop)
   703  	if !ok || sprop != 42 {
   704  		t.Errorf("TestProps error -- intprop inherited %v != %v\n", sint, 42)
   705  	}
   706  	sprop, ok = schild2.PropInherit("intprop", NoInherit, NoTypeProps)
   707  	if ok {
   708  		t.Errorf("TestProps error -- intprop should not be found!  was: %v\n", sprop)
   709  	}
   710  
   711  	parent.SetProp("floatprop", 42.0)
   712  	sprop, ok = schild2.PropInherit("floatprop", Inherit, NoTypeProps)
   713  	if !ok {
   714  		t.Errorf("TestProps error -- floatprop inherited not found\n")
   715  	}
   716  	spropf, ok := kit.ToFloat(sprop)
   717  	if !ok || spropf != 42.0 {
   718  		t.Errorf("TestProps error -- floatprop inherited %v != %v\n", spropf, 42.0)
   719  	}
   720  
   721  	tstr := "test string"
   722  	parent.SetProp("stringprop", tstr)
   723  	sprop, ok = schild2.PropInherit("stringprop", Inherit, NoTypeProps)
   724  	if !ok {
   725  		t.Errorf("TestProps error -- stringprop not found\n")
   726  	}
   727  	sprops := kit.ToString(sprop)
   728  	if sprops != tstr {
   729  		t.Errorf("TestProps error -- sprops inherited %v != %v\n", sprops, tstr)
   730  	}
   731  
   732  	parent.DeleteProp("floatprop")
   733  	sprop, ok = schild2.PropInherit("floatprop", Inherit, NoTypeProps)
   734  	if ok {
   735  		t.Errorf("TestProps error -- floatprop should be gone\n")
   736  	}
   737  
   738  	sprop, ok = parent.PropInherit("floatprop", Inherit, TypeProps)
   739  	if !ok {
   740  		t.Errorf("TestProps error -- floatprop on type not found\n")
   741  	}
   742  	spropf, ok = kit.ToFloat(sprop)
   743  	if !ok || spropf != 3.1415 {
   744  		t.Errorf("TestProps error -- floatprop from type %v != %v\n", spropf, 3.1415)
   745  	}
   746  }
   747  
   748  func TestTreeMod(t *testing.T) {
   749  	SignalTrace = true
   750  	sigs := ""
   751  	SignalTraceString = &sigs
   752  
   753  	tree1 := Node{}
   754  	typ := reflect.TypeOf(tree1)
   755  	tree1.InitName(&tree1, "tree1")
   756  	// child11 :=
   757  	tree1.AddNewChild(typ, "child11")
   758  	child12 := tree1.AddNewChild(typ, "child12")
   759  	// child13 :=
   760  	tree1.AddNewChild(typ, "child13")
   761  	// schild12 :=
   762  	child12.AddNewChild(typ, "subchild12")
   763  
   764  	tree2 := Node{}
   765  	tree2.InitName(&tree2, "tree2")
   766  	// child21 :=
   767  	tree2.AddNewChild(typ, "child21")
   768  	child22 := tree2.AddNewChild(typ, "child22")
   769  	// child23 :=
   770  	tree2.AddNewChild(typ, "child23")
   771  	// schild22 :=
   772  	child22.AddNewChild(typ, "subchild22")
   773  
   774  	// fmt.Printf("Setup Signals:\n%v", sigs)
   775  	sigs = ""
   776  
   777  	// fmt.Printf("#################################\n")
   778  
   779  	// fmt.Printf("Trees before:\n%v%v", tree1, tree2)
   780  	updt := tree2.UpdateStart()
   781  	tree2.SetChildAdded()
   782  	MoveToParent(child12.This(), tree2.This())
   783  	tree2.UpdateEnd(updt)
   784  
   785  	// fmt.Printf("#################################\n")
   786  	// fmt.Printf("Trees after add child12 move:\n%v%v", tree1, tree2)
   787  
   788  	mvsigs := `ki.Signal Emit from: tree1 sig: NodeSignalUpdated data: 260
   789  ki.Signal Emit from: tree2 sig: NodeSignalUpdated data: 132
   790  `
   791  
   792  	_ = mvsigs
   793  	// fmt.Printf("Move Signals:\n%v", sigs)
   794  	if sigs != mvsigs {
   795  		t.Errorf("TestTreeMod child12 move signals:\n%v\nnot as expected:\n%v\n", sigs, mvsigs)
   796  	}
   797  	sigs = ""
   798  
   799  	updt = tree2.UpdateStart()
   800  	tree2.DeleteChild(child12, true)
   801  	tree2.UpdateEnd(updt)
   802  
   803  	// fmt.Printf("#################################\n")
   804  
   805  	delsigs := `ki.Signal Emit from: child12 sig: NodeSignalDeleting data: <nil>
   806  ki.Signal Emit from: subchild12 sig: NodeSignalDeleting data: <nil>
   807  ki.Signal Emit from: tree2 sig: NodeSignalUpdated data: 260
   808  `
   809  
   810  	_ = delsigs
   811  	// fmt.Printf("Delete Signals:\n%v", sigs)
   812  	if sigs != delsigs {
   813  		t.Errorf("TestTreeMod child12 delete signals:\n%v\nnot as expected:\n%v\n", sigs, delsigs)
   814  	}
   815  	sigs = ""
   816  
   817  }
   818  
   819  func TestNodeFieldFunc(t *testing.T) {
   820  	parent := NodeField{}
   821  	parent.InitName(&parent, "par1")
   822  	res := make([]string, 0, 10)
   823  	parent.FuncDownMeFirst(0, "fun_down", func(k Ki, level int, d interface{}) bool {
   824  		res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   825  		return Continue
   826  	})
   827  	// fmt.Printf("node field fun result: %v\n", res)
   828  
   829  	trg := []string{"[par1, fun_down, lev 0]", "[Field1, fun_down, lev 1]"}
   830  	if !reflect.DeepEqual(res, trg) {
   831  		t.Errorf("NodeField FuncDown error -- results: %v != target: %v\n", res, trg)
   832  	}
   833  	res = res[:0]
   834  
   835  	par2 := NodeField2{}
   836  	par2.InitName(&par2, "par2")
   837  	par2.FuncDownMeFirst(0, "fun_down", func(k Ki, level int, d interface{}) bool {
   838  		res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   839  		return Continue
   840  	})
   841  	// fmt.Printf("node field fun result: %v\n", res)
   842  	trg = []string{"[par2, fun_down, lev 0]", "[Field1, fun_down, lev 1]", "[Field2, fun_down, lev 1]"}
   843  	if !reflect.DeepEqual(res, trg) {
   844  		t.Errorf("NodeField FuncDown error -- results: %v != target: %v\n", res, trg)
   845  	}
   846  	res = res[:0]
   847  
   848  	par2.FuncDownMeLast(0, "fun_down_me_last", func(k Ki, level int, d interface{}) bool {
   849  		return Continue
   850  	},
   851  		func(k Ki, level int, d interface{}) bool {
   852  			res = append(res, fmt.Sprintf("[%v, %v, lev %v]", k.Name(), d, level))
   853  			return Continue
   854  		})
   855  	// fmt.Printf("node field fun result: %v\n", res)
   856  	trg = []string{"[Field1, fun_down_me_last, lev 1]", "[Field2, fun_down_me_last, lev 1]", "[par2, fun_down_me_last, lev 0]"}
   857  	if !reflect.DeepEqual(res, trg) {
   858  		t.Errorf("NodeField FuncDownMeLast error -- results:\n%v\n!= target:\n%v\n", res, trg)
   859  	}
   860  	res = res[:0]
   861  }
   862  
   863  func TestNodeFieldJSONSave(t *testing.T) {
   864  	parent := NodeField2{}
   865  	parent.InitName(&parent, "par1")
   866  	typ := reflect.TypeOf(parent)
   867  	parent.Mbr1 = "bloop"
   868  	parent.Mbr2 = 32
   869  	// child1 :=
   870  	parent.AddNewChild(typ, "child1")
   871  	child2 := parent.AddNewChild(typ, "child1").(*NodeField2)
   872  	// child3 :=
   873  	parent.AddNewChild(typ, "child1")
   874  	child2.AddNewChild(typ, "subchild1")
   875  
   876  	var buf bytes.Buffer
   877  	err := parent.WriteJSON(&buf, true)
   878  	if err != nil {
   879  		t.Error(err)
   880  		// } else {
   881  		// 	fmt.Printf("json output:\n%v\n", string(buf.Bytes()))
   882  	}
   883  	b := buf.Bytes()
   884  
   885  	tstload := NodeField2{}
   886  	tstload.InitName(&tstload, "")
   887  	err = tstload.ReadJSON(bytes.NewReader(b))
   888  	if err != nil {
   889  		t.Error(err)
   890  	} else {
   891  		var buf2 bytes.Buffer
   892  		err = tstload.WriteJSON(&buf2, true)
   893  		if err != nil {
   894  			t.Error(err)
   895  		}
   896  		tstb := buf2.Bytes()
   897  		// fmt.Printf("test loaded json output: %v\n", string(tstb))
   898  		if !bytes.Equal(tstb, b) {
   899  			t.Error("original and unmarshal'd json rep are not equivalent")
   900  			ioutil.WriteFile("/tmp/jsonout1", b, 0644)
   901  			ioutil.WriteFile("/tmp/jsonout2", tstb, 0644)
   902  		}
   903  	}
   904  
   905  	nwnd, err := ReadNewJSON(bytes.NewReader(b))
   906  	if err != nil {
   907  		t.Error(err)
   908  	} else {
   909  		var buf2 bytes.Buffer
   910  		err = nwnd.WriteJSON(&buf2, true)
   911  		if err != nil {
   912  			t.Error(err)
   913  		}
   914  		tstb := buf2.Bytes()
   915  		// fmt.Printf("test loaded json output: %v\n", string(tstb))
   916  		if !bytes.Equal(tstb, b) {
   917  			t.Error("original and unmarshal'd json rep are not equivalent")
   918  		}
   919  	}
   920  }
   921  
   922  func TestNodeFieldSet(t *testing.T) {
   923  	parent := NodeField2{}
   924  	parent.InitName(&parent, "par1")
   925  	typ := reflect.TypeOf(parent)
   926  	parent.Mbr1 = "bloop"
   927  	parent.Mbr2 = 32
   928  	// child1 :=
   929  	parent.AddNewChild(typ, "child1")
   930  	child2 := parent.AddNewChild(typ, "child1").(*NodeField2)
   931  	// child3 :=
   932  	parent.AddNewChild(typ, "child1")
   933  	child2.AddNewChild(typ, "subchild1")
   934  
   935  	ts := "child2 is nice"
   936  	err := child2.SetField("Mbr1", ts)
   937  	if err != nil {
   938  		t.Error(err)
   939  	}
   940  	fs := kit.NonPtrInterface(FieldByName(child2.This(), "Mbr1"))
   941  	if fs != ts {
   942  		t.Errorf("Set field error: %+v != %+v\n", fs, ts)
   943  	}
   944  
   945  	ts = "45.21"
   946  	err = child2.SetField("Mbr1", 45.21)
   947  	if err != nil {
   948  		t.Error(err)
   949  	}
   950  	fs = kit.NonPtrInterface(FieldByName(child2.This(), "Mbr1"))
   951  	if fs != ts {
   952  		t.Errorf("Set field error: %+v != %+v\n", fs, ts)
   953  	}
   954  }
   955  
   956  func TestClone(t *testing.T) {
   957  	parent := NodeField2{}
   958  	parent.InitName(&parent, "par1")
   959  	typ := reflect.TypeOf(parent)
   960  	parent.Mbr1 = "bloop"
   961  	parent.Mbr2 = 32
   962  	// child1 :=
   963  	parent.AddNewChild(typ, "child1")
   964  	child2 := parent.AddNewChild(typ, "child1").(*NodeField2)
   965  	// child3 :=
   966  	parent.AddNewChild(typ, "child1")
   967  	child2.AddNewChild(typ, "subchild1")
   968  
   969  	var buf bytes.Buffer
   970  	err := parent.WriteJSON(&buf, true)
   971  	if err != nil {
   972  		t.Error(err)
   973  		// } else {
   974  		// 	fmt.Printf("json output:\n%v\n", string(buf.Bytes()))
   975  	}
   976  	b := buf.Bytes()
   977  
   978  	tstload := parent.Clone()
   979  	var buf2 bytes.Buffer
   980  	err = tstload.WriteJSON(&buf2, true)
   981  	if err != nil {
   982  		t.Error(err)
   983  	}
   984  	tstb := buf2.Bytes()
   985  	// fmt.Printf("test loaded json output: %v\n", string(tstb))
   986  	if !bytes.Equal(tstb, b) {
   987  		t.Error("original and unmarshal'd json rep are not equivalent")
   988  		ioutil.WriteFile("/tmp/jsonout1", b, 0644)
   989  		ioutil.WriteFile("/tmp/jsonout2", tstb, 0644)
   990  	}
   991  }
   992  
   993  // BuildGuiTreeSlow builds a tree that is typical of GUI structures where there are
   994  // many widgets in a container and each widget has some number of parts.
   995  // Uses slow AddChild method instead of fast one.
   996  func BuildGuiTreeSlow(widgets, parts int, typ reflect.Type) Ki {
   997  	win := NewOfType(typ)
   998  	win.InitName(win, "window")
   999  	updt := win.UpdateStart()
  1000  
  1001  	vp := win.AddNewChild(typ, "vp")
  1002  	frame := vp.AddNewChild(typ, "frame")
  1003  	for wi := 0; wi < widgets; wi++ {
  1004  		widg := frame.AddNewChild(typ, fmt.Sprintf("widg_%d", wi))
  1005  
  1006  		for pi := 0; pi < parts; pi++ {
  1007  			widg.AddNewChild(typ, fmt.Sprintf("part_%d", pi))
  1008  		}
  1009  	}
  1010  	win.UpdateEnd(updt)
  1011  	return win
  1012  }
  1013  
  1014  // BuildGuiTree builds a tree that is typical of GUI structures where there are
  1015  // many widgets in a container and each widget has some number of parts.
  1016  func BuildGuiTree(widgets, parts int, typ reflect.Type) Ki {
  1017  	win := NewOfType(typ)
  1018  	win.InitName(win, "window")
  1019  	updt := win.UpdateStart()
  1020  
  1021  	vp := win.AddNewChild(typ, "vp")
  1022  	frame := vp.AddNewChild(typ, "frame")
  1023  	for wi := 0; wi < widgets; wi++ {
  1024  		widg := frame.AddNewChild(typ, fmt.Sprintf("widg_%d", wi))
  1025  
  1026  		for pi := 0; pi < parts; pi++ {
  1027  			widg.AddNewChild(typ, fmt.Sprintf("part_%d", pi))
  1028  		}
  1029  	}
  1030  	win.UpdateEnd(updt)
  1031  	return win
  1032  }
  1033  
  1034  var TotNodes int
  1035  var TestGUITree_NodeEmbed Ki
  1036  var TestGUITree_NodeField Ki
  1037  var TestGUITree_NodeField2 Ki
  1038  
  1039  var NWidgets = 10000
  1040  var NParts = 5
  1041  
  1042  func BenchmarkBuildGuiTree_NodeEmbed(b *testing.B) {
  1043  	for n := 0; n < b.N; n++ {
  1044  		wt := BuildGuiTree(NWidgets, NParts, KiT_NodeEmbed)
  1045  		TestGUITree_NodeEmbed = wt
  1046  	}
  1047  }
  1048  
  1049  func BenchmarkBuildGuiTree_NodeField(b *testing.B) {
  1050  	for n := 0; n < b.N; n++ {
  1051  		wt := BuildGuiTree(NWidgets, NParts, KiT_NodeField)
  1052  		TestGUITree_NodeField = wt
  1053  	}
  1054  }
  1055  
  1056  func BenchmarkBuildGuiTree_NodeField2(b *testing.B) {
  1057  	for n := 0; n < b.N; n++ {
  1058  		wt := BuildGuiTree(NWidgets, NParts, KiT_NodeField2)
  1059  		TestGUITree_NodeField2 = wt
  1060  	}
  1061  }
  1062  
  1063  func BenchmarkBuildGuiTreeSlow_NodeEmbed(b *testing.B) {
  1064  	// prof.Reset()
  1065  	// prof.Profiling = true
  1066  	for n := 0; n < b.N; n++ {
  1067  		wt := BuildGuiTreeSlow(NWidgets, NParts, KiT_NodeEmbed)
  1068  		TestGUITree_NodeEmbed = wt
  1069  	}
  1070  	// prof.Report(time.Millisecond)
  1071  	// prof.Profiling = false
  1072  }
  1073  
  1074  func BenchmarkFuncDownMeFirst_NodeEmbed(b *testing.B) {
  1075  	wt := TestGUITree_NodeEmbed
  1076  	nnodes := 0
  1077  	for n := 0; n < b.N; n++ {
  1078  		wt.FuncDownMeFirst(0, nil, func(k Ki, level int, d interface{}) bool {
  1079  			k.ClearFlag(int(Updating))
  1080  			nnodes++
  1081  			return Continue
  1082  		})
  1083  	}
  1084  	TotNodes = nnodes
  1085  	// fmt.Printf("tot nodes: %d\n", TotNodes)
  1086  }
  1087  
  1088  func BenchmarkFuncDownMeFirst_NodeField(b *testing.B) {
  1089  	wt := TestGUITree_NodeField
  1090  	nnodes := 0
  1091  	for n := 0; n < b.N; n++ {
  1092  		wt.FuncDownMeFirst(0, nil, func(k Ki, level int, d interface{}) bool {
  1093  			k.ClearFlag(int(Updating))
  1094  			nnodes++
  1095  			return Continue
  1096  		})
  1097  	}
  1098  	TotNodes = nnodes
  1099  	// fmt.Printf("tot nodes: %d\n", TotNodes)
  1100  }
  1101  
  1102  func BenchmarkFuncDownMeFirst_NodeField2(b *testing.B) {
  1103  	wt := TestGUITree_NodeField2
  1104  	nnodes := 0
  1105  	for n := 0; n < b.N; n++ {
  1106  		wt.FuncDownMeFirst(0, nil, func(k Ki, level int, d interface{}) bool {
  1107  			k.ClearFlag(int(Updating))
  1108  			nnodes++
  1109  			return Continue
  1110  		})
  1111  	}
  1112  	TotNodes = nnodes
  1113  	// fmt.Printf("tot nodes: %d\n", TotNodes)
  1114  }