git-lfs/api/upload_test.go

598 lines
13 KiB
Go
Raw Normal View History

2016-05-17 12:00:32 +00:00
package api_test // prevent import cycles
2015-03-20 01:55:40 +00:00
import (
"bytes"
"encoding/json"
2015-03-20 02:56:56 +00:00
"fmt"
2015-03-20 01:55:40 +00:00
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
2015-03-20 01:55:40 +00:00
"strconv"
"testing"
"github.com/github/git-lfs/api"
"github.com/github/git-lfs/config"
2016-08-18 20:20:33 +00:00
"github.com/github/git-lfs/errors"
"github.com/github/git-lfs/httputil"
2016-05-17 12:00:32 +00:00
"github.com/github/git-lfs/lfs"
"github.com/github/git-lfs/test"
2015-03-20 01:55:40 +00:00
)
func TestExistingUpload(t *testing.T) {
SetupTestCredentialsFunc()
repo := test.NewRepo(t)
repo.Pushd()
defer func() {
repo.Popd()
repo.Cleanup()
RestoreCredentialsFunc()
}()
mux := http.NewServeMux()
server := httptest.NewServer(mux)
tmp := tempdir(t)
defer server.Close()
defer os.RemoveAll(tmp)
postCalled := false
mux.HandleFunc("/media/objects", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
if r.Header.Get("Accept") != api.MediaType {
t.Errorf("Invalid Accept")
}
if r.Header.Get("Content-Type") != api.MediaType {
t.Errorf("Invalid Content-Type")
}
buf := &bytes.Buffer{}
tee := io.TeeReader(r.Body, buf)
reqObj := &api.ObjectResource{}
err := json.NewDecoder(tee).Decode(reqObj)
t.Logf("request header: %v", r.Header)
t.Logf("request body: %s", buf.String())
if err != nil {
t.Fatal(err)
}
if reqObj.Oid != "988881adc9fc3655077dc2d4d757d480b5ea0e11" {
t.Errorf("invalid oid from request: %s", reqObj.Oid)
}
if reqObj.Size != 4 {
t.Errorf("invalid size from request: %d", reqObj.Size)
}
obj := &api.ObjectResource{
Oid: reqObj.Oid,
Size: reqObj.Size,
Actions: map[string]*api.LinkRelation{
"upload": &api.LinkRelation{
Href: server.URL + "/upload",
Header: map[string]string{"A": "1"},
},
"verify": &api.LinkRelation{
Href: server.URL + "/verify",
Header: map[string]string{"B": "2"},
},
},
}
by, err := json.Marshal(obj)
if err != nil {
t.Fatal(err)
}
postCalled = true
head := w.Header()
head.Set("Content-Type", api.MediaType)
head.Set("Content-Length", strconv.Itoa(len(by)))
2015-03-21 17:28:33 +00:00
w.WriteHeader(200)
w.Write(by)
})
cfg := config.NewFrom(config.Values{
Git: map[string]string{
"lfs.url": server.URL + "/media",
},
})
2016-05-17 12:00:32 +00:00
oidPath, _ := lfs.LocalMediaPath("988881adc9fc3655077dc2d4d757d480b5ea0e11")
if err := ioutil.WriteFile(oidPath, []byte("test"), 0744); err != nil {
t.Fatal(err)
}
oid := filepath.Base(oidPath)
stat, _ := os.Stat(oidPath)
o, _, err := api.BatchOrLegacySingle(cfg, &api.ObjectResource{Oid: oid, Size: stat.Size()}, "upload", []string{"basic"})
2015-08-21 18:31:06 +00:00
if err != nil {
if isDockerConnectionError(err) {
return
}
2015-08-21 18:31:06 +00:00
t.Fatal(err)
}
if o != nil {
t.Errorf("Got an object back")
}
if !postCalled {
t.Errorf("POST not called")
}
}
2015-03-26 18:46:33 +00:00
func TestUploadWithRedirect(t *testing.T) {
SetupTestCredentialsFunc()
repo := test.NewRepo(t)
repo.Pushd()
defer func() {
repo.Popd()
repo.Cleanup()
RestoreCredentialsFunc()
}()
2015-03-26 18:46:33 +00:00
mux := http.NewServeMux()
server := httptest.NewServer(mux)
tmp := tempdir(t)
defer server.Close()
defer os.RemoveAll(tmp)
mux.HandleFunc("/redirect/objects", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
w.Header().Set("Location", server.URL+"/redirect2/objects")
w.WriteHeader(307)
})
mux.HandleFunc("/redirect2/objects", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
w.Header().Set("Location", server.URL+"/media/objects")
w.WriteHeader(307)
})
mux.HandleFunc("/media/objects", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
if r.Header.Get("Accept") != api.MediaType {
2015-03-26 18:46:33 +00:00
t.Errorf("Invalid Accept")
}
if r.Header.Get("Content-Type") != api.MediaType {
2015-03-26 18:46:33 +00:00
t.Errorf("Invalid Content-Type")
}
buf := &bytes.Buffer{}
tee := io.TeeReader(r.Body, buf)
reqObj := &api.ObjectResource{}
2015-03-26 18:46:33 +00:00
err := json.NewDecoder(tee).Decode(reqObj)
t.Logf("request header: %v", r.Header)
t.Logf("request body: %s", buf.String())
if err != nil {
t.Fatal(err)
}
if reqObj.Oid != "988881adc9fc3655077dc2d4d757d480b5ea0e11" {
2015-03-26 18:46:33 +00:00
t.Errorf("invalid oid from request: %s", reqObj.Oid)
}
if reqObj.Size != 4 {
t.Errorf("invalid size from request: %d", reqObj.Size)
}
obj := &api.ObjectResource{
Actions: map[string]*api.LinkRelation{
"upload": &api.LinkRelation{
2015-03-26 18:46:33 +00:00
Href: server.URL + "/upload",
Header: map[string]string{"A": "1"},
},
"verify": &api.LinkRelation{
2015-03-26 18:46:33 +00:00
Href: server.URL + "/verify",
Header: map[string]string{"B": "2"},
},
},
}
by, err := json.Marshal(obj)
if err != nil {
t.Fatal(err)
}
head := w.Header()
head.Set("Content-Type", api.MediaType)
2015-03-26 18:46:33 +00:00
head.Set("Content-Length", strconv.Itoa(len(by)))
w.WriteHeader(200)
w.Write(by)
})
cfg := config.NewFrom(config.Values{
Git: map[string]string{
"lfs.url": server.URL + "/redirect",
},
})
2015-03-26 18:46:33 +00:00
2016-05-17 12:00:32 +00:00
oidPath, _ := lfs.LocalMediaPath("988881adc9fc3655077dc2d4d757d480b5ea0e11")
2015-03-26 18:46:33 +00:00
if err := ioutil.WriteFile(oidPath, []byte("test"), 0744); err != nil {
t.Fatal(err)
}
oid := filepath.Base(oidPath)
stat, _ := os.Stat(oidPath)
o, _, err := api.BatchOrLegacySingle(cfg, &api.ObjectResource{Oid: oid, Size: stat.Size()}, "upload", []string{"basic"})
2015-08-21 18:31:06 +00:00
if err != nil {
if isDockerConnectionError(err) {
return
}
2015-08-21 18:31:06 +00:00
t.Fatal(err)
2015-03-26 18:46:33 +00:00
}
if o != nil {
t.Fatal("Received an object")
}
2015-03-26 18:46:33 +00:00
}
2015-03-20 01:55:40 +00:00
func TestSuccessfulUploadWithVerify(t *testing.T) {
SetupTestCredentialsFunc()
repo := test.NewRepo(t)
repo.Pushd()
defer func() {
repo.Popd()
repo.Cleanup()
RestoreCredentialsFunc()
}()
2015-03-20 01:55:40 +00:00
mux := http.NewServeMux()
server := httptest.NewServer(mux)
tmp := tempdir(t)
defer server.Close()
defer os.RemoveAll(tmp)
postCalled := false
verifyCalled := false
mux.HandleFunc("/media/objects", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
if r.Header.Get("Accept") != api.MediaType {
2015-03-20 01:55:40 +00:00
t.Errorf("Invalid Accept")
}
if r.Header.Get("Content-Type") != api.MediaType {
2015-03-20 01:55:40 +00:00
t.Errorf("Invalid Content-Type")
}
buf := &bytes.Buffer{}
tee := io.TeeReader(r.Body, buf)
reqObj := &api.ObjectResource{}
2015-03-20 01:55:40 +00:00
err := json.NewDecoder(tee).Decode(reqObj)
t.Logf("request header: %v", r.Header)
t.Logf("request body: %s", buf.String())
if err != nil {
t.Fatal(err)
}
if reqObj.Oid != "988881adc9fc3655077dc2d4d757d480b5ea0e11" {
2015-03-20 01:55:40 +00:00
t.Errorf("invalid oid from request: %s", reqObj.Oid)
}
if reqObj.Size != 4 {
t.Errorf("invalid size from request: %d", reqObj.Size)
}
obj := &api.ObjectResource{
Oid: reqObj.Oid,
Size: reqObj.Size,
Actions: map[string]*api.LinkRelation{
"upload": &api.LinkRelation{
2015-03-20 01:55:40 +00:00
Href: server.URL + "/upload",
Header: map[string]string{"A": "1"},
},
"verify": &api.LinkRelation{
2015-03-20 01:55:40 +00:00
Href: server.URL + "/verify",
Header: map[string]string{"B": "2"},
},
},
}
by, err := json.Marshal(obj)
if err != nil {
t.Fatal(err)
}
postCalled = true
head := w.Header()
head.Set("Content-Type", api.MediaType)
2015-03-20 01:55:40 +00:00
head.Set("Content-Length", strconv.Itoa(len(by)))
2015-03-21 17:28:33 +00:00
w.WriteHeader(202)
2015-03-20 01:55:40 +00:00
w.Write(by)
})
mux.HandleFunc("/verify", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
if r.Header.Get("B") != "2" {
t.Error("Invalid B")
}
if r.Header.Get("Content-Type") != api.MediaType {
2015-03-20 01:55:40 +00:00
t.Error("Invalid Content-Type")
}
buf := &bytes.Buffer{}
tee := io.TeeReader(r.Body, buf)
reqObj := &api.ObjectResource{}
2015-03-20 01:55:40 +00:00
err := json.NewDecoder(tee).Decode(reqObj)
t.Logf("request header: %v", r.Header)
t.Logf("request body: %s", buf.String())
if err != nil {
t.Fatal(err)
}
if reqObj.Oid != "988881adc9fc3655077dc2d4d757d480b5ea0e11" {
2015-03-20 01:55:40 +00:00
t.Errorf("invalid oid from request: %s", reqObj.Oid)
}
if reqObj.Size != 4 {
t.Errorf("invalid size from request: %d", reqObj.Size)
}
verifyCalled = true
w.WriteHeader(200)
})
cfg := config.NewFrom(config.Values{
Git: map[string]string{
"lfs.url": server.URL + "/media",
},
})
2015-03-20 01:55:40 +00:00
2016-05-17 12:00:32 +00:00
oidPath, _ := lfs.LocalMediaPath("988881adc9fc3655077dc2d4d757d480b5ea0e11")
2015-03-20 01:55:40 +00:00
if err := ioutil.WriteFile(oidPath, []byte("test"), 0744); err != nil {
t.Fatal(err)
}
oid := filepath.Base(oidPath)
stat, _ := os.Stat(oidPath)
o, _, err := api.BatchOrLegacySingle(cfg, &api.ObjectResource{Oid: oid, Size: stat.Size()}, "upload", []string{"basic"})
2015-08-21 18:31:06 +00:00
if err != nil {
if isDockerConnectionError(err) {
return
}
2015-08-21 18:31:06 +00:00
t.Fatal(err)
}
api.VerifyUpload(cfg, o)
2015-03-20 01:55:40 +00:00
if !postCalled {
t.Errorf("POST not called")
}
if !verifyCalled {
t.Errorf("verify not called")
}
2015-03-20 18:01:43 +00:00
2015-03-20 01:55:40 +00:00
}
2015-03-20 02:56:56 +00:00
func TestUploadApiError(t *testing.T) {
SetupTestCredentialsFunc()
repo := test.NewRepo(t)
repo.Pushd()
defer func() {
repo.Popd()
repo.Cleanup()
RestoreCredentialsFunc()
}()
2015-03-20 02:56:56 +00:00
mux := http.NewServeMux()
server := httptest.NewServer(mux)
tmp := tempdir(t)
defer server.Close()
defer os.RemoveAll(tmp)
postCalled := false
mux.HandleFunc("/media/objects", func(w http.ResponseWriter, r *http.Request) {
postCalled = true
w.WriteHeader(404)
})
cfg := config.NewFrom(config.Values{
Git: map[string]string{
"lfs.url": server.URL + "/media",
},
})
2015-03-20 02:56:56 +00:00
2016-05-17 12:00:32 +00:00
oidPath, _ := lfs.LocalMediaPath("988881adc9fc3655077dc2d4d757d480b5ea0e11")
2015-03-20 02:56:56 +00:00
if err := ioutil.WriteFile(oidPath, []byte("test"), 0744); err != nil {
t.Fatal(err)
}
oid := filepath.Base(oidPath)
stat, _ := os.Stat(oidPath)
_, _, err := api.BatchOrLegacySingle(cfg, &api.ObjectResource{Oid: oid, Size: stat.Size()}, "upload", []string{"basic"})
2015-08-21 18:31:06 +00:00
if err == nil {
t.Fatal(err)
2015-03-20 02:56:56 +00:00
}
2016-08-18 20:20:33 +00:00
if errors.IsFatalError(err) {
2015-03-20 02:56:56 +00:00
t.Fatal("should not panic")
}
if isDockerConnectionError(err) {
return
}
2016-08-17 23:56:44 +00:00
expected := "LFS: " + fmt.Sprintf(httputil.GetDefaultError(404), server.URL+"/media/objects")
if err.Error() != expected {
t.Fatalf("Expected: %s\nGot: %s", expected, err.Error())
2015-03-20 02:56:56 +00:00
}
if !postCalled {
t.Errorf("POST not called")
}
}
func TestUploadVerifyError(t *testing.T) {
SetupTestCredentialsFunc()
repo := test.NewRepo(t)
repo.Pushd()
defer func() {
repo.Popd()
repo.Cleanup()
RestoreCredentialsFunc()
}()
2015-03-20 02:56:56 +00:00
mux := http.NewServeMux()
server := httptest.NewServer(mux)
tmp := tempdir(t)
defer server.Close()
defer os.RemoveAll(tmp)
postCalled := false
verifyCalled := false
mux.HandleFunc("/media/objects", func(w http.ResponseWriter, r *http.Request) {
t.Logf("Server: %s %s", r.Method, r.URL)
if r.Method != "POST" {
w.WriteHeader(405)
return
}
if r.Header.Get("Accept") != api.MediaType {
2015-03-20 02:56:56 +00:00
t.Errorf("Invalid Accept")
}
if r.Header.Get("Content-Type") != api.MediaType {
2015-03-20 02:56:56 +00:00
t.Errorf("Invalid Content-Type")
}
buf := &bytes.Buffer{}
tee := io.TeeReader(r.Body, buf)
reqObj := &api.ObjectResource{}
2015-03-20 02:56:56 +00:00
err := json.NewDecoder(tee).Decode(reqObj)
t.Logf("request header: %v", r.Header)
t.Logf("request body: %s", buf.String())
if err != nil {
t.Fatal(err)
}
if reqObj.Oid != "988881adc9fc3655077dc2d4d757d480b5ea0e11" {
2015-03-20 02:56:56 +00:00
t.Errorf("invalid oid from request: %s", reqObj.Oid)
}
if reqObj.Size != 4 {
t.Errorf("invalid size from request: %d", reqObj.Size)
}
obj := &api.ObjectResource{
Oid: reqObj.Oid,
Size: reqObj.Size,
Actions: map[string]*api.LinkRelation{
"upload": &api.LinkRelation{
2015-03-20 02:56:56 +00:00
Href: server.URL + "/upload",
Header: map[string]string{"A": "1"},
},
"verify": &api.LinkRelation{
2015-03-20 02:56:56 +00:00
Href: server.URL + "/verify",
Header: map[string]string{"B": "2"},
},
},
}
by, err := json.Marshal(obj)
if err != nil {
t.Fatal(err)
}
postCalled = true
head := w.Header()
head.Set("Content-Type", api.MediaType)
2015-03-20 02:56:56 +00:00
head.Set("Content-Length", strconv.Itoa(len(by)))
2015-03-21 17:28:33 +00:00
w.WriteHeader(202)
2015-03-20 02:56:56 +00:00
w.Write(by)
})
mux.HandleFunc("/verify", func(w http.ResponseWriter, r *http.Request) {
verifyCalled = true
w.WriteHeader(404)
})
cfg := config.NewFrom(config.Values{
Git: map[string]string{
"lfs.url": server.URL + "/media",
},
})
2015-03-20 02:56:56 +00:00
2016-05-17 12:00:32 +00:00
oidPath, _ := lfs.LocalMediaPath("988881adc9fc3655077dc2d4d757d480b5ea0e11")
2015-03-20 02:56:56 +00:00
if err := ioutil.WriteFile(oidPath, []byte("test"), 0744); err != nil {
t.Fatal(err)
}
oid := filepath.Base(oidPath)
stat, _ := os.Stat(oidPath)
o, _, err := api.BatchOrLegacySingle(cfg, &api.ObjectResource{Oid: oid, Size: stat.Size()}, "upload", []string{"basic"})
2015-08-21 18:31:06 +00:00
if err != nil {
if isDockerConnectionError(err) {
return
}
2015-08-21 18:31:06 +00:00
t.Fatal(err)
}
err = api.VerifyUpload(cfg, o)
2015-08-21 18:31:06 +00:00
if err == nil {
t.Fatal("verify should fail")
2015-03-20 02:56:56 +00:00
}
2016-08-18 20:20:33 +00:00
if errors.IsFatalError(err) {
2015-03-20 02:56:56 +00:00
t.Fatal("should not panic")
}
2016-08-17 23:56:44 +00:00
expected := "LFS: " + fmt.Sprintf(httputil.GetDefaultError(404), server.URL+"/verify")
if err.Error() != expected {
t.Fatalf("Expected: %s\nGot: %s", expected, err.Error())
2015-03-20 02:56:56 +00:00
}
if !postCalled {
t.Errorf("POST not called")
}
if !verifyCalled {
t.Errorf("verify not called")
}
2015-03-20 02:56:56 +00:00
}