rest_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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 v1
  11. import (
  12. "bytes"
  13. "encoding/json"
  14. "flag"
  15. "io/ioutil"
  16. "net/http"
  17. "os"
  18. "strconv"
  19. "strings"
  20. "sync"
  21. "testing"
  22. "devt.de/krotik/common/errorutil"
  23. "devt.de/krotik/common/httputil"
  24. "devt.de/krotik/eliasdb/api"
  25. "devt.de/krotik/eliasdb/eql"
  26. "devt.de/krotik/eliasdb/graph"
  27. "devt.de/krotik/eliasdb/graph/data"
  28. "devt.de/krotik/eliasdb/graph/graphstorage"
  29. )
  30. const TESTPORT = ":9090"
  31. var gmMSM *graphstorage.MemoryGraphStorage
  32. // Main function for all tests in this package
  33. func TestMain(m *testing.M) {
  34. flag.Parse()
  35. gm, msm := filterGraph()
  36. api.GM = gm
  37. api.GS = msm
  38. gmMSM = msm
  39. hs, wg := startServer()
  40. if hs == nil {
  41. return
  42. }
  43. // Register endpoints for version 1
  44. api.RegisterRestEndpoints(V1EndpointMap)
  45. // Run the tests
  46. res := m.Run()
  47. // Teardown
  48. stopServer(hs, wg)
  49. os.Exit(res)
  50. }
  51. func TestSwaggerDefs(t *testing.T) {
  52. // Test we can build swagger defs from the endpoint
  53. data := map[string]interface{}{
  54. "paths": map[string]interface{}{},
  55. "definitions": map[string]interface{}{},
  56. }
  57. for _, inst := range V1EndpointMap {
  58. inst().SwaggerDefs(data)
  59. }
  60. }
  61. /*
  62. Send a request to a HTTP test server
  63. */
  64. func sendTestRequest(url string, method string, content []byte) (string, http.Header, string) {
  65. var req *http.Request
  66. var err error
  67. if content != nil {
  68. req, err = http.NewRequest(method, url, bytes.NewBuffer(content))
  69. } else {
  70. req, err = http.NewRequest(method, url, nil)
  71. }
  72. if err != nil {
  73. panic(err)
  74. }
  75. req.Header.Set("Content-Type", "application/json")
  76. client := &http.Client{}
  77. resp, err := client.Do(req)
  78. if err != nil {
  79. panic(err)
  80. }
  81. defer resp.Body.Close()
  82. body, _ := ioutil.ReadAll(resp.Body)
  83. bodyStr := strings.Trim(string(body), " \n")
  84. // Try json decoding first
  85. out := bytes.Buffer{}
  86. err = json.Indent(&out, []byte(bodyStr), "", " ")
  87. if err == nil {
  88. return resp.Status, resp.Header, out.String()
  89. }
  90. // Just return the body
  91. return resp.Status, resp.Header, bodyStr
  92. }
  93. /*
  94. formatJSONString formats a given JSON string.
  95. */
  96. func formatJSONString(str string) string {
  97. out := bytes.Buffer{}
  98. errorutil.AssertOk(json.Indent(&out, []byte(str), "", " "))
  99. return out.String()
  100. }
  101. /*
  102. formatData returns a given datastructure as JSON string.
  103. */
  104. func formatData(data interface{}) string {
  105. actualResultBytes, _ := json.MarshalIndent(data, "", " ")
  106. return string(actualResultBytes)
  107. }
  108. /*
  109. Start a HTTP test server.
  110. */
  111. func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {
  112. hs := &httputil.HTTPServer{}
  113. var wg sync.WaitGroup
  114. wg.Add(1)
  115. go hs.RunHTTPServer(TESTPORT, &wg)
  116. wg.Wait()
  117. // Server is started
  118. if hs.LastError != nil {
  119. panic(hs.LastError)
  120. }
  121. return hs, &wg
  122. }
  123. /*
  124. Stop a started HTTP test server.
  125. */
  126. func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {
  127. if hs.Running == true {
  128. wg.Add(1)
  129. // Server is shut down
  130. hs.Shutdown()
  131. wg.Wait()
  132. } else {
  133. panic("Server was not running as expected")
  134. }
  135. }
  136. func songGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
  137. mgs := graphstorage.NewMemoryGraphStorage("mystorage")
  138. gm := graph.NewGraphManager(mgs)
  139. constructEdge := func(key string, node1 data.Node, node2 data.Node, number int) data.Edge {
  140. edge := data.NewGraphEdge()
  141. edge.SetAttr("key", key)
  142. edge.SetAttr("kind", "Wrote")
  143. edge.SetAttr(data.EdgeEnd1Key, node1.Key())
  144. edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())
  145. edge.SetAttr(data.EdgeEnd1Role, "Author")
  146. edge.SetAttr(data.EdgeEnd1Cascading, true)
  147. edge.SetAttr(data.EdgeEnd2Key, node2.Key())
  148. edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())
  149. edge.SetAttr(data.EdgeEnd2Role, "Song")
  150. edge.SetAttr(data.EdgeEnd2Cascading, false)
  151. edge.SetAttr("number", number)
  152. return edge
  153. }
  154. storeSong := func(node data.Node, name string, ranking int, number int) {
  155. node3 := data.NewGraphNode()
  156. node3.SetAttr("key", name)
  157. node3.SetAttr("kind", "Song")
  158. node3.SetAttr("name", name)
  159. node3.SetAttr("ranking", ranking)
  160. gm.StoreNode("main", node3)
  161. gm.StoreEdge("main", constructEdge(name, node, node3, number))
  162. }
  163. node0 := data.NewGraphNode()
  164. node0.SetAttr("key", "000")
  165. node0.SetAttr("kind", "Author")
  166. node0.SetAttr("name", "John")
  167. node0.SetAttr("desc", "One of the most popular acoustic artists of the decade and one of its best-selling artists.")
  168. gm.StoreNode("main", node0)
  169. gm.StoreNode("test", node0) // Same node but different partition
  170. gm.StoreNode("_test", node0) // Same node but different (hidden) partition
  171. storeSong(node0, "Aria1", 8, 1)
  172. storeSong(node0, "Aria2", 2, 2)
  173. storeSong(node0, "Aria3", 4, 3)
  174. storeSong(node0, "Aria4", 18, 4)
  175. node1 := data.NewGraphNode()
  176. node1.SetAttr("key", "123")
  177. node1.SetAttr("kind", "Author")
  178. node1.SetAttr("name", "Mike")
  179. gm.StoreNode("main", node1)
  180. storeSong(node1, "LoveSong3", 1, 3)
  181. storeSong(node1, "FightSong4", 3, 4)
  182. storeSong(node1, "DeadSong2", 6, 2)
  183. storeSong(node1, "StrangeSong1", 5, 1)
  184. node2 := data.NewGraphNode()
  185. node2.SetAttr("key", "456")
  186. node2.SetAttr("kind", "Author")
  187. node2.SetAttr("name", "Hans")
  188. gm.StoreNode("main", node2)
  189. storeSong(node2, "MyOnlySong3", 19, 3)
  190. // Create lots of spam nodes
  191. for i := 0; i < 21; i++ {
  192. nodespam := data.NewGraphNode()
  193. nodespam.SetAttr("key", "000"+strconv.Itoa(i))
  194. nodespam.SetAttr("kind", "Spam")
  195. nodespam.SetAttr("name", "Spam"+strconv.Itoa(i))
  196. gm.StoreNode("main", nodespam)
  197. }
  198. return gm, mgs.(*graphstorage.MemoryGraphStorage)
  199. }
  200. func songGraphGroups() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
  201. gm, mgs := songGraph()
  202. node0 := data.NewGraphNode()
  203. node0.SetAttr("key", "Best")
  204. node0.SetAttr("kind", eql.GroupNodeKind)
  205. gm.StoreNode("main", node0)
  206. constructEdge := func(songkey string) data.Edge {
  207. edge := data.NewGraphEdge()
  208. edge.SetAttr("key", songkey)
  209. edge.SetAttr("kind", "Contains")
  210. edge.SetAttr(data.EdgeEnd1Key, node0.Key())
  211. edge.SetAttr(data.EdgeEnd1Kind, node0.Kind())
  212. edge.SetAttr(data.EdgeEnd1Role, "group")
  213. edge.SetAttr(data.EdgeEnd1Cascading, false)
  214. edge.SetAttr(data.EdgeEnd2Key, songkey)
  215. edge.SetAttr(data.EdgeEnd2Kind, "Song")
  216. edge.SetAttr(data.EdgeEnd2Role, "Song")
  217. edge.SetAttr(data.EdgeEnd2Cascading, false)
  218. return edge
  219. }
  220. gm.StoreEdge("main", constructEdge("LoveSong3"))
  221. gm.StoreEdge("main", constructEdge("Aria3"))
  222. gm.StoreEdge("main", constructEdge("MyOnlySong3"))
  223. gm.StoreEdge("main", constructEdge("StrangeSong1"))
  224. // Store additional groups
  225. node0 = data.NewGraphNode()
  226. node0.SetAttr("key", "foo")
  227. node0.SetAttr("kind", eql.GroupNodeKind)
  228. gm.StoreNode("main", node0)
  229. node0 = data.NewGraphNode()
  230. node0.SetAttr("key", "g1")
  231. node0.SetAttr("kind", eql.GroupNodeKind)
  232. gm.StoreNode("main", node0)
  233. node0 = data.NewGraphNode()
  234. node0.SetAttr("key", "g2")
  235. node0.SetAttr("kind", eql.GroupNodeKind)
  236. gm.StoreNode("main", node0)
  237. return gm, mgs
  238. }
  239. func filterGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
  240. gm, mgs := songGraphGroups()
  241. constructNode := func(key, val1, val2, val3 string) data.Node {
  242. node0 := data.NewGraphNode()
  243. node0.SetAttr("key", key)
  244. node0.SetAttr("kind", "filtertest")
  245. node0.SetAttr("val1", val1)
  246. node0.SetAttr("val2", val2)
  247. node0.SetAttr("val3", val3)
  248. return node0
  249. }
  250. gm.StoreNode("main", constructNode("1", "test", "Hans", "foo"))
  251. gm.StoreNode("main", constructNode("2", "test1", "Hans", "foo"))
  252. gm.StoreNode("main", constructNode("3", "test2", "Hans", "foo"))
  253. gm.StoreNode("main", constructNode("4", "test3", "Peter", "foo"))
  254. gm.StoreNode("main", constructNode("5", "test4", "Peter", "foo"))
  255. gm.StoreNode("main", constructNode("6", "test5", "Peter", "foo"))
  256. gm.StoreNode("main", constructNode("7", "test6", "Anna", "foo"))
  257. gm.StoreNode("main", constructNode("8", "test7", "Anna", "foo"))
  258. gm.StoreNode("main", constructNode("9", "test8", "Steve", "foo"))
  259. gm.StoreNode("main", constructNode("10", "test9", "Steve", "foo"))
  260. gm.StoreNode("main", constructNode("11", "test10", "Franz", "foo"))
  261. gm.StoreNode("main", constructNode("12", "test11", "Kevin", "foo"))
  262. gm.StoreNode("main", constructNode("13", "test12", "Kevin", "foo"))
  263. gm.StoreNode("main", constructNode("14", "test13", "Kevin", "foo"))
  264. gm.StoreNode("main", constructNode("15", "test14", "X1", "foo"))
  265. gm.StoreNode("main", constructNode("16", "test15", "X2", "foo"))
  266. gm.StoreNode("main", constructNode("17", "test16", "X3", "foo"))
  267. gm.StoreNode("main", constructNode("18", "test17", "X4", "foo"))
  268. gm.StoreNode("main", constructNode("19", "test18", "X5", "foo"))
  269. return gm, mgs
  270. }