rest_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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 v1
  11. import (
  12. "bytes"
  13. "crypto/tls"
  14. "encoding/json"
  15. "flag"
  16. "fmt"
  17. "io/ioutil"
  18. "log"
  19. "net/http"
  20. "os"
  21. "path"
  22. "path/filepath"
  23. "strings"
  24. "sync"
  25. "testing"
  26. "time"
  27. "devt.de/krotik/common/cryptutil"
  28. "devt.de/krotik/common/errorutil"
  29. "devt.de/krotik/common/fileutil"
  30. "devt.de/krotik/common/httputil"
  31. "devt.de/krotik/rufs"
  32. "devt.de/krotik/rufs/api"
  33. "devt.de/krotik/rufs/config"
  34. )
  35. const TESTPORT = ":9040"
  36. // Main function for all tests in this package
  37. func TestMain(m *testing.M) {
  38. flag.Parse()
  39. // Create a ssl certificate directory
  40. if res, _ := fileutil.PathExists(certdir); res {
  41. os.RemoveAll(certdir)
  42. }
  43. err := os.Mkdir(certdir, 0770)
  44. if err != nil {
  45. fmt.Print("Could not create test directory:", err.Error())
  46. os.Exit(1)
  47. }
  48. // Create client certificate
  49. certFile := fmt.Sprintf("cert-client.pem")
  50. keyFile := fmt.Sprintf("key-client.pem")
  51. host := "localhost"
  52. err = cryptutil.GenCert(certdir, certFile, keyFile, host, "", 365*24*time.Hour, true, 2048, "")
  53. if err != nil {
  54. panic(err)
  55. }
  56. cert, err := tls.LoadX509KeyPair(path.Join(certdir, certFile), path.Join(certdir, keyFile))
  57. if err != nil {
  58. panic(err)
  59. }
  60. // Set the default client certificate and configuration for the REST API
  61. api.TreeConfigTemplate = map[string]interface{}{
  62. config.TreeSecret: "123",
  63. }
  64. api.TreeCertTemplate = &cert
  65. // Ensure logging is discarded
  66. log.SetOutput(ioutil.Discard)
  67. // Set up test branches
  68. b1, err := createBranch("footest", "foo")
  69. errorutil.AssertOk(err)
  70. b2, err := createBranch("bartest", "bar")
  71. errorutil.AssertOk(err)
  72. footest = b1
  73. bartest = b2
  74. // Create some test files
  75. ioutil.WriteFile("foo/test1", []byte("Test1 file"), 0770)
  76. ioutil.WriteFile("foo/test2", []byte("Test2 file"), 0770)
  77. os.Mkdir("foo/sub1", 0770)
  78. ioutil.WriteFile("foo/sub1/test3", []byte("Sub dir test file"), 0770)
  79. ioutil.WriteFile("bar/test1", []byte("Test3 file"), 0770)
  80. // Start the server
  81. hs, wg := startServer()
  82. if hs == nil {
  83. return
  84. }
  85. // Register endpoints for version 1
  86. api.RegisterRestEndpoints(api.GeneralEndpointMap)
  87. api.RegisterRestEndpoints(V1EndpointMap)
  88. // Run the tests
  89. res := m.Run()
  90. // Teardown
  91. stopServer(hs, wg)
  92. // Shutdown the branches
  93. errorutil.AssertOk(b1.Shutdown())
  94. errorutil.AssertOk(b2.Shutdown())
  95. // Remove all directories again
  96. if err = os.RemoveAll(certdir); err != nil {
  97. fmt.Print("Could not remove test directory:", err.Error())
  98. }
  99. if err = os.RemoveAll("foo"); err != nil {
  100. fmt.Print("Could not remove test directory:", err.Error())
  101. }
  102. if err = os.RemoveAll("bar"); err != nil {
  103. fmt.Print("Could not remove test directory:", err.Error())
  104. }
  105. os.Exit(res)
  106. }
  107. func TestSwaggerDefs(t *testing.T) {
  108. // Test we can build swagger defs from the endpoint
  109. data := map[string]interface{}{
  110. "paths": map[string]interface{}{},
  111. "definitions": map[string]interface{}{},
  112. }
  113. for _, inst := range V1EndpointMap {
  114. inst().SwaggerDefs(data)
  115. }
  116. // Show swagger output
  117. /*
  118. queryURL := "http://localhost" + TESTPORT + api.EndpointSwagger
  119. _, _, res := sendTestRequest(queryURL, "GET", nil)
  120. fmt.Println(res)
  121. */
  122. }
  123. /*
  124. Send a request to a HTTP test server
  125. */
  126. func sendTestRequest(url string, method string, content []byte) (string, http.Header, string) {
  127. var req *http.Request
  128. var err error
  129. ct := "application/json"
  130. if method == "FORMPOST" {
  131. method = "POST"
  132. ct = "application/x-www-form-urlencoded"
  133. }
  134. if content != nil {
  135. req, err = http.NewRequest(method, url, bytes.NewBuffer(content))
  136. } else {
  137. req, err = http.NewRequest(method, url, nil)
  138. }
  139. if err != nil {
  140. panic(err)
  141. }
  142. req.Header.Set("Content-Type", ct)
  143. client := &http.Client{}
  144. resp, err := client.Do(req)
  145. if err != nil {
  146. panic(err)
  147. }
  148. defer resp.Body.Close()
  149. body, _ := ioutil.ReadAll(resp.Body)
  150. bodyStr := strings.Trim(string(body), " \n")
  151. // Try json decoding first
  152. out := bytes.Buffer{}
  153. err = json.Indent(&out, []byte(bodyStr), "", " ")
  154. if err == nil {
  155. return resp.Status, resp.Header, out.String()
  156. }
  157. // Just return the body
  158. return resp.Status, resp.Header, bodyStr
  159. }
  160. /*
  161. Start a HTTP test server.
  162. */
  163. func startServer() (*httputil.HTTPServer, *sync.WaitGroup) {
  164. hs := &httputil.HTTPServer{}
  165. var wg sync.WaitGroup
  166. wg.Add(1)
  167. go hs.RunHTTPServer(TESTPORT, &wg)
  168. wg.Wait()
  169. // Server is started
  170. if hs.LastError != nil {
  171. panic(hs.LastError)
  172. }
  173. return hs, &wg
  174. }
  175. /*
  176. Stop a started HTTP test server.
  177. */
  178. func stopServer(hs *httputil.HTTPServer, wg *sync.WaitGroup) {
  179. if hs.Running == true {
  180. wg.Add(1)
  181. // Server is shut down
  182. hs.Shutdown()
  183. wg.Wait()
  184. } else {
  185. panic("Server was not running as expected")
  186. }
  187. }
  188. const certdir = "certs" // Directory for certificates
  189. var portCount = 0 // Port assignment counter for Branch ports
  190. var footest, bartest *rufs.Branch // Branches
  191. var branchConfigs = map[string]map[string]interface{}{} // All branch configs
  192. /*
  193. createBranch creates a new branch.
  194. */
  195. func createBranch(name, dir string) (*rufs.Branch, error) {
  196. // Create the path directory
  197. if res, _ := fileutil.PathExists(dir); res {
  198. os.RemoveAll(dir)
  199. }
  200. err := os.Mkdir(dir, 0770)
  201. if err != nil {
  202. fmt.Print("Could not create test directory:", err.Error())
  203. os.Exit(1)
  204. }
  205. // Create the certificate
  206. portCount++
  207. host := fmt.Sprintf("localhost:%v", 9020+portCount)
  208. // Generate a certificate and private key
  209. certFile := fmt.Sprintf("cert-%v.pem", portCount)
  210. keyFile := fmt.Sprintf("key-%v.pem", portCount)
  211. err = cryptutil.GenCert(certdir, certFile, keyFile, host, "", 365*24*time.Hour, true, 2048, "")
  212. if err != nil {
  213. panic(err)
  214. }
  215. cert, err := tls.LoadX509KeyPair(filepath.Join(certdir, certFile), filepath.Join(certdir, keyFile))
  216. if err != nil {
  217. panic(err)
  218. }
  219. // Create the Branch
  220. cfg := map[string]interface{}{
  221. config.BranchName: name,
  222. config.BranchSecret: "123",
  223. config.EnableReadOnly: false,
  224. config.RPCHost: "localhost",
  225. config.RPCPort: fmt.Sprint(9020 + portCount),
  226. config.LocalFolder: dir,
  227. }
  228. branchConfigs[name] = cfg
  229. return rufs.NewBranch(cfg, &cert)
  230. }