go.ligato.io/vpp-agent/v3@v3.5.0/plugins/kvscheduler/internal/graph/graph_test.go (about)

     1  // Copyright (c) 2018 Cisco and/or its affiliates.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at:
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package graph
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	. "github.com/onsi/gomega"
    22  	"google.golang.org/protobuf/proto"
    23  
    24  	. "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/internal/test"
    25  	. "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/internal/utils"
    26  )
    27  
    28  const (
    29  	minutesInOneDay  = uint32(1440)
    30  	minutesInOneHour = uint32(60)
    31  )
    32  
    33  func TestEmptyGraph(t *testing.T) {
    34  	RegisterTestingT(t)
    35  
    36  	graph := NewGraph(commonOpts)
    37  	Expect(graph).ToNot(BeNil())
    38  
    39  	graphR := graph.Read()
    40  	Expect(graphR).ToNot(BeNil())
    41  
    42  	Expect(graphR.GetNode(keyA1)).To(BeNil())
    43  	Expect(graphR.GetNodeTimeline(keyA1)).To(BeEmpty())
    44  	Expect(graphR.GetNodes(prefixASelector)).To(BeEmpty())
    45  	Expect(graphR.GetMetadataMap(metadataMapA)).To(BeNil())
    46  	Expect(graphR.GetSnapshot(time.Now())).To(BeEmpty())
    47  	flagStats := graphR.GetFlagStats(ColorFlagIndex, nil)
    48  	Expect(flagStats.TotalCount).To(BeEquivalentTo(0))
    49  	Expect(flagStats.PerValueCount).To(BeEmpty())
    50  	graphR.Release()
    51  }
    52  
    53  func TestSingleNode(t *testing.T) {
    54  	RegisterTestingT(t)
    55  
    56  	startTime := time.Now()
    57  
    58  	graph := NewGraph(commonOpts)
    59  	graphW := graph.Write(false, true)
    60  
    61  	graphW.RegisterMetadataMap(metadataMapA, NewNameToInteger(metadataMapA))
    62  
    63  	nodeW := graphW.SetNode(keyA1)
    64  	// new node, everything except the key is unset:
    65  	Expect(nodeW.GetKey()).To(BeEquivalentTo(keyA1))
    66  	Expect(nodeW.GetValue()).To(BeNil())
    67  	Expect(nodeW.GetTargets(relation1)).To(BeEmpty())
    68  	Expect(nodeW.GetSources(relation1)).To(BeEmpty())
    69  	Expect(nodeW.GetMetadata()).To(BeNil())
    70  	Expect(nodeW.GetFlag(ColorFlagIndex)).To(BeNil())
    71  
    72  	// set attributes:
    73  	nodeW.SetLabel(value1Label)
    74  	nodeW.SetValue(value1)
    75  	nodeW.SetMetadata(&OnlyInteger{Integer: 1})
    76  	nodeW.SetMetadataMap(metadataMapA)
    77  	nodeW.SetFlags(ColorFlag(Red), AbstractFlag())
    78  
    79  	// check attributes:
    80  	Expect(nodeW.GetLabel()).To(Equal(value1Label))
    81  	Expect(nodeW.GetValue()).To(Equal(value1))
    82  	Expect(nodeW.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
    83  	flag := nodeW.GetFlag(ColorFlagIndex)
    84  	Expect(flag).ToNot(BeNil())
    85  	colorFlag := flag.(*ColorFlagImpl)
    86  	Expect(colorFlag.Color).To(Equal(Red))
    87  	Expect(nodeW.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
    88  	Expect(nodeW.GetFlag(TemporaryFlagIndex)).To(BeNil())
    89  	Expect(nodeW.GetTargets(relation1)).To(BeEmpty())
    90  	Expect(nodeW.GetSources(relation1)).To(BeEmpty())
    91  
    92  	// not applied into the graph until saved
    93  	graphR := graph.Read()
    94  	Expect(graphR.GetNode(keyA1)).To(BeNil())
    95  	Expect(graphR.GetMetadataMap(metadataMapA)).To(BeNil())
    96  	graphR.Release()
    97  
    98  	// save new node
    99  	graphW.Save()
   100  	graphW.Release()
   101  
   102  	// check that the new node was saved correctly
   103  	graphR = graph.Read()
   104  	nodeR := graphR.GetNode(keyA1)
   105  	Expect(nodeR).ToNot(BeNil())
   106  	Expect(nodeR.GetLabel()).To(Equal(value1Label))
   107  	Expect(nodeR.GetValue()).To(Equal(value1))
   108  	Expect(nodeR.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
   109  	flag = nodeR.GetFlag(ColorFlagIndex)
   110  	Expect(flag).ToNot(BeNil())
   111  	colorFlag = flag.(*ColorFlagImpl)
   112  	Expect(colorFlag.Color).To(Equal(Red))
   113  	Expect(nodeR.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   114  	Expect(nodeR.GetFlag(TemporaryFlagIndex)).To(BeNil())
   115  	Expect(nodeR.GetTargets(relation1)).To(BeEmpty())
   116  	Expect(nodeR.GetSources(relation1)).To(BeEmpty())
   117  
   118  	// check metadata
   119  	metaMap := graphR.GetMetadataMap(metadataMapA)
   120  	Expect(metaMap).ToNot(BeNil())
   121  	Expect(metaMap.ListAllNames()).To(Equal([]string{value1Label}))
   122  	intMap := metaMap.(NameToInteger)
   123  	metadata, exists := intMap.LookupByName(value1Label)
   124  	Expect(exists).To(BeTrue())
   125  	Expect(metadata.GetInteger()).To(Equal(1))
   126  	label, metadata, exists := intMap.LookupByIndex(1)
   127  	Expect(exists).To(BeTrue())
   128  	Expect(metadata.GetInteger()).To(Equal(1))
   129  	Expect(label).To(Equal(value1Label))
   130  
   131  	// check history
   132  	flagStats := graphR.GetFlagStats(ColorFlagIndex, prefixASelector)
   133  	Expect(flagStats.TotalCount).To(BeEquivalentTo(1))
   134  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{Red.String(): 1}))
   135  	timeline := graphR.GetNodeTimeline(keyA1)
   136  	Expect(timeline).To(HaveLen(1))
   137  	record := timeline[0]
   138  	Expect(record.Key).To(Equal(keyA1))
   139  	Expect(record.Since.After(startTime)).To(BeTrue())
   140  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   141  	Expect(record.Until.IsZero()).To(BeTrue())
   142  	Expect(record.Label).To(Equal(value1Label))
   143  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   144  	Expect(record.Targets).To(BeEmpty())
   145  	Expect(record.TargetUpdateOnly).To(BeFalse())
   146  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   147  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Red), AbstractFlag()}}))
   148  }
   149  
   150  func TestSingleNodeCreatedInPlace(t *testing.T) {
   151  	RegisterTestingT(t)
   152  
   153  	startTime := time.Now()
   154  
   155  	graph := NewGraph(commonOpts)
   156  	graphW := graph.Write(true, true)
   157  
   158  	graphW.RegisterMetadataMap(metadataMapA, NewNameToInteger(metadataMapA))
   159  
   160  	nodeW := graphW.SetNode(keyA1)
   161  	// new node, everything except the key is unset:
   162  	Expect(nodeW.GetKey()).To(BeEquivalentTo(keyA1))
   163  	Expect(nodeW.GetValue()).To(BeNil())
   164  	Expect(nodeW.GetTargets(relation1)).To(BeEmpty())
   165  	Expect(nodeW.GetSources(relation1)).To(BeEmpty())
   166  	Expect(nodeW.GetMetadata()).To(BeNil())
   167  	Expect(nodeW.GetFlag(ColorFlagIndex)).To(BeNil())
   168  
   169  	// set attributes:
   170  	nodeW.SetLabel(value1Label)
   171  	nodeW.SetValue(value1)
   172  	nodeW.SetMetadata(&OnlyInteger{Integer: 1})
   173  	nodeW.SetMetadataMap(metadataMapA)
   174  	nodeW.SetFlags(ColorFlag(Red), AbstractFlag())
   175  
   176  	// check attributes:
   177  	Expect(nodeW.GetLabel()).To(Equal(value1Label))
   178  	Expect(nodeW.GetValue()).To(Equal(value1))
   179  	Expect(nodeW.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
   180  	flag := nodeW.GetFlag(ColorFlagIndex)
   181  	Expect(flag).ToNot(BeNil())
   182  	colorFlag := flag.(*ColorFlagImpl)
   183  	Expect(colorFlag.Color).To(Equal(Red))
   184  	Expect(nodeW.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   185  	Expect(nodeW.GetFlag(TemporaryFlagIndex)).To(BeNil())
   186  	Expect(nodeW.GetTargets(relation1)).To(BeEmpty())
   187  	Expect(nodeW.GetSources(relation1)).To(BeEmpty())
   188  
   189  	// not needed to save to have the changes applied
   190  	graphW.Release()
   191  
   192  	// check that the new node was saved correctly
   193  	graphR := graph.Read()
   194  	nodeR := graphR.GetNode(keyA1)
   195  	Expect(nodeR).ToNot(BeNil())
   196  	Expect(nodeR.GetLabel()).To(Equal(value1Label))
   197  	Expect(nodeR.GetValue()).To(Equal(value1))
   198  	Expect(nodeR.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
   199  	flag = nodeR.GetFlag(ColorFlagIndex)
   200  	Expect(flag).ToNot(BeNil())
   201  	colorFlag = flag.(*ColorFlagImpl)
   202  	Expect(colorFlag.Color).To(Equal(Red))
   203  	Expect(nodeR.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   204  	Expect(nodeR.GetFlag(TemporaryFlagIndex)).To(BeNil())
   205  	Expect(nodeR.GetTargets(relation1)).To(BeEmpty())
   206  	Expect(nodeR.GetSources(relation1)).To(BeEmpty())
   207  
   208  	// check metadata
   209  	metaMap := graphR.GetMetadataMap(metadataMapA)
   210  	Expect(metaMap).ToNot(BeNil())
   211  	Expect(metaMap.ListAllNames()).To(Equal([]string{value1Label}))
   212  	intMap := metaMap.(NameToInteger)
   213  	metadata, exists := intMap.LookupByName(value1Label)
   214  	Expect(exists).To(BeTrue())
   215  	Expect(metadata.GetInteger()).To(Equal(1))
   216  	label, metadata, exists := intMap.LookupByIndex(1)
   217  	Expect(exists).To(BeTrue())
   218  	Expect(metadata.GetInteger()).To(Equal(1))
   219  	Expect(label).To(Equal(value1Label))
   220  
   221  	// check history
   222  	flagStats := graphR.GetFlagStats(ColorFlagIndex, prefixASelector)
   223  	Expect(flagStats.TotalCount).To(BeEquivalentTo(1))
   224  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{Red.String(): 1}))
   225  	timeline := graphR.GetNodeTimeline(keyA1)
   226  	Expect(timeline).To(HaveLen(1))
   227  	record := timeline[0]
   228  	Expect(record.Key).To(Equal(keyA1))
   229  	Expect(record.Since.After(startTime)).To(BeTrue())
   230  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   231  	Expect(record.Until.IsZero()).To(BeTrue())
   232  	Expect(record.Label).To(Equal(value1Label))
   233  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   234  	Expect(record.Targets).To(BeEmpty())
   235  	Expect(record.TargetUpdateOnly).To(BeFalse())
   236  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   237  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Red), AbstractFlag()}}))
   238  }
   239  
   240  func TestMultipleNodes(t *testing.T) {
   241  	RegisterTestingT(t)
   242  	testMultipleNodes(false)
   243  }
   244  
   245  func TestMultipleNodesCreatedInPlace(t *testing.T) {
   246  	RegisterTestingT(t)
   247  	testMultipleNodes(true)
   248  }
   249  
   250  func testMultipleNodes(wInPlace bool) {
   251  	startTime := time.Now()
   252  	graph := buildGraph(nil, wInPlace, true, true, selectNodesToBuild(1, 2, 3, 4))
   253  
   254  	// check graph content
   255  	graphR := graph.Read()
   256  
   257  	// -> node1:
   258  	node1 := graphR.GetNode(keyA1)
   259  	Expect(node1).ToNot(BeNil())
   260  	Expect(node1.GetLabel()).To(Equal(value1Label))
   261  	Expect(node1.GetValue()).To(Equal(value1))
   262  	Expect(node1.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
   263  	flag := node1.GetFlag(ColorFlagIndex)
   264  	Expect(flag).ToNot(BeNil())
   265  	colorFlag := flag.(*ColorFlagImpl)
   266  	Expect(colorFlag.Color).To(Equal(Red))
   267  	Expect(node1.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   268  	Expect(node1.GetFlag(TemporaryFlagIndex)).To(BeNil())
   269  	Expect(node1.GetTargets(relation1)).To(HaveLen(1))
   270  	checkTargets(node1, relation1, "node2", keyA2)
   271  	checkSources(node1, relation1, keyB1)
   272  	Expect(node1.GetTargets(relation2)).To(HaveLen(1))
   273  	checkTargets(node1, relation2, "prefixB", keyB1)
   274  	checkSources(node1, relation2, keyA3)
   275  
   276  	// -> node2:
   277  	node2 := graphR.GetNode(keyA2)
   278  	Expect(node2).ToNot(BeNil())
   279  	Expect(node2.GetLabel()).To(Equal(value2Label))
   280  	Expect(node2.GetValue()).To(Equal(value2))
   281  	Expect(node2.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(2))
   282  	flag = node2.GetFlag(ColorFlagIndex)
   283  	Expect(flag).ToNot(BeNil())
   284  	colorFlag = flag.(*ColorFlagImpl)
   285  	Expect(colorFlag.Color).To(Equal(Blue))
   286  	Expect(node2.GetFlag(AbstractFlagIndex)).To(BeNil())
   287  	Expect(node2.GetFlag(TemporaryFlagIndex)).To(BeNil())
   288  	Expect(node2.GetTargets(relation1)).To(HaveLen(1))
   289  	checkTargets(node2, relation1, "node3", keyA3)
   290  	checkSources(node2, relation1, keyA1, keyB1)
   291  	Expect(node2.GetTargets(relation2)).To(HaveLen(0))
   292  	checkSources(node2, relation2, keyA3)
   293  
   294  	// -> node3:
   295  	node3 := graphR.GetNode(keyA3)
   296  	Expect(node3).ToNot(BeNil())
   297  	Expect(node3.GetLabel()).To(Equal(value3Label))
   298  	Expect(node3.GetValue()).To(Equal(value3))
   299  	Expect(node3.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(3))
   300  	flag = node3.GetFlag(ColorFlagIndex)
   301  	Expect(flag).ToNot(BeNil())
   302  	colorFlag = flag.(*ColorFlagImpl)
   303  	Expect(colorFlag.Color).To(Equal(Green))
   304  	Expect(node3.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   305  	Expect(node3.GetFlag(TemporaryFlagIndex)).ToNot(BeNil())
   306  	Expect(node3.GetTargets(relation1)).To(BeEmpty())
   307  	checkSources(node3, relation1, keyA2, keyB1)
   308  	Expect(node3.GetTargets(relation2)).To(HaveLen(2))
   309  	checkTargets(node3, relation2, "node1+node2", keyA1, keyA2)
   310  	checkTargets(node3, relation2, "prefixB", keyB1)
   311  	checkSources(node3, relation2)
   312  
   313  	// -> node4:
   314  	node4 := graphR.GetNode(keyB1)
   315  	Expect(node4).ToNot(BeNil())
   316  	Expect(node4.GetLabel()).To(Equal(value4Label))
   317  	Expect(node4.GetValue()).To(Equal(value4))
   318  	Expect(node4.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
   319  	Expect(node4.GetFlag(ColorFlagIndex)).To(BeNil())
   320  	Expect(node4.GetFlag(AbstractFlagIndex)).To(BeNil())
   321  	Expect(node4.GetFlag(TemporaryFlagIndex)).ToNot(BeNil())
   322  	Expect(node4.GetTargets(relation1)).To(HaveLen(1))
   323  	checkTargets(node4, relation1, "prefixA", keyA1, keyA2, keyA3)
   324  	checkSources(node4, relation1)
   325  	Expect(node4.GetTargets(relation2)).To(HaveLen(1))
   326  	checkTargets(node4, relation2, "non-existing-key")
   327  	checkSources(node4, relation2, keyA1, keyA3)
   328  
   329  	// check metadata
   330  
   331  	// -> metadata for prefixA:
   332  	metaMap := graphR.GetMetadataMap(metadataMapA)
   333  	Expect(metaMap).ToNot(BeNil())
   334  	checkMetadataValues(metaMap, value1Label, value2Label, value3Label)
   335  	intMap := metaMap.(NameToInteger)
   336  	label, metadata, exists := intMap.LookupByIndex(1)
   337  	Expect(exists).To(BeTrue())
   338  	Expect(metadata.GetInteger()).To(Equal(1))
   339  	Expect(label).To(Equal(value1Label))
   340  	label, metadata, exists = intMap.LookupByIndex(2)
   341  	Expect(exists).To(BeTrue())
   342  	Expect(metadata.GetInteger()).To(Equal(2))
   343  	Expect(label).To(Equal(value2Label))
   344  	label, metadata, exists = intMap.LookupByIndex(3)
   345  	Expect(exists).To(BeTrue())
   346  	Expect(metadata.GetInteger()).To(Equal(3))
   347  	Expect(label).To(Equal(value3Label))
   348  
   349  	// -> metadata for prefixB:
   350  	metaMap = graphR.GetMetadataMap(metadataMapB)
   351  	Expect(metaMap).ToNot(BeNil())
   352  	checkMetadataValues(metaMap, value4Label)
   353  	intMap = metaMap.(NameToInteger)
   354  	label, metadata, exists = intMap.LookupByIndex(1)
   355  	Expect(exists).To(BeTrue())
   356  	Expect(metadata.GetInteger()).To(Equal(1))
   357  	Expect(label).To(Equal(value4Label))
   358  
   359  	// check history
   360  
   361  	// -> flags:
   362  	flagStats := graphR.GetFlagStats(ColorFlagIndex, prefixASelector)
   363  	Expect(flagStats.TotalCount).To(BeEquivalentTo(3))
   364  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{
   365  		Red.String():   1,
   366  		Blue.String():  1,
   367  		Green.String(): 1,
   368  	}))
   369  	flagStats = graphR.GetFlagStats(ColorFlagIndex, prefixBSelector)
   370  	Expect(flagStats.TotalCount).To(BeEquivalentTo(0))
   371  	Expect(flagStats.PerValueCount).To(BeEmpty())
   372  	flagStats = graphR.GetFlagStats(AbstractFlagIndex, nil)
   373  	Expect(flagStats.TotalCount).To(BeEquivalentTo(2))
   374  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{"": 2}))
   375  	flagStats = graphR.GetFlagStats(TemporaryFlagIndex, nil)
   376  	Expect(flagStats.TotalCount).To(BeEquivalentTo(2))
   377  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{"": 2}))
   378  
   379  	// -> timeline node1:
   380  	timeline := graphR.GetNodeTimeline(keyA1)
   381  	Expect(timeline).To(HaveLen(1))
   382  	record := timeline[0]
   383  	Expect(record.Key).To(Equal(keyA1))
   384  	Expect(record.Since.After(startTime)).To(BeTrue())
   385  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   386  	Expect(record.Until.IsZero()).To(BeTrue())
   387  	Expect(record.Label).To(Equal(value1Label))
   388  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   389  	Expect(record.Targets).To(HaveLen(2))
   390  	checkRecordedTargets(record.Targets, relation1, 1, "node2", keyA2)
   391  	checkRecordedTargets(record.Targets, relation2, 1, "prefixB", keyB1)
   392  	Expect(record.TargetUpdateOnly).To(BeFalse())
   393  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   394  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Red), AbstractFlag()}}))
   395  
   396  	// -> timeline node2:
   397  	timeline = graphR.GetNodeTimeline(keyA2)
   398  	Expect(timeline).To(HaveLen(1))
   399  	record = timeline[0]
   400  	Expect(record.Key).To(Equal(keyA2))
   401  	Expect(record.Since.After(startTime)).To(BeTrue())
   402  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   403  	Expect(record.Until.IsZero()).To(BeTrue())
   404  	Expect(record.Label).To(Equal(value2Label))
   405  	Expect(proto.Equal(record.Value, RecordProtoMessage(value2))).To(BeTrue())
   406  	Expect(record.Targets).To(HaveLen(1))
   407  	checkRecordedTargets(record.Targets, relation1, 1, "node3", keyA3)
   408  	Expect(record.TargetUpdateOnly).To(BeFalse())
   409  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"2"}}))
   410  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Blue)}}))
   411  
   412  	// -> timeline node3:
   413  	timeline = graphR.GetNodeTimeline(keyA3)
   414  	Expect(timeline).To(HaveLen(1))
   415  	record = timeline[0]
   416  	Expect(record.Key).To(Equal(keyA3))
   417  	Expect(record.Since.After(startTime)).To(BeTrue())
   418  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   419  	Expect(record.Until.IsZero()).To(BeTrue())
   420  	Expect(record.Label).To(Equal(value3Label))
   421  	Expect(proto.Equal(record.Value, RecordProtoMessage(value3))).To(BeTrue())
   422  	Expect(record.Targets).To(HaveLen(2))
   423  	checkRecordedTargets(record.Targets, relation2, 2, "node1+node2", keyA1, keyA2)
   424  	checkRecordedTargets(record.Targets, relation2, 2, "prefixB", keyB1)
   425  	Expect(record.TargetUpdateOnly).To(BeFalse())
   426  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"3"}}))
   427  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Green), AbstractFlag(), TemporaryFlag()}}))
   428  
   429  	// -> timeline node4:
   430  	timeline = graphR.GetNodeTimeline(keyB1)
   431  	Expect(timeline).To(HaveLen(1))
   432  	record = timeline[0]
   433  	Expect(record.Key).To(Equal(keyB1))
   434  	Expect(record.Since.After(startTime)).To(BeTrue())
   435  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   436  	Expect(record.Until.IsZero()).To(BeTrue())
   437  	Expect(record.Label).To(Equal(value4Label))
   438  	Expect(proto.Equal(record.Value, RecordProtoMessage(value4))).To(BeTrue())
   439  	Expect(record.Targets).To(HaveLen(2))
   440  	checkRecordedTargets(record.Targets, relation1, 1, "prefixA", keyA1, keyA2, keyA3)
   441  	checkRecordedTargets(record.Targets, relation2, 1, "non-existing-key")
   442  	Expect(record.TargetUpdateOnly).To(BeFalse())
   443  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   444  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{flags(TemporaryFlag())}))
   445  
   446  	// check snapshot:
   447  	// -> before the changes
   448  	records := graphR.GetSnapshot(startTime)
   449  	checkRecordedNodes(records)
   450  	// -> after the changes
   451  	records = graphR.GetSnapshot(time.Now())
   452  	checkRecordedNodes(records, keyA1, keyA2, keyA3, keyB1)
   453  
   454  	graphR.Release()
   455  }
   456  
   457  func TestSelectors(t *testing.T) {
   458  	RegisterTestingT(t)
   459  
   460  	graph := buildGraph(nil, false, true, true, selectNodesToBuild(1, 2, 3, 4))
   461  	graphR := graph.Read()
   462  
   463  	// test key selector
   464  	checkNodes(graphR.GetNodes(prefixASelector), keyA1, keyA2, keyA3)
   465  	checkNodes(graphR.GetNodes(prefixBSelector), keyB1)
   466  	checkNodes(graphR.GetNodes(keySelector(keyA1, keyB1)), keyA1, keyB1)
   467  	checkNodes(graphR.GetNodes(func(key string) bool { return false }))
   468  
   469  	// test flag selectors
   470  	checkNodes(graphR.GetNodes(nil, WithFlags(AnyColorFlag())), keyA1, keyA2, keyA3)
   471  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Red))), keyA1)
   472  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Blue))), keyA2)
   473  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Green))), keyA3)
   474  	checkNodes(graphR.GetNodes(nil, WithFlags(AnyColorFlag()), WithoutFlags(TemporaryFlag())), keyA1, keyA2)
   475  	checkNodes(graphR.GetNodes(nil, WithoutFlags(TemporaryFlag())), keyA1, keyA2)
   476  	checkNodes(graphR.GetNodes(nil, WithoutFlags(AbstractFlag())), keyA2, keyB1)
   477  
   478  	// test combination of key selector and flag selector
   479  	checkNodes(graphR.GetNodes(prefixASelector, WithoutFlags(AbstractFlag())), keyA2)
   480  	checkNodes(graphR.GetNodes(prefixBSelector, WithoutFlags(TemporaryFlag())))
   481  	checkNodes(graphR.GetNodes(keySelector(keyA1, keyB1), WithFlags(AnyColorFlag())), keyA1)
   482  
   483  	// change flags and re-test flag selectors
   484  	graphR.Release()
   485  	graphW := graph.Write(false, false)
   486  	graphW.SetNode(keyA1).SetFlags(ColorFlag(Green), TemporaryFlag())
   487  	graphW.SetNode(keyA1).DelFlags(AbstractFlagIndex)
   488  	graphW.SetNode(keyA3).DelFlags(ColorFlagIndex)
   489  	graphW.Save()
   490  	graphW.Release()
   491  
   492  	graphR = graph.Read()
   493  	checkNodes(graphR.GetNodes(nil, WithFlags(AnyColorFlag())), keyA1, keyA2)
   494  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Red))))
   495  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Blue))), keyA2)
   496  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Green))), keyA1)
   497  	checkNodes(graphR.GetNodes(nil, WithFlags(AnyColorFlag()), WithoutFlags(TemporaryFlag())), keyA2)
   498  	checkNodes(graphR.GetNodes(nil, WithoutFlags(TemporaryFlag())), keyA2)
   499  	checkNodes(graphR.GetNodes(nil, WithoutFlags(AbstractFlag())), keyA1, keyA2, keyB1)
   500  	graphR.Release()
   501  }
   502  
   503  func TestNodeRemoval(t *testing.T) {
   504  	RegisterTestingT(t)
   505  
   506  	startTime := time.Now()
   507  	graph := buildGraph(nil, false, true, true, selectNodesToBuild(1, 2, 3, 4))
   508  
   509  	// delete node2 & node 4
   510  	delTime := time.Now()
   511  	graphW := graph.Write(false, true)
   512  	graphW.DeleteNode(keyA2)
   513  	Expect(graphW.ValidateEdges()).To(BeNil())
   514  	graphW.DeleteNode(keyB1)
   515  	Expect(graphW.ValidateEdges()).To(BeNil())
   516  	graphW.Save()
   517  	graphW.Release()
   518  
   519  	// check graph content
   520  	graphR := graph.Read()
   521  
   522  	// -> node1:
   523  	node1 := graphR.GetNode(keyA1)
   524  	Expect(node1).ToNot(BeNil())
   525  	Expect(node1.GetLabel()).To(Equal(value1Label))
   526  	Expect(node1.GetValue()).To(Equal(value1))
   527  	Expect(node1.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(1))
   528  	flag := node1.GetFlag(ColorFlagIndex)
   529  	Expect(flag).ToNot(BeNil())
   530  	colorFlag := flag.(*ColorFlagImpl)
   531  	Expect(colorFlag.Color).To(Equal(Red))
   532  	Expect(node1.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   533  	Expect(node1.GetFlag(TemporaryFlagIndex)).To(BeNil())
   534  	Expect(node1.GetTargets(relation1)).To(HaveLen(1))
   535  	checkTargets(node1, relation1, "node2")
   536  	checkSources(node1, relation1)
   537  	Expect(node1.GetTargets(relation2)).To(HaveLen(1))
   538  	checkTargets(node1, relation2, "prefixB")
   539  	checkSources(node1, relation2, keyA3)
   540  
   541  	// -> node2:
   542  	node2 := graphR.GetNode(keyA2)
   543  	Expect(node2).To(BeNil())
   544  
   545  	// -> node3:
   546  	node3 := graphR.GetNode(keyA3)
   547  	Expect(node3).ToNot(BeNil())
   548  	Expect(node3.GetLabel()).To(Equal(value3Label))
   549  	Expect(node3.GetValue()).To(Equal(value3))
   550  	Expect(node3.GetMetadata().(MetaWithInteger).GetInteger()).To(Equal(3))
   551  	flag = node3.GetFlag(ColorFlagIndex)
   552  	Expect(flag).ToNot(BeNil())
   553  	colorFlag = flag.(*ColorFlagImpl)
   554  	Expect(colorFlag.Color).To(Equal(Green))
   555  	Expect(node3.GetFlag(AbstractFlagIndex)).ToNot(BeNil())
   556  	Expect(node3.GetFlag(TemporaryFlagIndex)).ToNot(BeNil())
   557  	Expect(node3.GetTargets(relation1)).To(BeEmpty())
   558  	checkSources(node3, relation1)
   559  	Expect(node3.GetTargets(relation2)).To(HaveLen(2))
   560  	checkTargets(node3, relation2, "node1+node2", keyA1)
   561  	checkTargets(node3, relation2, "prefixB")
   562  	checkSources(node3, relation2)
   563  
   564  	// -> node4:
   565  	node4 := graphR.GetNode(keyB1)
   566  	Expect(node4).To(BeNil())
   567  
   568  	// check metadata
   569  
   570  	// -> metadata for prefixA:
   571  	metaMap := graphR.GetMetadataMap(metadataMapA)
   572  	Expect(metaMap).ToNot(BeNil())
   573  	checkMetadataValues(metaMap, value1Label, value3Label)
   574  	intMap := metaMap.(NameToInteger)
   575  	label, metadata, exists := intMap.LookupByIndex(1)
   576  	Expect(exists).To(BeTrue())
   577  	Expect(metadata.GetInteger()).To(Equal(1))
   578  	Expect(label).To(Equal(value1Label))
   579  	_, _, exists = intMap.LookupByIndex(2)
   580  	Expect(exists).To(BeFalse())
   581  	label, metadata, exists = intMap.LookupByIndex(3)
   582  	Expect(exists).To(BeTrue())
   583  	Expect(metadata.GetInteger()).To(Equal(3))
   584  	Expect(label).To(Equal(value3Label))
   585  
   586  	// -> metadata for prefixB:
   587  	metaMap = graphR.GetMetadataMap(metadataMapB)
   588  	Expect(metaMap).ToNot(BeNil())
   589  	checkMetadataValues(metaMap)
   590  	intMap = metaMap.(NameToInteger)
   591  	_, _, exists = intMap.LookupByIndex(1)
   592  	Expect(exists).To(BeFalse())
   593  
   594  	// check history
   595  
   596  	// -> flags:
   597  	flagStats := graphR.GetFlagStats(ColorFlagIndex, prefixASelector)
   598  	Expect(flagStats.TotalCount).To(BeEquivalentTo(3))
   599  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{
   600  		Red.String():   1,
   601  		Blue.String():  1,
   602  		Green.String(): 1,
   603  	}))
   604  	flagStats = graphR.GetFlagStats(ColorFlagIndex, prefixBSelector)
   605  	Expect(flagStats.TotalCount).To(BeEquivalentTo(0))
   606  	Expect(flagStats.PerValueCount).To(BeEmpty())
   607  	flagStats = graphR.GetFlagStats(AbstractFlagIndex, nil)
   608  	Expect(flagStats.TotalCount).To(BeEquivalentTo(2))
   609  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{"": 2}))
   610  	flagStats = graphR.GetFlagStats(TemporaryFlagIndex, nil)
   611  	Expect(flagStats.TotalCount).To(BeEquivalentTo(2))
   612  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{"": 2}))
   613  
   614  	// -> timeline node1:
   615  	timeline := graphR.GetNodeTimeline(keyA1)
   616  	Expect(timeline).To(HaveLen(2))
   617  	//   -> prev record
   618  	record := timeline[0]
   619  	Expect(record.Key).To(Equal(keyA1))
   620  	Expect(record.Since.After(startTime)).To(BeTrue())
   621  	Expect(record.Since.Before(delTime)).To(BeTrue())
   622  	Expect(record.Until.After(delTime)).To(BeTrue())
   623  	Expect(record.Until.Before(time.Now())).To(BeTrue())
   624  	Expect(record.Label).To(Equal(value1Label))
   625  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   626  	Expect(record.Targets).To(HaveLen(2))
   627  	checkRecordedTargets(record.Targets, relation1, 1, "node2", keyA2)
   628  	checkRecordedTargets(record.Targets, relation2, 1, "prefixB", keyB1)
   629  	Expect(record.TargetUpdateOnly).To(BeFalse())
   630  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   631  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Red), AbstractFlag()}}))
   632  	//   -> new record
   633  	record = timeline[1]
   634  	Expect(record.Key).To(Equal(keyA1))
   635  	Expect(record.Since.After(delTime)).To(BeTrue())
   636  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   637  	Expect(record.Until.IsZero()).To(BeTrue())
   638  	Expect(record.Label).To(Equal(value1Label))
   639  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   640  	Expect(record.Targets).To(HaveLen(2))
   641  	checkRecordedTargets(record.Targets, relation1, 1, "node2")
   642  	checkRecordedTargets(record.Targets, relation2, 1, "prefixB")
   643  	Expect(record.TargetUpdateOnly).To(BeTrue())
   644  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   645  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Red), AbstractFlag()}}))
   646  
   647  	// -> timeline node2:
   648  	timeline = graphR.GetNodeTimeline(keyA2)
   649  	Expect(timeline).To(HaveLen(1))
   650  	//   -> old record
   651  	record = timeline[0]
   652  	Expect(record.Key).To(Equal(keyA2))
   653  	Expect(record.Since.After(startTime)).To(BeTrue())
   654  	Expect(record.Since.Before(delTime)).To(BeTrue())
   655  	Expect(record.Until.After(delTime)).To(BeTrue())
   656  	Expect(record.Until.Before(time.Now())).To(BeTrue())
   657  	Expect(record.Label).To(Equal(value2Label))
   658  	Expect(proto.Equal(record.Value, RecordProtoMessage(value2))).To(BeTrue())
   659  	Expect(record.Targets).To(HaveLen(1))
   660  	checkRecordedTargets(record.Targets, relation1, 1, "node3", keyA3)
   661  	Expect(record.TargetUpdateOnly).To(BeFalse())
   662  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"2"}}))
   663  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Blue)}}))
   664  
   665  	// -> timeline node3:
   666  	timeline = graphR.GetNodeTimeline(keyA3)
   667  	Expect(timeline).To(HaveLen(2))
   668  	//   -> old record
   669  	record = timeline[0]
   670  	Expect(record.Key).To(Equal(keyA3))
   671  	Expect(record.Since.After(startTime)).To(BeTrue())
   672  	Expect(record.Since.Before(delTime)).To(BeTrue())
   673  	Expect(record.Until.After(delTime)).To(BeTrue())
   674  	Expect(record.Until.Before(time.Now())).To(BeTrue())
   675  	Expect(record.Label).To(Equal(value3Label))
   676  	Expect(proto.Equal(record.Value, RecordProtoMessage(value3))).To(BeTrue())
   677  	Expect(record.Targets).To(HaveLen(2))
   678  	checkRecordedTargets(record.Targets, relation2, 2, "node1+node2", keyA1, keyA2)
   679  	checkRecordedTargets(record.Targets, relation2, 2, "prefixB", keyB1)
   680  	Expect(record.TargetUpdateOnly).To(BeFalse())
   681  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"3"}}))
   682  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Green), AbstractFlag(), TemporaryFlag()}}))
   683  	//   -> new record
   684  	record = timeline[1]
   685  	Expect(record.Key).To(Equal(keyA3))
   686  	Expect(record.Since.After(delTime)).To(BeTrue())
   687  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   688  	Expect(record.Until.IsZero()).To(BeTrue())
   689  	Expect(record.Label).To(Equal(value3Label))
   690  	Expect(proto.Equal(record.Value, RecordProtoMessage(value3))).To(BeTrue())
   691  	Expect(record.Targets).To(HaveLen(2))
   692  	checkRecordedTargets(record.Targets, relation2, 2, "node1+node2", keyA1)
   693  	checkRecordedTargets(record.Targets, relation2, 2, "prefixB")
   694  	Expect(record.TargetUpdateOnly).To(BeTrue())
   695  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"3"}}))
   696  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Green), AbstractFlag(), TemporaryFlag()}}))
   697  
   698  	// -> timeline node4:
   699  	//   -> old record
   700  	timeline = graphR.GetNodeTimeline(keyB1)
   701  	Expect(timeline).To(HaveLen(1))
   702  	record = timeline[0]
   703  	Expect(record.Key).To(Equal(keyB1))
   704  	Expect(record.Since.After(startTime)).To(BeTrue())
   705  	Expect(record.Since.Before(delTime)).To(BeTrue())
   706  	Expect(record.Until.After(delTime)).To(BeTrue())
   707  	Expect(record.Until.Before(time.Now())).To(BeTrue())
   708  	Expect(record.Label).To(Equal(value4Label))
   709  	Expect(proto.Equal(record.Value, RecordProtoMessage(value4))).To(BeTrue())
   710  	Expect(record.Targets).To(HaveLen(2))
   711  	checkRecordedTargets(record.Targets, relation1, 1, "prefixA", keyA1, keyA2, keyA3)
   712  	checkRecordedTargets(record.Targets, relation2, 1, "non-existing-key")
   713  	Expect(record.TargetUpdateOnly).To(BeFalse())
   714  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   715  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{flags(TemporaryFlag())}))
   716  
   717  	// check snapshot:
   718  	records := graphR.GetSnapshot(time.Now())
   719  	checkRecordedNodes(records, keyA1, keyA3)
   720  
   721  	graphR.Release()
   722  }
   723  
   724  func TestNodeTimeline(t *testing.T) {
   725  	RegisterTestingT(t)
   726  
   727  	// add node1
   728  	startTime := time.Now()
   729  	graph := buildGraph(nil, false, true, true, selectNodesToBuild(1))
   730  
   731  	// delete node1
   732  	delTime := time.Now()
   733  	graphW := graph.Write(false, true)
   734  	graphW.DeleteNode(keyA1)
   735  	graphW.Save()
   736  	graphW.Release()
   737  
   738  	// re-create node1, but without recording
   739  	buildGraph(graph, false, false, false, selectNodesToBuild(1))
   740  
   741  	// change flags
   742  	changeTime1 := time.Now()
   743  	graphW = graph.Write(false, true)
   744  	node := graphW.SetNode(keyA1)
   745  	node.SetFlags(ColorFlag(Blue))
   746  	graphW.Save()
   747  	graphW.Release()
   748  
   749  	// change metadata + flags
   750  	changeTime2 := time.Now()
   751  	graphW = graph.Write(false, true)
   752  	node = graphW.SetNode(keyA1)
   753  	node.SetFlags(TemporaryFlag())
   754  	node.DelFlags(AbstractFlagIndex)
   755  	node.SetMetadata(&OnlyInteger{Integer: 2})
   756  	graphW.Save()
   757  	graphW.Release()
   758  
   759  	// check history
   760  	graphR := graph.Read()
   761  
   762  	// -> flags:
   763  	flagStats := graphR.GetFlagStats(ColorFlagIndex, nil)
   764  	Expect(flagStats.TotalCount).To(BeEquivalentTo(3))
   765  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{
   766  		Red.String():  1,
   767  		Blue.String(): 2,
   768  	}))
   769  	flagStats = graphR.GetFlagStats(AbstractFlagIndex, nil)
   770  	Expect(flagStats.TotalCount).To(BeEquivalentTo(2))
   771  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{"": 2}))
   772  	flagStats = graphR.GetFlagStats(TemporaryFlagIndex, nil)
   773  	Expect(flagStats.TotalCount).To(BeEquivalentTo(1))
   774  	Expect(flagStats.PerValueCount).To(BeEquivalentTo(map[string]uint{"": 1}))
   775  
   776  	// -> timeline node1:
   777  	timeline := graphR.GetNodeTimeline(keyA1)
   778  	Expect(timeline).To(HaveLen(3))
   779  	//   -> first record
   780  	record := timeline[0]
   781  	Expect(record.Key).To(Equal(keyA1))
   782  	Expect(record.Since.After(startTime)).To(BeTrue())
   783  	Expect(record.Since.Before(delTime)).To(BeTrue())
   784  	Expect(record.Until.After(delTime)).To(BeTrue())
   785  	Expect(record.Until.Before(changeTime1)).To(BeTrue())
   786  	Expect(record.Label).To(Equal(value1Label))
   787  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   788  	Expect(record.Targets).To(HaveLen(2))
   789  	checkRecordedTargets(record.Targets, relation1, 1, "node2")
   790  	checkRecordedTargets(record.Targets, relation2, 1, "prefixB")
   791  	Expect(record.TargetUpdateOnly).To(BeFalse())
   792  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   793  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{[maxFlags]Flag{ColorFlag(Red), AbstractFlag()}}))
   794  	//   -> second record
   795  	record = timeline[1]
   796  	Expect(record.Key).To(Equal(keyA1))
   797  	Expect(record.Since.After(changeTime1)).To(BeTrue())
   798  	Expect(record.Since.Before(changeTime2)).To(BeTrue())
   799  	Expect(record.Until.After(changeTime2)).To(BeTrue())
   800  	Expect(record.Until.Before(time.Now())).To(BeTrue())
   801  	Expect(record.Label).To(Equal(value1Label))
   802  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   803  	Expect(record.Targets).To(HaveLen(2))
   804  	checkRecordedTargets(record.Targets, relation1, 1, "node2")
   805  	checkRecordedTargets(record.Targets, relation2, 1, "prefixB")
   806  	Expect(record.TargetUpdateOnly).To(BeFalse())
   807  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"1"}}))
   808  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{flags(AbstractFlag(), ColorFlag(Blue))}))
   809  	//   -> third record
   810  	record = timeline[2]
   811  	Expect(record.Key).To(Equal(keyA1))
   812  	Expect(record.Since.After(changeTime2)).To(BeTrue())
   813  	Expect(record.Since.Before(time.Now())).To(BeTrue())
   814  	Expect(record.Until.IsZero()).To(BeTrue())
   815  	Expect(record.Label).To(Equal(value1Label))
   816  	Expect(proto.Equal(record.Value, RecordProtoMessage(value1))).To(BeTrue())
   817  	Expect(record.Targets).To(HaveLen(2))
   818  	checkRecordedTargets(record.Targets, relation1, 1, "node2")
   819  	checkRecordedTargets(record.Targets, relation2, 1, "prefixB")
   820  	Expect(record.TargetUpdateOnly).To(BeFalse())
   821  	Expect(record.MetadataFields).To(BeEquivalentTo(map[string][]string{IntegerKey: {"2"}}))
   822  	Expect(record.Flags).To(BeEquivalentTo(RecordedFlags{flags(ColorFlag(Blue), TemporaryFlag())}))
   823  
   824  	graphR.Release()
   825  }
   826  
   827  func TestNodeMetadata(t *testing.T) {
   828  	RegisterTestingT(t)
   829  
   830  	// add node1-node3
   831  	graph := buildGraph(nil, false, true, true, selectNodesToBuild(1, 2, 3))
   832  
   833  	// check metadata
   834  	graphR := graph.Read()
   835  
   836  	// -> metadata for prefixA:
   837  	metaMap := graphR.GetMetadataMap(metadataMapA)
   838  	Expect(metaMap).ToNot(BeNil())
   839  	checkMetadataValues(metaMap, value1Label, value2Label, value3Label)
   840  	intMap := metaMap.(NameToInteger)
   841  	label, metadata, exists := intMap.LookupByIndex(1)
   842  	Expect(exists).To(BeTrue())
   843  	Expect(metadata.GetInteger()).To(Equal(1))
   844  	Expect(label).To(Equal(value1Label))
   845  	label, metadata, exists = intMap.LookupByIndex(2)
   846  	Expect(exists).To(BeTrue())
   847  	Expect(metadata.GetInteger()).To(Equal(2))
   848  	Expect(label).To(Equal(value2Label))
   849  	label, metadata, exists = intMap.LookupByIndex(3)
   850  	Expect(exists).To(BeTrue())
   851  	Expect(metadata.GetInteger()).To(Equal(3))
   852  	Expect(label).To(Equal(value3Label))
   853  
   854  	// -> metadata for prefixB:
   855  	metaMap = graphR.GetMetadataMap(metadataMapB)
   856  	Expect(metaMap).ToNot(BeNil())
   857  	checkMetadataValues(metaMap)
   858  	intMap = metaMap.(NameToInteger)
   859  	_, _, exists = intMap.LookupByIndex(1)
   860  	Expect(exists).To(BeFalse())
   861  	graphR.Release()
   862  
   863  	// add node4, remove node1 & change metadata for node2
   864  	buildGraph(graph, false, true, false, selectNodesToBuild(4))
   865  	graphW := graph.Write(false, true)
   866  	graphW.DeleteNode(keyA1)
   867  	graphW.SetNode(keyA2).SetMetadata(&OnlyInteger{Integer: 4})
   868  	graphW.Save()
   869  	graphW.Release()
   870  
   871  	// check metadata after the changes
   872  	graphR = graph.Read()
   873  
   874  	// -> metadata for prefixA:
   875  	metaMap = graphR.GetMetadataMap(metadataMapA)
   876  	Expect(metaMap).ToNot(BeNil())
   877  	checkMetadataValues(metaMap, value2Label, value3Label)
   878  	intMap = metaMap.(NameToInteger)
   879  	_, _, exists = intMap.LookupByIndex(1)
   880  	Expect(exists).To(BeFalse())
   881  	_, _, exists = intMap.LookupByIndex(2)
   882  	Expect(exists).To(BeFalse())
   883  	label, metadata, exists = intMap.LookupByIndex(4)
   884  	Expect(exists).To(BeTrue())
   885  	Expect(metadata.GetInteger()).To(Equal(4))
   886  	Expect(label).To(Equal(value2Label))
   887  	label, metadata, exists = intMap.LookupByIndex(3)
   888  	Expect(exists).To(BeTrue())
   889  	Expect(metadata.GetInteger()).To(Equal(3))
   890  	Expect(label).To(Equal(value3Label))
   891  
   892  	// -> metadata for prefixB:
   893  	metaMap = graphR.GetMetadataMap(metadataMapB)
   894  	Expect(metaMap).ToNot(BeNil())
   895  	checkMetadataValues(metaMap, value4Label)
   896  	intMap = metaMap.(NameToInteger)
   897  	label, metadata, exists = intMap.LookupByIndex(1)
   898  	Expect(exists).To(BeTrue())
   899  	Expect(metadata.GetInteger()).To(Equal(1))
   900  	Expect(label).To(Equal(value4Label))
   901  	graphR.Release()
   902  }
   903  
   904  func TestReuseNodeAfterSave(t *testing.T) {
   905  	RegisterTestingT(t)
   906  
   907  	graph := NewGraph(commonOpts)
   908  	graphW := graph.Write(false, true)
   909  
   910  	// add new node
   911  	nodeW := graphW.SetNode(keyA1)
   912  	nodeW.SetValue(value1)
   913  	nodeW.SetFlags(ColorFlag(Red))
   914  
   915  	// save new node
   916  	graphW.Save()
   917  
   918  	// keep using the same node handle
   919  	nodeW.SetFlags(AbstractFlag())
   920  
   921  	// save changes
   922  	graphW.Save()
   923  
   924  	// get new handle
   925  	nodeW = graphW.SetNode(keyA1)
   926  	nodeW.SetFlags(TemporaryFlag())
   927  
   928  	// save changes
   929  	graphW.Save()
   930  	graphW.Release()
   931  
   932  	// check that all 3 flags are applied
   933  	graphR := graph.Read()
   934  	checkNodes(graphR.GetNodes(nil, WithFlags(ColorFlag(Red), AbstractFlag(), TemporaryFlag())), keyA1)
   935  	graphR.Release()
   936  }