github.com/stffabi/git-lfs@v2.3.5-0.20180214015214-8eeaa8d88902+incompatible/locking/api_test.go (about)

     1  package locking
     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/git"
    14  	"github.com/git-lfs/git-lfs/lfsapi"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  	"github.com/xeipuuv/gojsonschema"
    18  )
    19  
    20  func TestAPILock(t *testing.T) {
    21  	require.NotNil(t, createReqSchema)
    22  	require.NotNil(t, createResSchema)
    23  
    24  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    25  		if r.URL.Path != "/api/locks" {
    26  			w.WriteHeader(404)
    27  			return
    28  		}
    29  
    30  		assert.Equal(t, "POST", r.Method)
    31  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Accept"))
    32  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Content-Type"))
    33  		assert.Equal(t, "53", r.Header.Get("Content-Length"))
    34  
    35  		reqLoader, body := gojsonschema.NewReaderLoader(r.Body)
    36  		lockReq := &lockRequest{}
    37  		err := json.NewDecoder(body).Decode(lockReq)
    38  		r.Body.Close()
    39  		assert.Nil(t, err)
    40  		assert.Equal(t, "refs/heads/master", lockReq.Ref.Name)
    41  		assert.Equal(t, "request", lockReq.Path)
    42  		assertSchema(t, createReqSchema, reqLoader)
    43  
    44  		w.Header().Set("Content-Type", "application/json")
    45  		resLoader, resWriter := gojsonschema.NewWriterLoader(w)
    46  		err = json.NewEncoder(resWriter).Encode(&lockResponse{
    47  			Lock: &Lock{
    48  				Id:   "1",
    49  				Path: "response",
    50  			},
    51  		})
    52  		assert.Nil(t, err)
    53  		assertSchema(t, createResSchema, resLoader)
    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  	lc := &lockClient{Client: c}
    63  	lockRes, res, err := lc.Lock("", &lockRequest{Path: "request", Ref: &lockRef{Name: "refs/heads/master"}})
    64  	require.Nil(t, err)
    65  	assert.Equal(t, 200, res.StatusCode)
    66  	assert.Equal(t, "1", lockRes.Lock.Id)
    67  	assert.Equal(t, "response", lockRes.Lock.Path)
    68  }
    69  
    70  func TestAPIUnlock(t *testing.T) {
    71  	require.NotNil(t, delReqSchema)
    72  	require.NotNil(t, createResSchema)
    73  
    74  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    75  		if r.URL.Path != "/api/locks/123/unlock" {
    76  			w.WriteHeader(404)
    77  			return
    78  		}
    79  
    80  		assert.Equal(t, "POST", r.Method)
    81  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Accept"))
    82  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Content-Type"))
    83  
    84  		reqLoader, body := gojsonschema.NewReaderLoader(r.Body)
    85  		unlockReq := &unlockRequest{}
    86  		err := json.NewDecoder(body).Decode(unlockReq)
    87  		r.Body.Close()
    88  		assert.Nil(t, err)
    89  		assert.True(t, unlockReq.Force)
    90  		assertSchema(t, delReqSchema, reqLoader)
    91  
    92  		w.Header().Set("Content-Type", "application/json")
    93  		resLoader, resWriter := gojsonschema.NewWriterLoader(w)
    94  		err = json.NewEncoder(resWriter).Encode(&unlockResponse{
    95  			Lock: &Lock{
    96  				Id:   "123",
    97  				Path: "response",
    98  			},
    99  		})
   100  		assert.Nil(t, err)
   101  		assertSchema(t, createResSchema, resLoader)
   102  	}))
   103  	defer srv.Close()
   104  
   105  	c, err := lfsapi.NewClient(lfsapi.NewContext(nil, nil, map[string]string{
   106  		"lfs.url": srv.URL + "/api",
   107  	}))
   108  	require.Nil(t, err)
   109  
   110  	lc := &lockClient{Client: c}
   111  	unlockRes, res, err := lc.Unlock(&git.Ref{
   112  		Name: "master",
   113  		Sha:  "6161616161616161616161616161616161616161",
   114  		Type: git.RefTypeLocalBranch,
   115  	}, "", "123", true)
   116  	require.Nil(t, err)
   117  	assert.Equal(t, 200, res.StatusCode)
   118  	assert.Equal(t, "123", unlockRes.Lock.Id)
   119  	assert.Equal(t, "response", unlockRes.Lock.Path)
   120  }
   121  
   122  func TestAPISearch(t *testing.T) {
   123  	require.NotNil(t, listResSchema)
   124  
   125  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   126  		if r.URL.Path != "/api/locks" {
   127  			w.WriteHeader(404)
   128  			return
   129  		}
   130  
   131  		assert.Equal(t, "GET", r.Method)
   132  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Accept"))
   133  		assert.Equal(t, "", r.Header.Get("Content-Type"))
   134  
   135  		q := r.URL.Query()
   136  		assert.Equal(t, "A", q.Get("a"))
   137  		assert.Equal(t, "cursor", q.Get("cursor"))
   138  		assert.Equal(t, "5", q.Get("limit"))
   139  
   140  		w.Header().Set("Content-Type", "application/json")
   141  		resLoader, resWriter := gojsonschema.NewWriterLoader(w)
   142  		err := json.NewEncoder(resWriter).Encode(&lockList{
   143  			Locks: []Lock{
   144  				{Id: "1"},
   145  				{Id: "2"},
   146  			},
   147  		})
   148  		assert.Nil(t, err)
   149  		assertSchema(t, listResSchema, resLoader)
   150  	}))
   151  	defer srv.Close()
   152  
   153  	c, err := lfsapi.NewClient(lfsapi.NewContext(nil, nil, map[string]string{
   154  		"lfs.url": srv.URL + "/api",
   155  	}))
   156  	require.Nil(t, err)
   157  
   158  	lc := &lockClient{Client: c}
   159  	locks, res, err := lc.Search("", &lockSearchRequest{
   160  		Filters: []lockFilter{
   161  			{Property: "a", Value: "A"},
   162  		},
   163  		Cursor: "cursor",
   164  		Limit:  5,
   165  	})
   166  	require.Nil(t, err)
   167  	assert.Equal(t, 200, res.StatusCode)
   168  	assert.Equal(t, 2, len(locks.Locks))
   169  	assert.Equal(t, "1", locks.Locks[0].Id)
   170  	assert.Equal(t, "2", locks.Locks[1].Id)
   171  }
   172  
   173  func TestAPIVerifiableLocks(t *testing.T) {
   174  	require.NotNil(t, verifyResSchema)
   175  
   176  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   177  		if r.URL.Path != "/api/locks/verify" {
   178  			w.WriteHeader(404)
   179  			return
   180  		}
   181  
   182  		assert.Equal(t, "POST", r.Method)
   183  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Accept"))
   184  		assert.Equal(t, lfsapi.MediaType, r.Header.Get("Content-Type"))
   185  
   186  		body := lockVerifiableRequest{}
   187  		if assert.Nil(t, json.NewDecoder(r.Body).Decode(&body)) {
   188  			assert.Equal(t, "cursor", body.Cursor)
   189  			assert.Equal(t, 5, body.Limit)
   190  		}
   191  
   192  		w.Header().Set("Content-Type", "application/json")
   193  		resLoader, resWriter := gojsonschema.NewWriterLoader(w)
   194  		err := json.NewEncoder(resWriter).Encode(&lockVerifiableList{
   195  			Ours: []Lock{
   196  				{Id: "1"},
   197  				{Id: "2"},
   198  			},
   199  			Theirs: []Lock{
   200  				{Id: "3"},
   201  			},
   202  		})
   203  		assert.Nil(t, err)
   204  		assertSchema(t, verifyResSchema, resLoader)
   205  	}))
   206  	defer srv.Close()
   207  
   208  	c, err := lfsapi.NewClient(lfsapi.NewContext(nil, nil, map[string]string{
   209  		"lfs.url": srv.URL + "/api",
   210  	}))
   211  	require.Nil(t, err)
   212  
   213  	lc := &lockClient{Client: c}
   214  	locks, res, err := lc.SearchVerifiable("", &lockVerifiableRequest{
   215  		Cursor: "cursor",
   216  		Limit:  5,
   217  	})
   218  	require.Nil(t, err)
   219  	assert.Equal(t, 200, res.StatusCode)
   220  	assert.Equal(t, 2, len(locks.Ours))
   221  	assert.Equal(t, "1", locks.Ours[0].Id)
   222  	assert.Equal(t, "2", locks.Ours[1].Id)
   223  	assert.Equal(t, 1, len(locks.Theirs))
   224  	assert.Equal(t, "3", locks.Theirs[0].Id)
   225  }
   226  
   227  var (
   228  	createReqSchema *sourcedSchema
   229  	createResSchema *sourcedSchema
   230  	delReqSchema    *sourcedSchema
   231  	listResSchema   *sourcedSchema
   232  	verifyResSchema *sourcedSchema
   233  )
   234  
   235  func init() {
   236  	wd, err := os.Getwd()
   237  	if err != nil {
   238  		fmt.Println("getwd error:", err)
   239  		return
   240  	}
   241  
   242  	createReqSchema = getSchema(wd, "schemas/http-lock-create-request-schema.json")
   243  	createResSchema = getSchema(wd, "schemas/http-lock-create-response-schema.json")
   244  	delReqSchema = getSchema(wd, "schemas/http-lock-delete-request-schema.json")
   245  	listResSchema = getSchema(wd, "schemas/http-lock-list-response-schema.json")
   246  	verifyResSchema = getSchema(wd, "schemas/http-lock-verify-response-schema.json")
   247  }
   248  
   249  type sourcedSchema struct {
   250  	Source string
   251  	*gojsonschema.Schema
   252  }
   253  
   254  func getSchema(wd, relpath string) *sourcedSchema {
   255  	abspath := filepath.ToSlash(filepath.Join(wd, relpath))
   256  	s, err := gojsonschema.NewSchema(gojsonschema.NewReferenceLoader(fmt.Sprintf("file:///%s", abspath)))
   257  	if err != nil {
   258  		fmt.Printf("schema load error for %q: %+v\n", relpath, err)
   259  	}
   260  	return &sourcedSchema{Source: relpath, Schema: s}
   261  }
   262  
   263  func assertSchema(t *testing.T, schema *sourcedSchema, dataLoader gojsonschema.JSONLoader) {
   264  	res, err := schema.Validate(dataLoader)
   265  	if assert.Nil(t, err) {
   266  		if res.Valid() {
   267  			return
   268  		}
   269  
   270  		resErrors := res.Errors()
   271  		valErrors := make([]string, 0, len(resErrors))
   272  		for _, resErr := range resErrors {
   273  			valErrors = append(valErrors, resErr.String())
   274  		}
   275  		t.Errorf("Schema: %s\n%s", schema.Source, strings.Join(valErrors, "\n"))
   276  	}
   277  }