graphql-subscriptions_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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. "fmt"
  13. "testing"
  14. "devt.de/krotik/eliasdb/api"
  15. "devt.de/krotik/eliasdb/graph/data"
  16. "devt.de/krotik/eliasdb/storage"
  17. "github.com/gorilla/websocket"
  18. )
  19. func TestGraphQLSubscriptionConnectionErrors(t *testing.T) {
  20. queryURL := "http://localhost" + TESTPORT + EndpointGraphQLSubscriptions
  21. _, _, res := sendTestRequest(queryURL+"main", "GET", nil)
  22. if res != `Bad Request
  23. websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header` {
  24. t.Error("Unexpected response:", res)
  25. return
  26. }
  27. }
  28. func TestGraphQLSubscriptionMissingPartition(t *testing.T) {
  29. queryURL := "ws://localhost" + TESTPORT + EndpointGraphQLSubscriptions
  30. // Test missing partition
  31. c, _, err := websocket.DefaultDialer.Dial(queryURL, nil)
  32. if err != nil {
  33. t.Error("Could not open websocket:", err)
  34. return
  35. }
  36. _, message, err := c.ReadMessage()
  37. if msg := formatJSONString(string(message)); err != nil || msg != `{
  38. "id": "",
  39. "payload": {
  40. "errors": [
  41. "Need a 'partition' in path or as url parameter"
  42. ]
  43. },
  44. "type": "subscription_fail"
  45. }` {
  46. t.Error("Unexpected response:", msg, err)
  47. return
  48. }
  49. _, _, err = c.ReadMessage()
  50. if err == nil || err.Error() != "websocket: close 1003 (unsupported data): Need a 'partition' in path or as url parameter" {
  51. t.Error("Unexpected response:", err)
  52. return
  53. }
  54. if err = c.Close(); err != nil {
  55. t.Error("Could not close websocket:", err)
  56. return
  57. }
  58. }
  59. func TestGraphQLSubscription(t *testing.T) {
  60. queryURL := "ws://localhost" + TESTPORT + EndpointGraphQLSubscriptions + "main"
  61. // Test missing partition
  62. c, _, err := websocket.DefaultDialer.Dial(queryURL, nil)
  63. if err != nil {
  64. t.Error("Could not open websocket:", err)
  65. return
  66. }
  67. _, message, err := c.ReadMessage()
  68. if msg := formatJSONString(string(message)); err != nil || msg != `{
  69. "type": "init_success",
  70. "payload": {}
  71. }` {
  72. t.Error("Unexpected response:", msg, err)
  73. return
  74. }
  75. err = c.WriteMessage(websocket.TextMessage, []byte("buu"))
  76. if err != nil {
  77. t.Error("Could not send message:", err)
  78. return
  79. }
  80. _, message, err = c.ReadMessage()
  81. if msg := formatJSONString(string(message)); err != nil || msg != `{
  82. "id": "",
  83. "payload": {
  84. "errors": [
  85. "invalid character 'b' looking for beginning of value"
  86. ]
  87. },
  88. "type": "subscription_fail"
  89. }` {
  90. t.Error("Unexpected response:", msg, err)
  91. return
  92. }
  93. err = c.WriteJSON(map[string]interface{}{
  94. "type": "subscription_start",
  95. "id": "123",
  96. "query": "subscription { Author { key, ",
  97. })
  98. if err != nil {
  99. t.Error("Could not send message:", err)
  100. return
  101. }
  102. _, message, err = c.ReadMessage()
  103. if msg := formatJSONString(string(message)); err != nil || msg != `{
  104. "id": "123",
  105. "payload": {
  106. "errors": [
  107. "Parse error in Main query: Unexpected end (Line:1 Pos:29)"
  108. ]
  109. },
  110. "type": "subscription_fail"
  111. }` {
  112. t.Error("Unexpected response:", msg, err)
  113. return
  114. }
  115. err = c.WriteJSON(map[string]interface{}{
  116. "type": "subscription_start",
  117. "id": "123",
  118. "query": "subscription { Author { key, name }}",
  119. })
  120. if err != nil {
  121. t.Error("Could not send message:", err)
  122. return
  123. }
  124. _, message, err = c.ReadMessage()
  125. if msg := formatJSONString(string(message)); err != nil || msg != `{
  126. "id": "123",
  127. "type": "subscription_success",
  128. "payload": {}
  129. }` {
  130. t.Error("Unexpected response:", msg, err)
  131. return
  132. }
  133. _, message, err = c.ReadMessage()
  134. if msg := formatJSONString(string(message)); err != nil || msg != `{
  135. "id": "123",
  136. "payload": {
  137. "data": {
  138. "Author": [
  139. {
  140. "key": "123",
  141. "name": "Mike"
  142. },
  143. {
  144. "key": "456",
  145. "name": "Hans"
  146. },
  147. {
  148. "key": "000",
  149. "name": "John"
  150. }
  151. ]
  152. }
  153. },
  154. "type": "subscription_data"
  155. }` {
  156. t.Error("Unexpected response:", msg, err)
  157. return
  158. }
  159. api.GM.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  160. "key": "Hans",
  161. "kind": "Author",
  162. }))
  163. _, message, err = c.ReadMessage()
  164. if msg := formatJSONString(string(message)); err != nil || msg != `{
  165. "id": "123",
  166. "payload": {
  167. "data": {
  168. "Author": [
  169. {
  170. "key": "123",
  171. "name": "Mike"
  172. },
  173. {
  174. "key": "456",
  175. "name": "Hans"
  176. },
  177. {
  178. "key": "000",
  179. "name": "John"
  180. },
  181. {
  182. "key": "Hans",
  183. "name": null
  184. }
  185. ]
  186. }
  187. },
  188. "type": "subscription_data"
  189. }` {
  190. t.Error("Unexpected response:", msg, err)
  191. return
  192. }
  193. // Insert an error into the db
  194. sm := gmMSM.StorageManager("mainAuthor.nodes", false)
  195. msm := sm.(*storage.MemoryStorageManager)
  196. msm.AccessMap[8] = storage.AccessCacheAndFetchSeriousError
  197. err = api.GM.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  198. "key": "Hans2",
  199. "kind": "Author",
  200. }))
  201. if err != nil {
  202. t.Error(err)
  203. return
  204. }
  205. _, message, err = c.ReadMessage()
  206. if msg := formatJSONString(string(message)); err != nil || msg != `{
  207. "id": "123",
  208. "payload": {
  209. "data": {
  210. "Author": []
  211. },
  212. "errors": [
  213. {
  214. "locations": [
  215. {
  216. "column": 23,
  217. "line": 1
  218. }
  219. ],
  220. "message": "GraphError: Could not read graph information (Record is already in-use (? - ))",
  221. "path": [
  222. "Author"
  223. ]
  224. }
  225. ]
  226. },
  227. "type": "subscription_data"
  228. }` {
  229. t.Error("Unexpected response:", msg, err)
  230. return
  231. }
  232. delete(msm.AccessMap, 8)
  233. // Create a callback error
  234. subscriptionCallbackError = fmt.Errorf("Oh dear")
  235. err = api.GM.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  236. "key": "Hans3",
  237. "kind": "Author",
  238. }))
  239. if err != nil {
  240. t.Error(err)
  241. return
  242. }
  243. _, message, err = c.ReadMessage()
  244. if msg := formatJSONString(string(message)); err != nil || msg != `{
  245. "id": "123",
  246. "payload": {
  247. "errors": [
  248. "Oh dear"
  249. ]
  250. },
  251. "type": "subscription_fail"
  252. }` {
  253. t.Error("Unexpected response:", msg, err)
  254. return
  255. }
  256. _, _, err = c.ReadMessage()
  257. if err == nil || err.Error() != "websocket: close 1003 (unsupported data): Oh dear" {
  258. t.Error("Unexpected response:", err)
  259. return
  260. }
  261. if err = c.Close(); err != nil {
  262. t.Error("Could not close websocket:", err)
  263. return
  264. }
  265. }