rest_test.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Rufs - Remote Union File System
  3. *
  4. * Copyright 2017 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package api
  11. import (
  12. "bytes"
  13. "encoding/json"
  14. "flag"
  15. "fmt"
  16. "io/ioutil"
  17. "net/http"
  18. "os"
  19. "strings"
  20. "sync"
  21. "testing"
  22. "devt.de/krotik/common/httputil"
  23. "devt.de/krotik/rufs"
  24. )
  25. const testPort = ":9040"
  26. var testQueryURL = "http://localhost" + testPort
  27. var lastRes []string
  28. type testEndpoint struct {
  29. *DefaultEndpointHandler
  30. }
  31. /*
  32. handleSearchQuery handles a search query REST call.
  33. */
  34. func (te *testEndpoint) HandleGET(w http.ResponseWriter, r *http.Request, resources []string) {
  35. lastRes = resources
  36. te.DefaultEndpointHandler.HandleGET(w, r, resources)
  37. }
  38. func (te *testEndpoint) SwaggerDefs(s map[string]interface{}) {
  39. }
  40. var testEndpointMap = map[string]RestEndpointInst{
  41. "/": func() RestEndpointHandler {
  42. return &testEndpoint{}
  43. },
  44. }
  45. func TestMain(m *testing.M) {
  46. flag.Parse()
  47. hs, wg := startServer()
  48. if hs == nil {
  49. return
  50. }
  51. defer stopServer(hs, wg)
  52. RegisterRestEndpoints(testEndpointMap)
  53. RegisterRestEndpoints(GeneralEndpointMap)
  54. // Run the tests
  55. res := m.Run()
  56. // Teardown
  57. stopServer(hs, wg)
  58. os.Exit(res)
  59. }
  60. func TestTreeManagement(t *testing.T) {
  61. if err := AddTree("1", &rufs.Tree{}); err != nil {
  62. t.Error(err)
  63. return
  64. }
  65. if err := AddTree("1", &rufs.Tree{}); err == nil || err.Error() != "Tree 1 already exists" {
  66. t.Error(err)
  67. return
  68. }
  69. if res, _ := Trees(); fmt.Sprint(res) != "map[1:/: ]" {
  70. t.Error("Unexpected result: ", res)
  71. return
  72. }
  73. if res, _, _ := GetTree("1"); res == nil {
  74. t.Error("Unexpected result: ", res)
  75. return
  76. }
  77. if err := RemoveTree("1"); err != nil {
  78. t.Error(err)
  79. return
  80. }
  81. if err := RemoveTree("1"); err == nil || err.Error() != "Tree 1 does not exist" {
  82. t.Error(err)
  83. return
  84. }
  85. if err := AddTree("1", &rufs.Tree{}); err != nil {
  86. t.Error(err)
  87. return
  88. }
  89. ResetTrees()
  90. if res, _ := Trees(); fmt.Sprint(res) != "map[]" {
  91. t.Error("Unexpected result: ", res)
  92. return
  93. }
  94. }
  95. func TestEndpointHandling(t *testing.T) {
  96. lastRes = nil
  97. if _, _, res, _ := sendTestRequest(testQueryURL, "GET", nil); res != "Method Not Allowed" {
  98. t.Error("Unexpected response:", res)
  99. return
  100. }
  101. if lastRes != nil {
  102. t.Error("Unexpected lastRes:", lastRes)
  103. }
  104. lastRes = nil
  105. if _, _, res, _ := sendTestRequest(testQueryURL+"/foo/bar", "GET", nil); res != "Method Not Allowed" {
  106. t.Error("Unexpected response:", res)
  107. return
  108. }
  109. if fmt.Sprint(lastRes) != "[foo bar]" {
  110. t.Error("Unexpected lastRes:", lastRes)
  111. }
  112. lastRes = nil
  113. if _, _, res, _ := sendTestRequest(testQueryURL+"/foo/bar/", "GET", nil); res != "Method Not Allowed" {
  114. t.Error("Unexpected response:", res)
  115. return
  116. }
  117. if fmt.Sprint(lastRes) != "[foo bar]" {
  118. t.Error("Unexpected lastRes:", lastRes)
  119. }
  120. if _, _, res, _ := sendTestRequest(testQueryURL, "POST", nil); res != "Method Not Allowed" {
  121. t.Error("Unexpected response:", res)
  122. return
  123. }
  124. if _, _, res, _ := sendTestRequest(testQueryURL, "PUT", nil); res != "Method Not Allowed" {
  125. t.Error("Unexpected response:", res)
  126. return
  127. }
  128. if _, _, res, _ := sendTestRequest(testQueryURL, "DELETE", nil); res != "Method Not Allowed" {
  129. t.Error("Unexpected response:", res)
  130. return
  131. }
  132. if _, _, res, _ := sendTestRequest(testQueryURL, "UPDATE", nil); res != "Method Not Allowed" {
  133. t.Error("Unexpected response:", res)
  134. return
  135. }
  136. // Test swagger endpoint
  137. if _, _, res, _ := sendTestRequest(testQueryURL+"/fs/swagger.json", "GET", nil); res != `
  138. {
  139. "basePath": "/fs",
  140. "definitions": {
  141. "Error": {
  142. "description": "A human readable error mesage.",
  143. "type": "string"
  144. }
  145. },
  146. "host": "localhost:9040",
  147. "info": {
  148. "description": "Query and control the Remote Union File System.",
  149. "title": "RUFS API",
  150. "version": "1.0.0"
  151. },
  152. "paths": {
  153. "/about": {
  154. "get": {
  155. "description": "Returns available API versions, product name and product version.",
  156. "produces": [
  157. "application/json"
  158. ],
  159. "responses": {
  160. "200": {
  161. "description": "About info object",
  162. "schema": {
  163. "properties": {
  164. "api_versions": {
  165. "description": "List of available API versions.",
  166. "items": {
  167. "description": "Available API version.",
  168. "type": "string"
  169. },
  170. "type": "array"
  171. },
  172. "product": {
  173. "description": "Product name of the REST API provider.",
  174. "type": "string"
  175. },
  176. "version": {
  177. "description": "Version of the REST API provider.",
  178. "type": "string"
  179. }
  180. },
  181. "type": "object"
  182. }
  183. },
  184. "default": {
  185. "description": "Error response",
  186. "schema": {
  187. "$ref": "#/definitions/Error"
  188. }
  189. }
  190. },
  191. "summary": "Return information about the REST API provider."
  192. }
  193. }
  194. },
  195. "produces": [
  196. "application/json"
  197. ],
  198. "schemes": [
  199. "https"
  200. ],
  201. "swagger": "2.0"
  202. }`[1:] {
  203. t.Error("Unexpected response:", res)
  204. return
  205. }
  206. }
  207. /*
  208. Send a request to a HTTP test server
  209. */
  210. func sendTestRequest(url string, method string, content []byte) (string, http.Header, string, *http.Response) {
  211. var req *http.Request
  212. var err error
  213. if content != nil {
  214. req, err = http.NewRequest(method, url, bytes.NewBuffer(content))
  215. } else {
  216. req, err = http.NewRequest(method, url, nil)
  217. }
  218. if err != nil {
  219. panic(err)
  220. }
  221. req.Header.Set("Content-Type", "application/json")
  222. client := &http.Client{}
  223. resp, err := client.Do(req)
  224. if err != nil {
  225. panic(err)
  226. }
  227. defer resp.Body.Close()
  228. body, _ := ioutil.ReadAll(resp.Body)
  229. bodyStr := strings.Trim(string(body), " \n")
  230. // Try json decoding first
  231. out := bytes.Buffer{}
  232. err = json.Indent(&out, []byte(bodyStr), "", " ")
  233. if err == nil {
  234. return resp.Status, resp.Header, out.String(), resp
  235. }
  236. // Just return the body
  237. return resp.Status, resp.Header, bodyStr, resp
  238. }
  239. /*
  240. Start a HTTP test server.
  241. */
  242. func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {
  243. hs := &httputil.HTTPServer{}
  244. var wg sync.WaitGroup
  245. wg.Add(1)
  246. go hs.RunHTTPServer(testPort, &wg)
  247. wg.Wait()
  248. // Server is started
  249. if hs.LastError != nil {
  250. panic(hs.LastError)
  251. }
  252. return hs, &wg
  253. }
  254. /*
  255. Stop a started HTTP test server.
  256. */
  257. func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {
  258. if hs.Running == true {
  259. wg.Add(1)
  260. // Server is shut down
  261. hs.Shutdown()
  262. wg.Wait()
  263. } else {
  264. panic("Server was not running as expected")
  265. }
  266. }