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