server_unit_test.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. package server
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "net/http/httptest"
  9. "strings"
  10. "testing"
  11. "github.com/dotcloud/docker/api"
  12. "github.com/dotcloud/docker/engine"
  13. )
  14. func TestGetBoolParam(t *testing.T) {
  15. if ret, err := getBoolParam("true"); err != nil || !ret {
  16. t.Fatalf("true -> true, nil | got %t %s", ret, err)
  17. }
  18. if ret, err := getBoolParam("True"); err != nil || !ret {
  19. t.Fatalf("True -> true, nil | got %t %s", ret, err)
  20. }
  21. if ret, err := getBoolParam("1"); err != nil || !ret {
  22. t.Fatalf("1 -> true, nil | got %t %s", ret, err)
  23. }
  24. if ret, err := getBoolParam(""); err != nil || ret {
  25. t.Fatalf("\"\" -> false, nil | got %t %s", ret, err)
  26. }
  27. if ret, err := getBoolParam("false"); err != nil || ret {
  28. t.Fatalf("false -> false, nil | got %t %s", ret, err)
  29. }
  30. if ret, err := getBoolParam("0"); err != nil || ret {
  31. t.Fatalf("0 -> false, nil | got %t %s", ret, err)
  32. }
  33. if ret, err := getBoolParam("faux"); err == nil || ret {
  34. t.Fatalf("faux -> false, err | got %t %s", ret, err)
  35. }
  36. }
  37. func TesthttpError(t *testing.T) {
  38. r := httptest.NewRecorder()
  39. httpError(r, fmt.Errorf("No such method"))
  40. if r.Code != http.StatusNotFound {
  41. t.Fatalf("Expected %d, got %d", http.StatusNotFound, r.Code)
  42. }
  43. httpError(r, fmt.Errorf("This accound hasn't been activated"))
  44. if r.Code != http.StatusForbidden {
  45. t.Fatalf("Expected %d, got %d", http.StatusForbidden, r.Code)
  46. }
  47. httpError(r, fmt.Errorf("Some error"))
  48. if r.Code != http.StatusInternalServerError {
  49. t.Fatalf("Expected %d, got %d", http.StatusInternalServerError, r.Code)
  50. }
  51. }
  52. func TestGetVersion(t *testing.T) {
  53. eng := engine.New()
  54. var called bool
  55. eng.Register("version", func(job *engine.Job) engine.Status {
  56. called = true
  57. v := &engine.Env{}
  58. v.SetJson("Version", "42.1")
  59. v.Set("ApiVersion", "1.1.1.1.1")
  60. v.Set("GoVersion", "2.42")
  61. v.Set("Os", "Linux")
  62. v.Set("Arch", "x86_64")
  63. if _, err := v.WriteTo(job.Stdout); err != nil {
  64. return job.Error(err)
  65. }
  66. return engine.StatusOK
  67. })
  68. r := serveRequest("GET", "/version", nil, eng, t)
  69. if !called {
  70. t.Fatalf("handler was not called")
  71. }
  72. v := readEnv(r.Body, t)
  73. if v.Get("Version") != "42.1" {
  74. t.Fatalf("%#v\n", v)
  75. }
  76. if r.HeaderMap.Get("Content-Type") != "application/json" {
  77. t.Fatalf("%#v\n", r)
  78. }
  79. }
  80. func TestGetInfo(t *testing.T) {
  81. eng := engine.New()
  82. var called bool
  83. eng.Register("info", func(job *engine.Job) engine.Status {
  84. called = true
  85. v := &engine.Env{}
  86. v.SetInt("Containers", 1)
  87. v.SetInt("Images", 42000)
  88. if _, err := v.WriteTo(job.Stdout); err != nil {
  89. return job.Error(err)
  90. }
  91. return engine.StatusOK
  92. })
  93. r := serveRequest("GET", "/info", nil, eng, t)
  94. if !called {
  95. t.Fatalf("handler was not called")
  96. }
  97. v := readEnv(r.Body, t)
  98. if v.GetInt("Images") != 42000 {
  99. t.Fatalf("%#v\n", v)
  100. }
  101. if v.GetInt("Containers") != 1 {
  102. t.Fatalf("%#v\n", v)
  103. }
  104. if r.HeaderMap.Get("Content-Type") != "application/json" {
  105. t.Fatalf("%#v\n", r)
  106. }
  107. }
  108. func TestGetContainersByName(t *testing.T) {
  109. eng := engine.New()
  110. name := "container_name"
  111. var called bool
  112. eng.Register("container_inspect", func(job *engine.Job) engine.Status {
  113. called = true
  114. if job.Args[0] != name {
  115. t.Fatalf("name != '%s': %#v", name, job.Args[0])
  116. }
  117. if api.APIVERSION.LessThan("1.12") && !job.GetenvBool("dirty") {
  118. t.Fatal("dirty env variable not set")
  119. } else if api.APIVERSION.GreaterThanOrEqualTo("1.12") && job.GetenvBool("dirty") {
  120. t.Fatal("dirty env variable set when it shouldn't")
  121. }
  122. v := &engine.Env{}
  123. v.SetBool("dirty", true)
  124. if _, err := v.WriteTo(job.Stdout); err != nil {
  125. return job.Error(err)
  126. }
  127. return engine.StatusOK
  128. })
  129. r := serveRequest("GET", "/containers/"+name+"/json", nil, eng, t)
  130. if !called {
  131. t.Fatal("handler was not called")
  132. }
  133. if r.HeaderMap.Get("Content-Type") != "application/json" {
  134. t.Fatalf("%#v\n", r)
  135. }
  136. var stdoutJson interface{}
  137. if err := json.Unmarshal(r.Body.Bytes(), &stdoutJson); err != nil {
  138. t.Fatalf("%#v", err)
  139. }
  140. if stdoutJson.(map[string]interface{})["dirty"].(float64) != 1 {
  141. t.Fatalf("%#v", stdoutJson)
  142. }
  143. }
  144. func TestLogs(t *testing.T) {
  145. eng := engine.New()
  146. var inspect bool
  147. var logs bool
  148. eng.Register("container_inspect", func(job *engine.Job) engine.Status {
  149. inspect = true
  150. if len(job.Args) == 0 {
  151. t.Fatal("Job arguments is empty")
  152. }
  153. if job.Args[0] != "test" {
  154. t.Fatalf("Container name %s, must be test", job.Args[0])
  155. }
  156. return engine.StatusOK
  157. })
  158. expected := "logs"
  159. eng.Register("logs", func(job *engine.Job) engine.Status {
  160. logs = true
  161. if len(job.Args) == 0 {
  162. t.Fatal("Job arguments is empty")
  163. }
  164. if job.Args[0] != "test" {
  165. t.Fatalf("Container name %s, must be test", job.Args[0])
  166. }
  167. follow := job.Getenv("follow")
  168. if follow != "1" {
  169. t.Fatalf("follow: %s, must be 1", follow)
  170. }
  171. stdout := job.Getenv("stdout")
  172. if stdout != "1" {
  173. t.Fatalf("stdout %s, must be 1", stdout)
  174. }
  175. stderr := job.Getenv("stderr")
  176. if stderr != "" {
  177. t.Fatalf("stderr %s, must be empty", stderr)
  178. }
  179. timestamps := job.Getenv("timestamps")
  180. if timestamps != "1" {
  181. t.Fatalf("timestamps %s, must be 1", timestamps)
  182. }
  183. job.Stdout.Write([]byte(expected))
  184. return engine.StatusOK
  185. })
  186. r := serveRequest("GET", "/containers/test/logs?follow=1&stdout=1&timestamps=1", nil, eng, t)
  187. if r.Code != http.StatusOK {
  188. t.Fatalf("Got status %d, expected %d", r.Code, http.StatusOK)
  189. }
  190. if !inspect {
  191. t.Fatal("container_inspect job was not called")
  192. }
  193. if !logs {
  194. t.Fatal("logs job was not called")
  195. }
  196. res := r.Body.String()
  197. if res != expected {
  198. t.Fatalf("Output %s, expected %s", res, expected)
  199. }
  200. }
  201. func TestLogsNoStreams(t *testing.T) {
  202. eng := engine.New()
  203. var inspect bool
  204. var logs bool
  205. eng.Register("container_inspect", func(job *engine.Job) engine.Status {
  206. inspect = true
  207. if len(job.Args) == 0 {
  208. t.Fatal("Job arguments is empty")
  209. }
  210. if job.Args[0] != "test" {
  211. t.Fatalf("Container name %s, must be test", job.Args[0])
  212. }
  213. return engine.StatusOK
  214. })
  215. eng.Register("logs", func(job *engine.Job) engine.Status {
  216. logs = true
  217. return engine.StatusOK
  218. })
  219. r := serveRequest("GET", "/containers/test/logs", nil, eng, t)
  220. if r.Code != http.StatusBadRequest {
  221. t.Fatalf("Got status %d, expected %d", r.Code, http.StatusBadRequest)
  222. }
  223. if inspect {
  224. t.Fatal("container_inspect job was called, but it shouldn't")
  225. }
  226. if logs {
  227. t.Fatal("logs job was called, but it shouldn't")
  228. }
  229. res := strings.TrimSpace(r.Body.String())
  230. expected := "Bad parameters: you must choose at least one stream"
  231. if !strings.Contains(res, expected) {
  232. t.Fatalf("Output %s, expected %s in it", res, expected)
  233. }
  234. }
  235. func serveRequest(method, target string, body io.Reader, eng *engine.Engine, t *testing.T) *httptest.ResponseRecorder {
  236. r := httptest.NewRecorder()
  237. req, err := http.NewRequest(method, target, body)
  238. if err != nil {
  239. t.Fatal(err)
  240. }
  241. if err := ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  242. t.Fatal(err)
  243. }
  244. return r
  245. }
  246. func readEnv(src io.Reader, t *testing.T) *engine.Env {
  247. out := engine.NewOutput()
  248. v, err := out.AddEnv()
  249. if err != nil {
  250. t.Fatal(err)
  251. }
  252. if _, err := io.Copy(out, src); err != nil {
  253. t.Fatal(err)
  254. }
  255. out.Close()
  256. return v
  257. }
  258. func toJson(data interface{}, t *testing.T) io.Reader {
  259. var buf bytes.Buffer
  260. if err := json.NewEncoder(&buf).Encode(data); err != nil {
  261. t.Fatal(err)
  262. }
  263. return &buf
  264. }