parent
f0089045d7
commit
416f4c1dd2
@ -1,52 +0,0 @@
|
|||||||
package aria2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/cache"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRPCService_Init(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
caller := &RPCService{}
|
|
||||||
asserts.Error(caller.Init("ws://", "", 1, nil))
|
|
||||||
asserts.NoError(caller.Init("http://127.0.0.1", "", 1, nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRPCService_Status(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
caller := &RPCService{}
|
|
||||||
asserts.NoError(caller.Init("http://127.0.0.1", "", 1, nil))
|
|
||||||
|
|
||||||
_, err := caller.Status(&model.Download{})
|
|
||||||
asserts.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRPCService_Cancel(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
caller := &RPCService{}
|
|
||||||
asserts.NoError(caller.Init("http://127.0.0.1", "", 1, nil))
|
|
||||||
|
|
||||||
err := caller.Cancel(&model.Download{Parent: "test"})
|
|
||||||
asserts.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRPCService_Select(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
caller := &RPCService{}
|
|
||||||
asserts.NoError(caller.Init("http://127.0.0.1", "", 1, nil))
|
|
||||||
|
|
||||||
err := caller.Select(&model.Download{Parent: "test"}, []int{1, 2, 3})
|
|
||||||
asserts.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRPCService_CreateTask(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
caller := &RPCService{}
|
|
||||||
asserts.NoError(caller.Init("http://127.0.0.1", "", 1, nil))
|
|
||||||
cache.Set("setting_aria2_temp_path", "test", 0)
|
|
||||||
err := caller.CreateTask(&model.Download{Parent: "test"}, map[string]interface{}{"1": "1"})
|
|
||||||
asserts.Error(err)
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package aria2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/cloudreve/Cloudreve/v3/pkg/aria2/rpc"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNotifier_Notify(t *testing.T) {
|
|
||||||
asserts := assert.New(t)
|
|
||||||
notifier2 := &Notifier{}
|
|
||||||
notifyChan := make(chan StatusEvent, 10)
|
|
||||||
notifier2.Subscribe(notifyChan, "1")
|
|
||||||
|
|
||||||
// 未订阅
|
|
||||||
{
|
|
||||||
notifier2.Notify([]rpc.Event{rpc.Event{Gid: ""}}, 1)
|
|
||||||
asserts.Len(notifyChan, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 订阅
|
|
||||||
{
|
|
||||||
notifier2.Notify([]rpc.Event{{Gid: "1"}}, 1)
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
|
|
||||||
notifier2.OnBtDownloadComplete([]rpc.Event{{Gid: "1"}})
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
|
|
||||||
notifier2.OnDownloadStart([]rpc.Event{{Gid: "1"}})
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
|
|
||||||
notifier2.OnDownloadPause([]rpc.Event{{Gid: "1"}})
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
|
|
||||||
notifier2.OnDownloadStop([]rpc.Event{{Gid: "1"}})
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
|
|
||||||
notifier2.OnDownloadComplete([]rpc.Event{{Gid: "1"}})
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
|
|
||||||
notifier2.OnDownloadError([]rpc.Event{{Gid: "1"}})
|
|
||||||
asserts.Len(notifyChan, 1)
|
|
||||||
<-notifyChan
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package balancer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewBalancer(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
a.NotNil(NewBalancer(""))
|
||||||
|
a.IsType(&RoundRobin{}, NewBalancer("RoundRobin"))
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package balancer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRoundRobin_NextIndex(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
r := &RoundRobin{}
|
||||||
|
total := 5
|
||||||
|
for i := 1; i < total; i++ {
|
||||||
|
a.Equal(i, r.NextIndex(total))
|
||||||
|
}
|
||||||
|
for i := 0; i < total; i++ {
|
||||||
|
a.Equal(i, r.NextIndex(total))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRoundRobin_NextPeer(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
r := &RoundRobin{}
|
||||||
|
|
||||||
|
// not slice
|
||||||
|
{
|
||||||
|
err, _ := r.NextPeer("s")
|
||||||
|
a.Equal(ErrInputNotSlice, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// no nodes
|
||||||
|
{
|
||||||
|
err, _ := r.NextPeer([]string{})
|
||||||
|
a.Equal(ErrNoAvaliableNode, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass
|
||||||
|
{
|
||||||
|
err, res := r.NextPeer([]string{"a"})
|
||||||
|
a.NoError(err)
|
||||||
|
a.Equal("a", res.(string))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,254 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/aria2/common"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/auth"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/mq"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/request"
|
||||||
|
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
testMock "github.com/stretchr/testify/mock"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInitController(t *testing.T) {
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
InitController()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlaveController_HandleHeartBeat(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
c := &slaveController{
|
||||||
|
masters: make(map[string]MasterInfo),
|
||||||
|
}
|
||||||
|
|
||||||
|
// first heart beat
|
||||||
|
{
|
||||||
|
_, err := c.HandleHeartBeat(&serializer.NodePingReq{
|
||||||
|
SiteID: "1",
|
||||||
|
Node: &model.Node{},
|
||||||
|
})
|
||||||
|
a.NoError(err)
|
||||||
|
|
||||||
|
_, err = c.HandleHeartBeat(&serializer.NodePingReq{
|
||||||
|
SiteID: "2",
|
||||||
|
Node: &model.Node{},
|
||||||
|
})
|
||||||
|
a.NoError(err)
|
||||||
|
|
||||||
|
a.Len(c.masters, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second heart beat, no fresh
|
||||||
|
{
|
||||||
|
_, err := c.HandleHeartBeat(&serializer.NodePingReq{
|
||||||
|
SiteID: "1",
|
||||||
|
SiteURL: "http://127.0.0.1",
|
||||||
|
Node: &model.Node{},
|
||||||
|
})
|
||||||
|
a.NoError(err)
|
||||||
|
a.Len(c.masters, 2)
|
||||||
|
a.Empty(c.masters["1"].URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second heart beat, fresh
|
||||||
|
{
|
||||||
|
_, err := c.HandleHeartBeat(&serializer.NodePingReq{
|
||||||
|
SiteID: "1",
|
||||||
|
IsUpdate: true,
|
||||||
|
SiteURL: "http://127.0.0.1",
|
||||||
|
Node: &model.Node{},
|
||||||
|
})
|
||||||
|
a.NoError(err)
|
||||||
|
a.Len(c.masters, 2)
|
||||||
|
a.Equal("http://127.0.0.1", c.masters["1"].URL.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// second heart beat, fresh, url illegal
|
||||||
|
{
|
||||||
|
_, err := c.HandleHeartBeat(&serializer.NodePingReq{
|
||||||
|
SiteID: "1",
|
||||||
|
IsUpdate: true,
|
||||||
|
SiteURL: string([]byte{0x7f}),
|
||||||
|
Node: &model.Node{},
|
||||||
|
})
|
||||||
|
a.Error(err)
|
||||||
|
a.Len(c.masters, 2)
|
||||||
|
a.Equal("http://127.0.0.1", c.masters["1"].URL.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeMock struct {
|
||||||
|
testMock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) Init(node *model.Node) {
|
||||||
|
n.Called(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) IsFeatureEnabled(feature string) bool {
|
||||||
|
args := n.Called(feature)
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) SubscribeStatusChange(callback func(isActive bool, id uint)) {
|
||||||
|
n.Called(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) Ping(req *serializer.NodePingReq) (*serializer.NodePingResp, error) {
|
||||||
|
args := n.Called(req)
|
||||||
|
return args.Get(0).(*serializer.NodePingResp), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) IsActive() bool {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) GetAria2Instance() common.Aria2 {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Get(0).(common.Aria2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) ID() uint {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Get(0).(uint)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) Kill() {
|
||||||
|
n.Called()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) IsMater() bool {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) MasterAuthInstance() auth.Auth {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Get(0).(auth.Auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) SlaveAuthInstance() auth.Auth {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Get(0).(auth.Auth)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nodeMock) DBModel() *model.Node {
|
||||||
|
args := n.Called()
|
||||||
|
return args.Get(0).(*model.Node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlaveController_GetAria2Instance(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
mockNode := &nodeMock{}
|
||||||
|
mockNode.On("GetAria2Instance").Return(&common.DummyAria2{})
|
||||||
|
c := &slaveController{
|
||||||
|
masters: map[string]MasterInfo{
|
||||||
|
"1": {Instance: mockNode},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// node node found
|
||||||
|
{
|
||||||
|
res, err := c.GetAria2Instance("2")
|
||||||
|
a.Nil(res)
|
||||||
|
a.Equal(ErrMasterNotFound, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// node found
|
||||||
|
{
|
||||||
|
res, err := c.GetAria2Instance("1")
|
||||||
|
a.NotNil(res)
|
||||||
|
a.NoError(err)
|
||||||
|
mockNode.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type requestMock struct {
|
||||||
|
testMock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r requestMock) Request(method, target string, body io.Reader, opts ...request.Option) *request.Response {
|
||||||
|
return r.Called(method, target, body, opts).Get(0).(*request.Response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlaveController_SendNotification(t *testing.T) {
|
||||||
|
a := assert.New(t)
|
||||||
|
c := &slaveController{
|
||||||
|
masters: map[string]MasterInfo{
|
||||||
|
"1": {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// node not exit
|
||||||
|
{
|
||||||
|
a.Equal(ErrMasterNotFound, c.SendNotification("2", "", mq.Message{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// gob encode error
|
||||||
|
{
|
||||||
|
type randomType struct{}
|
||||||
|
a.Error(c.SendNotification("1", "", mq.Message{
|
||||||
|
Content: randomType{},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// return none 200
|
||||||
|
{
|
||||||
|
mockRequest := &requestMock{}
|
||||||
|
mockRequest.On("Request", "PUT", "/api/v3/slave/notification/s1", testMock.Anything, testMock.Anything).Return(&request.Response{
|
||||||
|
Response: &http.Response{StatusCode: http.StatusConflict},
|
||||||
|
})
|
||||||
|
c := &slaveController{
|
||||||
|
masters: map[string]MasterInfo{
|
||||||
|
"1": {Client: mockRequest},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
a.Error(c.SendNotification("1", "s1", mq.Message{}))
|
||||||
|
mockRequest.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// master return error
|
||||||
|
{
|
||||||
|
mockRequest := &requestMock{}
|
||||||
|
mockRequest.On("Request", "PUT", "/api/v3/slave/notification/s2", testMock.Anything, testMock.Anything).Return(&request.Response{
|
||||||
|
Response: &http.Response{
|
||||||
|
StatusCode: 200,
|
||||||
|
Body: ioutil.NopCloser(strings.NewReader("{\"code\":1}")),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
c := &slaveController{
|
||||||
|
masters: map[string]MasterInfo{
|
||||||
|
"1": {Client: mockRequest},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
a.Equal(1, c.SendNotification("1", "s2", mq.Message{}).(serializer.AppError).Code)
|
||||||
|
mockRequest.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// success
|
||||||
|
{
|
||||||
|
mockRequest := &requestMock{}
|
||||||
|
mockRequest.On("Request", "PUT", "/api/v3/slave/notification/s3", testMock.Anything, testMock.Anything).Return(&request.Response{
|
||||||
|
Response: &http.Response{
|
||||||
|
StatusCode: 200,
|
||||||
|
Body: ioutil.NopCloser(strings.NewReader("{\"code\":0}")),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
c := &slaveController{
|
||||||
|
masters: map[string]MasterInfo{
|
||||||
|
"1": {Client: mockRequest},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
a.NoError(c.SendNotification("1", "s3", mq.Message{}))
|
||||||
|
mockRequest.AssertExpectations(t)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue