github.com/git-lfs/git-lfs@v2.5.2+incompatible/t/git-lfs-test-server-api/testupload.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/git-lfs/git-lfs/tools"
     9  	"github.com/git-lfs/git-lfs/tq"
    10  )
    11  
    12  // "upload" - all missing
    13  func uploadAllMissing(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
    14  	retobjs, err := callBatchApi(manifest, tq.Upload, oidsMissing)
    15  
    16  	if err != nil {
    17  		return err
    18  	}
    19  
    20  	if len(retobjs) != len(oidsMissing) {
    21  		return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", len(oidsMissing), len(retobjs))
    22  	}
    23  
    24  	var errbuf bytes.Buffer
    25  	for _, o := range retobjs {
    26  		rel, _ := o.Rel("upload")
    27  		if rel == nil {
    28  			errbuf.WriteString(fmt.Sprintf("Missing upload link for %s\n", o.Oid))
    29  		}
    30  		// verify link is optional so don't check
    31  	}
    32  
    33  	if errbuf.Len() > 0 {
    34  		return errors.New(errbuf.String())
    35  	}
    36  
    37  	return nil
    38  }
    39  
    40  // "upload" - all present
    41  func uploadAllExists(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
    42  	retobjs, err := callBatchApi(manifest, tq.Upload, oidsExist)
    43  
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	if len(retobjs) != len(oidsExist) {
    49  		return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", len(oidsExist), len(retobjs))
    50  	}
    51  
    52  	var errbuf bytes.Buffer
    53  	for _, o := range retobjs {
    54  		link, _ := o.Rel("upload")
    55  		if link == nil {
    56  			errbuf.WriteString(fmt.Sprintf("Upload link should not exist for %s, was %+v\n", o.Oid, link))
    57  		}
    58  	}
    59  
    60  	if errbuf.Len() > 0 {
    61  		return errors.New(errbuf.String())
    62  	}
    63  
    64  	return nil
    65  }
    66  
    67  // "upload" - mix of missing & present
    68  func uploadMixed(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
    69  	existSet := tools.NewStringSetWithCapacity(len(oidsExist))
    70  	for _, o := range oidsExist {
    71  		existSet.Add(o.Oid)
    72  	}
    73  	missingSet := tools.NewStringSetWithCapacity(len(oidsMissing))
    74  	for _, o := range oidsMissing {
    75  		missingSet.Add(o.Oid)
    76  	}
    77  
    78  	calloids := interleaveTestData(oidsExist, oidsMissing)
    79  	retobjs, err := callBatchApi(manifest, tq.Upload, calloids)
    80  
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	count := len(oidsExist) + len(oidsMissing)
    86  	if len(retobjs) != count {
    87  		return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", count, len(retobjs))
    88  	}
    89  
    90  	var errbuf bytes.Buffer
    91  	for _, o := range retobjs {
    92  		link, _ := o.Rel("upload")
    93  		if existSet.Contains(o.Oid) {
    94  			if link != nil {
    95  				errbuf.WriteString(fmt.Sprintf("Upload link should not exist for %s, was %+v\n", o.Oid, link))
    96  			}
    97  		}
    98  		if missingSet.Contains(o.Oid) && link == nil {
    99  			errbuf.WriteString(fmt.Sprintf("Missing upload link for %s\n", o.Oid))
   100  		}
   101  
   102  	}
   103  
   104  	if errbuf.Len() > 0 {
   105  		return errors.New(errbuf.String())
   106  	}
   107  
   108  	return nil
   109  
   110  }
   111  
   112  func uploadEdgeCases(manifest *tq.Manifest, oidsExist, oidsMissing []TestObject) error {
   113  	errorCases := make([]TestObject, 0, 5)
   114  	errorCodeMap := make(map[string]int, 5)
   115  	errorReasonMap := make(map[string]string, 5)
   116  	validCases := make([]TestObject, 0, 1)
   117  	validReasonMap := make(map[string]string, 5)
   118  
   119  	// Invalid SHAs - code 422
   120  	// Too short
   121  	sha := "a345cde"
   122  	errorCases = append(errorCases, TestObject{Oid: sha, Size: 99})
   123  	errorCodeMap[sha] = 422
   124  	errorReasonMap[sha] = "SHA is too short"
   125  	// Too long
   126  	sha = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
   127  	errorCases = append(errorCases, TestObject{Oid: sha, Size: 99})
   128  	errorCodeMap[sha] = 422
   129  	errorReasonMap[sha] = "SHA is too long"
   130  	// Invalid characters -----!---------------------------------!
   131  	sha = "bf3e3e2af9366a3b704ax0c31de5afa64193ebabffde2091936ad2G7510bc03a"
   132  	errorCases = append(errorCases, TestObject{Oid: sha, Size: 99})
   133  	errorCodeMap[sha] = 422
   134  	errorReasonMap[sha] = "SHA contains invalid characters"
   135  
   136  	// Invalid size - code 422
   137  	sha = "e3bf3e2af9366a3b704af0c31de5afa64193ebabffde2091936ad237510bc03a"
   138  	errorCases = append(errorCases, TestObject{Oid: sha, Size: -1})
   139  	errorCodeMap[sha] = 422
   140  	errorReasonMap[sha] = "Negative size"
   141  	sha = "d2983e2af9366a3b704af0c31de5afa64193ebabffde2091936ad237510bc03a"
   142  	errorCases = append(errorCases, TestObject{Oid: sha, Size: -125})
   143  	errorCodeMap[sha] = 422
   144  	errorReasonMap[sha] = "Negative size"
   145  
   146  	// Zero size - should be allowed
   147  	sha = "159f6ac723b9023b704af0c31de5afa64193ebabffde2091936ad237510bc03a"
   148  	validCases = append(validCases, TestObject{Oid: sha, Size: 0})
   149  	validReasonMap[sha] = "Zero size should be allowed"
   150  
   151  	calloids := interleaveTestData(errorCases, validCases)
   152  	retobjs, err := callBatchApi(manifest, tq.Upload, calloids)
   153  
   154  	if err != nil {
   155  		return err
   156  	}
   157  
   158  	count := len(errorCases) + len(validCases)
   159  	if len(retobjs) != count {
   160  		return fmt.Errorf("Incorrect number of returned objects, expected %d, got %d", count, len(retobjs))
   161  	}
   162  
   163  	var errbuf bytes.Buffer
   164  	for _, o := range retobjs {
   165  		link, _ := o.Rel("upload")
   166  		if code, iserror := errorCodeMap[o.Oid]; iserror {
   167  			reason, _ := errorReasonMap[o.Oid]
   168  			if link != nil {
   169  				errbuf.WriteString(fmt.Sprintf("Upload link should not exist for %s, was %+v, reason %s\n", o.Oid, link, reason))
   170  			}
   171  			if o.Error == nil {
   172  				errbuf.WriteString(fmt.Sprintf("Upload should include an error for invalid object %s, reason %s", o.Oid, reason))
   173  			} else if o.Error.Code != code {
   174  				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))
   175  			}
   176  
   177  		}
   178  		if reason, reasonok := validReasonMap[o.Oid]; reasonok {
   179  			if link == nil {
   180  				errbuf.WriteString(fmt.Sprintf("Missing upload link for %s, should be present because %s\n", o.Oid, reason))
   181  			}
   182  		}
   183  
   184  	}
   185  
   186  	if errbuf.Len() > 0 {
   187  		return errors.New(errbuf.String())
   188  	}
   189  
   190  	return nil
   191  
   192  }
   193  
   194  func init() {
   195  	addTest("Test upload: all missing", uploadAllMissing)
   196  	addTest("Test upload: all present", uploadAllExists)
   197  	addTest("Test upload: mixed", uploadMixed)
   198  	addTest("Test upload: edge cases", uploadEdgeCases)
   199  }