diff --git a/cmd/serve/webdav/testdata/golden/a.txt b/cmd/serve/webdav/testdata/golden/a.txt new file mode 100644 index 000000000..2bdf67abb --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/a.txt @@ -0,0 +1 @@ +three diff --git a/cmd/serve/webdav/testdata/golden/dirnotfound.html b/cmd/serve/webdav/testdata/golden/dirnotfound.html new file mode 100644 index 000000000..4c30256ec --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/dirnotfound.html @@ -0,0 +1 @@ +Directory not found diff --git a/cmd/serve/webdav/testdata/golden/hidden.txt b/cmd/serve/webdav/testdata/golden/hidden.txt new file mode 100644 index 000000000..853730769 --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/hidden.txt @@ -0,0 +1 @@ +Not Found \ No newline at end of file diff --git a/cmd/serve/webdav/testdata/golden/hiddendir.html b/cmd/serve/webdav/testdata/golden/hiddendir.html new file mode 100644 index 000000000..4c30256ec --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/hiddendir.html @@ -0,0 +1 @@ +Directory not found diff --git a/cmd/serve/webdav/testdata/golden/index.html b/cmd/serve/webdav/testdata/golden/index.html new file mode 100644 index 000000000..8afb9b697 --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/index.html @@ -0,0 +1,13 @@ + + + + +Directory listing of / + + +

Directory listing of /

+one%.txt
+three/
+two.txt
+ + diff --git a/cmd/serve/webdav/testdata/golden/indexhead.txt b/cmd/serve/webdav/testdata/golden/indexhead.txt new file mode 100644 index 000000000..e69de29bb diff --git a/cmd/serve/webdav/testdata/golden/indexpost.txt b/cmd/serve/webdav/testdata/golden/indexpost.txt new file mode 100644 index 000000000..772cdf01d --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/indexpost.txt @@ -0,0 +1 @@ +Method Not Allowed \ No newline at end of file diff --git a/cmd/serve/webdav/testdata/golden/notfound.html b/cmd/serve/webdav/testdata/golden/notfound.html new file mode 100644 index 000000000..853730769 --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/notfound.html @@ -0,0 +1 @@ +Not Found \ No newline at end of file diff --git a/cmd/serve/webdav/testdata/golden/one.txt b/cmd/serve/webdav/testdata/golden/one.txt new file mode 100644 index 000000000..07f46ed0f --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/one.txt @@ -0,0 +1 @@ +one% diff --git a/cmd/serve/webdav/testdata/golden/onehead.txt b/cmd/serve/webdav/testdata/golden/onehead.txt new file mode 100644 index 000000000..e69de29bb diff --git a/cmd/serve/webdav/testdata/golden/onepost.txt b/cmd/serve/webdav/testdata/golden/onepost.txt new file mode 100644 index 000000000..07f46ed0f --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/onepost.txt @@ -0,0 +1 @@ +one% diff --git a/cmd/serve/webdav/testdata/golden/three.html b/cmd/serve/webdav/testdata/golden/three.html new file mode 100644 index 000000000..85ea95184 --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/three.html @@ -0,0 +1,12 @@ + + + + +Directory listing of /three + + +

Directory listing of /three

+a.txt
+b.txt
+ + diff --git a/cmd/serve/webdav/testdata/golden/two-6.txt b/cmd/serve/webdav/testdata/golden/two-6.txt new file mode 100644 index 000000000..fe9492017 --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/two-6.txt @@ -0,0 +1 @@ +0123456 \ No newline at end of file diff --git a/cmd/serve/webdav/testdata/golden/two.txt b/cmd/serve/webdav/testdata/golden/two.txt new file mode 100644 index 000000000..11f11f9be --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/two.txt @@ -0,0 +1 @@ +0123456789 diff --git a/cmd/serve/webdav/testdata/golden/two2-5.txt b/cmd/serve/webdav/testdata/golden/two2-5.txt new file mode 100644 index 000000000..a35de6dba --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/two2-5.txt @@ -0,0 +1 @@ +2345 \ No newline at end of file diff --git a/cmd/serve/webdav/testdata/golden/two3-.txt b/cmd/serve/webdav/testdata/golden/two3-.txt new file mode 100644 index 000000000..60754f988 --- /dev/null +++ b/cmd/serve/webdav/testdata/golden/two3-.txt @@ -0,0 +1 @@ +3456789 diff --git a/cmd/serve/webdav/webdav.go b/cmd/serve/webdav/webdav.go index 6f4416e7f..795ecceb2 100644 --- a/cmd/serve/webdav/webdav.go +++ b/cmd/serve/webdav/webdav.go @@ -22,8 +22,8 @@ import ( ) var ( - hashName string - hashType = hash.None + hashName string + hashType = hash.None disableGETDir = false ) diff --git a/cmd/serve/webdav/webdav_test.go b/cmd/serve/webdav/webdav_test.go index 0f74a5356..c80c0b759 100644 --- a/cmd/serve/webdav/webdav_test.go +++ b/cmd/serve/webdav/webdav_test.go @@ -8,14 +8,22 @@ package webdav import ( + "flag" + "io/ioutil" + "net/http" "os" "os/exec" + "strings" "testing" + "time" _ "github.com/ncw/rclone/backend/local" "github.com/ncw/rclone/cmd/serve/httplib" + "github.com/ncw/rclone/fs" + "github.com/ncw/rclone/fs/filter" "github.com/ncw/rclone/fstest" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/net/webdav" ) @@ -78,3 +86,185 @@ func TestWebDav(t *testing.T) { } assert.NoError(t, err, "Running webdav integration tests") } + +// Test serve http functionality in serve webdav +// While similar to http serve, there are some inconsistencies +// in the handling of some requests such as POST requests + +var ( + updateGolden = flag.Bool("updategolden", false, "update golden files for regression test") +) + +func TestHTTPFunction(t *testing.T) { + // cd to correct directory for testing + err := os.Chdir("../../cmd/serve/webdav") + assert.NoError(t, err, "failed to cd to webdav cmd directory") + + // exclude files called hidden.txt and directories called hidden + require.NoError(t, filter.Active.AddRule("- hidden.txt")) + require.NoError(t, filter.Active.AddRule("- hidden/**")) + + // Uses the same test files as http tests but with different golden. + f, err := fs.NewFs("../http/testdata/files") + assert.NoError(t, err) + + opt := httplib.DefaultOpt + opt.ListenAddr = testBindAddress + + // Start the server + w := newWebDAV(f, &opt) + assert.NoError(t, w.serve()) + defer func() { + w.Close() + w.Wait() + }() + testURL := w.Server.URL() + pause := time.Millisecond + i := 0 + for ; i < 10; i++ { + resp, err := http.Head(testURL) + if err == nil { + _ = resp.Body.Close() + break + } + // t.Logf("couldn't connect, sleeping for %v: %v", pause, err) + time.Sleep(pause) + pause *= 2 + } + if i >= 10 { + t.Fatal("couldn't connect to server") + } + + HelpTestGET(t, testURL) +} + +// check body against the file, or re-write body if -updategolden is +// set. +func checkGolden(t *testing.T, fileName string, got []byte) { + if *updateGolden { + t.Logf("Updating golden file %q", fileName) + err := ioutil.WriteFile(fileName, got, 0666) + require.NoError(t, err) + } else { + want, err := ioutil.ReadFile(fileName) + require.NoError(t, err, "problem") + wants := strings.Split(string(want), "\n") + gots := strings.Split(string(got), "\n") + assert.Equal(t, wants, gots, fileName) + } +} + +func HelpTestGET(t *testing.T, testURL string) { + for _, test := range []struct { + URL string + Status int + Golden string + Method string + Range string + }{ + { + URL: "", + Status: http.StatusOK, + Golden: "testdata/golden/index.html", + }, + { + URL: "notfound", + Status: http.StatusNotFound, + Golden: "testdata/golden/notfound.html", + }, + { + URL: "dirnotfound/", + Status: http.StatusNotFound, + Golden: "testdata/golden/dirnotfound.html", + }, + { + URL: "hidden/", + Status: http.StatusNotFound, + Golden: "testdata/golden/hiddendir.html", + }, + { + URL: "one%25.txt", + Status: http.StatusOK, + Golden: "testdata/golden/one.txt", + }, + { + URL: "hidden.txt", + Status: http.StatusNotFound, + Golden: "testdata/golden/hidden.txt", + }, + { + URL: "three/", + Status: http.StatusOK, + Golden: "testdata/golden/three.html", + }, + { + URL: "three/a.txt", + Status: http.StatusOK, + Golden: "testdata/golden/a.txt", + }, + { + URL: "", + Method: "HEAD", + Status: http.StatusOK, + Golden: "testdata/golden/indexhead.txt", + }, + { + URL: "one%25.txt", + Method: "HEAD", + Status: http.StatusOK, + Golden: "testdata/golden/onehead.txt", + }, + { + URL: "", + Method: "POST", + Status: http.StatusMethodNotAllowed, + Golden: "testdata/golden/indexpost.txt", + }, + { + URL: "one%25.txt", + Method: "POST", + Status: http.StatusOK, + Golden: "testdata/golden/onepost.txt", + }, + { + URL: "two.txt", + Status: http.StatusOK, + Golden: "testdata/golden/two.txt", + }, + { + URL: "two.txt", + Status: http.StatusPartialContent, + Range: "bytes=2-5", + Golden: "testdata/golden/two2-5.txt", + }, + { + URL: "two.txt", + Status: http.StatusPartialContent, + Range: "bytes=0-6", + Golden: "testdata/golden/two-6.txt", + }, + { + URL: "two.txt", + Status: http.StatusPartialContent, + Range: "bytes=3-", + Golden: "testdata/golden/two3-.txt", + }, + } { + method := test.Method + if method == "" { + method = "GET" + } + req, err := http.NewRequest(method, testURL+test.URL, nil) + require.NoError(t, err) + if test.Range != "" { + req.Header.Add("Range", test.Range) + } + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + assert.Equal(t, test.Status, resp.StatusCode, test.Golden) + body, err := ioutil.ReadAll(resp.Body) + require.NoError(t, err) + + checkGolden(t, test.Golden, body) + } +}