github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/webdav/webdav_test.go (about) 1 // Copyright 2015 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 webdav 6 7 import ( 8 "errors" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "net/http" 13 "net/http/httptest" 14 "net/url" 15 "os" 16 "reflect" 17 "regexp" 18 "sort" 19 "strings" 20 "testing" 21 ) 22 23 // TODO: add tests to check XML responses with the expected prefix path 24 func TestPrefix(t *testing.T) { 25 const dst, blah = "Destination", "blah blah blah" 26 27 do := func(method, urlStr string, body io.Reader, wantStatusCode int, headers ...string) error { 28 req, err := http.NewRequest(method, urlStr, body) 29 if err != nil { 30 return err 31 } 32 for len(headers) >= 2 { 33 req.Header.Add(headers[0], headers[1]) 34 headers = headers[2:] 35 } 36 res, err := http.DefaultClient.Do(req) 37 if err != nil { 38 return err 39 } 40 defer res.Body.Close() 41 if res.StatusCode != wantStatusCode { 42 return fmt.Errorf("got status code %d, want %d", res.StatusCode, wantStatusCode) 43 } 44 return nil 45 } 46 47 prefixes := []string{ 48 "/", 49 "/a/", 50 "/a/b/", 51 "/a/b/c/", 52 } 53 for _, prefix := range prefixes { 54 fs := NewMemFS() 55 h := &Handler{ 56 FileSystem: fs, 57 LockSystem: NewMemLS(), 58 } 59 mux := http.NewServeMux() 60 if prefix != "/" { 61 h.Prefix = prefix 62 } 63 mux.Handle(prefix, h) 64 srv := httptest.NewServer(mux) 65 defer srv.Close() 66 67 // The script is: 68 // MKCOL /a 69 // MKCOL /a/b 70 // PUT /a/b/c 71 // COPY /a/b/c /a/b/d 72 // MKCOL /a/b/e 73 // MOVE /a/b/d /a/b/e/f 74 // which should yield the (possibly stripped) filenames /a/b/c and 75 // /a/b/e/f, plus their parent directories. 76 77 wantA := map[string]int{ 78 "/": http.StatusCreated, 79 "/a/": http.StatusMovedPermanently, 80 "/a/b/": http.StatusNotFound, 81 "/a/b/c/": http.StatusNotFound, 82 }[prefix] 83 if err := do("MKCOL", srv.URL+"/a", nil, wantA); err != nil { 84 t.Errorf("prefix=%-9q MKCOL /a: %v", prefix, err) 85 continue 86 } 87 88 wantB := map[string]int{ 89 "/": http.StatusCreated, 90 "/a/": http.StatusCreated, 91 "/a/b/": http.StatusMovedPermanently, 92 "/a/b/c/": http.StatusNotFound, 93 }[prefix] 94 if err := do("MKCOL", srv.URL+"/a/b", nil, wantB); err != nil { 95 t.Errorf("prefix=%-9q MKCOL /a/b: %v", prefix, err) 96 continue 97 } 98 99 wantC := map[string]int{ 100 "/": http.StatusCreated, 101 "/a/": http.StatusCreated, 102 "/a/b/": http.StatusCreated, 103 "/a/b/c/": http.StatusMovedPermanently, 104 }[prefix] 105 if err := do("PUT", srv.URL+"/a/b/c", strings.NewReader(blah), wantC); err != nil { 106 t.Errorf("prefix=%-9q PUT /a/b/c: %v", prefix, err) 107 continue 108 } 109 110 wantD := map[string]int{ 111 "/": http.StatusCreated, 112 "/a/": http.StatusCreated, 113 "/a/b/": http.StatusCreated, 114 "/a/b/c/": http.StatusMovedPermanently, 115 }[prefix] 116 if err := do("COPY", srv.URL+"/a/b/c", nil, wantD, dst, srv.URL+"/a/b/d"); err != nil { 117 t.Errorf("prefix=%-9q COPY /a/b/c /a/b/d: %v", prefix, err) 118 continue 119 } 120 121 wantE := map[string]int{ 122 "/": http.StatusCreated, 123 "/a/": http.StatusCreated, 124 "/a/b/": http.StatusCreated, 125 "/a/b/c/": http.StatusNotFound, 126 }[prefix] 127 if err := do("MKCOL", srv.URL+"/a/b/e", nil, wantE); err != nil { 128 t.Errorf("prefix=%-9q MKCOL /a/b/e: %v", prefix, err) 129 continue 130 } 131 132 wantF := map[string]int{ 133 "/": http.StatusCreated, 134 "/a/": http.StatusCreated, 135 "/a/b/": http.StatusCreated, 136 "/a/b/c/": http.StatusNotFound, 137 }[prefix] 138 if err := do("MOVE", srv.URL+"/a/b/d", nil, wantF, dst, srv.URL+"/a/b/e/f"); err != nil { 139 t.Errorf("prefix=%-9q MOVE /a/b/d /a/b/e/f: %v", prefix, err) 140 continue 141 } 142 143 got, err := find(nil, fs, "/") 144 if err != nil { 145 t.Errorf("prefix=%-9q find: %v", prefix, err) 146 continue 147 } 148 sort.Strings(got) 149 want := map[string][]string{ 150 "/": []string{"/", "/a", "/a/b", "/a/b/c", "/a/b/e", "/a/b/e/f"}, 151 "/a/": []string{"/", "/b", "/b/c", "/b/e", "/b/e/f"}, 152 "/a/b/": []string{"/", "/c", "/e", "/e/f"}, 153 "/a/b/c/": []string{"/"}, 154 }[prefix] 155 if !reflect.DeepEqual(got, want) { 156 t.Errorf("prefix=%-9q find:\ngot %v\nwant %v", prefix, got, want) 157 continue 158 } 159 } 160 } 161 162 func TestFilenameEscape(t *testing.T) { 163 re := regexp.MustCompile(`<D:href>([^<]*)</D:href>`) 164 do := func(method, urlStr string) (string, error) { 165 req, err := http.NewRequest(method, urlStr, nil) 166 if err != nil { 167 return "", err 168 } 169 res, err := http.DefaultClient.Do(req) 170 if err != nil { 171 return "", err 172 } 173 defer res.Body.Close() 174 175 b, err := ioutil.ReadAll(res.Body) 176 if err != nil { 177 return "", err 178 } 179 m := re.FindStringSubmatch(string(b)) 180 if len(m) != 2 { 181 return "", errors.New("D:href not found") 182 } 183 184 return m[1], nil 185 } 186 187 testCases := []struct { 188 name, want string 189 }{{ 190 name: `/foo%bar`, 191 want: `/foo%25bar`, 192 }, { 193 name: `/こんにちわ世界`, 194 want: `/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%82%8F%E4%B8%96%E7%95%8C`, 195 }, { 196 name: `/Program Files/`, 197 want: `/Program%20Files`, 198 }, { 199 name: `/go+lang`, 200 want: `/go+lang`, 201 }, { 202 name: `/go&lang`, 203 want: `/go&lang`, 204 }} 205 fs := NewMemFS() 206 for _, tc := range testCases { 207 if strings.HasSuffix(tc.name, "/") { 208 if err := fs.Mkdir(tc.name, 0755); err != nil { 209 t.Fatalf("name=%q: Mkdir: %v", tc.name, err) 210 } 211 } else { 212 f, err := fs.OpenFile(tc.name, os.O_CREATE, 0644) 213 if err != nil { 214 t.Fatalf("name=%q: OpenFile: %v", tc.name, err) 215 } 216 f.Close() 217 } 218 } 219 220 srv := httptest.NewServer(&Handler{ 221 FileSystem: fs, 222 LockSystem: NewMemLS(), 223 }) 224 defer srv.Close() 225 226 u, err := url.Parse(srv.URL) 227 if err != nil { 228 t.Fatal(err) 229 } 230 231 for _, tc := range testCases { 232 u.Path = tc.name 233 got, err := do("PROPFIND", u.String()) 234 if err != nil { 235 t.Errorf("name=%q: PROPFIND: %v", tc.name, err) 236 continue 237 } 238 if got != tc.want { 239 t.Errorf("name=%q: got %q, want %q", tc.name, got, tc.want) 240 } 241 } 242 }