1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/vcs-all-in-one-lfs-test-server

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
server_test.go 16 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Shuanglei Tao Отправлено 19.06.2017 11:03 f5f7f0f
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"testing"
)
func TestGetAuthed(t *testing.T) {
res, err := api("GET", "/user/repo/objects/"+contentOid, contentMediaType, testUser, testPass, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
by, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("expected response to contain content, got error: %s", err)
}
if string(by) != content {
t.Fatalf("expected content to be `content`, got: %s", string(by))
}
}
func TestGetAuthedWithRange(t *testing.T) {
req, err := http.NewRequest("GET", lfsServer.URL+"/user/repo/objects/"+contentOid, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
req.SetBasicAuth(testUser, testPass)
req.Header.Set("Accept", contentMediaType)
fromByte := 5
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", fromByte))
res, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("response error: %s", err)
}
if res.StatusCode != 206 {
t.Fatalf("expected status 206, got %d", res.StatusCode)
}
if cr := res.Header.Get("Content-Range"); len(cr) > 0 {
expected := fmt.Sprintf("bytes %d-%d/%d", fromByte, len(content)-1, len(content)-fromByte)
if cr != expected {
t.Fatalf("expected Content-Range header of %q, got %q", expected, cr)
}
} else {
t.Fatalf("missing Content-Range header in response")
}
by, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("expected response to contain content, got error: %s", err)
}
if string(by) != content[fromByte:] {
t.Fatalf("expected content to be `content`, got: %s", string(by))
}
}
func TestGetUnAuthed(t *testing.T) {
res, err := api("GET", "/user/repo/objects/"+contentOid, contentMediaType, "", "", nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestGetBadAuth(t *testing.T) {
res, err := api("GET", "/user/repo/objects/"+contentOid, contentMediaType, testUser, testPass+"123", nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestGetMetaAuthed(t *testing.T) {
res, err := api("GET", "/bilbo/repo/objects/"+contentOid, metaMediaType, testUser, testPass, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
var meta Representation
dec := json.NewDecoder(res.Body)
dec.Decode(&meta)
if meta.Oid != contentOid {
t.Fatalf("expected to see oid `%s` in meta, got: `%s`", contentOid, meta.Oid)
}
if meta.Size != contentSize {
t.Fatalf("expected to see a size of `%d`, got: `%d`", contentSize, meta.Size)
}
download := meta.Actions["download"]
if download.Href != "http://localhost:8080/bilbo/repo/objects/"+contentOid {
t.Fatalf("expected download link, got %s", download.Href)
}
}
func TestGetMetaUnAuthed(t *testing.T) {
res, err := api("GET", "/user/repo/objects/"+contentOid, metaMediaType, "", "", nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestPostAuthedNewObject(t *testing.T) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"oid":"%s", "size":1234}`, nonExistingOid))
res, err := api("POST", "/bilbo/repo/objects", metaMediaType, testUser, testPass, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 202 {
t.Fatalf("expected status 202, got %d", res.StatusCode)
}
var meta Representation
dec := json.NewDecoder(res.Body)
dec.Decode(&meta)
if meta.Oid != nonExistingOid {
t.Fatalf("expected to see oid `%s` in meta, got: `%s`", nonExistingOid, meta.Oid)
}
if meta.Size != 1234 {
t.Fatalf("expected to see a size of `1234`, got: `%d`", meta.Size)
}
if download, ok := meta.Actions["download"]; ok {
t.Fatalf("expected POST to not contain a download link, got %s", download.Href)
}
upload, ok := meta.Actions["upload"]
if !ok {
t.Fatal("expected upload link to be present")
}
if upload.Href != "http://localhost:8080/bilbo/repo/objects/"+nonExistingOid {
t.Fatalf("expected upload link, got %s", upload.Href)
}
}
func TestPostAuthedExistingObject(t *testing.T) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"oid":"%s", "size":%d}`, contentOid, contentSize))
res, err := api("POST", "/bilbo/repo/objects", metaMediaType, testUser, testPass, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
var meta Representation
dec := json.NewDecoder(res.Body)
dec.Decode(&meta)
if meta.Oid != contentOid {
t.Fatalf("expected to see oid `%s` in meta, got: `%s`", contentOid, meta.Oid)
}
if meta.Size != contentSize {
t.Fatalf("expected to see a size of `%d`, got: `%d`", contentSize, meta.Size)
}
download := meta.Actions["download"]
if download.Href != "http://localhost:8080/bilbo/repo/objects/"+contentOid {
t.Fatalf("expected download link, got %s", download.Href)
}
upload, ok := meta.Actions["upload"]
if !ok {
t.Fatalf("expected upload link to be present")
}
if upload.Href != "http://localhost:8080/bilbo/repo/objects/"+contentOid {
t.Fatalf("expected upload link, got %s", upload.Href)
}
}
func TestPostUnAuthed(t *testing.T) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"oid":"%s", "size":%d}`, contentOid, contentSize))
res, err := api("POST", "/bilbo/readonly/objects", metaMediaType, "", "", buf)
if err != nil {
t.Fatalf("response error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestPut(t *testing.T) {
req, err := http.NewRequest("PUT", lfsServer.URL+"/user/repo/objects/"+contentOid, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
req.SetBasicAuth(testUser, testPass)
req.Header.Set("Accept", contentMediaType)
req.Header.Set("Content-Type", "application/octet-stream")
req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte(content)))
res, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("response error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
r, err := testContentStore.Get(&MetaObject{Oid: contentOid}, 0)
if err != nil {
t.Fatalf("error retreiving from content store: %s", err)
} else {
defer r.Close()
}
c, err := ioutil.ReadAll(r)
if err != nil {
t.Fatalf("error reading content: %s", err)
}
if string(c) != content {
t.Fatalf("expected content, got `%s`", string(c))
}
}
func TestMediaTypesRequired(t *testing.T) {
m := []string{"GET", "PUT", "POST", "HEAD"}
for _, method := range m {
res, err := api(method, "/user/repo/objects/"+contentOid, "", testUser, testPass, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 404 {
t.Fatalf("expected status 404, got %d", res.StatusCode)
}
}
}
func TestMediaTypesParsed(t *testing.T) {
accept := contentMediaType + "; charset=utf-8"
res, err := api("GET", "/user/repo/objects/"+contentOid, accept, testUser, testPass, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
}
func TestLocksList(t *testing.T) {
res, err := api("GET", "/user/repo/locks", metaMediaType, testUser, testPass, nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("expected response to contain content, got error: %s", err)
}
var list LockList
if err := json.Unmarshal(body, &list); err != nil {
t.Fatalf("expected response body to be LockList, got error: %s", err)
}
if len(list.Locks) != 1 {
t.Errorf("expected returned lock count to match, got: %d", len(list.Locks))
}
if list.Locks[0].Id != lockId {
t.Errorf("expected lockId to match, got: %s", list.Locks[0].Id)
}
}
func TestLocksListUnAuthed(t *testing.T) {
res, err := api("GET", "/user/repo/locks", metaMediaType, "", "", nil)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestLocksVerify(t *testing.T) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"cursor": "", "limit": 0}`))
res, err := api("POST", "/user/repo/locks/verify", metaMediaType, testUser, testPass, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("expected response to contain content, got error: %s", err)
}
var list VerifiableLockList
if err := json.Unmarshal(body, &list); err != nil {
t.Fatalf("expected response body to be VerifiableLockList, got error: %s", err)
}
}
func TestLocksVerifyUnAuthed(t *testing.T) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"cursor": "", "limit": 0}`))
res, err := api("POST", "/user/repo/locks/verify", metaMediaType, "", "", buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestLock(t *testing.T) {
path := "TestLock"
lock, err := createLock(testUser, testPass, path)
if err != nil {
t.Fatalf("create lock error: %s", err)
}
if lock == nil {
t.Errorf("expected lock to be created, got: %s", lock)
}
if lock.Owner.Name != testUser {
t.Errorf("expected lock owner to be match, got: %s", lock.Owner.Name)
}
if lock.Path != path {
t.Errorf("expected lock path to be match, got: %s", lock.Path)
}
}
func TestLockExists(t *testing.T) {
l, err := createLock(testUser, testPass, "TestLockExists")
if err != nil {
t.Fatalf("create lock error: %s", err)
}
buf := bytes.NewBufferString(fmt.Sprintf(`{"path":"%s"}`, l.Path))
res, err := api("POST", "/user/repo/locks", metaMediaType, testUser, testPass, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 409 {
t.Fatalf("expected status 409, got %d", res.StatusCode)
}
}
func TestLockUnAuthed(t *testing.T) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"path":"%s"}`, "TestLockUnAuthed"))
res, err := api("POST", "/user/repo/locks", metaMediaType, "", "", buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestUnlock(t *testing.T) {
l, err := createLock(testUser, testPass, "TestUnlock")
if err != nil {
t.Fatalf("create lock error: %s", err)
}
buf := bytes.NewBufferString(fmt.Sprintf(`{"force": %t}`, false))
res, err := api("POST", "/user/repo/locks/"+l.Id+"/unlock", metaMediaType, testUser, testPass, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("expected response to contain content, got error: %s", err)
}
var unlockResponse UnlockResponse
if err := json.Unmarshal(body, &unlockResponse); err != nil {
t.Fatalf("expected response body to be UnlockResponse, got error: %s", err)
}
lock := unlockResponse.Lock
if lock == nil || lock.Id != l.Id {
t.Errorf("expected deleted lock to be returned, got: %s", lock)
}
}
func TestUnLockUnAuthed(t *testing.T) {
l, err := createLock(testUser, testPass, "TestUnLockUnAuthed")
if err != nil {
t.Fatalf("create lock error: %s", err)
}
buf := bytes.NewBufferString(fmt.Sprintf(`{"force": %t}`, false))
res, err := api("POST", "/user/repo/locks/"+l.Id+"/unlock", metaMediaType, "", "", buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 401 {
t.Fatalf("expected status 401, got %d", res.StatusCode)
}
}
func TestUnlockNotOwner(t *testing.T) {
l, err := createLock(testUser, testPass, "TestUnlockNotOwner")
if err != nil {
t.Fatalf("create lock error: %s", err)
}
buf := bytes.NewBufferString(fmt.Sprintf(`{"force": %t}`, false))
res, err := api("POST", "/user/repo/locks/"+l.Id+"/unlock", metaMediaType, testUser1, testPass1, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 403 {
t.Fatalf("expected status 403, got %d", res.StatusCode)
}
}
func TestUnlockNotOwnerForce(t *testing.T) {
l, err := createLock(testUser, testPass, "TestUnlockNotOwnerForce")
if err != nil {
t.Fatalf("create lock error: %s", err)
}
buf := bytes.NewBufferString(fmt.Sprintf(`{"force": %t}`, true))
res, err := api("POST", "/user/repo/locks/"+l.Id+"/unlock", metaMediaType, testUser1, testPass1, buf)
if err != nil {
t.Fatalf("request error: %s", err)
}
if res.StatusCode != 200 {
t.Fatalf("expected status 200, got %d", res.StatusCode)
}
}
func createLock(username, password, path string) (*Lock, error) {
buf := bytes.NewBufferString(fmt.Sprintf(`{"path":"%s"}`, path))
res, err := api("POST", "/user/repo/locks", metaMediaType, username, password, buf)
if err != nil {
return nil, fmt.Errorf("request error: %s", err)
}
if res.StatusCode != 201 {
return nil, fmt.Errorf("expected status 201, got %d", res.StatusCode)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("expected response to contain content, got error: %s", err)
}
var lockResponse LockResponse
if err := json.Unmarshal(body, &lockResponse); err != nil {
return nil, fmt.Errorf("expected response body to be LockResponse, got error: %s", err)
}
return lockResponse.Lock, nil
}
// simple http client for making api request
func api(method, path, accept, username, password string, body *bytes.Buffer) (*http.Response, error) {
req, err := http.NewRequest(method, lfsServer.URL+path, nil)
if err != nil {
return nil, err
}
if accept != "" {
req.Header.Set("Accept", accept)
}
if username != "" || password != "" {
req.SetBasicAuth(username, password)
}
if (method == "POST" || method == "PUT") && body != nil {
req.Body = ioutil.NopCloser(body)
}
return http.DefaultClient.Do(req)
}
var (
lfsServer *httptest.Server
testMetaStore *MetaStore
testContentStore *ContentStore
)
const (
testUser = "bilbo"
testPass = "baggins"
testUser1 = "bilbo1"
testPass1 = "baggins1"
testRepo = "repo"
content = "this is my content"
contentSize = int64(len(content))
contentOid = "f97e1b2936a56511b3b6efc99011758e4700d60fb1674d31445d1ee40b663f24"
nonExistingOid = "aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f"
lockId = "3cfec93346f7ff337c60f2da50cd86740715e2f6"
nonExistingLockId = "f310c1555a2485e2e5229ea015a94c9d590763d3"
lockPath = "this/is/lock/path"
)
func TestMain(m *testing.M) {
os.Remove("lfs-test.db")
var err error
testMetaStore, err = NewMetaStore("lfs-test.db")
if err != nil {
fmt.Printf("Error creating meta store: %s", err)
os.Exit(1)
}
testContentStore, err = NewContentStore("lfs-content-test")
if err != nil {
fmt.Printf("Error creating content store: %s", err)
os.Exit(1)
}
if err := seedMetaStore(); err != nil {
fmt.Printf("Error seeding meta store: %s", err)
os.Exit(1)
}
if err := seedContentStore(); err != nil {
fmt.Printf("Error seeding content store: %s", err)
os.Exit(1)
}
app := NewApp(testContentStore, testMetaStore)
lfsServer = httptest.NewServer(app)
logger = NewKVLogger(ioutil.Discard)
ret := m.Run()
lfsServer.Close()
testMetaStore.Close()
os.Remove("lfs-test.db")
os.RemoveAll("lfs-content-test")
os.Exit(ret)
}
func seedMetaStore() error {
if err := testMetaStore.AddUser(testUser, testPass); err != nil {
return err
}
if err := testMetaStore.AddUser(testUser1, testPass1); err != nil {
return err
}
rv := &RequestVars{Oid: contentOid, Size: contentSize}
if _, err := testMetaStore.Put(rv); err != nil {
return err
}
lock := NewTestLock(lockId, lockPath, testUser)
if err := testMetaStore.AddLocks(testRepo, lock); err != nil {
return err
}
return nil
}
func seedContentStore() error {
meta := &MetaObject{Oid: contentOid, Size: contentSize}
buf := bytes.NewBuffer([]byte(content))
if err := testContentStore.Put(meta, buf); err != nil {
return err
}
return nil
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/vcs-all-in-one-lfs-test-server.git
git@api.gitlife.ru:oschina-mirror/vcs-all-in-one-lfs-test-server.git
oschina-mirror
vcs-all-in-one-lfs-test-server
vcs-all-in-one-lfs-test-server
master