♻️ Improved bbolt.DB testing
This commit is contained in:
parent
e2961e6642
commit
a7ba6267aa
|
@ -29,19 +29,10 @@ type (
|
|||
|
||||
var ErrNotExist error = xerrors.New("key not exist")
|
||||
|
||||
func NewBoltTokenRepository(db *bolt.DB) (token.Repository, error) {
|
||||
if err := db.Update(func(tx *bolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
_, err := tx.CreateBucketIfNotExists(Token{}.Bucket())
|
||||
|
||||
return errors.Wrap(err, "failed to create a bucket")
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to update the storage structure")
|
||||
}
|
||||
|
||||
func NewBoltTokenRepository(db *bolt.DB) token.Repository {
|
||||
return &boltTokenRepository{
|
||||
db: db,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (repo *boltTokenRepository) Get(ctx context.Context, accessToken string) (*domain.Token, error) {
|
||||
|
|
|
@ -3,101 +3,62 @@ package bolt_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
json "github.com/goccy/go-json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.etcd.io/bbolt"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
|
||||
"source.toby3d.me/website/oauth/internal/domain"
|
||||
"source.toby3d.me/website/oauth/internal/random"
|
||||
"source.toby3d.me/website/oauth/internal/token"
|
||||
"source.toby3d.me/website/oauth/internal/token/repository/bolt"
|
||||
repository "source.toby3d.me/website/oauth/internal/token/repository/bolt"
|
||||
"source.toby3d.me/website/oauth/internal/util"
|
||||
)
|
||||
|
||||
//nolint: gochecknoglobals
|
||||
var (
|
||||
db *bbolt.DB
|
||||
repo token.Repository
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
|
||||
dbPath := filepath.Join("..", "..", "..", "..", "test", "testing.db")
|
||||
if db, err = bbolt.Open(dbPath, os.ModePerm, nil); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
if repo, err = bolt.NewBoltTokenRepository(db); err != nil {
|
||||
_ = db.Close()
|
||||
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
_ = db.Close()
|
||||
_ = os.RemoveAll(dbPath)
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, cleanup := util.TestBolt(t, repository.Token{}.Bucket())
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
accessToken := domain.TestToken(t)
|
||||
accessToken.Profile = nil
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = db.Update(func(tx *bbolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Delete([]byte(accessToken.AccessToken))
|
||||
})
|
||||
})
|
||||
dto := new(repository.Token)
|
||||
dto.Populate(accessToken)
|
||||
|
||||
src, err := json.Marshal(&bolt.Token{
|
||||
AccessToken: accessToken.AccessToken,
|
||||
ClientID: accessToken.ClientID,
|
||||
Me: accessToken.Me,
|
||||
Scope: strings.Join(accessToken.Scopes, " "),
|
||||
Type: accessToken.Type,
|
||||
})
|
||||
src, err := json.Marshal(dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, db.Update(func(tx *bbolt.Tx) error {
|
||||
require.NoError(t, db.Update(func(tx *bolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Put([]byte(accessToken.AccessToken), src)
|
||||
return tx.Bucket(repository.Token{}.Bucket()).Put([]byte(accessToken.AccessToken), src)
|
||||
}))
|
||||
|
||||
tkn, err := repo.Get(context.TODO(), accessToken.AccessToken)
|
||||
result, err := repository.NewBoltTokenRepository(db).Get(context.TODO(), accessToken.AccessToken)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, accessToken, tkn)
|
||||
assert.Equal(t, accessToken, result)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
accessToken := domain.TestToken(t)
|
||||
db, cleanup := util.TestBolt(t, repository.Token{}.Bucket())
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = db.Update(func(tx *bbolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Delete([]byte(accessToken.AccessToken))
|
||||
})
|
||||
})
|
||||
repo := repository.NewBoltTokenRepository(db)
|
||||
accessToken := domain.TestToken(t)
|
||||
accessToken.Profile = nil
|
||||
|
||||
require.NoError(t, repo.Create(context.TODO(), accessToken))
|
||||
|
||||
result := new(domain.Token)
|
||||
|
||||
require.NoError(t, db.View(func(tx *bbolt.Tx) error {
|
||||
require.NoError(t, db.View(func(tx *bolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return new(bolt.Token).Bind(tx.Bucket(bolt.Token{}.Bucket()).Get([]byte(accessToken.AccessToken)),
|
||||
result)
|
||||
return new(repository.Token).Bind(tx.Bucket(repository.Token{}.Bucket()).
|
||||
Get([]byte(accessToken.AccessToken)), result)
|
||||
}))
|
||||
|
||||
assert.Equal(t, accessToken, result)
|
||||
|
@ -107,83 +68,67 @@ func TestCreate(t *testing.T) {
|
|||
func TestUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
accessToken := random.New().String(32)
|
||||
db, cleanup := util.TestBolt(t, repository.Token{}.Bucket())
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = db.Update(func(tx *bbolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Delete([]byte(accessToken))
|
||||
})
|
||||
})
|
||||
accessToken := domain.TestToken(t)
|
||||
|
||||
src, err := json.Marshal(&bolt.Token{
|
||||
AccessToken: accessToken,
|
||||
ClientID: "https://app.example.com/",
|
||||
Me: "https://toby3d.me/",
|
||||
Scope: "read update delete",
|
||||
Type: "Bearer",
|
||||
})
|
||||
src, err := json.Marshal(accessToken)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, db.Update(func(tx *bbolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Put([]byte(accessToken), src)
|
||||
//nolint: exhaustivestruct
|
||||
require.NoError(t, db.Update(func(tx *bolt.Tx) error {
|
||||
return tx.Bucket(repository.Token{}.Bucket()).Put([]byte(accessToken.AccessToken), src)
|
||||
}))
|
||||
|
||||
require.NoError(t, repo.Update(context.TODO(), &domain.Token{
|
||||
AccessToken: accessToken,
|
||||
ClientID: "https://client.example.com/",
|
||||
require.NoError(t, repository.NewBoltTokenRepository(db).Update(context.TODO(), &domain.Token{
|
||||
AccessToken: accessToken.AccessToken,
|
||||
ClientID: "https://client.example.net/",
|
||||
Me: "https://toby3d.ru/",
|
||||
Scopes: []string{"read"},
|
||||
Type: "Bearer",
|
||||
Profile: nil,
|
||||
}))
|
||||
|
||||
result := domain.NewToken()
|
||||
|
||||
require.NoError(t, db.View(func(tx *bbolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return new(bolt.Token).Bind(tx.Bucket(bolt.Token{}.Bucket()).Get([]byte(accessToken)), result)
|
||||
//nolint: exhaustivestruct
|
||||
require.NoError(t, db.View(func(tx *bolt.Tx) error {
|
||||
return new(repository.Token).Bind(tx.Bucket(repository.Token{}.Bucket()).
|
||||
Get([]byte(accessToken.AccessToken)), result)
|
||||
}))
|
||||
|
||||
assert.Equal(t, &domain.Token{
|
||||
AccessToken: accessToken,
|
||||
ClientID: "https://client.example.com/",
|
||||
AccessToken: accessToken.AccessToken,
|
||||
ClientID: "https://client.example.net/",
|
||||
Me: "https://toby3d.ru/",
|
||||
Scopes: []string{"read"},
|
||||
Type: "Bearer",
|
||||
Profile: nil,
|
||||
}, result)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
accessToken := random.New().String(32)
|
||||
db, cleanup := util.TestBolt(t, repository.Token{}.Bucket())
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = db.Update(func(tx *bbolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Delete([]byte(accessToken))
|
||||
})
|
||||
})
|
||||
accessToken := domain.TestToken(t)
|
||||
|
||||
src, err := json.Marshal(&bolt.Token{
|
||||
AccessToken: accessToken,
|
||||
ClientID: "https://app.example.com/",
|
||||
Me: "https://toby3d.me/",
|
||||
Scope: "read update delete",
|
||||
Type: "Bearer",
|
||||
})
|
||||
src, err := json.Marshal(accessToken)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, db.Update(func(tx *bbolt.Tx) error {
|
||||
require.NoError(t, db.Update(func(tx *bolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
return tx.Bucket(bolt.Token{}.Bucket()).Put([]byte(accessToken), src)
|
||||
return tx.Bucket(repository.Token{}.Bucket()).Put([]byte(accessToken.AccessToken), src)
|
||||
}))
|
||||
|
||||
require.NoError(t, repo.Remove(context.TODO(), accessToken))
|
||||
require.NoError(t, repository.NewBoltTokenRepository(db).Remove(context.TODO(), accessToken.AccessToken))
|
||||
|
||||
require.NoError(t, db.View(func(tx *bbolt.Tx) error {
|
||||
require.NoError(t, db.View(func(tx *bolt.Tx) error {
|
||||
//nolint: exhaustivestruct
|
||||
assert.Nil(t, tx.Bucket(bolt.Token{}.Bucket()).Get([]byte(accessToken)))
|
||||
assert.Nil(t, tx.Bucket(repository.Token{}.Bucket()).Get([]byte(accessToken.AccessToken)))
|
||||
|
||||
return nil
|
||||
}))
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
func TestBolt(tb testing.TB, buckets ...[]byte) (*bolt.DB, func()) {
|
||||
tb.Helper()
|
||||
|
||||
f, err := os.CreateTemp("", "bbolt_*.db")
|
||||
require.NoError(tb, err)
|
||||
|
||||
filePath := f.Name()
|
||||
assert.NoError(tb, f.Close())
|
||||
|
||||
db, err := bolt.Open(filePath, os.ModePerm, nil)
|
||||
require.NoError(tb, err)
|
||||
|
||||
for _, bucket := range buckets {
|
||||
bucket := bucket
|
||||
|
||||
assert.NoError(tb, db.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucket(bucket)
|
||||
|
||||
return err //nolint: errcheck
|
||||
}))
|
||||
}
|
||||
|
||||
return db, func() {
|
||||
db.Close() //nolint: errcheck
|
||||
os.Remove(filePath) //nolint: errcheck
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue