rest_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. req.Header.Set("Content-Type", "application/json")
  73. client := &http.Client{}
  74. resp, err := client.Do(req)
  75. if err != nil {
  76. panic(err)
  77. }
  78. defer resp.Body.Close()
  79. body, _ := ioutil.ReadAll(resp.Body)
  80. bodyStr := strings.Trim(string(body), " \n")
  81. // Try json decoding first
  82. out := bytes.Buffer{}
  83. err = json.Indent(&out, []byte(bodyStr), "", " ")
  84. if err == nil {
  85. return resp.Status, resp.Header, out.String()
  86. }
  87. // Just return the body
  88. return resp.Status, resp.Header, bodyStr
  89. }
  90. /*
  91. formatJSONString formats a given JSON string.
  92. */
  93. func formatJSONString(str string) string {
  94. out := bytes.Buffer{}
  95. errorutil.AssertOk(json.Indent(&out, []byte(str), "", " "))
  96. return out.String()
  97. }
  98. /*
  99. formatData returns a given datastructure as JSON string.
  100. */
  101. func formatData(data interface{}) string {
  102. actualResultBytes, _ := json.MarshalIndent(data, "", " ")
  103. return string(actualResultBytes)
  104. }
  105. /*
  106. Start a HTTP test server.
  107. */
  108. func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {
  109. hs := &httputil.HTTPServer{}
  110. var wg sync.WaitGroup
  111. wg.Add(1)
  112. go hs.RunHTTPServer(TESTPORT, &wg)
  113. wg.Wait()
  114. // Server is started
  115. if hs.LastError != nil {
  116. panic(hs.LastError)
  117. }
  118. return hs, &wg
  119. }
  120. /*
  121. Stop a started HTTP test server.
  122. */
  123. func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {
  124. if hs.Running == true {
  125. wg.Add(1)
  126. // Server is shut down
  127. hs.Shutdown()
  128. wg.Wait()
  129. } else {
  130. panic("Server was not running as expected")
  131. }
  132. }
  133. func songGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
  134. mgs := graphstorage.NewMemoryGraphStorage("mystorage")
  135. gm := graph.NewGraphManager(mgs)
  136. constructEdge := func(key string, node1 data.Node, node2 data.Node, number int) data.Edge {
  137. edge := data.NewGraphEdge()
  138. edge.SetAttr("key", key)
  139. edge.SetAttr("kind", "Wrote")
  140. edge.SetAttr(data.EdgeEnd1Key, node1.Key())
  141. edge.SetAttr(data.EdgeEnd1Kind, node1.Kind())
  142. edge.SetAttr(data.EdgeEnd1Role, "Author")
  143. edge.SetAttr(data.EdgeEnd1Cascading, true)
  144. edge.SetAttr(data.EdgeEnd2Key, node2.Key())
  145. edge.SetAttr(data.EdgeEnd2Kind, node2.Kind())
  146. edge.SetAttr(data.EdgeEnd2Role, "Song")
  147. edge.SetAttr(data.EdgeEnd2Cascading, false)
  148. edge.SetAttr("number", number)
  149. return edge
  150. }
  151. storeSong := func(node data.Node, name string, ranking int, number int) {
  152. node3 := data.NewGraphNode()
  153. node3.SetAttr("key", name)
  154. node3.SetAttr("kind", "Song")
  155. node3.SetAttr("name", name)
  156. node3.SetAttr("ranking", ranking)
  157. gm.StoreNode("main", node3)
  158. gm.StoreEdge("main", constructEdge(name, node, node3, number))
  159. }
  160. node0 := data.NewGraphNode()
  161. node0.SetAttr("key", "000")
  162. node0.SetAttr("kind", "Author")
  163. node0.SetAttr("name", "John")
  164. node0.SetAttr("desc", "One of the most popular acoustic artists of the decade and one of its best-selling artists.")
  165. gm.StoreNode("main", node0)
  166. gm.StoreNode("test", node0) // Same node but different partition
  167. gm.StoreNode("_test", node0) // Same node but different (hidden) partition
  168. storeSong(node0, "Aria1", 8, 1)
  169. storeSong(node0, "Aria2", 2, 2)
  170. storeSong(node0, "Aria3", 4, 3)
  171. storeSong(node0, "Aria4", 18, 4)
  172. node1 := data.NewGraphNode()
  173. node1.SetAttr("key", "123")
  174. node1.SetAttr("kind", "Author")
  175. node1.SetAttr("name", "Mike")
  176. gm.StoreNode("main", node1)
  177. storeSong(node1, "LoveSong3", 1, 3)
  178. storeSong(node1, "FightSong4", 3, 4)
  179. storeSong(node1, "DeadSong2", 6, 2)
  180. storeSong(node1, "StrangeSong1", 5, 1)
  181. node2 := data.NewGraphNode()
  182. node2.SetAttr("key", "456")
  183. node2.SetAttr("kind", "Author")
  184. node2.SetAttr("name", "Hans")
  185. gm.StoreNode("main", node2)
  186. storeSong(node2, "MyOnlySong3", 19, 3)
  187. // Create lots of spam nodes
  188. for i := 0; i < 21; i++ {
  189. nodespam := data.NewGraphNode()
  190. nodespam.SetAttr("key", "000"+strconv.Itoa(i))
  191. nodespam.SetAttr("kind", "Spam")
  192. nodespam.SetAttr("name", "Spam"+strconv.Itoa(i))
  193. gm.StoreNode("main", nodespam)
  194. }
  195. return gm, mgs.(*graphstorage.MemoryGraphStorage)
  196. }
  197. func songGraphGroups() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
  198. gm, mgs := songGraph()
  199. node0 := data.NewGraphNode()
  200. node0.SetAttr("key", "Best")
  201. node0.SetAttr("kind", eql.GroupNodeKind)
  202. gm.StoreNode("main", node0)
  203. constructEdge := func(songkey string) data.Edge {
  204. edge := data.NewGraphEdge()
  205. edge.SetAttr("key", songkey)
  206. edge.SetAttr("kind", "Contains")
  207. edge.SetAttr(data.EdgeEnd1Key, node0.Key())
  208. edge.SetAttr(data.EdgeEnd1Kind, node0.Kind())
  209. edge.SetAttr(data.EdgeEnd1Role, "group")
  210. edge.SetAttr(data.EdgeEnd1Cascading, false)
  211. edge.SetAttr(data.EdgeEnd2Key, songkey)
  212. edge.SetAttr(data.EdgeEnd2Kind, "Song")
  213. edge.SetAttr(data.EdgeEnd2Role, "Song")
  214. edge.SetAttr(data.EdgeEnd2Cascading, false)
  215. return edge
  216. }
  217. gm.StoreEdge("main", constructEdge("LoveSong3"))
  218. gm.StoreEdge("main", constructEdge("Aria3"))
  219. gm.StoreEdge("main", constructEdge("MyOnlySong3"))
  220. gm.StoreEdge("main", constructEdge("StrangeSong1"))
  221. // Store additional groups
  222. node0 = data.NewGraphNode()
  223. node0.SetAttr("key", "foo")
  224. node0.SetAttr("kind", eql.GroupNodeKind)
  225. gm.StoreNode("main", node0)
  226. node0 = data.NewGraphNode()
  227. node0.SetAttr("key", "g1")
  228. node0.SetAttr("kind", eql.GroupNodeKind)
  229. gm.StoreNode("main", node0)
  230. node0 = data.NewGraphNode()
  231. node0.SetAttr("key", "g2")
  232. node0.SetAttr("kind", eql.GroupNodeKind)
  233. gm.StoreNode("main", node0)
  234. return gm, mgs
  235. }
  236. func filterGraph() (*graph.Manager, *graphstorage.MemoryGraphStorage) {
  237. gm, mgs := songGraphGroups()
  238. constructNode := func(key, val1, val2, val3 string) data.Node {
  239. node0 := data.NewGraphNode()
  240. node0.SetAttr("key", key)
  241. node0.SetAttr("kind", "filtertest")
  242. node0.SetAttr("val1", val1)
  243. node0.SetAttr("val2", val2)
  244. node0.SetAttr("val3", val3)
  245. return node0
  246. }
  247. gm.StoreNode("main", constructNode("1", "test", "Hans", "foo"))
  248. gm.StoreNode("main", constructNode("2", "test1", "Hans", "foo"))
  249. gm.StoreNode("main", constructNode("3", "test2", "Hans", "foo"))
  250. gm.StoreNode("main", constructNode("4", "test3", "Peter", "foo"))
  251. gm.StoreNode("main", constructNode("5", "test4", "Peter", "foo"))
  252. gm.StoreNode("main", constructNode("6", "test5", "Peter", "foo"))
  253. gm.StoreNode("main", constructNode("7", "test6", "Anna", "foo"))
  254. gm.StoreNode("main", constructNode("8", "test7", "Anna", "foo"))
  255. gm.StoreNode("main", constructNode("9", "test8", "Steve", "foo"))
  256. gm.StoreNode("main", constructNode("10", "test9", "Steve", "foo"))
  257. gm.StoreNode("main", constructNode("11", "test10", "Franz", "foo"))
  258. gm.StoreNode("main", constructNode("12", "test11", "Kevin", "foo"))
  259. gm.StoreNode("main", constructNode("13", "test12", "Kevin", "foo"))
  260. gm.StoreNode("main", constructNode("14", "test13", "Kevin", "foo"))
  261. gm.StoreNode("main", constructNode("15", "test14", "X1", "foo"))
  262. gm.StoreNode("main", constructNode("16", "test15", "X2", "foo"))
  263. gm.StoreNode("main", constructNode("17", "test16", "X3", "foo"))
  264. gm.StoreNode("main", constructNode("18", "test17", "X4", "foo"))
  265. gm.StoreNode("main", constructNode("19", "test18", "X5", "foo"))
  266. return gm, mgs
  267. }