diff options
author | ᴜɴᴋɴᴡᴏɴ <u@gogs.io> | 2020-04-06 23:53:55 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-06 23:53:55 +0800 |
commit | 2b3655fa118abaa33a0e064233fdc8c670487c62 (patch) | |
tree | c160e5aaa886e920f4cef8bd2bb29a002e6399fe /internal | |
parent | ca2f7a7e1610fd8e99649dc1ed2058c2f362c57d (diff) |
lfs: add tests to batch endpoint (#6073)
Diffstat (limited to 'internal')
-rw-r--r-- | internal/conf/mocks.go | 17 | ||||
-rw-r--r-- | internal/conf/static.go | 82 | ||||
-rw-r--r-- | internal/db/mocks.go | 31 | ||||
-rw-r--r-- | internal/route/lfs/batch_test.go | 105 |
4 files changed, 195 insertions, 40 deletions
diff --git a/internal/conf/mocks.go b/internal/conf/mocks.go new file mode 100644 index 00000000..1f8e16f2 --- /dev/null +++ b/internal/conf/mocks.go @@ -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 + }) +} diff --git a/internal/conf/static.go b/internal/conf/static.go index 8daebe79..35d1a8f4 100644 --- a/internal/conf/static.go +++ b/internal/conf/static.go @@ -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 != "" { diff --git a/internal/db/mocks.go b/internal/db/mocks.go index 0a52042b..b81dab13 100644 --- a/internal/db/mocks.go +++ b/internal/db/mocks.go @@ -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 { diff --git a/internal/route/lfs/batch_test.go b/internal/route/lfs/batch_test.go new file mode 100644 index 00000000..7dce2004 --- /dev/null +++ b/internal/route/lfs/batch_test.go @@ -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)) + }) + } +} |