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&amp;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  }