-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
webdav: only require locks when necessary #93
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,12 +21,8 @@ import ( | |
"testing" | ||
) | ||
|
||
// TODO: add tests to check XML responses with the expected prefix path | ||
func TestPrefix(t *testing.T) { | ||
const dst, blah = "Destination", "blah blah blah" | ||
|
||
// createLockBody comes from the example in Section 9.10.7. | ||
const createLockBody = `<?xml version="1.0" encoding="utf-8" ?> | ||
// createLockBody comes from the example in Section 9.10.7. | ||
const createLockBody = `<?xml version="1.0" encoding="utf-8" ?> | ||
<D:lockinfo xmlns:D='DAV:'> | ||
<D:lockscope><D:exclusive/></D:lockscope> | ||
<D:locktype><D:write/></D:locktype> | ||
|
@@ -36,6 +32,10 @@ func TestPrefix(t *testing.T) { | |
</D:lockinfo> | ||
` | ||
|
||
// TODO: add tests to check XML responses with the expected prefix path | ||
func TestPrefix(t *testing.T) { | ||
const dst, blah = "Destination", "blah blah blah" | ||
|
||
do := func(method, urlStr string, body string, wantStatusCode int, headers ...string) (http.Header, error) { | ||
var bodyReader io.Reader | ||
if body != "" { | ||
|
@@ -185,6 +185,29 @@ func TestPrefix(t *testing.T) { | |
continue | ||
} | ||
|
||
wantI := map[string]int{ | ||
"/": http.StatusLocked, | ||
"/a/": http.StatusLocked, | ||
"/a/b/": http.StatusLocked, | ||
"/a/b/c/": http.StatusNotFound, | ||
}[prefix] | ||
if _, err := do("PUT", srv.URL+"/a/b/e/g", blah, wantI); err != nil { | ||
t.Errorf("prefix=%-9q PUT /a/b/e/g: %v", prefix, err) | ||
continue | ||
} | ||
|
||
badIfHeader := fmt.Sprintf("<%s/a/b/e/g> (foobar)", srv.URL) | ||
wantJ := map[string]int{ | ||
"/": http.StatusPreconditionFailed, | ||
"/a/": http.StatusPreconditionFailed, | ||
"/a/b/": http.StatusPreconditionFailed, | ||
"/a/b/c/": http.StatusNotFound, | ||
}[prefix] | ||
if _, err := do("PUT", srv.URL+"/a/b/e/g", blah, wantJ, "If", badIfHeader); err != nil { | ||
t.Errorf("prefix=%-9q PUT /a/b/e/g: %v", prefix, err) | ||
continue | ||
} | ||
|
||
got, err := find(ctx, nil, fs, "/") | ||
if err != nil { | ||
t.Errorf("prefix=%-9q find: %v", prefix, err) | ||
|
@@ -347,3 +370,64 @@ func TestFilenameEscape(t *testing.T) { | |
} | ||
} | ||
} | ||
|
||
func TestMoveLockedSrcUnlockedDst(t *testing.T) { | ||
// This test reproduces https://github.com/golang/go/issues/43556 | ||
do := func(method, urlStr string, body string, wantStatusCode int, headers ...string) (http.Header, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these tests could do with some refactoring. I tend to favour writing simple test harnesses that handle much of the common behaviour between tests. In this case, I think we could refactor the 'do' function as well as the server setup. That would simplify both the existing tests, and any new ones which use a similar pattern. I was going to do it in this PR, but it probably makes more sense to do it in a separate one specific to that refactoring. Let me know if you're interested. |
||
var bodyReader io.Reader | ||
if body != "" { | ||
bodyReader = strings.NewReader(body) | ||
} | ||
req, err := http.NewRequest(method, urlStr, bodyReader) | ||
if err != nil { | ||
return nil, err | ||
} | ||
for len(headers) >= 2 { | ||
req.Header.Add(headers[0], headers[1]) | ||
headers = headers[2:] | ||
} | ||
res, err := http.DefaultTransport.RoundTrip(req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer res.Body.Close() | ||
if res.StatusCode != wantStatusCode { | ||
return nil, fmt.Errorf("got status code %d, want %d", res.StatusCode, wantStatusCode) | ||
} | ||
return res.Header, nil | ||
} | ||
|
||
srv := httptest.NewServer(&Handler{ | ||
FileSystem: NewMemFS(), | ||
LockSystem: NewMemLS(), | ||
}) | ||
defer srv.Close() | ||
|
||
src, err := url.Parse(srv.URL) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
src.Path = "/locked_src" | ||
hdrs, err := do("LOCK", src.String(), createLockBody, http.StatusCreated) | ||
klarose marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
lockToken := hdrs.Get("Lock-Token") | ||
if lockToken == "" { | ||
t.Errorf("Expected lock token") | ||
} | ||
|
||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
ifHeader := fmt.Sprintf("<%s%s> (%s)", srv.URL, src.Path, lockToken) | ||
headers := []string{"If", ifHeader, "Destination", "/unlocked_path"} | ||
|
||
_, err = do("MOVE", src.String(), "", http.StatusCreated, headers...) | ||
|
||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a huge fan of this -- it feels a little messy to depend on the behaviour of atLeastOnIfListPasses, but I think the newly created functions name + the comment make it clear enough what's expected.