|
|
|
package mongo
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/globalsign/mgo"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/tal-tech/go-zero/core/breaker"
|
|
|
|
"github.com/tal-tech/go-zero/core/logx"
|
|
|
|
"github.com/tal-tech/go-zero/core/stores/mongo/internal"
|
|
|
|
"github.com/tal-tech/go-zero/core/stringx"
|
|
|
|
)
|
|
|
|
|
|
|
|
var errDummy = errors.New("dummy")
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
logx.Disable()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKeepPromise_accept(t *testing.T) {
|
|
|
|
p := new(mockPromise)
|
|
|
|
kp := keepablePromise{
|
|
|
|
promise: p,
|
|
|
|
log: func(error) {},
|
|
|
|
}
|
|
|
|
assert.Nil(t, kp.accept(nil))
|
|
|
|
assert.Equal(t, mgo.ErrNotFound, kp.accept(mgo.ErrNotFound))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKeepPromise_keep(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
err error
|
|
|
|
accepted bool
|
|
|
|
reason string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
err: nil,
|
|
|
|
accepted: true,
|
|
|
|
reason: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
err: mgo.ErrNotFound,
|
|
|
|
accepted: true,
|
|
|
|
reason: "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
err: errors.New("any"),
|
|
|
|
accepted: false,
|
|
|
|
reason: "any",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(stringx.RandId(), func(t *testing.T) {
|
|
|
|
p := new(mockPromise)
|
|
|
|
kp := keepablePromise{
|
|
|
|
promise: p,
|
|
|
|
log: func(error) {},
|
|
|
|
}
|
|
|
|
assert.Equal(t, test.err, kp.keep(test.err))
|
|
|
|
assert.Equal(t, test.accepted, p.accepted)
|
|
|
|
assert.Equal(t, test.reason, p.reason)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNewCollection(t *testing.T) {
|
|
|
|
col := newCollection(&mgo.Collection{
|
|
|
|
Database: nil,
|
|
|
|
Name: "foo",
|
|
|
|
FullName: "bar",
|
|
|
|
}, breaker.GetBreaker("localhost"))
|
|
|
|
assert.Equal(t, "bar", col.(*decoratedCollection).name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionFind(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
var query mgo.Query
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().Find(gomock.Any()).Return(&query)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
actual := c.Find(nil)
|
|
|
|
switch v := actual.(type) {
|
|
|
|
case promisedQuery:
|
|
|
|
assert.Equal(t, &query, v.Query)
|
|
|
|
assert.Equal(t, errDummy, v.promise.keep(errDummy))
|
|
|
|
default:
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
actual = c.Find(nil)
|
|
|
|
assert.Equal(t, rejectedQuery{}, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionFindId(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
var query mgo.Query
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().FindId(gomock.Any()).Return(&query)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
actual := c.FindId(nil)
|
|
|
|
switch v := actual.(type) {
|
|
|
|
case promisedQuery:
|
|
|
|
assert.Equal(t, &query, v.Query)
|
|
|
|
assert.Equal(t, errDummy, v.promise.keep(errDummy))
|
|
|
|
default:
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
actual = c.FindId(nil)
|
|
|
|
assert.Equal(t, rejectedQuery{}, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionInsert(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().Insert(nil, nil).Return(errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
err := c.Insert(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
err = c.Insert(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionPipe(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
var pipe mgo.Pipe
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().Pipe(gomock.Any()).Return(&pipe)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
actual := c.Pipe(nil)
|
|
|
|
switch v := actual.(type) {
|
|
|
|
case promisedPipe:
|
|
|
|
assert.Equal(t, &pipe, v.Pipe)
|
|
|
|
assert.Equal(t, errDummy, v.promise.keep(errDummy))
|
|
|
|
default:
|
|
|
|
t.Fail()
|
|
|
|
}
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
actual = c.Pipe(nil)
|
|
|
|
assert.Equal(t, rejectedPipe{}, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionRemove(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().Remove(gomock.Any()).Return(errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
err := c.Remove(nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
err = c.Remove(nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionRemoveAll(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().RemoveAll(gomock.Any()).Return(nil, errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
_, err := c.RemoveAll(nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
_, err = c.RemoveAll(nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionRemoveId(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().RemoveId(gomock.Any()).Return(errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
err := c.RemoveId(nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
err = c.RemoveId(nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionUpdate(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().Update(gomock.Any(), gomock.Any()).Return(errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
err := c.Update(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
err = c.Update(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionUpdateId(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().UpdateId(gomock.Any(), gomock.Any()).Return(errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
err := c.UpdateId(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
err = c.UpdateId(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCollectionUpsert(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
col := internal.NewMockMgoCollection(ctrl)
|
|
|
|
col.EXPECT().Upsert(gomock.Any(), gomock.Any()).Return(nil, errDummy)
|
|
|
|
c := decoratedCollection{
|
|
|
|
collection: col,
|
|
|
|
brk: breaker.NewBreaker(),
|
|
|
|
}
|
|
|
|
_, err := c.Upsert(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
c.brk = new(dropBreaker)
|
|
|
|
_, err = c.Upsert(nil, nil)
|
|
|
|
assert.Equal(t, errDummy, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockPromise struct {
|
|
|
|
accepted bool
|
|
|
|
reason string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockPromise) Accept() {
|
|
|
|
p.accepted = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockPromise) Reject(reason string) {
|
|
|
|
p.reason = reason
|
|
|
|
}
|
|
|
|
|
|
|
|
type dropBreaker struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dropBreaker) Name() string {
|
|
|
|
return "dummy"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dropBreaker) Allow() (breaker.Promise, error) {
|
|
|
|
return nil, errDummy
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dropBreaker) Do(req func() error) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dropBreaker) DoWithAcceptable(req func() error, acceptable breaker.Acceptable) error {
|
|
|
|
return errDummy
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dropBreaker) DoWithFallback(req func() error, fallback func(err error) error) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *dropBreaker) DoWithFallbackAcceptable(req func() error, fallback func(err error) error,
|
|
|
|
acceptable breaker.Acceptable) error {
|
|
|
|
return nil
|
|
|
|
}
|