mirror of https://github.com/gogs/gogs.git
db: add tests for LFS (#6087)
* Improve DB test setup * Discard GORM logs in non-verbose mode * Add tests to lfs * Fix data racepull/6092/head
parent
62dda96159
commit
e077ecdd9d
|
@ -56,12 +56,12 @@ type AccessToken struct {
|
|||
|
||||
// NOTE: This is a GORM create hook.
|
||||
func (t *AccessToken) BeforeCreate() {
|
||||
t.CreatedUnix = t.Created.Unix()
|
||||
t.CreatedUnix = gorm.NowFunc().Unix()
|
||||
}
|
||||
|
||||
// NOTE: This is a GORM update hook.
|
||||
func (t *AccessToken) BeforeUpdate() {
|
||||
t.UpdatedUnix = t.Updated.Unix()
|
||||
t.UpdatedUnix = gorm.NowFunc().Unix()
|
||||
}
|
||||
|
||||
// NOTE: This is a GORM query hook.
|
||||
|
@ -69,14 +69,13 @@ func (t *AccessToken) AfterFind() {
|
|||
t.Created = time.Unix(t.CreatedUnix, 0).Local()
|
||||
t.Updated = time.Unix(t.UpdatedUnix, 0).Local()
|
||||
t.HasUsed = t.Updated.After(t.Created)
|
||||
t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(time.Now())
|
||||
t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(gorm.NowFunc())
|
||||
}
|
||||
|
||||
var _ AccessTokensStore = (*accessTokens)(nil)
|
||||
|
||||
type accessTokens struct {
|
||||
*gorm.DB
|
||||
clock func() time.Time
|
||||
}
|
||||
|
||||
type ErrAccessTokenAlreadyExist struct {
|
||||
|
@ -101,10 +100,9 @@ func (db *accessTokens) Create(userID int64, name string) (*AccessToken, error)
|
|||
}
|
||||
|
||||
token := &AccessToken{
|
||||
UserID: userID,
|
||||
Name: name,
|
||||
Sha1: tool.SHA1(gouuid.NewV4().String()),
|
||||
Created: db.clock(),
|
||||
UserID: userID,
|
||||
Name: name,
|
||||
Sha1: tool.SHA1(gouuid.NewV4().String()),
|
||||
}
|
||||
return token, db.DB.Create(token).Error
|
||||
}
|
||||
|
@ -150,6 +148,5 @@ func (db *accessTokens) List(userID int64) ([]*AccessToken, error) {
|
|||
}
|
||||
|
||||
func (db *accessTokens) Save(t *AccessToken) error {
|
||||
t.Updated = db.clock()
|
||||
return db.DB.Save(t).Error
|
||||
}
|
||||
|
|
|
@ -5,15 +5,12 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/errutil"
|
||||
)
|
||||
|
||||
|
@ -24,33 +21,9 @@ func Test_accessTokens(t *testing.T) {
|
|||
|
||||
t.Parallel()
|
||||
|
||||
dbpath := filepath.Join(os.TempDir(), fmt.Sprintf("gogs-%d.db", time.Now().Unix()))
|
||||
gdb, err := openDB(conf.DatabaseOpts{
|
||||
Type: "sqlite3",
|
||||
Path: dbpath,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
db := &accessTokens{
|
||||
DB: initTestDB(t, "accessTokens", new(AccessToken)),
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_ = gdb.Close()
|
||||
|
||||
if t.Failed() {
|
||||
t.Logf("Database %q left intact for inspection", dbpath)
|
||||
return
|
||||
}
|
||||
|
||||
_ = os.Remove(dbpath)
|
||||
})
|
||||
|
||||
err = gdb.AutoMigrate(new(AccessToken)).Error
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
now := time.Now().Truncate(time.Second)
|
||||
clock := func() time.Time { return now }
|
||||
db := &accessTokens{DB: gdb, clock: clock}
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
|
@ -64,7 +37,7 @@ func Test_accessTokens(t *testing.T) {
|
|||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
err := deleteTables(gdb, new(AccessToken))
|
||||
err := deleteTables(db.DB, new(AccessToken))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -84,7 +57,13 @@ func test_accessTokens_Create(t *testing.T, db *accessTokens) {
|
|||
assert.Equal(t, int64(1), token.UserID)
|
||||
assert.Equal(t, "Test", token.Name)
|
||||
assert.Equal(t, 40, len(token.Sha1), "sha1 length")
|
||||
assert.Equal(t, db.clock(), token.Created)
|
||||
|
||||
// Get it back and check the Created field
|
||||
token, err = db.GetBySHA(token.Sha1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), token.Created.Format(time.RFC3339))
|
||||
|
||||
// Try create second access token with same name should fail
|
||||
_, err = db.Create(token.UserID, token.Name)
|
||||
|
@ -197,5 +176,5 @@ func test_accessTokens_Save(t *testing.T, db *accessTokens) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, db.clock(), token.Updated)
|
||||
assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), token.Updated.Format(time.RFC3339))
|
||||
}
|
||||
|
|
|
@ -163,9 +163,12 @@ func Init() error {
|
|||
return errors.Wrap(err, "migrate schemes")
|
||||
}
|
||||
|
||||
clock := func() time.Time {return time.Now().UTC().Truncate(time.Microsecond)}
|
||||
gorm.NowFunc = func() time.Time {
|
||||
return time.Now().UTC().Truncate(time.Microsecond)
|
||||
}
|
||||
|
||||
// Initialize stores, sorted in alphabetical order.
|
||||
AccessTokens = &accessTokens{DB: db, clock: clock}
|
||||
AccessTokens = &accessTokens{DB: db}
|
||||
LoginSources = &loginSources{DB: db}
|
||||
LFS = &lfs{DB: db}
|
||||
Perms = &perms{DB: db}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// 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 db
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gogs.io/gogs/internal/errutil"
|
||||
"gogs.io/gogs/internal/lfsutil"
|
||||
)
|
||||
|
||||
func Test_lfs(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
|
||||
db := &lfs{
|
||||
DB: initTestDB(t, "lfs", new(LFSObject)),
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
test func(*testing.T, *lfs)
|
||||
}{
|
||||
{"CreateObject", test_lfs_CreateObject},
|
||||
{"GetObjectByOID", test_lfs_GetObjectByOID},
|
||||
{"GetObjectsByOIDs", test_lfs_GetObjectsByOIDs},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
err := deleteTables(db.DB, new(LFSObject))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
tc.test(t, db)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func test_lfs_CreateObject(t *testing.T, db *lfs) {
|
||||
// Create first LFS object
|
||||
repoID := int64(1)
|
||||
oid := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
||||
err := db.CreateObject(repoID, oid, 12, lfsutil.StorageLocal)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Get it back and check the CreatedAt field
|
||||
object, err := db.GetObjectByOID(repoID, oid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), object.CreatedAt.Format(time.RFC3339))
|
||||
|
||||
// Try create second LFS object with same oid should fail
|
||||
err = db.CreateObject(repoID, oid, 12, lfsutil.StorageLocal)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func test_lfs_GetObjectByOID(t *testing.T, db *lfs) {
|
||||
// Create a LFS object
|
||||
repoID := int64(1)
|
||||
oid := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
||||
err := db.CreateObject(repoID, oid, 12, lfsutil.StorageLocal)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// We should be able to get it back
|
||||
_, err = db.GetObjectByOID(repoID, oid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Try to get a non-existent object
|
||||
_, err = db.GetObjectByOID(repoID, "bad_oid")
|
||||
expErr := ErrLFSObjectNotExist{args: errutil.Args{"repoID": repoID, "oid": lfsutil.OID("bad_oid")}}
|
||||
assert.Equal(t, expErr, err)
|
||||
}
|
||||
|
||||
func test_lfs_GetObjectsByOIDs(t *testing.T, db *lfs) {
|
||||
// Create two LFS objects
|
||||
repoID := int64(1)
|
||||
oid1 := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
||||
oid2 := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64g")
|
||||
err := db.CreateObject(repoID, oid1, 12, lfsutil.StorageLocal)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = db.CreateObject(repoID, oid2, 12, lfsutil.StorageLocal)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// We should be able to get them back and ignore non-existent ones
|
||||
objects, err := db.GetObjectsByOIDs(repoID, oid1, oid2, "bad_oid")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, 2, len(objects), "number of objects")
|
||||
|
||||
assert.Equal(t, repoID, objects[0].RepoID)
|
||||
assert.Equal(t, oid1, objects[0].OID)
|
||||
|
||||
assert.Equal(t, repoID, objects[1].RepoID)
|
||||
assert.Equal(t, oid2, objects[1].OID)
|
||||
}
|
|
@ -7,12 +7,17 @@ package db
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/dbutil"
|
||||
"gogs.io/gogs/internal/testutil"
|
||||
)
|
||||
|
||||
|
@ -27,6 +32,10 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
now := time.Now().Truncate(time.Second)
|
||||
gorm.NowFunc = func() time.Time { return now }
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
|
@ -39,3 +48,38 @@ func deleteTables(db *gorm.DB, tables ...interface{}) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initTestDB(t *testing.T, suite string, tables ...interface{}) *gorm.DB {
|
||||
t.Helper()
|
||||
|
||||
dbpath := filepath.Join(os.TempDir(), fmt.Sprintf("gogs-%s-%d.db", suite, time.Now().Unix()))
|
||||
db, err := openDB(conf.DatabaseOpts{
|
||||
Type: "sqlite3",
|
||||
Path: dbpath,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_ = db.Close()
|
||||
|
||||
if t.Failed() {
|
||||
t.Logf("Database %q left intact for inspection", dbpath)
|
||||
return
|
||||
}
|
||||
|
||||
_ = os.Remove(dbpath)
|
||||
})
|
||||
|
||||
db.SingularTable(true)
|
||||
if !testing.Verbose() {
|
||||
db.SetLogger(&dbutil.Writer{Writer: ioutil.Discard})
|
||||
}
|
||||
|
||||
err = db.AutoMigrate(tables...).Error
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue