| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311 | /* * EliasDB * * Copyright 2016 Matthias Ladkau. All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */package graphimport (	"errors"	"fmt"	"strings"	"testing"	"devt.de/krotik/eliasdb/graph/data"	"devt.de/krotik/eliasdb/graph/graphstorage"	"devt.de/krotik/eliasdb/graph/util"	"devt.de/krotik/eliasdb/hash"	"devt.de/krotik/eliasdb/storage")func TestSimpleGraphStorage(t *testing.T) {	if !RunDiskStorageTests {		return	}	dgs, err := graphstorage.NewDiskGraphStorage(GraphManagerTestDBDir3, false)	if err != nil {		t.Error(err)		return	}	gm := newGraphManagerNoRules(dgs)	node1 := data.NewGraphNode()	node1.SetAttr("key", "123")	node1.SetAttr("kind", "mykind")	node1.SetAttr("Name", "Node1")	gm.StoreNode("main", node1)	node2 := data.NewGraphNode()	node2.SetAttr("key", "456")	node2.SetAttr("kind", "mykind")	node2.SetAttr("Name", "Node2")	gm.StoreNode("main", node2)	node3 := data.NewGraphNode()	node3.SetAttr("key", "789")	node3.SetAttr("kind", "mykind")	node3.SetAttr("Name", "Node3")	gm.StoreNode("main", node3)	edge := data.NewGraphEdge()	edge.SetAttr("key", "abc")	edge.SetAttr("kind", "myedge")	edge.SetAttr(data.EdgeEnd1Key, node1.Key())	edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())	edge.SetAttr(data.EdgeEnd1Role, "node1")	edge.SetAttr(data.EdgeEnd1Cascading, true)	edge.SetAttr(data.EdgeEnd2Key, node2.Key())	edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())	edge.SetAttr(data.EdgeEnd2Role, "node2")	edge.SetAttr(data.EdgeEnd2Cascading, false)	err = gm.StoreEdge("main", edge)	if err != nil {		t.Error(err)	}	if gm.EdgeCount("myedge") != 1 {		t.Error("Unexpected edge count")		return	}	// Check that the correct data has been written	edgeTree, _ := gm.getEdgeStorageHTree("main", "myedge", false)	keyAttrs := PrefixNSAttrs + edge.Key()	val, err := edgeTree.Get([]byte(keyAttrs))	if err != nil || val == nil {		t.Error("Unexpected result:", val, val)		return	}	if res := len(val.([]string)); res != 8 {		t.Error("Unexpected number of stored attributes:", res)	}	keyAttr := PrefixNSAttr + edge.Key() + gm.nm.Encode32(data.EdgeEnd2Key, false)	if val, err := edgeTree.Get([]byte(keyAttr)); err != nil || val != node2.Key() {		t.Error("Unexpected result:", err, val)		return	}	_, nodeTree, _ := gm.getNodeStorageHTree("main", "mykind", false)	specMap, err := nodeTree.Get([]byte(PrefixNSSpecs + node2.Key()))	if err != nil || specMap == nil {		t.Error("Unexpected result:", specMap, err)	}	if len(specMap.(map[string]string)) != 1 {		t.Error("Unexpected size of spec map")		return	}	if _, ok := specMap.(map[string]string)[gm.nm.Encode16(edge.End2Role(), false)+gm.nm.Encode16(edge.Kind(), false)+		gm.nm.Encode16(edge.End1Role(), false)+gm.nm.Encode16(edge.End1Kind(), false)]; !ok {		t.Error("Unexpected content of spec map")		return	}	fetchedEdge, err := gm.FetchEdge("main", edge.Key(), edge.Kind())	if err != nil {		t.Error(err)		return	}	if !data.NodeCompare(edge, fetchedEdge, nil) {		t.Error("Fetched edge should contain the same data as the stored edge")		return	}	// Try to change one of the endpoints	edge.SetAttr(data.EdgeEnd1Key, node3.Key())	err = gm.StoreEdge("main", edge)	if err.Error() != "GraphError: Invalid data (Cannot update endpoints or spec of existing edge: abc)" {		t.Error(err)		return	}	// Try again to make sure it was not updated	edge.SetAttr(data.EdgeEnd1Key, node3.Key())	err = gm.StoreEdge("main", edge)	if err.Error() != "GraphError: Invalid data (Cannot update endpoints or spec of existing edge: abc)" {		t.Error(err)	}	edge.SetAttr(data.EdgeEnd1Key, node1.Key())	edge.SetAttr("Name", "Test")	err = gm.StoreEdge("main", edge)	if err != nil {		t.Error(err)		return	}	fetchedEdge, err = gm.FetchEdge("main", edge.Key(), edge.Kind())	if err != nil {		t.Error(err)		return	}	if fetchedEdge.Attr("Name") != "Test" {		t.Error("Unexpected attribute value")		return	}	if gm.EdgeCount("myedge") != 1 {		t.Error("Unexpected edge count")		return	}	// Store more edges	edge2 := data.NewGraphEdge()	edge2.SetAttr("key", "def")	edge2.SetAttr("kind", "myedge")	edge2.SetAttr(data.EdgeEnd1Key, node1.Key())	edge2.SetAttr(data.EdgeEnd1Kind, node1.Kind())	edge2.SetAttr(data.EdgeEnd1Role, "node1")	edge2.SetAttr(data.EdgeEnd1Cascading, true)	edge2.SetAttr(data.EdgeEnd2Key, node3.Key())	edge2.SetAttr(data.EdgeEnd2Kind, node3.Kind())	edge2.SetAttr(data.EdgeEnd2Role, "node2")	edge2.SetAttr(data.EdgeEnd2Cascading, false)	err = gm.StoreEdge("main", edge2)	if err != nil {		t.Error(err)		return	}	// Spec map has still one entry	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node1.Key()))	if err != nil || specMap == nil {		t.Error("Unexpected result:", specMap, err)	}	if len(specMap.(map[string]string)) != 1 {		t.Error("Unexpected size of spec map")		return	}	if gm.EdgeCount("myedge") != 2 {		t.Error("Unexpected edge count")		return	}	edge2.SetAttr("key", "ghi")	err = gm.StoreEdge("main", edge2)	if err != nil {		t.Error(err)		return	}	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node1.Key()))	if err != nil || specMap == nil {		t.Error("Unexpected result:", specMap, err)	}	spec1 := gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.Kind(), true) +		gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.End2Kind(), true)	edgeInfo1Key := PrefixNSEdge + edge.End1Key() + spec1	obj, err := nodeTree.Get([]byte(edgeInfo1Key))	targetMap := obj.(map[string]*edgeTargetInfo)	// There should be 3 entries in the target map at this point	if len(targetMap) != 3 {		t.Error("Unexpected size of target map")		return	}	testInfo := targetMap["def"]	if !testInfo.CascadeToTarget {		t.Error("Edge should cascade to target from end1")		return	}	if testInfo.TargetNodeKey != node3.Key() {		t.Error("Edge should go to node3")		return	}	if testInfo.TargetNodeKind != node3.Kind() {		t.Error("Edge should go to node3")		return	}	if len(specMap.(map[string]string)) != 1 {		t.Error("Unexpected size of spec map")		return	}	// At this point there are 3 relationships in the db:	// node1 -> node2 [abc]	// node1 -> node3 [def]	// node1 -> node3 [ghi]	if gm.EdgeCount("myedge") != 3 {		t.Error("Unexpected edge count")		return	}	// Test index lookup	iq, _ := gm.EdgeIndexQuery("main", "myedge")	res, _ := iq.LookupValue("Name", "test")	if fmt.Sprint(res) != "["+edge.Key()+"]" {		t.Error("Unexpected result:", res)		return	}	// Test removal	removedEdge, err := gm.RemoveEdge("main", edge.Key(), edge.Kind())	if !data.NodeCompare(edge, removedEdge, nil) {		t.Error("Unexpected result")		return	}	if gm.EdgeCount("myedge") != 2 {		t.Error("Unexpected edge count")		return	}	// Check that the correct data has been removed	edgeTree, _ = gm.getEdgeStorageHTree("main", "myedge", false)	keyAttrs = PrefixNSAttrs + edge.Key()	val, err = edgeTree.Get([]byte(keyAttrs))	if err != nil || val != nil {		t.Error("Unexpected result:", val, val)		return	}	// Check that the spec entry is still there	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node1.Key()))	if err != nil || specMap == nil {		t.Error("Unexpected result:", specMap, err)		return	}	if len(specMap.(map[string]string)) != 1 {		t.Error("Unexpected size of spec map")		return	}	obj, err = nodeTree.Get([]byte(edgeInfo1Key))	targetMap = obj.(map[string]*edgeTargetInfo)	// There should be 2 entries in the target map at this point	if len(targetMap) != 2 {		t.Error("Unexpected size of target map")		return	}	removedEdge, err = gm.RemoveEdge("main", edge2.Key(), edge2.Kind())	if !data.NodeCompare(edge2, removedEdge, nil) {		t.Error("Unexpected result")		return	}	if gm.EdgeCount("myedge") != 1 {		t.Error("Unexpected edge count")		return	}	// Check that the spec entry is still there	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node1.Key()))	if err != nil || specMap == nil {		t.Error("Unexpected result:", specMap, err)		return	}	if len(specMap.(map[string]string)) != 1 {		t.Error("Unexpected size of spec map")		return	}	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node3.Key()))	if err != nil || specMap == nil {		t.Error("Unexpected result:", specMap, err)		return	}	if len(specMap.(map[string]string)) != 1 {		t.Error("Unexpected size of spec map")		return	}	obj, err = nodeTree.Get([]byte(edgeInfo1Key))	targetMap = obj.(map[string]*edgeTargetInfo)	// There should be 1 entries in the target map at this point	if len(targetMap) != 1 {		t.Error("Unexpected size of target map")		return	}	edge2.SetAttr(data.NodeKey, "def")	removedEdge, err = gm.RemoveEdge("main", edge2.Key(), edge2.Kind())	if !data.NodeCompare(edge2, removedEdge, nil) {		t.Error("Unexpected result")		return	}	if gm.EdgeCount("myedge") != 0 {		t.Error("Unexpected edge count")		return	}	// Check that the spec entry has been removed	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node1.Key()))	if err != nil || specMap != nil {		t.Error("Unexpected result:", specMap, err)		return	}	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node2.Key()))	if err != nil || specMap != nil {		t.Error("Unexpected result:", specMap, err)		return	}	specMap, err = nodeTree.Get([]byte(PrefixNSSpecs + node3.Key()))	if err != nil || specMap != nil {		t.Error("Unexpected result:", specMap, err)		return	}	// Check that the target map has been removed	obj, err = nodeTree.Get([]byte(edgeInfo1Key))	if err != nil || obj != nil {		t.Error("Unexpected result:", specMap, err)		return	}	it := hash.NewHTreeIterator(edgeTree)	if it.HasNext() {		t.Error("Tree iterator should find no elements in the tree")		return	}	dgs.Close()}func TestSimpleGraphStorageErrorCases(t *testing.T) {	node1 := data.NewGraphNode()	node1.SetAttr("key", "123")	node1.SetAttr("kind", "mykind")	node1.SetAttr("Name", "Node1")	node2 := data.NewGraphNode()	node2.SetAttr("key", "456")	node2.SetAttr("kind", "mynewkind")	node2.SetAttr("Name", "Node2")	// Creeate storage and insert test nodes	mgs := graphstorage.NewMemoryGraphStorage("mystorage")	gm := newGraphManagerNoRules(mgs)	gm.StoreNode("main", node1)	gm.StoreNode("main", node2)	edge := data.NewGraphEdge()	edge.SetAttr("key", "abc")	edge.SetAttr("kind", "myedge")	edge.SetAttr(data.EdgeEnd1Key, node1.Key())	edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())	edge.SetAttr(data.EdgeEnd1Role, "node1-")	edge.SetAttr(data.EdgeEnd1Cascading, true)	edge.SetAttr(data.EdgeEnd2Key, node2.Key())	edge.SetAttr(data.EdgeEnd2Kind, "xxx")	edge.SetAttr(data.EdgeEnd2Role, "node2-")	edge.SetAttr(data.NodeName, "Edge name")	_, _, err := gm.Traverse("main", node1.Key(), node2.Kind(), "abc", false)	if err.Error() != "GraphError: Invalid data (Invalid spec: abc)" {		t.Error("Unexpected store result:", err)		return	}	_, _, err = gm.Traverse("main", node1.Key(), node2.Kind(), ":::abc", false)	if err.Error() != "GraphError: Invalid data (Invalid spec: :::abc - spec needs to be fully specified for direct traversal)" {		t.Error("Unexpected store result:", err)		return	}	_, _, err = gm.TraverseMulti("main", node1.Key(), node2.Kind(), "abc", false)	if err.Error() != "GraphError: Invalid data (Invalid spec: abc)" {		t.Error("Unexpected store result:", err)		return	}	if err := gm.StoreEdge("main", edge); err.Error() !=		"GraphError: Invalid data (Edge role node1- is not alphanumeric - can only contain [a-zA-Z0-9_])" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd1Role, "node1")	if err := gm.StoreEdge("main", edge); err.Error() !=		"GraphError: Invalid data (Edge role node2- is not alphanumeric - can only contain [a-zA-Z0-9_])" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd2Role, "node2")	if err := gm.StoreEdge("main", edge); err.Error() !=		"GraphError: Invalid data (Edge is missing a cascading value for end2)" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd2Cascading, false)	if err := gm.StoreEdge("main", edge); err.Error() != "GraphError: Invalid data (Can't store edge to non-existing node kind: xxx)" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())	edge.SetAttr(data.EdgeEnd1Kind, "xxx")	if err := gm.StoreEdge("main", edge); err.Error() != "GraphError: Invalid data (Can't store edge to non-existing node kind: xxx)" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())	edge.SetAttr(data.EdgeEnd1Key, "xxx")	if err := gm.StoreEdge("main", edge); err.Error() != "GraphError: Invalid data (Can't find edge endpoint: xxx (mykind))" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd1Key, node1.Key())	edge.SetAttr(data.EdgeEnd2Key, "xxx")	if err := gm.StoreEdge("main", edge); err.Error() != "GraphError: Invalid data (Can't find edge endpoint: xxx (mynewkind))" {		t.Error("Unexpected store result:", err)		return	}	edge.SetAttr(data.EdgeEnd2Key, node2.Key())	// Test storage access failures	sm := gm.gs.StorageManager("main"+"myedge"+StorageSuffixEdgesIndex, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	if err := gm.StoreEdge("main", edge); err == nil {		t.Error("Unexpected store result:", err)		return	}	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); err == nil {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	sm.(*storage.MemoryStorageManager).AccessMap[2] = storage.AccessInsertError	if err := gm.StoreEdge("main", edge); err == nil {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 2)	// Reset storage and insert test nodes	mgs = graphstorage.NewMemoryGraphStorage("mystorage")	gm = newGraphManagerNoRules(mgs)	gm.StoreNode("main", node1)	gm.StoreNode("main", node2)	// Test high level errors	sm = gm.gs.StorageManager("main"+"mykind"+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	if err := gm.StoreEdge("main", edge); err == nil {		t.Error("Unexpected store result:", err)		return	}	if _, _, err := gm.Traverse("main", "bla", "mykind", "", false); err == nil {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	sm = gm.gs.StorageManager("main"+"myedge"+StorageSuffixEdges, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); err == nil {		t.Error("Unexpected store result:", err)		return	}	if _, err := gm.FetchEdge("main", edge.Key(), edge.Kind()); err == nil {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	sm = gm.gs.StorageManager("main"+"mynewkind"+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	if err := gm.StoreEdge("main", edge); err == nil {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	graphstorage.MgsRetFlushMain = &util.GraphError{Type: util.ErrFlushing, Detail: errors.New("Test").Error()}	if err := gm.StoreEdge("main", edge); err == nil {		t.Error("Unexpected store result:", err)		return	}	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); err == nil {		t.Error("Unexpected store result:", err)		return	}	graphstorage.MgsRetFlushMain = nil	// Finally insert the edge	if err := gm.StoreEdge("main", edge); err != nil {		t.Error("Unexpected store result:", err)		return	}	sm = gm.gs.StorageManager("main"+"myedge"+StorageSuffixEdges, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	traverseSpec := edge.End2Role() + ":" + edge.Kind() + ":" + edge.End1Role() + ":" + edge.End1Kind()	_, _, err = gm.Traverse("main", edge.End2Key(), edge.End2Kind(), traverseSpec, true)	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	sm = gm.gs.StorageManager("main"+"myedge"+StorageSuffixEdgesIndex, false)	sm.(*storage.MemoryStorageManager).AccessMap[5] = storage.AccessInsertError	edge.SetAttr("name", "New edge name")	if err := gm.StoreEdge("main", edge); err == nil {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 5)	resetStorage := func() {		mgs = graphstorage.NewMemoryGraphStorage("mystorage")		gm = newGraphManagerNoRules(mgs)		gm.StoreNode("main", node1)		gm.StoreNode("main", node2)		gm.StoreEdge("main", edge)	}	// Test low level errors	spec1 := gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.Kind(), true) +		gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.End2Kind(), true)	spec2 := gm.nm.Encode16(edge.End2Role(), true) + gm.nm.Encode16(edge.Kind(), true) +		gm.nm.Encode16(edge.End1Role(), true) + gm.nm.Encode16(edge.End1Kind(), true)	specsNode1Key := PrefixNSSpecs + edge.End1Key()	edgeInfo1Key := PrefixNSEdge + edge.End1Key() + spec1	specsNode2Key := PrefixNSSpecs + edge.End2Key()	edgeInfo2Key := PrefixNSEdge + edge.End2Key() + spec2	resetStorage()	// Test error case of index lookup	sm = gm.gs.StorageManager("main"+edge.Kind()+StorageSuffixEdgesIndex, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	if _, err := gm.EdgeIndexQuery("main", "myedge"); err == nil {		t.Error(err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	_, nodeTree, _ := gm.getNodeStorageHTree("main", edge.End2Kind(), false)	_, loc, _ := nodeTree.GetValueAndLocation([]byte(specsNode2Key))	sm = gm.gs.StorageManager("main"+edge.End2Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessCacheAndFetchError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	if err := gm.StoreEdge("main", edge); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	resetStorage()	_, nodeTree, _ = gm.getNodeStorageHTree("main", edge.End1Kind(), false)	_, _ = nodeTree.Remove([]byte(specsNode1Key))	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Expected spec entry is missing") {		t.Error("Unexpected store result:", err)		return	}	resetStorage()	_, nodeTree, _ = gm.getNodeStorageHTree("main", edge.End2Kind(), false)	_, loc, _ = nodeTree.GetValueAndLocation([]byte(specsNode2Key))	sm = gm.gs.StorageManager("main"+edge.End2Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessFreeError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	resetStorage()	_, nodeTree, _ = gm.getNodeStorageHTree("main", edge.End1Kind(), false)	val, loc, _ := nodeTree.GetValueAndLocation([]byte(specsNode1Key))	val.(map[string]string)["test2"] = "test3"	sm = gm.gs.StorageManager("main"+edge.End1Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessUpdateError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	if err := gm.StoreEdge("main", edge); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	resetStorage()	_, nodeTree, _ = gm.getNodeStorageHTree("main", edge.End2Kind(), false)	_, loc, _ = nodeTree.GetValueAndLocation([]byte(edgeInfo2Key))	sm = gm.gs.StorageManager("main"+edge.End2Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessCacheAndFetchError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	if err := gm.StoreEdge("main", edge); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	traverseSpec = edge.End2Role() + ":" + edge.Kind() + ":" + edge.End1Role() + ":" + edge.End1Kind()	_, _, err = gm.Traverse("main", edge.End2Key(), edge.End2Kind(), traverseSpec, false)	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	traverseSpec = ":" + edge.Kind() + ":" + edge.End1Role() + ":" + edge.End1Kind()	_, _, err = gm.TraverseMulti("main", edge.End2Key(), edge.End2Kind(), traverseSpec, false)	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	resetStorage()	_, nodeTree, _ = gm.getNodeStorageHTree("main", edge.End1Kind(), false)	_, _ = nodeTree.Remove([]byte(edgeInfo1Key))	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Expected edgeTargetInfo entry is missing") {		t.Error("Unexpected store result:", err)		return	}	resetStorage()	_, nodeTree, _ = gm.getNodeStorageHTree("main", edge.End2Kind(), false)	_, loc, _ = nodeTree.GetValueAndLocation([]byte(edgeInfo2Key))	sm = gm.gs.StorageManager("main"+edge.End2Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessFreeError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	resetStorage()	nodeattTree, nodeTree, _ := gm.getNodeStorageHTree("main", edge.End1Kind(), false)	val, loc, _ = nodeTree.GetValueAndLocation([]byte(edgeInfo1Key))	val.(map[string]*edgeTargetInfo)["test2"] = nil	sm = gm.gs.StorageManager("main"+edge.End1Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessUpdateError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	if err := gm.StoreEdge("main", edge); !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	_, loc, _ = nodeattTree.GetValueAndLocation([]byte(PrefixNSAttrs + edge.End1Key()))	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessCacheAndFetchError	traverseSpec = edge.End2Role() + ":" + edge.Kind() + ":" + edge.End1Role() + ":" + edge.End1Kind()	_, _, err = gm.Traverse("main", edge.End2Key(), edge.End2Kind(), traverseSpec, true)	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	mgs = graphstorage.NewMemoryGraphStorage("mystorage")	gm = newGraphManagerNoRules(mgs)	gm.StoreNode("main", node1)	gm.StoreNode("main", node2)	sm = gm.gs.StorageManager("main"+edge.Kind()+StorageSuffixEdges, true)	sm.(*storage.MemoryStorageManager).AccessMap[11] = storage.AccessInsertError	if err := gm.StoreEdge("main", edge); !strings.Contains(err.Error(), "Could not write graph information") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 11)	resetStorage()	sm = gm.gs.StorageManager("main"+edge.Kind()+StorageSuffixEdges, false)	sm.(*storage.MemoryStorageManager).AccessMap[11] = storage.AccessCacheAndFetchError	traverseSpec = edge.End1Role() + ":" + edge.Kind() + ":" + edge.End2Role() + ":" + edge.End2Kind()	_, _, err = gm.Traverse("main", edge.End1Key(), edge.End1Kind(), traverseSpec, true)	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	sm.(*storage.MemoryStorageManager).AccessMap[11] = storage.AccessFreeError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Could not write graph information") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 11)	resetStorage()	sm = gm.gs.StorageManager("main"+edge.End1Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Failed to access graph storage component") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	resetStorage()	sm = gm.gs.StorageManager("main"+edge.End2Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	traverseSpec = edge.End1Role() + ":" + edge.Kind() + ":" + edge.End2Role() + ":" + edge.End2Kind()	_, _, err = gm.Traverse("main", edge.End1Key(), edge.End1Kind(), traverseSpec, true)	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected store result:", err)		return	}	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Failed to access graph storage component") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	resetStorage()	sm = gm.gs.StorageManager("main"+edge.Kind()+StorageSuffixEdgesIndex, false)	sm.(*storage.MemoryStorageManager).AccessMap[2] = storage.AccessFreeError	if _, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); !strings.Contains(err.Error(), "Index error") {		t.Error("Unexpected store result:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 2)	// Test removal of non-existing edge	resetStorage()	if obj, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); obj == nil || err != nil {		t.Error("Unexpected store result:", obj, err)		return	}	if obj, err := gm.RemoveEdge("main", edge.Key(), edge.Kind()); obj != nil || err != nil {		t.Error("Unexpected store result:", obj, err)		return	}}func TestEdgeOperations(t *testing.T) {	node1 := data.NewGraphNode()	node1.SetAttr("key", "123")	node1.SetAttr("kind", "mykind")	node1.SetAttr("Name", "Node1")	node2 := data.NewGraphNode()	node2.SetAttr("key", "456")	node2.SetAttr("kind", "mynewkind")	node2.SetAttr("Name", "Node2")	constructEdge := func(kind string) data.Edge {		edge := data.NewGraphEdge()		edge.SetAttr("key", "abc")		edge.SetAttr("kind", kind)		edge.SetAttr(data.EdgeEnd1Key, node1.Key())		edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())		edge.SetAttr(data.EdgeEnd1Role, "node1")		edge.SetAttr(data.EdgeEnd1Cascading, true)		edge.SetAttr(data.EdgeEnd1CascadingLast, true)		edge.SetAttr(data.EdgeEnd2Key, node2.Key())		edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())		edge.SetAttr(data.EdgeEnd2Role, "node2")		edge.SetAttr(data.EdgeEnd2Cascading, false)		edge.SetAttr(data.NodeName, "Edge "+kind)		return edge	}	// Creeate storage and insert test nodes	mgs := graphstorage.NewMemoryGraphStorage("mystorage")	gm := newGraphManagerNoRules(mgs)	if err := gm.StoreNode("main", node1); err != nil {		t.Error(err)	}	if err := gm.StoreNode("main", node2); err != nil {		t.Error(err)	}	edge1 := constructEdge("myedge")	if err := gm.StoreEdge("main", edge1); err != nil {		t.Error(err)	}	edge2 := constructEdge("myotheredge")	if err := gm.StoreEdge("main", edge2); err != nil {		t.Error(err)	}	specs, err := gm.FetchNodeEdgeSpecs("main", node1.Key(), node1.Kind())	if err != nil {		t.Error(err)		return	}	if fmt.Sprint(specs) != "[node1:myedge:node2:mynewkind node1:myotheredge:node2:mynewkind]" {		t.Error("Unexpected specs result:", specs)		return	}	sm := gm.gs.StorageManager("main"+node1.Kind()+StorageSuffixNodes, false)	sm.(*storage.MemoryStorageManager).AccessMap[1] = storage.AccessCacheAndFetchError	_, err = gm.FetchNodeEdgeSpecs("main", node1.Key(), node1.Kind())	if err.Error() != "GraphError: Failed to access graph storage component (Slot not found (mystorage/mainmykind.nodes - Location:1))" {		t.Error("Unexpected error:", err)		return	}	_, _, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(), ":::", false)	if err.Error() != "GraphError: Failed to access graph storage component (Slot not found (mystorage/mainmykind.nodes - Location:1))" {		t.Error("Unexpected error:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, 1)	_, tree, _ := gm.getNodeStorageHTree("main", node1.Kind(), false)	_, loc, _ := tree.GetValueAndLocation([]byte(PrefixNSSpecs + node1.Key()))	sm.(*storage.MemoryStorageManager).AccessMap[loc] = storage.AccessCacheAndFetchError	_, err = gm.FetchNodeEdgeSpecs("main", node1.Key(), node1.Kind())	if !strings.Contains(err.Error(), "Slot not found") {		t.Error("Unexpected error:", err)		return	}	delete(sm.(*storage.MemoryStorageManager).AccessMap, loc)	nodes, edges, err := gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node1:myotheredge:node2:mynewkind", false)	if err != nil {		t.Error(err)		return	}	if len(nodes) != 1 || len(edges) != 1 {		t.Error("Unexpected result:", nodes, edges)		return	}	if !data.NodeCompare(edges[0], edge2, []string{data.NodeKey, data.NodeKind,		data.EdgeEnd1Key, data.EdgeEnd1Kind, data.EdgeEnd1Role, data.EdgeEnd1Cascading,		data.EdgeEnd2Key, data.EdgeEnd2Kind, data.EdgeEnd2Role, data.EdgeEnd2Cascading}) {		t.Error("Edges should match:", edge2, edges[0])		return	}	if !data.NodeCompare(nodes[0], node2, []string{data.NodeKey, data.NodeKind}) {		t.Error("Nodes should match:", node2, nodes[0])		return	}	// Now lookup from the other side	nodes2, edges2, err := gm.Traverse("main", node2.Key(), node2.Kind(),		"node2:myotheredge:node1:mykind", false)	if err != nil {		t.Error(err)		return	}	if len(nodes2) != 1 || len(edges2) != 1 {		t.Error("Unexpected result:", nodes2, edges2)		return	}	if !data.NodeCompare(nodes2[0], node1, []string{data.NodeKey, data.NodeKind}) {		t.Error("Nodes should match:", node1, nodes2[0])		return	}	if !data.NodeCompare(edges2[0], edge2, []string{data.NodeKey, data.NodeKind}) {		t.Error("Edges should match:", edge2, edges2[0])		return	}	// Check that the correct ends have been set	if edges2[0].End1Key() != node2.Key() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1Kind() != node2.Kind() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1Role() != "node2" {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1IsCascading() != false {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1IsCascadingLast() != false {		t.Error("Unexpected value in traversed edge")		return	}	if edges2[0].End2Key() != node1.Key() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2Kind() != node1.Kind() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2Role() != "node1" {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2IsCascading() != true {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2IsCascadingLast() != true {		t.Error("Unexpected value in traversed edge")		return	}	// Lookup from the other side getting all attributes	nodes2, edges2, err = gm.Traverse("main", node2.Key(), node2.Kind(),		"node2:myotheredge:node1:mykind", true)	if err != nil {		t.Error(err)		return	}	if len(nodes2) != 1 || len(edges2) != 1 {		t.Error("Unexpected result:", nodes2, edges2)		return	}	if !data.NodeCompare(nodes2[0], node1, []string{data.NodeKey, data.NodeKind, data.NodeName}) {		t.Error("Nodes should match:", node1, nodes2[0])		return	}	if !data.NodeCompare(edges2[0], edge2, []string{data.NodeKey, data.NodeKind, data.NodeName}) {		t.Error("Edges should match:", edge2, edges2[0])		return	}	// Check that the correct ends have been set	if edges2[0].End1Key() != node2.Key() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1Kind() != node2.Kind() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1Role() != "node2" {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End1IsCascading() != false {		t.Error("Unexpected value in traversed edge")		return	}	if edges2[0].End2Key() != node1.Key() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2Kind() != node1.Kind() {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2Role() != "node1" {		t.Error("Unexpected value in traversed edge")		return	} else if edges2[0].End2IsCascading() != true {		t.Error("Unexpected value in traversed edge")		return	}	// Lookup from the original side with all attributes	nodes, edges, err = gm.Traverse("main", node1.Key(), node1.Kind(),		"node1:myotheredge:node2:mynewkind", true)	if err != nil {		t.Error(err)		return	}	if len(nodes) != 1 || len(edges) != 1 {		t.Error("Unexpected result:", nodes, edges)		return	}	if !data.NodeCompare(nodes[0], node2, nil) {		t.Error("Nodes should match:", node2, nodes[0])		return	}	if !data.NodeCompare(edges[0], edge2, nil) {		t.Error("Edges should match:", edge2, edges[0])		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		":::", false)	if err != nil {		t.Error(err)		return	}	if len(nodes) != 2 || len(edges) != 2 {		t.Error("Unexpected result:", nodes, edges)		return	} else if nodes[0].Key() != node2.Key() || nodes[1].Key() != node2.Key() {		t.Error("Unexpected result:", nodes, edges)		return	} else if edges[0].Key() != edge1.Key() || edges[1].Key() != edge2.Key() {		t.Error("Unexpected result:", nodes, edges)		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node1::node2:mynewkind", false)	if err != nil {		t.Error(err)		return	}	if len(nodes) != 2 || len(edges) != 2 {		t.Error("Unexpected result:", nodes, edges)		return	} else if nodes[0].Key() != node2.Key() || nodes[1].Key() != node2.Key() {		t.Error("Unexpected result:", nodes, edges)		return	} else if edges[0].Key() != edge1.Key() || edges[1].Key() != edge2.Key() {		t.Error("Unexpected result:", nodes, edges)		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node1:myotheredge::mynewkind", false)	if err != nil {		t.Error(err)		return	}	if len(nodes) != 1 || len(edges) != 1 {		t.Error("Unexpected result:", nodes, edges)		return	} else if nodes[0].Key() != node2.Key() {		t.Error("Unexpected result:", nodes, edges)		return	} else if edges[0].Key() != edge2.Key() {		t.Error("Unexpected result:", nodes, edges)		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node2:myotheredge:node2:mynewkind", false)	if err != nil {		t.Error(err)		return	} else if len(nodes) != 0 || len(edges) != 0 {		t.Error("Unexpected result:", nodes, edges)		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node1:myotheredge2:node2:mynewkind", false)	if err != nil {		t.Error(err)		return	} else if len(nodes) != 0 || len(edges) != 0 {		t.Error("Unexpected result:", nodes, edges)		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node1:myotheredge:node3:mynewkind", false)	if err != nil {		t.Error(err)		return	} else if len(nodes) != 0 || len(edges) != 0 {		t.Error("Unexpected result:", nodes, edges)		return	}	nodes, edges, err = gm.TraverseMulti("main", node1.Key(), node1.Kind(),		"node1:myotheredge:node2:mynewkind2", false)	if err != nil {		t.Error(err)		return	} else if len(nodes) != 0 || len(edges) != 0 {		t.Error("Unexpected result:", nodes, edges)		return	}}
 |