OSDN Git Service

libgo: Update to weekly.2011-11-18.
[pf3gnuchains/gcc-fork.git] / libgo / go / net / http / fs_test.go
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package http_test
6
7 import (
8         "fmt"
9         "io/ioutil"
10         . "net/http"
11         "net/http/httptest"
12         "net/url"
13         "os"
14         "path/filepath"
15         "strings"
16         "testing"
17 )
18
19 const (
20         testFile       = "testdata/file"
21         testFileLength = 11
22 )
23
24 var ServeFileRangeTests = []struct {
25         start, end int
26         r          string
27         code       int
28 }{
29         {0, testFileLength, "", StatusOK},
30         {0, 5, "0-4", StatusPartialContent},
31         {2, testFileLength, "2-", StatusPartialContent},
32         {testFileLength - 5, testFileLength, "-5", StatusPartialContent},
33         {3, 8, "3-7", StatusPartialContent},
34         {0, 0, "20-", StatusRequestedRangeNotSatisfiable},
35 }
36
37 func TestServeFile(t *testing.T) {
38         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
39                 ServeFile(w, r, "testdata/file")
40         }))
41         defer ts.Close()
42
43         var err error
44
45         file, err := ioutil.ReadFile(testFile)
46         if err != nil {
47                 t.Fatal("reading file:", err)
48         }
49
50         // set up the Request (re-used for all tests)
51         var req Request
52         req.Header = make(Header)
53         if req.URL, err = url.Parse(ts.URL); err != nil {
54                 t.Fatal("ParseURL:", err)
55         }
56         req.Method = "GET"
57
58         // straight GET
59         _, body := getBody(t, req)
60         if !equal(body, file) {
61                 t.Fatalf("body mismatch: got %q, want %q", body, file)
62         }
63
64         // Range tests
65         for _, rt := range ServeFileRangeTests {
66                 req.Header.Set("Range", "bytes="+rt.r)
67                 if rt.r == "" {
68                         req.Header["Range"] = nil
69                 }
70                 r, body := getBody(t, req)
71                 if r.StatusCode != rt.code {
72                         t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
73                 }
74                 if rt.code == StatusRequestedRangeNotSatisfiable {
75                         continue
76                 }
77                 h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
78                 if rt.r == "" {
79                         h = ""
80                 }
81                 cr := r.Header.Get("Content-Range")
82                 if cr != h {
83                         t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
84                 }
85                 if !equal(body, file[rt.start:rt.end]) {
86                         t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
87                 }
88         }
89 }
90
91 var fsRedirectTestData = []struct {
92         original, redirect string
93 }{
94         {"/test/index.html", "/test/"},
95         {"/test/testdata", "/test/testdata/"},
96         {"/test/testdata/file/", "/test/testdata/file"},
97 }
98
99 func TestFSRedirect(t *testing.T) {
100         ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
101         defer ts.Close()
102
103         for _, data := range fsRedirectTestData {
104                 res, err := Get(ts.URL + data.original)
105                 if err != nil {
106                         t.Fatal(err)
107                 }
108                 res.Body.Close()
109                 if g, e := res.Request.URL.Path, data.redirect; g != e {
110                         t.Errorf("redirect from %s: got %s, want %s", data.original, g, e)
111                 }
112         }
113 }
114
115 type testFileSystem struct {
116         open func(name string) (File, error)
117 }
118
119 func (fs *testFileSystem) Open(name string) (File, error) {
120         return fs.open(name)
121 }
122
123 func TestFileServerCleans(t *testing.T) {
124         ch := make(chan string, 1)
125         fs := FileServer(&testFileSystem{func(name string) (File, error) {
126                 ch <- name
127                 return nil, os.ENOENT
128         }})
129         tests := []struct {
130                 reqPath, openArg string
131         }{
132                 {"/foo.txt", "/foo.txt"},
133                 {"//foo.txt", "/foo.txt"},
134                 {"/../foo.txt", "/foo.txt"},
135         }
136         req, _ := NewRequest("GET", "http://example.com", nil)
137         for n, test := range tests {
138                 rec := httptest.NewRecorder()
139                 req.URL.Path = test.reqPath
140                 fs.ServeHTTP(rec, req)
141                 if got := <-ch; got != test.openArg {
142                         t.Errorf("test %d: got %q, want %q", n, got, test.openArg)
143                 }
144         }
145 }
146
147 func TestFileServerImplicitLeadingSlash(t *testing.T) {
148         tempDir, err := ioutil.TempDir("", "")
149         if err != nil {
150                 t.Fatalf("TempDir: %v", err)
151         }
152         defer os.RemoveAll(tempDir)
153         if err := ioutil.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil {
154                 t.Fatalf("WriteFile: %v", err)
155         }
156         ts := httptest.NewServer(StripPrefix("/bar/", FileServer(Dir(tempDir))))
157         defer ts.Close()
158         get := func(suffix string) string {
159                 res, err := Get(ts.URL + suffix)
160                 if err != nil {
161                         t.Fatalf("Get %s: %v", suffix, err)
162                 }
163                 b, err := ioutil.ReadAll(res.Body)
164                 if err != nil {
165                         t.Fatalf("ReadAll %s: %v", suffix, err)
166                 }
167                 return string(b)
168         }
169         if s := get("/bar/"); !strings.Contains(s, ">foo.txt<") {
170                 t.Logf("expected a directory listing with foo.txt, got %q", s)
171         }
172         if s := get("/bar/foo.txt"); s != "Hello world" {
173                 t.Logf("expected %q, got %q", "Hello world", s)
174         }
175 }
176
177 func TestDirJoin(t *testing.T) {
178         wfi, err := os.Stat("/etc/hosts")
179         if err != nil {
180                 t.Logf("skipping test; no /etc/hosts file")
181                 return
182         }
183         test := func(d Dir, name string) {
184                 f, err := d.Open(name)
185                 if err != nil {
186                         t.Fatalf("open of %s: %v", name, err)
187                 }
188                 defer f.Close()
189                 gfi, err := f.Stat()
190                 if err != nil {
191                         t.Fatalf("stat of %s: %v", name, err)
192                 }
193                 if gfi.Ino != wfi.Ino {
194                         t.Errorf("%s got different inode", name)
195                 }
196         }
197         test(Dir("/etc/"), "/hosts")
198         test(Dir("/etc/"), "hosts")
199         test(Dir("/etc/"), "../../../../hosts")
200         test(Dir("/etc"), "/hosts")
201         test(Dir("/etc"), "hosts")
202         test(Dir("/etc"), "../../../../hosts")
203
204         // Not really directories, but since we use this trick in
205         // ServeFile, test it:
206         test(Dir("/etc/hosts"), "")
207         test(Dir("/etc/hosts"), "/")
208         test(Dir("/etc/hosts"), "../")
209 }
210
211 func TestEmptyDirOpenCWD(t *testing.T) {
212         test := func(d Dir) {
213                 name := "fs_test.go"
214                 f, err := d.Open(name)
215                 if err != nil {
216                         t.Fatalf("open of %s: %v", name, err)
217                 }
218                 defer f.Close()
219         }
220         test(Dir(""))
221         test(Dir("."))
222         test(Dir("./"))
223 }
224
225 func TestServeFileContentType(t *testing.T) {
226         const ctype = "icecream/chocolate"
227         override := false
228         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
229                 if override {
230                         w.Header().Set("Content-Type", ctype)
231                 }
232                 ServeFile(w, r, "testdata/file")
233         }))
234         defer ts.Close()
235         get := func(want string) {
236                 resp, err := Get(ts.URL)
237                 if err != nil {
238                         t.Fatal(err)
239                 }
240                 if h := resp.Header.Get("Content-Type"); h != want {
241                         t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
242                 }
243         }
244         get("text/plain; charset=utf-8")
245         override = true
246         get(ctype)
247 }
248
249 func TestServeFileMimeType(t *testing.T) {
250         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
251                 ServeFile(w, r, "testdata/style.css")
252         }))
253         defer ts.Close()
254         resp, err := Get(ts.URL)
255         if err != nil {
256                 t.Fatal(err)
257         }
258         want := "text/css; charset=utf-8"
259         if h := resp.Header.Get("Content-Type"); h != want {
260                 t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
261         }
262 }
263
264 func TestServeFileFromCWD(t *testing.T) {
265         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
266                 ServeFile(w, r, "fs_test.go")
267         }))
268         defer ts.Close()
269         r, err := Get(ts.URL)
270         if err != nil {
271                 t.Fatal(err)
272         }
273         if r.StatusCode != 200 {
274                 t.Fatalf("expected 200 OK, got %s", r.Status)
275         }
276 }
277
278 func TestServeFileWithContentEncoding(t *testing.T) {
279         ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
280                 w.Header().Set("Content-Encoding", "foo")
281                 ServeFile(w, r, "testdata/file")
282         }))
283         defer ts.Close()
284         resp, err := Get(ts.URL)
285         if err != nil {
286                 t.Fatal(err)
287         }
288         if g, e := resp.ContentLength, int64(-1); g != e {
289                 t.Errorf("Content-Length mismatch: got %d, want %d", g, e)
290         }
291 }
292
293 func TestServeIndexHtml(t *testing.T) {
294         const want = "index.html says hello\n"
295         ts := httptest.NewServer(FileServer(Dir(".")))
296         defer ts.Close()
297
298         for _, path := range []string{"/testdata/", "/testdata/index.html"} {
299                 res, err := Get(ts.URL + path)
300                 if err != nil {
301                         t.Fatal(err)
302                 }
303                 defer res.Body.Close()
304                 b, err := ioutil.ReadAll(res.Body)
305                 if err != nil {
306                         t.Fatal("reading Body:", err)
307                 }
308                 if s := string(b); s != want {
309                         t.Errorf("for path %q got %q, want %q", path, s, want)
310                 }
311         }
312 }
313
314 func getBody(t *testing.T, req Request) (*Response, []byte) {
315         r, err := DefaultClient.Do(&req)
316         if err != nil {
317                 t.Fatal(req.URL.String(), "send:", err)
318         }
319         b, err := ioutil.ReadAll(r.Body)
320         if err != nil {
321                 t.Fatal("reading Body:", err)
322         }
323         return r, b
324 }
325
326 func equal(a, b []byte) bool {
327         if len(a) != len(b) {
328                 return false
329         }
330         for i := range a {
331                 if a[i] != b[i] {
332                         return false
333                 }
334         }
335         return true
336 }