server_unit_test.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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 TestGetEvents(t *testing.T) {
  145. eng := engine.New()
  146. var called bool
  147. eng.Register("events", func(job *engine.Job) engine.Status {
  148. called = true
  149. since := job.Getenv("since")
  150. if since != "1" {
  151. t.Fatalf("'since' should be 1, found %#v instead", since)
  152. }
  153. until := job.Getenv("until")
  154. if until != "0" {
  155. t.Fatalf("'until' should be 0, found %#v instead", until)
  156. }
  157. v := &engine.Env{}
  158. v.Set("since", since)
  159. v.Set("until", until)
  160. if _, err := v.WriteTo(job.Stdout); err != nil {
  161. return job.Error(err)
  162. }
  163. return engine.StatusOK
  164. })
  165. r := serveRequest("GET", "/events?since=1&until=0", nil, eng, t)
  166. if !called {
  167. t.Fatal("handler was not called")
  168. }
  169. if r.HeaderMap.Get("Content-Type") != "application/json" {
  170. t.Fatalf("%#v\n", r)
  171. }
  172. var stdout_json struct {
  173. Since int
  174. Until int
  175. }
  176. if err := json.Unmarshal(r.Body.Bytes(), &stdout_json); err != nil {
  177. t.Fatalf("%#v", err)
  178. }
  179. if stdout_json.Since != 1 {
  180. t.Fatalf("since != 1: %#v", stdout_json.Since)
  181. }
  182. if stdout_json.Until != 0 {
  183. t.Fatalf("until != 0: %#v", stdout_json.Until)
  184. }
  185. }
  186. func TestLogs(t *testing.T) {
  187. eng := engine.New()
  188. var inspect bool
  189. var logs bool
  190. eng.Register("container_inspect", func(job *engine.Job) engine.Status {
  191. inspect = true
  192. if len(job.Args) == 0 {
  193. t.Fatal("Job arguments is empty")
  194. }
  195. if job.Args[0] != "test" {
  196. t.Fatalf("Container name %s, must be test", job.Args[0])
  197. }
  198. return engine.StatusOK
  199. })
  200. expected := "logs"
  201. eng.Register("logs", func(job *engine.Job) engine.Status {
  202. logs = true
  203. if len(job.Args) == 0 {
  204. t.Fatal("Job arguments is empty")
  205. }
  206. if job.Args[0] != "test" {
  207. t.Fatalf("Container name %s, must be test", job.Args[0])
  208. }
  209. follow := job.Getenv("follow")
  210. if follow != "1" {
  211. t.Fatalf("follow: %s, must be 1", follow)
  212. }
  213. stdout := job.Getenv("stdout")
  214. if stdout != "1" {
  215. t.Fatalf("stdout %s, must be 1", stdout)
  216. }
  217. stderr := job.Getenv("stderr")
  218. if stderr != "" {
  219. t.Fatalf("stderr %s, must be empty", stderr)
  220. }
  221. timestamps := job.Getenv("timestamps")
  222. if timestamps != "1" {
  223. t.Fatalf("timestamps %s, must be 1", timestamps)
  224. }
  225. job.Stdout.Write([]byte(expected))
  226. return engine.StatusOK
  227. })
  228. r := serveRequest("GET", "/containers/test/logs?follow=1&stdout=1&timestamps=1", nil, eng, t)
  229. if r.Code != http.StatusOK {
  230. t.Fatalf("Got status %d, expected %d", r.Code, http.StatusOK)
  231. }
  232. if !inspect {
  233. t.Fatal("container_inspect job was not called")
  234. }
  235. if !logs {
  236. t.Fatal("logs job was not called")
  237. }
  238. res := r.Body.String()
  239. if res != expected {
  240. t.Fatalf("Output %s, expected %s", res, expected)
  241. }
  242. }
  243. func TestLogsNoStreams(t *testing.T) {
  244. eng := engine.New()
  245. var inspect bool
  246. var logs bool
  247. eng.Register("container_inspect", func(job *engine.Job) engine.Status {
  248. inspect = true
  249. if len(job.Args) == 0 {
  250. t.Fatal("Job arguments is empty")
  251. }
  252. if job.Args[0] != "test" {
  253. t.Fatalf("Container name %s, must be test", job.Args[0])
  254. }
  255. return engine.StatusOK
  256. })
  257. eng.Register("logs", func(job *engine.Job) engine.Status {
  258. logs = true
  259. return engine.StatusOK
  260. })
  261. r := serveRequest("GET", "/containers/test/logs", nil, eng, t)
  262. if r.Code != http.StatusBadRequest {
  263. t.Fatalf("Got status %d, expected %d", r.Code, http.StatusBadRequest)
  264. }
  265. if inspect {
  266. t.Fatal("container_inspect job was called, but it shouldn't")
  267. }
  268. if logs {
  269. t.Fatal("logs job was called, but it shouldn't")
  270. }
  271. res := strings.TrimSpace(r.Body.String())
  272. expected := "Bad parameters: you must choose at least one stream"
  273. if !strings.Contains(res, expected) {
  274. t.Fatalf("Output %s, expected %s in it", res, expected)
  275. }
  276. }
  277. func TestGetImagesHistory(t *testing.T) {
  278. eng := engine.New()
  279. imageName := "docker-test-image"
  280. var called bool
  281. eng.Register("history", func(job *engine.Job) engine.Status {
  282. called = true
  283. if len(job.Args) == 0 {
  284. t.Fatal("Job arguments is empty")
  285. }
  286. if job.Args[0] != imageName {
  287. t.Fatalf("name != '%s': %#v", imageName, job.Args[0])
  288. }
  289. v := &engine.Env{}
  290. if _, err := v.WriteTo(job.Stdout); err != nil {
  291. return job.Error(err)
  292. }
  293. return engine.StatusOK
  294. })
  295. r := serveRequest("GET", "/images/"+imageName+"/history", nil, eng, t)
  296. if !called {
  297. t.Fatalf("handler was not called")
  298. }
  299. if r.Code != http.StatusOK {
  300. t.Fatalf("Got status %d, expected %d", r.Code, http.StatusOK)
  301. }
  302. if r.HeaderMap.Get("Content-Type") != "application/json" {
  303. t.Fatalf("%#v\n", r)
  304. }
  305. }
  306. func serveRequest(method, target string, body io.Reader, eng *engine.Engine, t *testing.T) *httptest.ResponseRecorder {
  307. r := httptest.NewRecorder()
  308. req, err := http.NewRequest(method, target, body)
  309. if err != nil {
  310. t.Fatal(err)
  311. }
  312. if err := ServeRequest(eng, api.APIVERSION, r, req); err != nil {
  313. t.Fatal(err)
  314. }
  315. return r
  316. }
  317. func readEnv(src io.Reader, t *testing.T) *engine.Env {
  318. out := engine.NewOutput()
  319. v, err := out.AddEnv()
  320. if err != nil {
  321. t.Fatal(err)
  322. }
  323. if _, err := io.Copy(out, src); err != nil {
  324. t.Fatal(err)
  325. }
  326. out.Close()
  327. return v
  328. }
  329. func toJson(data interface{}, t *testing.T) io.Reader {
  330. var buf bytes.Buffer
  331. if err := json.NewEncoder(&buf).Encode(data); err != nil {
  332. t.Fatal(err)
  333. }
  334. return &buf
  335. }