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 graph
- import (
- "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
- }
- }
|