You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

176 lines
4.2 KiB

  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file or at
  5. // https://developers.google.com/open-source/licenses/bsd.
  6. package httputil_test
  7. import (
  8. "crypto/sha1"
  9. "encoding/hex"
  10. "io/ioutil"
  11. "net/http"
  12. "net/http/httptest"
  13. "net/url"
  14. "os"
  15. "reflect"
  16. "strconv"
  17. "testing"
  18. "time"
  19. "github.com/golang/gddo/httputil"
  20. )
  21. var (
  22. testHash = computeTestHash()
  23. testEtag = `"` + testHash + `"`
  24. testContentLength = computeTestContentLength()
  25. )
  26. func mustParseURL(urlStr string) *url.URL {
  27. u, err := url.Parse(urlStr)
  28. if err != nil {
  29. panic(err)
  30. }
  31. return u
  32. }
  33. func computeTestHash() string {
  34. p, err := ioutil.ReadFile("static_test.go")
  35. if err != nil {
  36. panic(err)
  37. }
  38. w := sha1.New()
  39. w.Write(p)
  40. return hex.EncodeToString(w.Sum(nil))
  41. }
  42. func computeTestContentLength() string {
  43. info, err := os.Stat("static_test.go")
  44. if err != nil {
  45. panic(err)
  46. }
  47. return strconv.FormatInt(info.Size(), 10)
  48. }
  49. var fileServerTests = []*struct {
  50. name string // test name for log
  51. ss *httputil.StaticServer
  52. r *http.Request
  53. header http.Header // expected response headers
  54. status int // expected response status
  55. empty bool // true if response body not expected.
  56. }{
  57. {
  58. name: "get",
  59. ss: &httputil.StaticServer{MaxAge: 3 * time.Second},
  60. r: &http.Request{
  61. URL: mustParseURL("/dir/static_test.go"),
  62. Method: "GET",
  63. },
  64. status: http.StatusOK,
  65. header: http.Header{
  66. "Etag": {testEtag},
  67. "Cache-Control": {"public, max-age=3"},
  68. "Content-Length": {testContentLength},
  69. "Content-Type": {"application/octet-stream"},
  70. },
  71. },
  72. {
  73. name: "get .",
  74. ss: &httputil.StaticServer{Dir: ".", MaxAge: 3 * time.Second},
  75. r: &http.Request{
  76. URL: mustParseURL("/dir/static_test.go"),
  77. Method: "GET",
  78. },
  79. status: http.StatusOK,
  80. header: http.Header{
  81. "Etag": {testEtag},
  82. "Cache-Control": {"public, max-age=3"},
  83. "Content-Length": {testContentLength},
  84. "Content-Type": {"application/octet-stream"},
  85. },
  86. },
  87. {
  88. name: "get with ?v=",
  89. ss: &httputil.StaticServer{MaxAge: 3 * time.Second},
  90. r: &http.Request{
  91. URL: mustParseURL("/dir/static_test.go?v=xxxxx"),
  92. Method: "GET",
  93. },
  94. status: http.StatusOK,
  95. header: http.Header{
  96. "Etag": {testEtag},
  97. "Cache-Control": {"public, max-age=31536000"},
  98. "Content-Length": {testContentLength},
  99. "Content-Type": {"application/octet-stream"},
  100. },
  101. },
  102. {
  103. name: "head",
  104. ss: &httputil.StaticServer{MaxAge: 3 * time.Second},
  105. r: &http.Request{
  106. URL: mustParseURL("/dir/static_test.go"),
  107. Method: "HEAD",
  108. },
  109. status: http.StatusOK,
  110. header: http.Header{
  111. "Etag": {testEtag},
  112. "Cache-Control": {"public, max-age=3"},
  113. "Content-Length": {testContentLength},
  114. "Content-Type": {"application/octet-stream"},
  115. },
  116. empty: true,
  117. },
  118. {
  119. name: "if-none-match",
  120. ss: &httputil.StaticServer{MaxAge: 3 * time.Second},
  121. r: &http.Request{
  122. URL: mustParseURL("/dir/static_test.go"),
  123. Method: "GET",
  124. Header: http.Header{"If-None-Match": {testEtag}},
  125. },
  126. status: http.StatusNotModified,
  127. header: http.Header{
  128. "Cache-Control": {"public, max-age=3"},
  129. "Etag": {testEtag},
  130. },
  131. empty: true,
  132. },
  133. }
  134. func testStaticServer(t *testing.T, f func(*httputil.StaticServer) http.Handler) {
  135. for _, tt := range fileServerTests {
  136. w := httptest.NewRecorder()
  137. h := f(tt.ss)
  138. h.ServeHTTP(w, tt.r)
  139. if w.Code != tt.status {
  140. t.Errorf("%s, status=%d, want %d", tt.name, w.Code, tt.status)
  141. }
  142. if !reflect.DeepEqual(w.HeaderMap, tt.header) {
  143. t.Errorf("%s\n\theader=%v,\n\twant %v", tt.name, w.HeaderMap, tt.header)
  144. }
  145. empty := w.Body.Len() == 0
  146. if empty != tt.empty {
  147. t.Errorf("%s empty=%v, want %v", tt.name, empty, tt.empty)
  148. }
  149. }
  150. }
  151. func TestFileHandler(t *testing.T) {
  152. testStaticServer(t, func(ss *httputil.StaticServer) http.Handler { return ss.FileHandler("static_test.go") })
  153. }
  154. func TestDirectoryHandler(t *testing.T) {
  155. testStaticServer(t, func(ss *httputil.StaticServer) http.Handler { return ss.DirectoryHandler("/dir", ".") })
  156. }
  157. func TestFilesHandler(t *testing.T) {
  158. testStaticServer(t, func(ss *httputil.StaticServer) http.Handler { return ss.FilesHandler("static_test.go") })
  159. }