mirror of https://github.com/gogs/gogs.git
lfs: add tests to batch endpoint (#6073)
parent
ca2f7a7e16
commit
2b3655fa11
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2020 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package conf
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func SetMockServer(t *testing.T, opts ServerOpts) {
|
||||
before := Server
|
||||
Server = opts
|
||||
t.Cleanup(func() {
|
||||
Server = before
|
||||
})
|
||||
}
|
|
@ -46,40 +46,6 @@ var (
|
|||
AppName string
|
||||
}
|
||||
|
||||
// Server settings
|
||||
Server struct {
|
||||
ExternalURL string `ini:"EXTERNAL_URL"`
|
||||
Domain string
|
||||
Protocol string
|
||||
HTTPAddr string `ini:"HTTP_ADDR"`
|
||||
HTTPPort string `ini:"HTTP_PORT"`
|
||||
CertFile string
|
||||
KeyFile string
|
||||
TLSMinVersion string `ini:"TLS_MIN_VERSION"`
|
||||
UnixSocketPermission string
|
||||
LocalRootURL string `ini:"LOCAL_ROOT_URL"`
|
||||
|
||||
OfflineMode bool
|
||||
DisableRouterLog bool
|
||||
EnableGzip bool
|
||||
|
||||
AppDataPath string
|
||||
LoadAssetsFromDisk bool
|
||||
|
||||
LandingURL string `ini:"LANDING_URL"`
|
||||
|
||||
// Derived from other static values
|
||||
URL *url.URL `ini:"-"` // Parsed URL object of ExternalURL.
|
||||
Subpath string `ini:"-"` // Subpath found the ExternalURL. Should be empty when not found.
|
||||
SubpathDepth int `ini:"-"` // The number of slashes found in the Subpath.
|
||||
UnixSocketMode os.FileMode `ini:"-"` // Parsed file mode of UnixSocketPermission.
|
||||
|
||||
// Deprecated: Use ExternalURL instead, will be removed in 0.13.
|
||||
RootURL string `ini:"ROOT_URL"`
|
||||
// Deprecated: Use LandingURL instead, will be removed in 0.13.
|
||||
LangdingPage string `ini:"LANDING_PAGE"`
|
||||
}
|
||||
|
||||
// SSH settings
|
||||
SSH struct {
|
||||
Disabled bool `ini:"DISABLE_SSH"`
|
||||
|
@ -127,9 +93,6 @@ var (
|
|||
} `ini:"repository.upload"`
|
||||
}
|
||||
|
||||
// Database settings
|
||||
Database DatabaseOpts
|
||||
|
||||
// Security settings
|
||||
Security struct {
|
||||
InstallLock bool
|
||||
|
@ -279,9 +242,6 @@ var (
|
|||
DefaultInterval int
|
||||
}
|
||||
|
||||
// I18n settings
|
||||
I18n *i18nConf
|
||||
|
||||
// Webhook settings
|
||||
Webhook struct {
|
||||
Types []string
|
||||
|
@ -401,6 +361,42 @@ var (
|
|||
HasRobotsTxt bool
|
||||
)
|
||||
|
||||
type ServerOpts struct {
|
||||
ExternalURL string `ini:"EXTERNAL_URL"`
|
||||
Domain string
|
||||
Protocol string
|
||||
HTTPAddr string `ini:"HTTP_ADDR"`
|
||||
HTTPPort string `ini:"HTTP_PORT"`
|
||||
CertFile string
|
||||
KeyFile string
|
||||
TLSMinVersion string `ini:"TLS_MIN_VERSION"`
|
||||
UnixSocketPermission string
|
||||
LocalRootURL string `ini:"LOCAL_ROOT_URL"`
|
||||
|
||||
OfflineMode bool
|
||||
DisableRouterLog bool
|
||||
EnableGzip bool
|
||||
|
||||
AppDataPath string
|
||||
LoadAssetsFromDisk bool
|
||||
|
||||
LandingURL string `ini:"LANDING_URL"`
|
||||
|
||||
// Derived from other static values
|
||||
URL *url.URL `ini:"-"` // Parsed URL object of ExternalURL.
|
||||
Subpath string `ini:"-"` // Subpath found the ExternalURL. Should be empty when not found.
|
||||
SubpathDepth int `ini:"-"` // The number of slashes found in the Subpath.
|
||||
UnixSocketMode os.FileMode `ini:"-"` // Parsed file mode of UnixSocketPermission.
|
||||
|
||||
// Deprecated: Use ExternalURL instead, will be removed in 0.13.
|
||||
RootURL string `ini:"ROOT_URL"`
|
||||
// Deprecated: Use LandingURL instead, will be removed in 0.13.
|
||||
LangdingPage string `ini:"LANDING_PAGE"`
|
||||
}
|
||||
|
||||
// Server settings
|
||||
var Server ServerOpts
|
||||
|
||||
type DatabaseOpts struct {
|
||||
Type string
|
||||
Host string
|
||||
|
@ -418,6 +414,9 @@ type DatabaseOpts struct {
|
|||
Passwd string
|
||||
}
|
||||
|
||||
// Database settings
|
||||
var Database DatabaseOpts
|
||||
|
||||
type i18nConf struct {
|
||||
Langs []string `delim:","`
|
||||
Names []string `delim:","`
|
||||
|
@ -433,6 +432,9 @@ func (c *i18nConf) DateLang(lang string) string {
|
|||
return "en"
|
||||
}
|
||||
|
||||
// I18n settings
|
||||
var I18n *i18nConf
|
||||
|
||||
// handleDeprecated transfers deprecated values to the new ones when set.
|
||||
func handleDeprecated() {
|
||||
if App.AppName != "" {
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"gogs.io/gogs/internal/lfsutil"
|
||||
)
|
||||
|
||||
// NOTE: Mocks are sorted in alphabetical order.
|
||||
|
@ -33,6 +36,34 @@ func SetMockAccessTokensStore(t *testing.T, mock AccessTokensStore) {
|
|||
})
|
||||
}
|
||||
|
||||
var _ LFSStore = (*MockLFSStore)(nil)
|
||||
|
||||
type MockLFSStore struct {
|
||||
MockCreateObject func(repoID int64, oid lfsutil.OID, rc io.ReadCloser, storage lfsutil.Storage) error
|
||||
MockGetObjectByOID func(repoID int64, oid lfsutil.OID) (*LFSObject, error)
|
||||
MockGetObjectsByOIDs func(repoID int64, oids ...lfsutil.OID) ([]*LFSObject, error)
|
||||
}
|
||||
|
||||
func (m *MockLFSStore) CreateObject(repoID int64, oid lfsutil.OID, rc io.ReadCloser, storage lfsutil.Storage) error {
|
||||
return m.MockCreateObject(repoID, oid, rc, storage)
|
||||
}
|
||||
|
||||
func (m *MockLFSStore) GetObjectByOID(repoID int64, oid lfsutil.OID) (*LFSObject, error) {
|
||||
return m.MockGetObjectByOID(repoID, oid)
|
||||
}
|
||||
|
||||
func (m *MockLFSStore) GetObjectsByOIDs(repoID int64, oids ...lfsutil.OID) ([]*LFSObject, error) {
|
||||
return m.MockGetObjectsByOIDs(repoID, oids...)
|
||||
}
|
||||
|
||||
func SetMockLFSStore(t *testing.T, mock LFSStore) {
|
||||
before := LFS
|
||||
LFS = mock
|
||||
t.Cleanup(func() {
|
||||
LFS = before
|
||||
})
|
||||
}
|
||||
|
||||
var _ PermsStore = (*MockPermsStore)(nil)
|
||||
|
||||
type MockPermsStore struct {
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2020 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package lfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/db"
|
||||
"gogs.io/gogs/internal/lfsutil"
|
||||
)
|
||||
|
||||
func Test_serveBatch(t *testing.T) {
|
||||
conf.SetMockServer(t, conf.ServerOpts{
|
||||
ExternalURL: "https://gogs.example.com/",
|
||||
})
|
||||
m := macaron.New()
|
||||
m.Use(func(c *macaron.Context) {
|
||||
c.Map(&db.User{Name: "owner"})
|
||||
c.Map(&db.Repository{Name: "repo"})
|
||||
})
|
||||
m.Post("/", serveBatch)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
body string
|
||||
mockLFSStore *db.MockLFSStore
|
||||
expStatusCode int
|
||||
expBody string
|
||||
}{
|
||||
{
|
||||
name: "unrecognized operation",
|
||||
body: `{"operation": "update"}`,
|
||||
expStatusCode: http.StatusBadRequest,
|
||||
expBody: `{"message":"Operation not recognized"}` + "\n",
|
||||
},
|
||||
{
|
||||
name: "upload: contains invalid oid",
|
||||
body: `{
|
||||
"operation": "upload",
|
||||
"objects": [
|
||||
{"oid": "bad_oid", "size": 123},
|
||||
{"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f", "size": 123}
|
||||
]}`,
|
||||
expStatusCode: http.StatusOK,
|
||||
expBody: `{"transfer":"basic","objects":[{"oid":"bad_oid","size":123,"actions":{"error":{"code":422,"message":"Object has invalid oid"}}},{"oid":"ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f","size":123,"actions":{"upload":{"href":"https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f"},"verify":{"href":"https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/verify"}}}]}` + "\n",
|
||||
},
|
||||
{
|
||||
name: "download: contains non-existent oid and mismatched size",
|
||||
body: `{
|
||||
"operation": "download",
|
||||
"objects": [
|
||||
{"oid": "bad_oid", "size": 123},
|
||||
{"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f", "size": 123},
|
||||
{"oid": "5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57", "size": 456}
|
||||
]}`,
|
||||
mockLFSStore: &db.MockLFSStore{
|
||||
MockGetObjectsByOIDs: func(repoID int64, oids ...lfsutil.OID) ([]*db.LFSObject, error) {
|
||||
return []*db.LFSObject{
|
||||
{
|
||||
OID: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
||||
Size: 1234,
|
||||
}, {
|
||||
OID: "5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57",
|
||||
Size: 456,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
expStatusCode: http.StatusOK,
|
||||
expBody: `{"transfer":"basic","objects":[{"oid":"bad_oid","size":123,"actions":{"error":{"code":404,"message":"Object does not exist"}}},{"oid":"ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f","size":123,"actions":{"error":{"code":422,"message":"Object size mismatch"}}},{"oid":"5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57","size":456,"actions":{"download":{"href":"https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57"}}}]}` + "\n",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
db.SetMockLFSStore(t, test.mockLFSStore)
|
||||
|
||||
r, err := http.NewRequest("POST", "/", bytes.NewBufferString(test.body))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
m.ServeHTTP(rr, r)
|
||||
|
||||
resp := rr.Result()
|
||||
assert.Equal(t, test.expStatusCode, resp.StatusCode)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, test.expBody, string(body))
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue