import_export_test.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. "bytes"
  13. "strings"
  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 TestImportExportError(t *testing.T) {
  20. var res bytes.Buffer
  21. // Create a memory only storage
  22. gs := graphstorage.NewMemoryGraphStorage("test")
  23. gm := NewGraphManager(gs)
  24. // Test incomplete import data
  25. err := ImportPartition(bytes.NewBufferString(`
  26. {
  27. "nodes" : [
  28. {
  29. "key": "1",
  30. "kind": "X",
  31. `), "main", gm)
  32. if err == nil || err.Error() != "Could not decode file content as object with list of nodes and edges: unexpected EOF" {
  33. t.Error("Unexpected result:", err)
  34. return
  35. }
  36. // Export an empty graph
  37. err = ExportPartition(&res, "aaa", gm)
  38. if err != nil || res.String() != `{
  39. "nodes" : [
  40. ],
  41. "edges" : [
  42. ]
  43. }` {
  44. t.Error("Unexpected result:", res.String(), err)
  45. return
  46. }
  47. // Try exporting nodes with unexportable attibutes
  48. err = gm.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  49. "key": "123",
  50. "kind": "bla",
  51. "test": data.NewGraphNode,
  52. }))
  53. if err != nil {
  54. t.Error(err)
  55. return
  56. }
  57. res.Reset()
  58. err = ExportPartition(&res, "main", gm)
  59. sortRes := SortDump(res.String())
  60. if err != nil || sortRes != `{
  61. "edges": [],
  62. "nodes": [
  63. {
  64. "key": "123",
  65. "kind": "bla",
  66. "test": null
  67. }
  68. ]
  69. }` {
  70. t.Error("Unexpected result:", sortRes, err)
  71. return
  72. }
  73. // Error when reading a node
  74. msm := gs.StorageManager("main"+"bla"+StorageSuffixNodes, false).(*storage.MemoryStorageManager)
  75. msm.AccessMap[1] = storage.AccessCacheAndFetchSeriousError
  76. res.Reset()
  77. err = ExportPartition(&res, "main", gm)
  78. if !strings.HasPrefix(err.Error(), "GraphError: Failed to access graph storage component") {
  79. t.Error("Unexpected graph error:", err)
  80. return
  81. }
  82. delete(msm.AccessMap, 1)
  83. err = gm.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  84. "key": "456",
  85. "kind": "bla",
  86. "test": data.NewGraphNode,
  87. }))
  88. msm = gs.StorageManager("main"+"bla"+StorageSuffixNodes, false).(*storage.MemoryStorageManager)
  89. msm.AccessMap[6] = storage.AccessCacheAndFetchSeriousError
  90. res.Reset()
  91. err = ExportPartition(&res, "main", gm)
  92. if !strings.HasPrefix(err.Error(), "GraphError: Could not read graph information") {
  93. t.Error("Unexpected graph error:", err)
  94. return
  95. }
  96. delete(msm.AccessMap, 6)
  97. msm.AccessMap[5] = storage.AccessCacheAndFetchSeriousError
  98. res.Reset()
  99. err = ExportPartition(&res, "main", gm)
  100. if !strings.HasPrefix(err.Error(), "GraphError: Could not read graph information") {
  101. t.Error("Unexpected graph error:", err)
  102. return
  103. }
  104. delete(msm.AccessMap, 5)
  105. gm.StoreEdge("main", data.NewGraphEdgeFromNode(data.NewGraphNodeFromMap(map[string]interface{}{
  106. "end1cascading": false,
  107. "end1key": "123",
  108. "end1kind": "bla",
  109. "end1role": "node",
  110. "end2cascading": false,
  111. "end2key": "456",
  112. "end2kind": "bla",
  113. "end2role": "node",
  114. "key": "3",
  115. "kind": "xxx",
  116. })))
  117. // Traverse to relationship should fail
  118. msm.AccessMap[7] = storage.AccessCacheAndFetchSeriousError
  119. res.Reset()
  120. err = ExportPartition(&res, "main", gm)
  121. if !strings.HasPrefix(err.Error(), "GraphError: Could not read graph information") {
  122. t.Error("Unexpected graph error:", err)
  123. return
  124. }
  125. delete(msm.AccessMap, 7)
  126. // Lookup of relationship should fail
  127. msm = gs.StorageManager("main"+"xxx"+StorageSuffixEdges, false).(*storage.MemoryStorageManager)
  128. msm.AccessMap[1] = storage.AccessCacheAndFetchSeriousError
  129. res.Reset()
  130. err = ExportPartition(&res, "main", gm)
  131. if !strings.HasPrefix(err.Error(), "GraphError: Failed to access graph storage component") {
  132. t.Error("Unexpected graph error:", err)
  133. return
  134. }
  135. delete(msm.AccessMap, 1)
  136. // Test invalid import data
  137. err = ImportPartition(bytes.NewBufferString(`{
  138. "nodes" : [
  139. {
  140. "key": "1",
  141. "kind": "X"
  142. },
  143. {
  144. "key": "2"
  145. }
  146. ],
  147. "edges" : [
  148. {
  149. "end1cascading": false,
  150. "end1key": "1",
  151. "end1kind": "X",
  152. "end1role": "node",
  153. "end2cascading": false,
  154. "end2key": "2",
  155. "end2kind": "Y",
  156. "end2role": "node",
  157. "key": "4",
  158. "kind": "A"
  159. }
  160. ]
  161. }`), "main", gm)
  162. if err == nil || err.Error() != "GraphError: Invalid data (Node is missing a kind value)" {
  163. t.Error("Unexpected result:", err)
  164. return
  165. }
  166. err = ImportPartition(bytes.NewBufferString(`{
  167. "nodes" : [
  168. {
  169. "key": "1",
  170. "kind": "X"
  171. },
  172. {
  173. "key": "2",
  174. "kind": "Y"
  175. }
  176. ],
  177. "edges" : [
  178. {
  179. "end1cascading": false,
  180. "end1key": "1",
  181. "end1kind": "X",
  182. "end1role": "node",
  183. "end2key": "2",
  184. "end2kind": "Y",
  185. "end2role": "node",
  186. "key": "4",
  187. "kind": "A"
  188. }
  189. ]
  190. }`), "main", gm)
  191. if err == nil || err.Error() != "GraphError: Invalid data (Edge is missing a cascading value for end2)" {
  192. t.Error("Unexpected result:", err)
  193. return
  194. }
  195. // Do actual import and exports
  196. gs = graphstorage.NewMemoryGraphStorage("test")
  197. gm = NewGraphManager(gs)
  198. err = ImportPartition(bytes.NewBufferString(`{
  199. "nodes" : [
  200. {
  201. "key": "1",
  202. "kind": "X"
  203. },
  204. {
  205. "key": "2",
  206. "kind": "Y"
  207. }
  208. ],
  209. "edges" : [
  210. {
  211. "end1cascading": false,
  212. "end1key": "1",
  213. "end1kind": "X",
  214. "end1role": "node",
  215. "end2cascading": false,
  216. "end2key": "2",
  217. "end2kind": "Y",
  218. "end2role": "node",
  219. "key": "4",
  220. "kind": "A"
  221. },
  222. {
  223. "end1cascading": false,
  224. "end1key": "1",
  225. "end1kind": "X",
  226. "end1role": "node",
  227. "end2cascading": false,
  228. "end2key": "2",
  229. "end2kind": "Y",
  230. "end2role": "node",
  231. "key": "5",
  232. "kind": "B"
  233. }
  234. ]
  235. }`), "main", gm)
  236. if err != nil {
  237. t.Error(err)
  238. return
  239. }
  240. err = ImportPartition(bytes.NewBufferString(`{
  241. "nodes" : [
  242. {
  243. "key": "1",
  244. "kind": "Xfoo"
  245. },
  246. {
  247. "key": "2",
  248. "kind": "Yfoo"
  249. }
  250. ],
  251. "edges" : [
  252. {
  253. "end1cascading": false,
  254. "end1key": "1",
  255. "end1kind": "Xfoo",
  256. "end1role": "node",
  257. "end2cascading": false,
  258. "end2key": "2",
  259. "end2kind": "Yfoo",
  260. "end2role": "node",
  261. "key": "4",
  262. "kind": "Afoo"
  263. },
  264. {
  265. "end1cascading": false,
  266. "end1key": "1",
  267. "end1kind": "Xfoo",
  268. "end1role": "node",
  269. "end2cascading": false,
  270. "end2key": "2",
  271. "end2kind": "Yfoo",
  272. "end2role": "node",
  273. "key": "5",
  274. "kind": "Bfoo"
  275. }
  276. ]
  277. }`), "foo", gm)
  278. if err != nil {
  279. t.Error(err)
  280. return
  281. }
  282. res.Reset()
  283. err = ExportPartition(&res, "main", gm)
  284. sortRes = SortDump(res.String())
  285. if err != nil || sortRes != `{
  286. "edges": [
  287. {
  288. "end1cascading": false,
  289. "end1key": "1",
  290. "end1kind": "X",
  291. "end1role": "node",
  292. "end2cascading": false,
  293. "end2key": "2",
  294. "end2kind": "Y",
  295. "end2role": "node",
  296. "key": "4",
  297. "kind": "A"
  298. },
  299. {
  300. "end1cascading": false,
  301. "end1key": "1",
  302. "end1kind": "X",
  303. "end1role": "node",
  304. "end2cascading": false,
  305. "end2key": "2",
  306. "end2kind": "Y",
  307. "end2role": "node",
  308. "key": "5",
  309. "kind": "B"
  310. }
  311. ],
  312. "nodes": [
  313. {
  314. "key": "1",
  315. "kind": "X"
  316. },
  317. {
  318. "key": "2",
  319. "kind": "Y"
  320. }
  321. ]
  322. }` {
  323. t.Error("Unexpected result:", sortRes, err)
  324. return
  325. }
  326. // Do an import with the export data and see that nothing changes
  327. err = ImportPartition(bytes.NewBufferString(sortRes), "main", gm)
  328. if err != nil {
  329. t.Error(err)
  330. return
  331. }
  332. res.Reset()
  333. err = ExportPartition(&res, "main", gm)
  334. if err != nil {
  335. t.Error(err)
  336. return
  337. }
  338. sortRes2 := SortDump(res.String())
  339. if sortRes2 != sortRes {
  340. t.Error("Export data differs from import data:", sortRes2)
  341. return
  342. }
  343. }