graphql-subscriptions_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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. c, _, err := websocket.DefaultDialer.Dial(queryURL, nil)
  62. if err != nil {
  63. t.Error("Could not open websocket:", err)
  64. return
  65. }
  66. _, message, err := c.ReadMessage()
  67. if msg := formatJSONString(string(message)); err != nil || msg != `{
  68. "type": "init_success",
  69. "payload": {}
  70. }` {
  71. t.Error("Unexpected response:", msg, err)
  72. return
  73. }
  74. err = c.WriteMessage(websocket.TextMessage, []byte("buu"))
  75. if err != nil {
  76. t.Error("Could not send message:", err)
  77. return
  78. }
  79. _, message, err = c.ReadMessage()
  80. if msg := formatJSONString(string(message)); err != nil || msg != `{
  81. "id": "",
  82. "payload": {
  83. "errors": [
  84. "invalid character 'b' looking for beginning of value"
  85. ]
  86. },
  87. "type": "subscription_fail"
  88. }` {
  89. t.Error("Unexpected response:", msg, err)
  90. return
  91. }
  92. err = c.WriteJSON(map[string]interface{}{
  93. "type": "subscription_start",
  94. "id": "123",
  95. "query": "subscription { Author { key, ",
  96. })
  97. if err != nil {
  98. t.Error("Could not send message:", err)
  99. return
  100. }
  101. _, message, err = c.ReadMessage()
  102. if msg := formatJSONString(string(message)); err != nil || msg != `{
  103. "id": "123",
  104. "payload": {
  105. "errors": [
  106. "Parse error in Main query: Unexpected end (Line:1 Pos:29)"
  107. ]
  108. },
  109. "type": "subscription_fail"
  110. }` {
  111. t.Error("Unexpected response:", msg, err)
  112. return
  113. }
  114. err = c.WriteJSON(map[string]interface{}{
  115. "type": "subscription_start",
  116. "id": "123",
  117. "query": "subscription { Author { key, name }}",
  118. })
  119. if err != nil {
  120. t.Error("Could not send message:", err)
  121. return
  122. }
  123. _, message, err = c.ReadMessage()
  124. if msg := formatJSONString(string(message)); err != nil || msg != `{
  125. "id": "123",
  126. "type": "subscription_success",
  127. "payload": {}
  128. }` {
  129. t.Error("Unexpected response:", msg, err)
  130. return
  131. }
  132. _, message, err = c.ReadMessage()
  133. if msg := formatJSONString(string(message)); err != nil || msg != `{
  134. "id": "123",
  135. "payload": {
  136. "data": {
  137. "Author": [
  138. {
  139. "key": "123",
  140. "name": "Mike"
  141. },
  142. {
  143. "key": "456",
  144. "name": "Hans"
  145. },
  146. {
  147. "key": "000",
  148. "name": "John"
  149. }
  150. ]
  151. }
  152. },
  153. "type": "subscription_data"
  154. }` {
  155. t.Error("Unexpected response:", msg, err)
  156. return
  157. }
  158. api.GM.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  159. "key": "Hans",
  160. "kind": "Author",
  161. }))
  162. _, message, err = c.ReadMessage()
  163. if msg := formatJSONString(string(message)); err != nil || msg != `{
  164. "id": "123",
  165. "payload": {
  166. "data": {
  167. "Author": [
  168. {
  169. "key": "123",
  170. "name": "Mike"
  171. },
  172. {
  173. "key": "456",
  174. "name": "Hans"
  175. },
  176. {
  177. "key": "000",
  178. "name": "John"
  179. },
  180. {
  181. "key": "Hans",
  182. "name": null
  183. }
  184. ]
  185. }
  186. },
  187. "type": "subscription_data"
  188. }` {
  189. t.Error("Unexpected response:", msg, err)
  190. return
  191. }
  192. // Insert an error into the db
  193. sm := gmMSM.StorageManager("mainAuthor.nodes", false)
  194. msm := sm.(*storage.MemoryStorageManager)
  195. msm.AccessMap[8] = storage.AccessCacheAndFetchSeriousError
  196. err = api.GM.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  197. "key": "Hans2",
  198. "kind": "Author",
  199. }))
  200. if err != nil {
  201. t.Error(err)
  202. return
  203. }
  204. _, message, err = c.ReadMessage()
  205. if msg := formatJSONString(string(message)); err != nil || msg != `{
  206. "id": "123",
  207. "payload": {
  208. "data": {
  209. "Author": []
  210. },
  211. "errors": [
  212. {
  213. "locations": [
  214. {
  215. "column": 23,
  216. "line": 1
  217. }
  218. ],
  219. "message": "GraphError: Could not read graph information (Record is already in-use (\u003cmemory\u003e - ))",
  220. "path": [
  221. "Author"
  222. ]
  223. }
  224. ]
  225. },
  226. "type": "subscription_data"
  227. }` {
  228. t.Error("Unexpected response:", msg, err)
  229. return
  230. }
  231. delete(msm.AccessMap, 8)
  232. // Create a callback error
  233. subscriptionCallbackError = fmt.Errorf("Oh dear")
  234. err = api.GM.StoreNode("main", data.NewGraphNodeFromMap(map[string]interface{}{
  235. "key": "Hans3",
  236. "kind": "Author",
  237. }))
  238. if err != nil {
  239. t.Error(err)
  240. return
  241. }
  242. _, message, err = c.ReadMessage()
  243. if msg := formatJSONString(string(message)); err != nil || msg != `{
  244. "id": "123",
  245. "payload": {
  246. "errors": [
  247. "Oh dear"
  248. ]
  249. },
  250. "type": "subscription_fail"
  251. }` {
  252. t.Error("Unexpected response:", msg, err)
  253. return
  254. }
  255. _, _, err = c.ReadMessage()
  256. if err == nil || err.Error() != "websocket: close 1003 (unsupported data): Oh dear" {
  257. t.Error("Unexpected response:", err)
  258. return
  259. }
  260. if err = c.Close(); err != nil {
  261. t.Error("Could not close websocket:", err)
  262. return
  263. }
  264. }