2016-12-05 18:16:30 +00:00
|
|
|
package locking
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2016-12-22 23:59:54 +00:00
|
|
|
"net/http/httptest"
|
2018-10-07 10:36:15 +00:00
|
|
|
"os"
|
2016-12-12 15:15:20 +00:00
|
|
|
"sort"
|
2016-12-05 18:16:30 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2018-12-05 16:15:52 +00:00
|
|
|
"github.com/git-lfs/git-lfs/config"
|
2018-10-07 10:36:15 +00:00
|
|
|
"github.com/git-lfs/git-lfs/git"
|
2016-12-22 23:59:54 +00:00
|
|
|
"github.com/git-lfs/git-lfs/lfsapi"
|
2018-09-06 21:42:41 +00:00
|
|
|
"github.com/git-lfs/git-lfs/lfshttp"
|
2016-12-05 18:16:30 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2016-12-22 23:59:54 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2016-12-05 18:16:30 +00:00
|
|
|
)
|
|
|
|
|
2016-12-12 15:15:20 +00:00
|
|
|
type LocksById []Lock
|
|
|
|
|
|
|
|
func (a LocksById) Len() int { return len(a) }
|
|
|
|
func (a LocksById) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
func (a LocksById) Less(i, j int) bool { return a[i].Id < a[j].Id }
|
|
|
|
|
2018-10-07 10:36:15 +00:00
|
|
|
func TestRemoteLocksWithCache(t *testing.T) {
|
|
|
|
var err error
|
|
|
|
tempDir, err := ioutil.TempDir("", "testCacheLock")
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
2018-10-08 07:32:43 +00:00
|
|
|
remoteQueries := 0
|
2018-10-07 10:36:15 +00:00
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2018-10-08 07:32:43 +00:00
|
|
|
remoteQueries++
|
|
|
|
|
2018-10-07 10:36:15 +00:00
|
|
|
assert.Equal(t, "GET", r.Method)
|
|
|
|
assert.Equal(t, "/api/locks", r.URL.Path)
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
err = json.NewEncoder(w).Encode(&lockList{
|
|
|
|
Locks: []Lock{
|
|
|
|
Lock{Id: "100", Path: "folder/test1.dat", Owner: &User{Name: "Alice"}},
|
|
|
|
Lock{Id: "101", Path: "folder/test2.dat", Owner: &User{Name: "Charles"}},
|
|
|
|
Lock{Id: "102", Path: "folder/test3.dat", Owner: &User{Name: "Fred"}},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
assert.Nil(t, err)
|
|
|
|
}))
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
srv.Close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
lfsclient, err := lfsapi.NewClient(lfshttp.NewContext(nil, nil, map[string]string{
|
|
|
|
"lfs.url": srv.URL + "/api",
|
|
|
|
"user.name": "Fred",
|
|
|
|
"user.email": "fred@bloggs.com",
|
|
|
|
}))
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
2018-12-05 16:15:52 +00:00
|
|
|
client, err := NewClient("", lfsclient, config.New())
|
2018-10-07 10:36:15 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.Nil(t, client.SetupFileCache(tempDir))
|
|
|
|
|
|
|
|
client.RemoteRef = &git.Ref{Name: "refs/heads/master"}
|
|
|
|
cacheFile, err := client.prepareCacheDirectory()
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
// Cache file should not exist
|
|
|
|
fi, err := os.Stat(cacheFile)
|
|
|
|
assert.True(t, os.IsNotExist(err))
|
|
|
|
|
2018-10-08 07:32:43 +00:00
|
|
|
// Querying non-existing cache file will report nothing
|
|
|
|
locks, err := client.SearchLocks(nil, 0, false, true)
|
|
|
|
assert.NotNil(t, err)
|
|
|
|
assert.Empty(t, locks)
|
|
|
|
assert.Equal(t, 0, remoteQueries)
|
|
|
|
|
2018-10-07 10:36:15 +00:00
|
|
|
// Need to include zero time in structure for equal to work
|
|
|
|
zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
|
|
|
|
// REMOTE QUERY: No cache file will be created when querying with a filter
|
2018-10-08 07:32:43 +00:00
|
|
|
locks, err = client.SearchLocks(map[string]string{
|
2018-10-07 10:36:15 +00:00
|
|
|
"key": "value",
|
2018-10-08 07:32:43 +00:00
|
|
|
}, 0, false, false)
|
2018-10-07 10:36:15 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
// Just make sure we have have received anything, content doesn't matter
|
|
|
|
assert.Equal(t, 3, len(locks))
|
2018-10-08 07:32:43 +00:00
|
|
|
assert.Equal(t, 1, remoteQueries)
|
2018-10-07 10:36:15 +00:00
|
|
|
|
|
|
|
fi, err = os.Stat(cacheFile)
|
|
|
|
assert.True(t, os.IsNotExist(err))
|
|
|
|
|
|
|
|
// REMOTE QUERY: No cache file will be created when querying with a limit
|
2018-10-08 07:32:43 +00:00
|
|
|
locks, err = client.SearchLocks(nil, 1, false, false)
|
2018-10-07 10:36:15 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
// Just make sure we have have received anything, content doesn't matter
|
|
|
|
assert.Equal(t, 1, len(locks))
|
2018-10-08 07:32:43 +00:00
|
|
|
assert.Equal(t, 2, remoteQueries)
|
2018-10-07 10:36:15 +00:00
|
|
|
|
|
|
|
fi, err = os.Stat(cacheFile)
|
|
|
|
assert.True(t, os.IsNotExist(err))
|
|
|
|
|
|
|
|
// REMOTE QUERY: locks will be reported and cache file should be created
|
2018-10-08 07:32:43 +00:00
|
|
|
locks, err = client.SearchLocks(nil, 0, false, false)
|
2018-10-07 10:36:15 +00:00
|
|
|
assert.Nil(t, err)
|
2018-10-08 07:32:43 +00:00
|
|
|
assert.Equal(t, 3, remoteQueries)
|
2018-10-07 10:36:15 +00:00
|
|
|
|
|
|
|
fi, err = os.Stat(cacheFile)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
const size int64 = 300
|
|
|
|
assert.Equal(t, size, fi.Size())
|
|
|
|
|
2018-10-08 07:32:43 +00:00
|
|
|
expectedLocks := []Lock{
|
2018-10-07 10:36:15 +00:00
|
|
|
Lock{Path: "folder/test1.dat", Id: "100", Owner: &User{Name: "Alice"}, LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/test2.dat", Id: "101", Owner: &User{Name: "Charles"}, LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/test3.dat", Id: "102", Owner: &User{Name: "Fred"}, LockedAt: zeroTime},
|
2018-10-08 07:32:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sort.Sort(LocksById(locks))
|
|
|
|
assert.Equal(t, expectedLocks, locks)
|
|
|
|
|
|
|
|
// Querying cache file should report same locks
|
|
|
|
locks, err = client.SearchLocks(nil, 0, false, true)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.Equal(t, 3, remoteQueries)
|
|
|
|
|
|
|
|
sort.Sort(LocksById(locks))
|
|
|
|
assert.Equal(t, expectedLocks, locks)
|
2018-10-07 10:36:15 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 18:16:30 +00:00
|
|
|
func TestRefreshCache(t *testing.T) {
|
|
|
|
var err error
|
2017-01-03 21:13:59 +00:00
|
|
|
tempDir, err := ioutil.TempDir("", "testCacheLock")
|
2016-12-05 18:16:30 +00:00
|
|
|
assert.Nil(t, err)
|
2016-12-22 23:59:54 +00:00
|
|
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2017-02-03 17:48:31 +00:00
|
|
|
assert.Equal(t, "POST", r.Method)
|
|
|
|
assert.Equal(t, "/api/locks/verify", r.URL.Path)
|
2016-12-22 23:59:54 +00:00
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
2017-02-03 17:48:31 +00:00
|
|
|
err = json.NewEncoder(w).Encode(lockVerifiableList{
|
|
|
|
Theirs: []Lock{
|
|
|
|
Lock{Id: "99", Path: "folder/test3.dat", Owner: &User{Name: "Alice"}},
|
|
|
|
Lock{Id: "199", Path: "other/test1.dat", Owner: &User{Name: "Charles"}},
|
|
|
|
},
|
|
|
|
Ours: []Lock{
|
|
|
|
Lock{Id: "101", Path: "folder/test1.dat", Owner: &User{Name: "Fred"}},
|
|
|
|
Lock{Id: "102", Path: "folder/test2.dat", Owner: &User{Name: "Fred"}},
|
|
|
|
Lock{Id: "103", Path: "root.dat", Owner: &User{Name: "Fred"}},
|
2016-12-22 23:59:54 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
assert.Nil(t, err)
|
|
|
|
}))
|
|
|
|
|
2016-12-05 18:16:30 +00:00
|
|
|
defer func() {
|
2016-12-22 23:59:54 +00:00
|
|
|
srv.Close()
|
2016-12-05 18:16:30 +00:00
|
|
|
}()
|
|
|
|
|
2018-09-06 21:42:41 +00:00
|
|
|
lfsclient, err := lfsapi.NewClient(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-22 23:59:54 +00:00
|
|
|
"lfs.url": srv.URL + "/api",
|
|
|
|
"user.name": "Fred",
|
|
|
|
"user.email": "fred@bloggs.com",
|
|
|
|
}))
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
2018-12-05 16:15:52 +00:00
|
|
|
client, err := NewClient("", lfsclient, config.New())
|
2016-12-05 18:16:30 +00:00
|
|
|
assert.Nil(t, err)
|
2017-01-03 21:42:48 +00:00
|
|
|
assert.Nil(t, client.SetupFileCache(tempDir))
|
2016-12-05 18:16:30 +00:00
|
|
|
|
|
|
|
// Should start with no cached items
|
2018-10-08 07:32:43 +00:00
|
|
|
locks, err := client.SearchLocks(nil, 0, true, false)
|
2016-12-13 14:48:17 +00:00
|
|
|
assert.Nil(t, err)
|
2016-12-05 18:16:30 +00:00
|
|
|
assert.Empty(t, locks)
|
|
|
|
|
2019-01-02 11:08:15 +00:00
|
|
|
_, _, err = client.SearchLocksVerifiable(&git.Ref{Name: "refs/heads/master"}, 100)
|
2016-12-05 18:16:30 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
2018-10-08 07:32:43 +00:00
|
|
|
locks, err = client.SearchLocks(nil, 0, true, false)
|
2016-12-13 14:48:17 +00:00
|
|
|
assert.Nil(t, err)
|
2016-12-05 18:16:30 +00:00
|
|
|
// Need to include zero time in structure for equal to work
|
|
|
|
zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
|
2016-12-12 15:15:20 +00:00
|
|
|
|
|
|
|
// Sort locks for stable comparison
|
|
|
|
sort.Sort(LocksById(locks))
|
2016-12-05 18:16:30 +00:00
|
|
|
assert.Equal(t, []Lock{
|
2017-02-03 17:48:31 +00:00
|
|
|
Lock{Path: "folder/test1.dat", Id: "101", Owner: &User{Name: "Fred"}, LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/test2.dat", Id: "102", Owner: &User{Name: "Fred"}, LockedAt: zeroTime},
|
|
|
|
Lock{Path: "root.dat", Id: "103", Owner: &User{Name: "Fred"}, LockedAt: zeroTime},
|
2017-10-31 17:23:37 +00:00
|
|
|
Lock{Path: "other/test1.dat", Id: "199", Owner: &User{Name: "Charles"}, LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/test3.dat", Id: "99", Owner: &User{Name: "Alice"}, LockedAt: zeroTime},
|
2016-12-05 18:16:30 +00:00
|
|
|
}, locks)
|
2017-01-31 00:49:42 +00:00
|
|
|
}
|
|
|
|
|
2019-01-02 10:10:04 +00:00
|
|
|
func TestSearchLocksVerifiable(t *testing.T) {
|
2017-01-31 00:49:42 +00:00
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
assert.Equal(t, "POST", r.Method)
|
|
|
|
assert.Equal(t, "/api/locks/verify", r.URL.Path)
|
|
|
|
|
|
|
|
body := lockVerifiableRequest{}
|
|
|
|
if assert.Nil(t, json.NewDecoder(r.Body).Decode(&body)) {
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
list := lockVerifiableList{}
|
|
|
|
if body.Cursor == "1" {
|
|
|
|
list.Ours = []Lock{
|
|
|
|
Lock{Path: "folder/1/test1.dat", Id: "111"},
|
|
|
|
}
|
|
|
|
list.Theirs = []Lock{
|
|
|
|
Lock{Path: "folder/1/test2.dat", Id: "112"},
|
|
|
|
Lock{Path: "folder/1/test3.dat", Id: "113"},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
list.Ours = []Lock{
|
|
|
|
Lock{Path: "folder/0/test1.dat", Id: "101"},
|
|
|
|
Lock{Path: "folder/0/test2.dat", Id: "102"},
|
|
|
|
}
|
|
|
|
list.Theirs = []Lock{
|
|
|
|
Lock{Path: "folder/0/test3.dat", Id: "103"},
|
|
|
|
}
|
|
|
|
list.NextCursor = "1"
|
|
|
|
}
|
|
|
|
|
|
|
|
err := json.NewEncoder(w).Encode(&list)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(500)
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
2018-09-06 21:42:41 +00:00
|
|
|
lfsclient, err := lfsapi.NewClient(lfshttp.NewContext(nil, nil, map[string]string{
|
2017-01-31 00:49:42 +00:00
|
|
|
"lfs.url": srv.URL + "/api",
|
|
|
|
"user.name": "Fred",
|
|
|
|
"user.email": "fred@bloggs.com",
|
|
|
|
}))
|
|
|
|
require.Nil(t, err)
|
|
|
|
|
2018-12-05 16:15:52 +00:00
|
|
|
client, err := NewClient("", lfsclient, config.New())
|
2017-01-31 00:49:42 +00:00
|
|
|
assert.Nil(t, err)
|
2016-12-05 18:16:30 +00:00
|
|
|
|
2019-01-02 11:08:15 +00:00
|
|
|
ourLocks, theirLocks, err := client.SearchLocksVerifiable(&git.Ref{Name: "refs/heads/master"}, 0)
|
2017-01-31 00:49:42 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
// Need to include zero time in structure for equal to work
|
|
|
|
zeroTime := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
|
|
|
|
// Sort locks for stable comparison
|
|
|
|
sort.Sort(LocksById(ourLocks))
|
|
|
|
assert.Equal(t, []Lock{
|
|
|
|
Lock{Path: "folder/0/test1.dat", Id: "101", LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/0/test2.dat", Id: "102", LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/1/test1.dat", Id: "111", LockedAt: zeroTime},
|
|
|
|
}, ourLocks)
|
|
|
|
|
|
|
|
sort.Sort(LocksById(theirLocks))
|
|
|
|
assert.Equal(t, []Lock{
|
|
|
|
Lock{Path: "folder/0/test3.dat", Id: "103", LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/1/test2.dat", Id: "112", LockedAt: zeroTime},
|
|
|
|
Lock{Path: "folder/1/test3.dat", Id: "113", LockedAt: zeroTime},
|
|
|
|
}, theirLocks)
|
2016-12-05 18:16:30 +00:00
|
|
|
}
|