/* * 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" "testing" "devt.de/krotik/eliasdb/graph/data" "devt.de/krotik/eliasdb/graph/graphstorage" "devt.de/krotik/eliasdb/storage" ) func TestSanityChecks(t *testing.T) { gs := graphstorage.NewMemoryGraphStorage("test") gm := newGraphManagerNoRules(gs) if gm.checkPartitionName("abba") != nil { t.Error("Partition name should be valid") return } if err := gm.checkPartitionName("abba 5").Error(); err != "GraphError: "+ "Invalid data (Partition name abba 5 is not alphanumeric - can only "+ "contain [a-zA-Z0-9_])" { t.Error("Partition name should be valid", err) return } node := data.NewGraphNode() if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data "+ "(Node is missing a key value)" { t.Error("Unexpected result:", err) return } node.SetAttr("key", "123") if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data (Node "+ "is missing a kind value)" { t.Error("Unexpected result:", err) return } node.SetAttr("kind", "123 3") if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data (Node "+ "kind 123 3 is not alphanumeric - can only contain [a-zA-Z0-9_])" { t.Error("Unexpected result:", err) return } node.SetAttr("kind", "123") node.SetAttr("", "123") if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data "+ "(Node contains empty string attribute name)" { t.Error("Unexpected result:", err) return } delete(node.Data(), "") if err := gm.checkNode(node); err != nil { t.Error("Unexpected result:", err) return } if err := gm.writeNodeCount("bla", 42, true); err != nil { t.Error(err) return } if cnt := gm.NodeCount("bla"); cnt != 42 { t.Error("Invalid node count:", cnt) return } if cnt := gm.NodeCount("bla1"); cnt != 0 { t.Error("Invalid node count:", cnt) return } if err := gm.writeEdgeCount("bla2", 55, true); err != nil { t.Error(err) return } if cnt := gm.EdgeCount("bla2"); cnt != 55 { t.Error("Invalid edge count:", cnt) return } if cnt := gm.EdgeCount("bla"); cnt != 0 { t.Error("Invalid edge count:", cnt) return } gs.StorageManager("blabla"+StorageSuffixNodes, true) gs.StorageManager("blabla"+StorageSuffixNodesIndex, true) gs.StorageManager("blabla"+StorageSuffixEdges, true) gs.StorageManager("blabla"+StorageSuffixEdgesIndex, true) storage.MsmRetFlush = errors.New("Test") if res := gm.flushNodeStorage("bla", "bla").Error(); res != "GraphError: Failed to flush changes (Test)" { t.Error("Unexpected flush result:", res) return } if res := gm.flushNodeIndex("bla", "bla").Error(); res != "GraphError: Failed to flush changes (Test)" { t.Error("Unexpected flush result:", res) return } if res := gm.flushEdgeStorage("bla", "bla").Error(); res != "GraphError: Failed to flush changes (Test)" { t.Error("Unexpected flush result:", res) return } if res := gm.flushEdgeIndex("bla", "bla").Error(); res != "GraphError: Failed to flush changes (Test)" { t.Error("Unexpected flush result:", res) return } storage.MsmRetFlush = nil storage.MsmRetRollback = errors.New("Test") if res := gm.rollbackNodeStorage("bla", "bla").Error(); res != "GraphError: Failed to rollback changes (Test)" { t.Error("Unexpected rollback result:", res) return } if res := gm.rollbackNodeIndex("bla", "bla").Error(); res != "GraphError: Failed to rollback changes (Test)" { t.Error("Unexpected rollback result:", res) return } if res := gm.rollbackEdgeStorage("bla", "bla").Error(); res != "GraphError: Failed to rollback changes (Test)" { t.Error("Unexpected rollback result:", res) return } if res := gm.rollbackEdgeIndex("bla", "bla").Error(); res != "GraphError: Failed to rollback changes (Test)" { t.Error("Unexpected rollback result:", res) return } storage.MsmRetRollback = nil if gm.flushNodeStorage("bla", "bla") != nil { t.Error("Unexpected flush result") return } if gm.flushNodeIndex("bla", "bla2") != nil { t.Error("Unexpected flush result") return } if gm.flushEdgeStorage("bla", "bla") != nil { t.Error("Unexpected flush result") return } if gm.flushEdgeIndex("bla", "bla2") != nil { t.Error("Unexpected flush result") return } if gm.rollbackNodeStorage("bla", "bla") != nil { t.Error("Unexpected rollback result") return } if gm.rollbackNodeIndex("bla", "bla2") != nil { t.Error("Unexpected rollback result") return } if gm.rollbackEdgeStorage("bla", "bla") != nil { t.Error("Unexpected rollback result") return } if gm.rollbackEdgeIndex("bla", "bla2") != nil { t.Error("Unexpected rollback result") return } if res, res2, err := gm.getNodeStorageHTree("my part", "mykind", false); res != nil || res2 != nil || err == nil { t.Error("Unexpected Error", err) return } if res, res2, err := gm.getNodeStorageHTree("mypart", "my kind", false); res != nil || res2 != nil || err.Error() != "GraphError: Invalid data (Node kind my kind is not alphanumeric - can only contain [a-zA-Z0-9_])" { t.Error("Unexpected Error", err) return } if res, res2, err := gm.getNodeStorageHTree("mypart", "mykind", false); res != nil || res2 != nil || err != nil { t.Error("Non existing node storage tree should not be created here:", res, err) return } res, res2, err := gm.getNodeStorageHTree("mypart", "mykind", true) if err != nil || res == nil || res2 == nil { t.Error(res, err) return } sm := gm.gs.StorageManager("mypart"+"mykind"+StorageSuffixNodes, false) oldroot := sm.Root(RootIDNodeHTree) sm.SetRoot(RootIDNodeHTree, 5) sm.(*storage.MemoryStorageManager).AccessMap[5] = storage.AccessCacheAndFetchError _, _, err = gm.getNodeStorageHTree("mypart", "mykind", true) if err.Error() != "GraphError: Failed to access graph storage component (Slot not found (test/mypartmykind.nodes - Location:5))" { t.Error(err) return } delete(sm.(*storage.MemoryStorageManager).AccessMap, 5) sm.SetRoot(RootIDNodeHTree, oldroot) oldroot = sm.Root(RootIDNodeHTreeSecond) sm.SetRoot(RootIDNodeHTreeSecond, 5) sm.(*storage.MemoryStorageManager).AccessMap[5] = storage.AccessCacheAndFetchError _, _, err = gm.getNodeStorageHTree("mypart", "mykind", true) if err.Error() != "GraphError: Failed to access graph storage component (Slot not found (test/mypartmykind.nodes - Location:5))" { t.Error(err) return } delete(sm.(*storage.MemoryStorageManager).AccessMap, 5) sm.SetRoot(RootIDNodeHTreeSecond, oldroot) if res, err := gm.getEdgeStorageHTree("my part", "mykind", false); res != nil || err == nil { t.Error("Unexpected Error", err) return } if res, err := gm.getEdgeStorageHTree("mypart", "my kind", false); res != nil || err.Error() != "GraphError: Invalid data (Edge kind my kind is not alphanumeric - can only contain [a-zA-Z0-9_])" { t.Error("Unexpected Error", err) return } if res, err := gm.getEdgeStorageHTree("mypart", "mykind", false); res != nil || err != nil { t.Error("Non existing node storage tree should not be created here:", res, err) return } res, err = gm.getEdgeStorageHTree("mypart", "mykind", true) if err != nil || res == nil { t.Error(res, err) return } if cnt := len(gs.MainDB()); cnt != 11 { t.Error("Unexpected number of main db entries:", cnt) return } if _, ok := gs.MainDB()[MainDBNodeAttrs+"mykind"]; !ok { t.Error("Missing main db entry") return } if _, ok := gs.MainDB()[MainDBNodeEdges+"mykind"]; !ok { t.Error("Missing main db entry") return } if _, ok := gs.MainDB()[MainDBNodeCount+"mykind"]; !ok { t.Error("Missing main db entry") return } edge := data.NewGraphEdge() if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a key value)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.NodeKey, "123") edge.SetAttr(data.NodeKind, "myedge") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a key value for end1)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd1Key, "456") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a kind value for end1)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd1Kind, "mykind1") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a role value for end1)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd1Role, "myrole1") edge.SetAttr(data.EdgeEnd1Cascading, "wrong") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a cascading value for end1)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd1Cascading, false) if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a key value for end2)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd2Key, "456") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a kind value for end2)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd2Kind, "mykind1") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a role value for end2)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd2Role, "myrole1") if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a cascading value for end2)" { t.Error("Unexpected result:", err) return } edge.SetAttr(data.EdgeEnd2Cascading, true) if err := gm.checkEdge(edge); err != nil { t.Error("Unexpected result:", err) return } } func TestStringLists(t *testing.T) { stringmap := map[string]string{ "test1": "testval1", } str := mapToString(stringmap) stringmap2 := stringToMap(str) if fmt.Sprint(stringmap2) != "map[test1:testval1]" { t.Error("Unexpected decoded list:", stringmap2) return } testStringDecodePanic(t) gm := newGraphManagerNoRules(graphstorage.NewMemoryGraphStorage("test")) // Test map storage gm.storeMainDBMap("mycoolmap", stringmap) // Remove the cached delete(gm.mapCache, "mycoolmap") // Map is a copy map1 := gm.getMainDBMap("mycoolmap") if &map1 != &stringmap && fmt.Sprint(map1) != fmt.Sprint(stringmap) { t.Error("Unexpected map return:", map1) return } // Map comes now from the cache map2 := gm.getMainDBMap("mycoolmap") if &map1 == &map2 { t.Error("Unexpected map return:", map1) return } } func testStringDecodePanic(t *testing.T) { defer func() { if r := recover(); r == nil { t.Error("Decoding a non encoded string did not cause a panic.") } }() stringToMap("test") }