|
|
|
package cluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
|
|
model "github.com/cloudreve/Cloudreve/v3/models"
|
|
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/balancer"
|
|
|
|
"github.com/jinzhu/gorm"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
var mock sqlmock.Sqlmock
|
|
|
|
|
|
|
|
// TestMain 初始化数据库Mock
|
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
var db *sql.DB
|
|
|
|
var err error
|
|
|
|
db, mock, err = sqlmock.New()
|
|
|
|
if err != nil {
|
|
|
|
panic("An error was not expected when opening a stub database connection")
|
|
|
|
}
|
|
|
|
model.DB, _ = gorm.Open("mysql", db)
|
|
|
|
defer db.Close()
|
|
|
|
m.Run()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInitFailed(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
mock.ExpectQuery("SELECT(.+)").WillReturnError(errors.New("error"))
|
|
|
|
Init()
|
|
|
|
a.NoError(mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInitSuccess(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "aria2_enabled", "type"}).AddRow(1, true, model.MasterNodeType))
|
|
|
|
Init()
|
|
|
|
a.NoError(mock.ExpectationsWereMet())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodePool_GetNodeByID(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
p := &NodePool{}
|
|
|
|
p.Init()
|
|
|
|
mockNode := &nodeMock{}
|
|
|
|
|
|
|
|
// inactive
|
|
|
|
{
|
|
|
|
p.inactive[1] = mockNode
|
|
|
|
a.Equal(mockNode, p.GetNodeByID(1))
|
|
|
|
}
|
|
|
|
|
|
|
|
// active
|
|
|
|
{
|
|
|
|
delete(p.inactive, 1)
|
|
|
|
p.active[1] = mockNode
|
|
|
|
a.Equal(mockNode, p.GetNodeByID(1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodePool_NodeStatusChange(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
p := &NodePool{}
|
|
|
|
n := &MasterNode{Model: &model.Node{}}
|
|
|
|
p.Init()
|
|
|
|
p.inactive[1] = n
|
|
|
|
|
|
|
|
p.nodeStatusChange(true, 1)
|
|
|
|
a.Len(p.inactive, 0)
|
|
|
|
a.Equal(n, p.active[1])
|
|
|
|
|
|
|
|
p.nodeStatusChange(false, 1)
|
|
|
|
a.Len(p.active, 0)
|
|
|
|
a.Equal(n, p.inactive[1])
|
|
|
|
|
|
|
|
p.nodeStatusChange(false, 1)
|
|
|
|
a.Len(p.active, 0)
|
|
|
|
a.Equal(n, p.inactive[1])
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodePool_Add(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
p := &NodePool{}
|
|
|
|
p.Init()
|
|
|
|
|
|
|
|
// new node
|
|
|
|
{
|
|
|
|
p.Add(&model.Node{})
|
|
|
|
a.Len(p.active, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// old node
|
|
|
|
{
|
|
|
|
p.inactive[0] = p.active[0]
|
|
|
|
delete(p.active, 0)
|
|
|
|
p.Add(&model.Node{})
|
|
|
|
a.Len(p.active, 0)
|
|
|
|
a.Len(p.inactive, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodePool_Delete(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
p := &NodePool{}
|
|
|
|
p.Init()
|
|
|
|
|
|
|
|
// active
|
|
|
|
{
|
|
|
|
mockNode := &nodeMock{}
|
|
|
|
mockNode.On("Kill")
|
|
|
|
p.active[0] = mockNode
|
|
|
|
p.Delete(0)
|
|
|
|
a.Len(p.active, 0)
|
|
|
|
a.Len(p.inactive, 0)
|
|
|
|
mockNode.AssertExpectations(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
p.Init()
|
|
|
|
|
|
|
|
// inactive
|
|
|
|
{
|
|
|
|
mockNode := &nodeMock{}
|
|
|
|
mockNode.On("Kill")
|
|
|
|
p.inactive[0] = mockNode
|
|
|
|
p.Delete(0)
|
|
|
|
a.Len(p.active, 0)
|
|
|
|
a.Len(p.inactive, 0)
|
|
|
|
mockNode.AssertExpectations(t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodePool_BalanceNodeByFeature(t *testing.T) {
|
|
|
|
a := assert.New(t)
|
|
|
|
p := &NodePool{}
|
|
|
|
p.Init()
|
|
|
|
|
|
|
|
// success
|
|
|
|
{
|
|
|
|
p.featureMap["test"] = []Node{&MasterNode{}}
|
|
|
|
err, res := p.BalanceNodeByFeature("test", balancer.NewBalancer("round-robin"))
|
|
|
|
a.NoError(err)
|
|
|
|
a.Equal(p.featureMap["test"][0], res)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NoNodes
|
|
|
|
{
|
|
|
|
p.featureMap["test"] = []Node{}
|
|
|
|
err, res := p.BalanceNodeByFeature("test", balancer.NewBalancer("round-robin"))
|
|
|
|
a.Error(err)
|
|
|
|
a.Nil(res)
|
|
|
|
}
|
|
|
|
|
|
|
|
// No match feature
|
|
|
|
{
|
|
|
|
err, res := p.BalanceNodeByFeature("test2", balancer.NewBalancer("round-robin"))
|
|
|
|
a.Error(err)
|
|
|
|
a.Nil(res)
|
|
|
|
}
|
|
|
|
}
|