helpers_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package graph
  11. import (
  12. "errors"
  13. "fmt"
  14. "testing"
  15. "devt.de/krotik/eliasdb/graph/data"
  16. "devt.de/krotik/eliasdb/graph/graphstorage"
  17. "devt.de/krotik/eliasdb/storage"
  18. )
  19. func TestSanityChecks(t *testing.T) {
  20. gs := graphstorage.NewMemoryGraphStorage("test")
  21. gm := newGraphManagerNoRules(gs)
  22. if gm.checkPartitionName("abba") != nil {
  23. t.Error("Partition name should be valid")
  24. return
  25. }
  26. if err := gm.checkPartitionName("abba 5").Error(); err != "GraphError: "+
  27. "Invalid data (Partition name abba 5 is not alphanumeric - can only "+
  28. "contain [a-zA-Z0-9_])" {
  29. t.Error("Partition name should be valid", err)
  30. return
  31. }
  32. node := data.NewGraphNode()
  33. if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data "+
  34. "(Node is missing a key value)" {
  35. t.Error("Unexpected result:", err)
  36. return
  37. }
  38. node.SetAttr("key", "123")
  39. if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data (Node "+
  40. "is missing a kind value)" {
  41. t.Error("Unexpected result:", err)
  42. return
  43. }
  44. node.SetAttr("kind", "123 3")
  45. if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data (Node "+
  46. "kind 123 3 is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  47. t.Error("Unexpected result:", err)
  48. return
  49. }
  50. node.SetAttr("kind", "123")
  51. node.SetAttr("", "123")
  52. if err := gm.checkNode(node); err.Error() != "GraphError: Invalid data "+
  53. "(Node contains empty string attribute name)" {
  54. t.Error("Unexpected result:", err)
  55. return
  56. }
  57. delete(node.Data(), "")
  58. if err := gm.checkNode(node); err != nil {
  59. t.Error("Unexpected result:", err)
  60. return
  61. }
  62. if err := gm.writeNodeCount("bla", 42, true); err != nil {
  63. t.Error(err)
  64. return
  65. }
  66. if cnt := gm.NodeCount("bla"); cnt != 42 {
  67. t.Error("Invalid node count:", cnt)
  68. return
  69. }
  70. if cnt := gm.NodeCount("bla1"); cnt != 0 {
  71. t.Error("Invalid node count:", cnt)
  72. return
  73. }
  74. if err := gm.writeEdgeCount("bla2", 55, true); err != nil {
  75. t.Error(err)
  76. return
  77. }
  78. if cnt := gm.EdgeCount("bla2"); cnt != 55 {
  79. t.Error("Invalid edge count:", cnt)
  80. return
  81. }
  82. if cnt := gm.EdgeCount("bla"); cnt != 0 {
  83. t.Error("Invalid edge count:", cnt)
  84. return
  85. }
  86. gs.StorageManager("blabla"+StorageSuffixNodes, true)
  87. gs.StorageManager("blabla"+StorageSuffixNodesIndex, true)
  88. gs.StorageManager("blabla"+StorageSuffixEdges, true)
  89. gs.StorageManager("blabla"+StorageSuffixEdgesIndex, true)
  90. storage.MsmRetFlush = errors.New("Test")
  91. if res := gm.flushNodeStorage("bla", "bla").Error(); res !=
  92. "GraphError: Failed to flush changes (Test)" {
  93. t.Error("Unexpected flush result:", res)
  94. return
  95. }
  96. if res := gm.flushNodeIndex("bla", "bla").Error(); res !=
  97. "GraphError: Failed to flush changes (Test)" {
  98. t.Error("Unexpected flush result:", res)
  99. return
  100. }
  101. if res := gm.flushEdgeStorage("bla", "bla").Error(); res !=
  102. "GraphError: Failed to flush changes (Test)" {
  103. t.Error("Unexpected flush result:", res)
  104. return
  105. }
  106. if res := gm.flushEdgeIndex("bla", "bla").Error(); res !=
  107. "GraphError: Failed to flush changes (Test)" {
  108. t.Error("Unexpected flush result:", res)
  109. return
  110. }
  111. storage.MsmRetFlush = nil
  112. storage.MsmRetRollback = errors.New("Test")
  113. if res := gm.rollbackNodeStorage("bla", "bla").Error(); res !=
  114. "GraphError: Failed to rollback changes (Test)" {
  115. t.Error("Unexpected rollback result:", res)
  116. return
  117. }
  118. if res := gm.rollbackNodeIndex("bla", "bla").Error(); res !=
  119. "GraphError: Failed to rollback changes (Test)" {
  120. t.Error("Unexpected rollback result:", res)
  121. return
  122. }
  123. if res := gm.rollbackEdgeStorage("bla", "bla").Error(); res !=
  124. "GraphError: Failed to rollback changes (Test)" {
  125. t.Error("Unexpected rollback result:", res)
  126. return
  127. }
  128. if res := gm.rollbackEdgeIndex("bla", "bla").Error(); res !=
  129. "GraphError: Failed to rollback changes (Test)" {
  130. t.Error("Unexpected rollback result:", res)
  131. return
  132. }
  133. storage.MsmRetRollback = nil
  134. if gm.flushNodeStorage("bla", "bla") != nil {
  135. t.Error("Unexpected flush result")
  136. return
  137. }
  138. if gm.flushNodeIndex("bla", "bla2") != nil {
  139. t.Error("Unexpected flush result")
  140. return
  141. }
  142. if gm.flushEdgeStorage("bla", "bla") != nil {
  143. t.Error("Unexpected flush result")
  144. return
  145. }
  146. if gm.flushEdgeIndex("bla", "bla2") != nil {
  147. t.Error("Unexpected flush result")
  148. return
  149. }
  150. if gm.rollbackNodeStorage("bla", "bla") != nil {
  151. t.Error("Unexpected rollback result")
  152. return
  153. }
  154. if gm.rollbackNodeIndex("bla", "bla2") != nil {
  155. t.Error("Unexpected rollback result")
  156. return
  157. }
  158. if gm.rollbackEdgeStorage("bla", "bla") != nil {
  159. t.Error("Unexpected rollback result")
  160. return
  161. }
  162. if gm.rollbackEdgeIndex("bla", "bla2") != nil {
  163. t.Error("Unexpected rollback result")
  164. return
  165. }
  166. if res, res2, err := gm.getNodeStorageHTree("my part", "mykind", false); res != nil ||
  167. res2 != nil || err == nil {
  168. t.Error("Unexpected Error", err)
  169. return
  170. }
  171. if res, res2, err := gm.getNodeStorageHTree("mypart", "my kind", false); res != nil ||
  172. res2 != nil || err.Error() !=
  173. "GraphError: Invalid data (Node kind my kind is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  174. t.Error("Unexpected Error", err)
  175. return
  176. }
  177. if res, res2, err := gm.getNodeStorageHTree("mypart", "mykind", false); res != nil ||
  178. res2 != nil || err != nil {
  179. t.Error("Non existing node storage tree should not be created here:", res, err)
  180. return
  181. }
  182. res, res2, err := gm.getNodeStorageHTree("mypart", "mykind", true)
  183. if err != nil || res == nil || res2 == nil {
  184. t.Error(res, err)
  185. return
  186. }
  187. sm := gm.gs.StorageManager("mypart"+"mykind"+StorageSuffixNodes, false)
  188. oldroot := sm.Root(RootIDNodeHTree)
  189. sm.SetRoot(RootIDNodeHTree, 5)
  190. sm.(*storage.MemoryStorageManager).AccessMap[5] = storage.AccessCacheAndFetchError
  191. _, _, err = gm.getNodeStorageHTree("mypart", "mykind", true)
  192. if err.Error() != "GraphError: Failed to access graph storage component (Slot not found (test/mypartmykind.nodes - Location:5))" {
  193. t.Error(err)
  194. return
  195. }
  196. delete(sm.(*storage.MemoryStorageManager).AccessMap, 5)
  197. sm.SetRoot(RootIDNodeHTree, oldroot)
  198. oldroot = sm.Root(RootIDNodeHTreeSecond)
  199. sm.SetRoot(RootIDNodeHTreeSecond, 5)
  200. sm.(*storage.MemoryStorageManager).AccessMap[5] = storage.AccessCacheAndFetchError
  201. _, _, err = gm.getNodeStorageHTree("mypart", "mykind", true)
  202. if err.Error() != "GraphError: Failed to access graph storage component (Slot not found (test/mypartmykind.nodes - Location:5))" {
  203. t.Error(err)
  204. return
  205. }
  206. delete(sm.(*storage.MemoryStorageManager).AccessMap, 5)
  207. sm.SetRoot(RootIDNodeHTreeSecond, oldroot)
  208. if res, err := gm.getEdgeStorageHTree("my part", "mykind", false); res != nil || err == nil {
  209. t.Error("Unexpected Error", err)
  210. return
  211. }
  212. if res, err := gm.getEdgeStorageHTree("mypart", "my kind", false); res != nil || err.Error() !=
  213. "GraphError: Invalid data (Edge kind my kind is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  214. t.Error("Unexpected Error", err)
  215. return
  216. }
  217. if res, err := gm.getEdgeStorageHTree("mypart", "mykind", false); res != nil || err != nil {
  218. t.Error("Non existing node storage tree should not be created here:", res, err)
  219. return
  220. }
  221. res, err = gm.getEdgeStorageHTree("mypart", "mykind", true)
  222. if err != nil || res == nil {
  223. t.Error(res, err)
  224. return
  225. }
  226. if cnt := len(gs.MainDB()); cnt != 11 {
  227. t.Error("Unexpected number of main db entries:", cnt)
  228. return
  229. }
  230. if _, ok := gs.MainDB()[MainDBNodeAttrs+"mykind"]; !ok {
  231. t.Error("Missing main db entry")
  232. return
  233. }
  234. if _, ok := gs.MainDB()[MainDBNodeEdges+"mykind"]; !ok {
  235. t.Error("Missing main db entry")
  236. return
  237. }
  238. if _, ok := gs.MainDB()[MainDBNodeCount+"mykind"]; !ok {
  239. t.Error("Missing main db entry")
  240. return
  241. }
  242. edge := data.NewGraphEdge()
  243. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a key value)" {
  244. t.Error("Unexpected result:", err)
  245. return
  246. }
  247. edge.SetAttr(data.NodeKey, "123")
  248. edge.SetAttr(data.NodeKind, "myedge")
  249. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a key value for end1)" {
  250. t.Error("Unexpected result:", err)
  251. return
  252. }
  253. edge.SetAttr(data.EdgeEnd1Key, "456")
  254. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a kind value for end1)" {
  255. t.Error("Unexpected result:", err)
  256. return
  257. }
  258. edge.SetAttr(data.EdgeEnd1Kind, "mykind1")
  259. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a role value for end1)" {
  260. t.Error("Unexpected result:", err)
  261. return
  262. }
  263. edge.SetAttr(data.EdgeEnd1Role, "myrole1")
  264. edge.SetAttr(data.EdgeEnd1Cascading, "wrong")
  265. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a cascading value for end1)" {
  266. t.Error("Unexpected result:", err)
  267. return
  268. }
  269. edge.SetAttr(data.EdgeEnd1Cascading, false)
  270. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a key value for end2)" {
  271. t.Error("Unexpected result:", err)
  272. return
  273. }
  274. edge.SetAttr(data.EdgeEnd2Key, "456")
  275. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a kind value for end2)" {
  276. t.Error("Unexpected result:", err)
  277. return
  278. }
  279. edge.SetAttr(data.EdgeEnd2Kind, "mykind1")
  280. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a role value for end2)" {
  281. t.Error("Unexpected result:", err)
  282. return
  283. }
  284. edge.SetAttr(data.EdgeEnd2Role, "myrole1")
  285. if err := gm.checkEdge(edge); err.Error() != "GraphError: Invalid data (Edge is missing a cascading value for end2)" {
  286. t.Error("Unexpected result:", err)
  287. return
  288. }
  289. edge.SetAttr(data.EdgeEnd2Cascading, true)
  290. if err := gm.checkEdge(edge); err != nil {
  291. t.Error("Unexpected result:", err)
  292. return
  293. }
  294. }
  295. func TestStringLists(t *testing.T) {
  296. stringmap := map[string]string{
  297. "test1": "testval1",
  298. }
  299. str := mapToString(stringmap)
  300. stringmap2 := stringToMap(str)
  301. if fmt.Sprint(stringmap2) != "map[test1:testval1]" {
  302. t.Error("Unexpected decoded list:", stringmap2)
  303. return
  304. }
  305. testStringDecodePanic(t)
  306. gm := newGraphManagerNoRules(graphstorage.NewMemoryGraphStorage("test"))
  307. // Test map storage
  308. gm.storeMainDBMap("mycoolmap", stringmap)
  309. // Remove the cached
  310. delete(gm.mapCache, "mycoolmap")
  311. // Map is a copy
  312. map1 := gm.getMainDBMap("mycoolmap")
  313. if &map1 != &stringmap && fmt.Sprint(map1) != fmt.Sprint(stringmap) {
  314. t.Error("Unexpected map return:", map1)
  315. return
  316. }
  317. // Map comes now from the cache
  318. map2 := gm.getMainDBMap("mycoolmap")
  319. if &map1 == &map2 {
  320. t.Error("Unexpected map return:", map1)
  321. return
  322. }
  323. }
  324. func testStringDecodePanic(t *testing.T) {
  325. defer func() {
  326. if r := recover(); r == nil {
  327. t.Error("Decoding a non encoded string did not cause a panic.")
  328. }
  329. }()
  330. stringToMap("test")
  331. }