edge_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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 dbfunc
  11. import (
  12. "fmt"
  13. "testing"
  14. "devt.de/krotik/eliasdb/graph"
  15. "devt.de/krotik/eliasdb/graph/data"
  16. "devt.de/krotik/eliasdb/graph/graphstorage"
  17. )
  18. func TestStoreAndRemoveEdge(t *testing.T) {
  19. mgs := graphstorage.NewMemoryGraphStorage("mystorage")
  20. gm := graph.NewGraphManager(mgs)
  21. se := &StoreEdgeFunc{gm}
  22. if _, err := se.DocString(); err != nil {
  23. t.Error(err)
  24. return
  25. }
  26. if _, err := se.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
  27. err.Error() != "Function requires 2 or 3 parameters: partition, edge map and optionally a transaction" {
  28. t.Error(err)
  29. return
  30. }
  31. if _, err := se.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  32. "key": "foo",
  33. }}); err == nil ||
  34. err.Error() != "GraphError: Invalid data (Edge is missing a kind value)" {
  35. t.Error(err)
  36. return
  37. }
  38. if _, err := se.Run("", nil, nil, 0, []interface{}{"main", "x"}); err == nil ||
  39. err.Error() != "Second parameter must be a map" {
  40. t.Error(err)
  41. return
  42. }
  43. if _, err := se.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  44. "key": "foo",
  45. }, "x"}); err == nil ||
  46. err.Error() != "Third parameter must be a transaction" {
  47. t.Error(err)
  48. return
  49. }
  50. gm.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  51. "key": "a",
  52. "kind": "b",
  53. }))
  54. gm.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  55. "key": "c",
  56. "kind": "d",
  57. }))
  58. if _, err := se.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  59. "key": "123",
  60. "kind": "e",
  61. "end1cascading": true,
  62. "end1key": "a",
  63. "end1kind": "b",
  64. "end1role": "role1",
  65. "end2cascading": false,
  66. "end2key": "c",
  67. "end2kind": "d",
  68. "end2role": "role2",
  69. }}); err != nil {
  70. t.Error(err)
  71. return
  72. }
  73. _, err := se.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  74. "key": "123",
  75. "kind": "e",
  76. "end1cascading": true,
  77. "end1key": "a",
  78. "end1kind": "b1",
  79. "end1role": "role1",
  80. "end2cascading": false,
  81. "end2key": "c",
  82. "end2kind": "d",
  83. "end2role": "role2",
  84. }})
  85. if err == nil || err.Error() != "GraphError: Invalid data (Can't store edge to non-existing node kind: b1)" {
  86. t.Error(err)
  87. return
  88. }
  89. fe := &FetchEdgeFunc{gm}
  90. if _, err := fe.DocString(); err != nil {
  91. t.Error(err)
  92. return
  93. }
  94. if _, err := fe.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
  95. err.Error() != "Function requires 3 parameters: partition, edge key and edge kind" {
  96. t.Error(err)
  97. return
  98. }
  99. if _, err := fe.Run("", nil, nil, 0, []interface{}{"mai n", "123", "e"}); err == nil ||
  100. err.Error() != "GraphError: Invalid data (Partition name mai n is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  101. t.Error(err)
  102. return
  103. }
  104. res, err := fe.Run("", nil, nil, 0, []interface{}{"main", "123", "e"})
  105. if fmt.Sprint(data.NewGraphEdgeFromNode(NewGraphNodeFromECALMap(res.(map[interface{}]interface{})))) != `
  106. GraphEdge:
  107. key : 123
  108. kind : e
  109. end1cascading : true
  110. end1key : a
  111. end1kind : b
  112. end1role : role1
  113. end2cascading : false
  114. end2key : c
  115. end2kind : d
  116. end2role : role2
  117. `[1:] || err != nil {
  118. t.Error("Unexpected result:", fmt.Sprint(data.NewGraphEdgeFromNode(NewGraphNodeFromECALMap(res.(map[interface{}]interface{})))), err)
  119. return
  120. }
  121. tr := &TraverseFunc{gm}
  122. if _, err := tr.DocString(); err != nil {
  123. t.Error(err)
  124. return
  125. }
  126. if _, err := tr.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
  127. err.Error() != "Function requires 4 parameters: partition, node key, node kind and a traversal spec" {
  128. t.Error(err)
  129. return
  130. }
  131. if _, err := tr.Run("", nil, nil, 0, []interface{}{"main", "c", "d", "::"}); err == nil ||
  132. err.Error() != "GraphError: Invalid data (Invalid spec: ::)" {
  133. t.Error(err)
  134. return
  135. }
  136. res, err = tr.Run("", nil, nil, 0, []interface{}{"main", "c", "d", ":::"})
  137. if err != nil {
  138. t.Error(err)
  139. return
  140. }
  141. if fmt.Sprint(data.NewGraphEdgeFromNode(NewGraphNodeFromECALMap(res.([]interface{})[1].([]interface{})[0].(map[interface{}]interface{})))) != `
  142. GraphEdge:
  143. key : 123
  144. kind : e
  145. end1cascading : false
  146. end1key : c
  147. end1kind : d
  148. end1role : role2
  149. end2cascading : true
  150. end2key : a
  151. end2kind : b
  152. end2role : role1
  153. `[1:] || err != nil {
  154. t.Error("Unexpected result:", fmt.Sprint(data.NewGraphEdgeFromNode(NewGraphNodeFromECALMap(res.([]interface{})[1].([]interface{})[0].(map[interface{}]interface{})))), err)
  155. return
  156. }
  157. if fmt.Sprint(NewGraphNodeFromECALMap(res.([]interface{})[0].([]interface{})[0].(map[interface{}]interface{}))) != `
  158. GraphNode:
  159. key : a
  160. kind : b
  161. `[1:] || err != nil {
  162. t.Error("Unexpected result:", fmt.Sprint(NewGraphNodeFromECALMap(res.([]interface{})[0].([]interface{})[0].(map[interface{}]interface{}))), err)
  163. return
  164. }
  165. re := &RemoveEdgeFunc{gm}
  166. if _, err := re.DocString(); err != nil {
  167. t.Error(err)
  168. return
  169. }
  170. if _, err := re.Run("", nil, nil, 0, []interface{}{""}); err == nil ||
  171. err.Error() != "Function requires 3 or 4 parameters: partition, edge key, edge kind and optionally a transaction" {
  172. t.Error(err)
  173. return
  174. }
  175. if _, err := re.Run("", nil, nil, 0, []interface{}{"mai n", "123", "e"}); err == nil ||
  176. err.Error() != "GraphError: Invalid data (Partition name mai n is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  177. t.Error(err)
  178. return
  179. }
  180. if _, err := re.Run("", nil, nil, 0, []interface{}{"mai n", "123", "e", "bla"}); err == nil ||
  181. err.Error() != "Fourth parameter must be a transaction" {
  182. t.Error(err)
  183. return
  184. }
  185. if _, err := re.Run("", nil, nil, 0, []interface{}{"main", "123", "e"}); err != nil {
  186. t.Error(err)
  187. return
  188. }
  189. res, err = fe.Run("", nil, nil, 0, []interface{}{"main", "123", "e"})
  190. if res != nil || err != nil {
  191. t.Error("Unexpected result:", res, err)
  192. return
  193. }
  194. }
  195. func TestStoreEdgeTrans(t *testing.T) {
  196. mgs := graphstorage.NewMemoryGraphStorage("mystorage")
  197. gm := graph.NewGraphManager(mgs)
  198. sn := &StoreNodeFunc{gm}
  199. se := &StoreEdgeFunc{gm}
  200. tc := &CommitTransFunc{gm}
  201. if _, err := tc.DocString(); err != nil {
  202. t.Error(err)
  203. return
  204. }
  205. trans := graph.NewGraphTrans(gm)
  206. if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  207. "key": "a",
  208. "kind": "b",
  209. }, trans}); err != nil {
  210. t.Error(err)
  211. return
  212. }
  213. if _, err := sn.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  214. "key": "c",
  215. "kind": "d",
  216. }, trans}); err != nil {
  217. t.Error(err)
  218. return
  219. }
  220. _, err := se.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  221. "key": "123",
  222. "kind": "e",
  223. "end1cascading": true,
  224. "end1key": "a",
  225. "end1kind": "b",
  226. "end1role": "role1",
  227. "end2cascading": false,
  228. "end2key": "c",
  229. "end2kind": "d",
  230. "end2role": "role2",
  231. }, trans})
  232. if err != nil {
  233. t.Error(err)
  234. return
  235. }
  236. if res := fmt.Sprint(trans.Counts()); res != "2 1 0 0" {
  237. t.Error("Unexpected result:", res)
  238. return
  239. }
  240. if _, err := tc.Run("", nil, nil, 0, []interface{}{trans}); err != nil {
  241. t.Error(err)
  242. return
  243. }
  244. // Check that the nodes have been committed
  245. if res := fmt.Sprint(trans.Counts()); res != "0 0 0 0" {
  246. t.Error("Unexpected result:", res)
  247. return
  248. }
  249. if res := gm.EdgeCount("e"); res != 1 {
  250. t.Error("Unexpected result:", res)
  251. return
  252. }
  253. se.Run("", nil, nil, 0, []interface{}{"main", map[interface{}]interface{}{
  254. "key": "123",
  255. "kind": "e",
  256. "end1cascading": true,
  257. "end1key": "a",
  258. "end1kind": "b",
  259. "end1role": "role1",
  260. "end2cascading": false,
  261. "end2key": "c1",
  262. "end2kind": "d",
  263. "end2role": "role2",
  264. }, trans})
  265. if _, err := tc.Run("", nil, nil, 0, []interface{}{trans}); err == nil || err.Error() !=
  266. "GraphError: Invalid data (Can't find edge endpoint: c1 (d))" {
  267. t.Error(err)
  268. return
  269. }
  270. re := &RemoveEdgeFunc{}
  271. if _, err := re.DocString(); err != nil {
  272. t.Error(err)
  273. return
  274. }
  275. if _, err := re.Run("", nil, nil, 0, []interface{}{"main", "123", "e", trans}); err != nil {
  276. t.Error(err)
  277. return
  278. }
  279. if res := fmt.Sprint(trans.Counts()); res != "0 0 0 1" {
  280. t.Error("Unexpected result:", res)
  281. return
  282. }
  283. if _, err := tc.Run("", nil, nil, 0, []interface{}{trans}); err != nil {
  284. t.Error(err)
  285. return
  286. }
  287. if res := fmt.Sprint(trans.Counts()); res != "0 0 0 0" {
  288. t.Error("Unexpected result:", res)
  289. return
  290. }
  291. if res := gm.EdgeCount("e"); res != 0 {
  292. t.Error("Unexpected result:", res)
  293. return
  294. }
  295. }