github.com/git-lfs/git-lfs@v2.5.2+incompatible/tq/api_test.go (about)

     1  package tq
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/git-lfs/git-lfs/lfsapi"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  	"github.com/xeipuuv/gojsonschema"
    17  )
    18  
    19  func TestAPIBatch(t *testing.T) {
    20  	require.NotNil(t, batchReqSchema, batchReqSchema.Source)
    21  	require.NotNil(t, batchResSchema, batchResSchema.Source)
    22  
    23  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    24  		if r.URL.Path != "/api/objects/batch" {
    25  			w.WriteHeader(404)
    26  			return
    27  		}
    28  
    29  		assert.Equal(t, "POST", r.Method)
    30  		assert.Equal(t, "91", r.Header.Get("Content-Length"))
    31  
    32  		bodyLoader, body := gojsonschema.NewReaderLoader(r.Body)
    33  		bReq := &batchRequest{}
    34  		err := json.NewDecoder(body).Decode(bReq)
    35  		r.Body.Close()
    36  		assert.Nil(t, err)
    37  		assertSchema(t, batchReqSchema, bodyLoader)
    38  
    39  		assert.EqualValues(t, []string{"basic", "whatev"}, bReq.TransferAdapterNames)
    40  		if assert.Equal(t, 1, len(bReq.Objects)) {
    41  			assert.Equal(t, "a", bReq.Objects[0].Oid)
    42  		}
    43  
    44  		w.Header().Set("Content-Type", "application/json")
    45  
    46  		writeLoader, resWriter := gojsonschema.NewWriterLoader(w)
    47  		err = json.NewEncoder(resWriter).Encode(&BatchResponse{
    48  			TransferAdapterName: "basic",
    49  			Objects:             bReq.Objects,
    50  		})
    51  
    52  		assert.Nil(t, err)
    53  		assertSchema(t, batchResSchema, writeLoader)
    54  	}))
    55  	defer srv.Close()
    56  
    57  	c, err := lfsapi.NewClient(lfsapi.NewContext(nil, nil, map[string]string{
    58  		"lfs.url": srv.URL + "/api",
    59  	}))
    60  	require.Nil(t, err)
    61  
    62  	tqc := &tqClient{Client: c}
    63  	bReq := &batchRequest{
    64  		TransferAdapterNames: []string{"basic", "whatev"},
    65  		Objects: []*Transfer{
    66  			&Transfer{Oid: "a", Size: 1},
    67  		},
    68  	}
    69  	bRes, err := tqc.Batch("remote", bReq)
    70  	require.Nil(t, err)
    71  	assert.Equal(t, "basic", bRes.TransferAdapterName)
    72  	if assert.Equal(t, 1, len(bRes.Objects)) {
    73  		assert.Equal(t, "a", bRes.Objects[0].Oid)
    74  	}
    75  }
    76  
    77  func TestAPIBatchOnlyBasic(t *testing.T) {
    78  	require.NotNil(t, batchReqSchema, batchReqSchema.Source)
    79  	require.NotNil(t, batchResSchema, batchResSchema.Source)
    80  
    81  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    82  		if r.URL.Path != "/api/objects/batch" {
    83  			w.WriteHeader(404)
    84  			return
    85  		}
    86  
    87  		assert.Equal(t, "POST", r.Method)
    88  
    89  		bodyLoader, body := gojsonschema.NewReaderLoader(r.Body)
    90  		bReq := &batchRequest{}
    91  		err := json.NewDecoder(body).Decode(bReq)
    92  		r.Body.Close()
    93  		assert.Nil(t, err)
    94  		assertSchema(t, batchReqSchema, bodyLoader)
    95  
    96  		assert.Equal(t, 0, len(bReq.TransferAdapterNames))
    97  		if assert.Equal(t, 1, len(bReq.Objects)) {
    98  			assert.Equal(t, "a", bReq.Objects[0].Oid)
    99  		}
   100  
   101  		w.Header().Set("Content-Type", "application/json")
   102  		writeLoader, resWriter := gojsonschema.NewWriterLoader(w)
   103  		err = json.NewEncoder(resWriter).Encode(&BatchResponse{
   104  			TransferAdapterName: "basic",
   105  			Objects:             make([]*Transfer, 0),
   106  		})
   107  
   108  		assert.Nil(t, err)
   109  		assertSchema(t, batchResSchema, writeLoader)
   110  	}))
   111  	defer srv.Close()
   112  
   113  	c, err := lfsapi.NewClient(lfsapi.NewContext(nil, nil, map[string]string{
   114  		"lfs.url": srv.URL + "/api",
   115  	}))
   116  	require.Nil(t, err)
   117  
   118  	tqc := &tqClient{Client: c}
   119  	bReq := &batchRequest{
   120  		TransferAdapterNames: []string{"basic"},
   121  		Objects: []*Transfer{
   122  			&Transfer{Oid: "a", Size: 1},
   123  		},
   124  	}
   125  	bRes, err := tqc.Batch("remote", bReq)
   126  	require.Nil(t, err)
   127  	assert.Equal(t, "basic", bRes.TransferAdapterName)
   128  }
   129  
   130  func TestAPIBatchEmptyObjects(t *testing.T) {
   131  	c, err := lfsapi.NewClient(nil)
   132  	require.Nil(t, err)
   133  
   134  	tqc := &tqClient{Client: c}
   135  	bReq := &batchRequest{
   136  		TransferAdapterNames: []string{"basic", "whatev"},
   137  	}
   138  	bRes, err := tqc.Batch("remote", bReq)
   139  	require.Nil(t, err)
   140  	assert.Equal(t, "", bRes.TransferAdapterName)
   141  	assert.Equal(t, 0, len(bRes.Objects))
   142  }
   143  
   144  var (
   145  	batchReqSchema *sourcedSchema
   146  	batchResSchema *sourcedSchema
   147  )
   148  
   149  func init() {
   150  	wd, err := os.Getwd()
   151  	if err != nil {
   152  		fmt.Println("getwd error:", err)
   153  		return
   154  	}
   155  
   156  	batchReqSchema = getSchema(wd, "schemas/http-batch-request-schema.json")
   157  	batchResSchema = getSchema(wd, "schemas/http-batch-response-schema.json")
   158  }
   159  
   160  type sourcedSchema struct {
   161  	Source string
   162  	*gojsonschema.Schema
   163  }
   164  
   165  func getSchema(wd, relpath string) *sourcedSchema {
   166  	abspath := filepath.ToSlash(filepath.Join(wd, relpath))
   167  	s, err := gojsonschema.NewSchema(gojsonschema.NewReferenceLoader(fmt.Sprintf("file:///%s", abspath)))
   168  	if err != nil {
   169  		fmt.Printf("schema load error for %q: %+v\n", relpath, err)
   170  	}
   171  	return &sourcedSchema{Source: relpath, Schema: s}
   172  }
   173  
   174  func assertSchema(t *testing.T, schema *sourcedSchema, dataLoader gojsonschema.JSONLoader) {
   175  	res, err := schema.Validate(dataLoader)
   176  	if assert.Nil(t, err) {
   177  		if res.Valid() {
   178  			return
   179  		}
   180  
   181  		resErrors := res.Errors()
   182  		valErrors := make([]string, 0, len(resErrors))
   183  		for _, resErr := range resErrors {
   184  			valErrors = append(valErrors, resErr.String())
   185  		}
   186  		t.Errorf("Schema: %s\n%s", schema.Source, strings.Join(valErrors, "\n"))
   187  	}
   188  }