2015-11-26 12:44:56 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/tools"
|
2017-01-07 03:13:31 +00:00
|
|
|
"github.com/git-lfs/git-lfs/tq"
|
2015-11-26 12:44:56 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// "upload" - all missing
|
2017-01-07 03:13:31 +00:00
|
|
|
func uploadAllMissing(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
|
|
|
|
retobjs, err := callBatchApi(manifest, tq.Upload, oidsMissing)
|
2015-11-26 12:44:56 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(retobjs) != len(oidsMissing) {
|
|
|
|
return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", len(oidsMissing), len(retobjs))
|
|
|
|
}
|
|
|
|
|
|
|
|
var errbuf bytes.Buffer
|
|
|
|
for _, o := range retobjs {
|
2017-03-06 21:33:58 +00:00
|
|
|
rel, _ := o.Rel("upload")
|
|
|
|
if rel == nil {
|
2015-11-26 12:44:56 +00:00
|
|
|
errbuf.WriteString(fmt.Sprintf("Missing upload link for %s\n", o.Oid))
|
|
|
|
}
|
|
|
|
// verify link is optional so don't check
|
|
|
|
}
|
|
|
|
|
|
|
|
if errbuf.Len() > 0 {
|
|
|
|
return errors.New(errbuf.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// "upload" - all present
|
2017-01-07 03:13:31 +00:00
|
|
|
func uploadAllExists(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
|
|
|
|
retobjs, err := callBatchApi(manifest, tq.Upload, oidsExist)
|
2015-11-26 12:44:56 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(retobjs) != len(oidsExist) {
|
|
|
|
return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", len(oidsExist), len(retobjs))
|
|
|
|
}
|
|
|
|
|
|
|
|
var errbuf bytes.Buffer
|
|
|
|
for _, o := range retobjs {
|
2017-03-06 21:33:58 +00:00
|
|
|
link, _ := o.Rel("upload")
|
|
|
|
if link == nil {
|
2017-12-15 02:07:06 +00:00
|
|
|
errbuf.WriteString(fmt.Sprintf("Upload link should not exist for %s, was %+v\n", o.Oid, link))
|
2015-11-26 12:44:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if errbuf.Len() > 0 {
|
|
|
|
return errors.New(errbuf.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// "upload" - mix of missing & present
|
2017-01-07 03:13:31 +00:00
|
|
|
func uploadMixed(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
|
2016-07-07 16:16:13 +00:00
|
|
|
existSet := tools.NewStringSetWithCapacity(len(oidsExist))
|
2015-11-26 12:44:56 +00:00
|
|
|
for _, o := range oidsExist {
|
|
|
|
existSet.Add(o.Oid)
|
|
|
|
}
|
2016-07-07 16:16:13 +00:00
|
|
|
missingSet := tools.NewStringSetWithCapacity(len(oidsMissing))
|
2015-11-26 12:44:56 +00:00
|
|
|
for _, o := range oidsMissing {
|
|
|
|
missingSet.Add(o.Oid)
|
|
|
|
}
|
|
|
|
|
|
|
|
calloids := interleaveTestData(oidsExist, oidsMissing)
|
2017-01-07 03:13:31 +00:00
|
|
|
retobjs, err := callBatchApi(manifest, tq.Upload, calloids)
|
2015-11-26 12:44:56 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
count := len(oidsExist) + len(oidsMissing)
|
|
|
|
if len(retobjs) != count {
|
|
|
|
return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", count, len(retobjs))
|
|
|
|
}
|
|
|
|
|
|
|
|
var errbuf bytes.Buffer
|
|
|
|
for _, o := range retobjs {
|
2017-03-06 21:33:58 +00:00
|
|
|
link, _ := o.Rel("upload")
|
2015-11-26 12:44:56 +00:00
|
|
|
if existSet.Contains(o.Oid) {
|
2017-03-06 21:33:58 +00:00
|
|
|
if link != nil {
|
2017-12-15 02:07:06 +00:00
|
|
|
errbuf.WriteString(fmt.Sprintf("Upload link should not exist for %s, was %+v\n", o.Oid, link))
|
2015-11-26 12:44:56 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-06 21:33:58 +00:00
|
|
|
if missingSet.Contains(o.Oid) && link == nil {
|
2015-11-26 12:44:56 +00:00
|
|
|
errbuf.WriteString(fmt.Sprintf("Missing upload link for %s\n", o.Oid))
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if errbuf.Len() > 0 {
|
|
|
|
return errors.New(errbuf.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-07 03:13:31 +00:00
|
|
|
func uploadEdgeCases(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
|
2015-11-26 12:44:56 +00:00
|
|
|
errorCases := make([]TestObject, 0, 5)
|
|
|
|
errorCodeMap := make(map[string]int, 5)
|
|
|
|
errorReasonMap := make(map[string]string, 5)
|
|
|
|
validCases := make([]TestObject, 0, 1)
|
|
|
|
validReasonMap := make(map[string]string, 5)
|
|
|
|
|
|
|
|
// Invalid SHAs - code 422
|
|
|
|
// Too short
|
|
|
|
sha := "a345cde"
|
|
|
|
errorCases = append(errorCases, TestObject{Oid: sha, Size: 99})
|
|
|
|
errorCodeMap[sha] = 422
|
|
|
|
errorReasonMap[sha] = "SHA is too short"
|
|
|
|
// Too long
|
|
|
|
sha = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
|
|
|
errorCases = append(errorCases, TestObject{Oid: sha, Size: 99})
|
|
|
|
errorCodeMap[sha] = 422
|
|
|
|
errorReasonMap[sha] = "SHA is too long"
|
|
|
|
// Invalid characters -----!---------------------------------!
|
|
|
|
sha = "bf3e3e2af9366a3b704ax0c31de5afa64193ebabffde2091936ad2G7510bc03a"
|
|
|
|
errorCases = append(errorCases, TestObject{Oid: sha, Size: 99})
|
|
|
|
errorCodeMap[sha] = 422
|
|
|
|
errorReasonMap[sha] = "SHA contains invalid characters"
|
|
|
|
|
|
|
|
// Invalid size - code 422
|
|
|
|
sha = "e3bf3e2af9366a3b704af0c31de5afa64193ebabffde2091936ad237510bc03a"
|
|
|
|
errorCases = append(errorCases, TestObject{Oid: sha, Size: -1})
|
|
|
|
errorCodeMap[sha] = 422
|
|
|
|
errorReasonMap[sha] = "Negative size"
|
|
|
|
sha = "d2983e2af9366a3b704af0c31de5afa64193ebabffde2091936ad237510bc03a"
|
|
|
|
errorCases = append(errorCases, TestObject{Oid: sha, Size: -125})
|
|
|
|
errorCodeMap[sha] = 422
|
|
|
|
errorReasonMap[sha] = "Negative size"
|
|
|
|
|
|
|
|
// Zero size - should be allowed
|
|
|
|
sha = "159f6ac723b9023b704af0c31de5afa64193ebabffde2091936ad237510bc03a"
|
|
|
|
validCases = append(validCases, TestObject{Oid: sha, Size: 0})
|
|
|
|
validReasonMap[sha] = "Zero size should be allowed"
|
|
|
|
|
|
|
|
calloids := interleaveTestData(errorCases, validCases)
|
2017-01-07 03:13:31 +00:00
|
|
|
retobjs, err := callBatchApi(manifest, tq.Upload, calloids)
|
2015-11-26 12:44:56 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
count := len(errorCases) + len(validCases)
|
|
|
|
if len(retobjs) != count {
|
|
|
|
return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", count, len(retobjs))
|
|
|
|
}
|
|
|
|
|
|
|
|
var errbuf bytes.Buffer
|
|
|
|
for _, o := range retobjs {
|
2017-03-06 21:33:58 +00:00
|
|
|
link, _ := o.Rel("upload")
|
2015-11-26 12:44:56 +00:00
|
|
|
if code, iserror := errorCodeMap[o.Oid]; iserror {
|
|
|
|
reason, _ := errorReasonMap[o.Oid]
|
2017-03-06 21:33:58 +00:00
|
|
|
if link != nil {
|
2017-12-15 02:07:06 +00:00
|
|
|
errbuf.WriteString(fmt.Sprintf("Upload link should not exist for %s, was %+v, reason %s\n", o.Oid, link, reason))
|
2015-11-26 12:44:56 +00:00
|
|
|
}
|
|
|
|
if o.Error == nil {
|
|
|
|
errbuf.WriteString(fmt.Sprintf("Upload should include an error for invalid object %s, reason %s", o.Oid, reason))
|
|
|
|
} else if o.Error.Code != code {
|
|
|
|
errbuf.WriteString(fmt.Sprintf("Upload error code for missing object %s should be %d, got %d, reason %s\n", o.Oid, code, o.Error.Code, reason))
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if reason, reasonok := validReasonMap[o.Oid]; reasonok {
|
2017-03-06 21:33:58 +00:00
|
|
|
if link == nil {
|
2015-11-26 12:44:56 +00:00
|
|
|
errbuf.WriteString(fmt.Sprintf("Missing upload link for %s, should be present because %s\n", o.Oid, reason))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if errbuf.Len() > 0 {
|
|
|
|
return errors.New(errbuf.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
addTest("Test upload: all missing", uploadAllMissing)
|
|
|
|
addTest("Test upload: all present", uploadAllExists)
|
|
|
|
addTest("Test upload: mixed", uploadMixed)
|
|
|
|
addTest("Test upload: edge cases", uploadEdgeCases)
|
|
|
|
}
|