mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2026-04-23 00:17:25 +08:00
0a92e96f20
* [Feature] add golang router * [Feature] add golang router * [Feature] add golang router * [Feature] add golang router * [Feature] add golang router * [Feature] Add Golang-based Router for Request Scheduling and Load Balancing * [Feature] Add Golang-based Router for Request Scheduling and Load Balancing * [Feature] Add Golang-based Router for Request Scheduling and Load Balancing * [Feature] Add Golang-based Router for Request Scheduling and Load Balancing --------- Co-authored-by: mouxin <mouxin@baidu.com>
305 lines
7.8 KiB
Go
305 lines
7.8 KiB
Go
package manager
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/PaddlePaddle/FastDeploy/router/internal/config"
|
|
"github.com/stretchr/testify/assert"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func TestInstanceRole_String(t *testing.T) {
|
|
assert.Equal(t, "mixed", MIXED.String())
|
|
assert.Equal(t, "prefill", PREFILL.String())
|
|
assert.Equal(t, "decode", DECODE.String())
|
|
}
|
|
|
|
func TestParseInstanceRole(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected InstanceRole
|
|
expectErr bool
|
|
}{
|
|
{"mixed lowercase", "mixed", MIXED, false},
|
|
{"mixed uppercase", "MIXED", MIXED, false},
|
|
{"prefill lowercase", "prefill", PREFILL, false},
|
|
{"prefill uppercase", "PREFILL", PREFILL, false},
|
|
{"decode lowercase", "decode", DECODE, false},
|
|
{"decode uppercase", "DECODE", DECODE, false},
|
|
{"invalid role", "invalid", -1, true},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result, err := ParseInstanceRole(tt.input)
|
|
if tt.expectErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRole_UnmarshalJSON(t *testing.T) {
|
|
t.Run("valid role from integer", func(t *testing.T) {
|
|
var role Role
|
|
err := json.Unmarshal([]byte("0"), &role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, MIXED, role.EnumValue)
|
|
assert.False(t, role.IsCustom)
|
|
})
|
|
|
|
t.Run("valid role from string", func(t *testing.T) {
|
|
var role Role
|
|
err := json.Unmarshal([]byte(`"prefill"`), &role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, PREFILL, role.EnumValue)
|
|
assert.False(t, role.IsCustom)
|
|
})
|
|
|
|
t.Run("custom role", func(t *testing.T) {
|
|
var role Role
|
|
err := json.Unmarshal([]byte(`"custom-role"`), &role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "custom-role", role.CustomName)
|
|
assert.True(t, role.IsCustom)
|
|
})
|
|
|
|
t.Run("invalid integer", func(t *testing.T) {
|
|
var role Role
|
|
err := json.Unmarshal([]byte("99"), &role)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestRole_UnmarshalYAML(t *testing.T) {
|
|
t.Run("valid role from integer", func(t *testing.T) {
|
|
var role Role
|
|
err := yaml.Unmarshal([]byte("1"), &role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, PREFILL, role.EnumValue)
|
|
assert.False(t, role.IsCustom)
|
|
})
|
|
|
|
t.Run("valid role from string", func(t *testing.T) {
|
|
var role Role
|
|
err := yaml.Unmarshal([]byte("decode"), &role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, DECODE, role.EnumValue)
|
|
assert.False(t, role.IsCustom)
|
|
})
|
|
}
|
|
|
|
func TestRole_MarshalJSON(t *testing.T) {
|
|
t.Run("standard role", func(t *testing.T) {
|
|
role := Role{EnumValue: MIXED, IsCustom: false}
|
|
data, err := json.Marshal(role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, `"mixed"`, string(data))
|
|
})
|
|
|
|
t.Run("custom role", func(t *testing.T) {
|
|
role := Role{CustomName: "custom", IsCustom: true}
|
|
data, err := json.Marshal(role)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, `"custom"`, string(data))
|
|
})
|
|
}
|
|
|
|
func TestPort_UnmarshalJSON(t *testing.T) {
|
|
t.Run("port as integer", func(t *testing.T) {
|
|
var port Port
|
|
err := json.Unmarshal([]byte("8080"), &port)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, Port("8080"), port)
|
|
})
|
|
|
|
t.Run("port as string", func(t *testing.T) {
|
|
var port Port
|
|
err := json.Unmarshal([]byte(`"9090"`), &port)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, Port("9090"), port)
|
|
})
|
|
}
|
|
|
|
func TestPort_UnmarshalYAML(t *testing.T) {
|
|
t.Run("port as integer", func(t *testing.T) {
|
|
var port Port
|
|
err := yaml.Unmarshal([]byte("8080"), &port)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, Port("8080"), port)
|
|
})
|
|
}
|
|
|
|
func TestIntToStringList_UnmarshalJSON(t *testing.T) {
|
|
t.Run("mixed types", func(t *testing.T) {
|
|
var list IntToStringList
|
|
err := json.Unmarshal([]byte(`["1", 2, 3.0]`), &list)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, IntToStringList{"1", "2", "3"}, list)
|
|
})
|
|
|
|
t.Run("invalid float", func(t *testing.T) {
|
|
var list IntToStringList
|
|
err := json.Unmarshal([]byte(`[1.5]`), &list)
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("invalid type", func(t *testing.T) {
|
|
var list IntToStringList
|
|
err := json.Unmarshal([]byte(`[true]`), &list)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestInstanceInfo_URL(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
}
|
|
|
|
url := info.URL()
|
|
assert.Equal(t, "http://127.0.0.1:8080", url)
|
|
}
|
|
|
|
func TestNewInstanceInfo(t *testing.T) {
|
|
// Setup DefaultManager
|
|
Init(&config.Config{Server: config.ServerConfig{Splitwise: true}})
|
|
|
|
t.Run("valid instance", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: PREFILL, IsSet: true},
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
ConnectorPort: Port("9000"),
|
|
TransferProtocol: []string{"rdma"},
|
|
RDMAPorts: IntToStringList{"5000", "5001"},
|
|
DeviceIDs: IntToStringList{"0", "1"},
|
|
}
|
|
|
|
result, err := NewInstanceInfo(info)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
})
|
|
|
|
t.Run("missing role", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "role is required")
|
|
})
|
|
|
|
t.Run("custom role", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{CustomName: "custom", IsCustom: true, IsSet: true},
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid role")
|
|
})
|
|
|
|
t.Run("missing host_ip", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: MIXED, IsSet: true},
|
|
Port: Port("8080"),
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "host_ip is required")
|
|
})
|
|
|
|
t.Run("invalid host_ip", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: MIXED, IsSet: true},
|
|
HostIP: "invalid-ip",
|
|
Port: Port("8080"),
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid host_ip")
|
|
})
|
|
|
|
t.Run("invalid port", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: MIXED, IsSet: true},
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("99999"),
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid port")
|
|
})
|
|
|
|
t.Run("invalid connector_port", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: PREFILL, IsSet: true},
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
ConnectorPort: Port("99999"),
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid connector_port")
|
|
})
|
|
|
|
t.Run("invalid transfer protocol", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: PREFILL, IsSet: true},
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
TransferProtocol: []string{"invalid"},
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid protocol")
|
|
})
|
|
|
|
t.Run("invalid rdma port", func(t *testing.T) {
|
|
info := &InstanceInfo{
|
|
Role: Role{EnumValue: PREFILL, IsSet: true},
|
|
HostIP: "127.0.0.1",
|
|
Port: Port("8080"),
|
|
TransferProtocol: []string{"rdma"},
|
|
RDMAPorts: IntToStringList{"99999"},
|
|
}
|
|
|
|
_, err := NewInstanceInfo(info)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "rdma_ports[0] invalid port")
|
|
})
|
|
}
|
|
|
|
func TestIsValidPort(t *testing.T) {
|
|
assert.True(t, isValidPort(Port("8080")))
|
|
assert.True(t, isValidPort(Port("1")))
|
|
assert.True(t, isValidPort(Port("65535")))
|
|
assert.False(t, isValidPort(Port("0")))
|
|
assert.False(t, isValidPort(Port("65536")))
|
|
assert.False(t, isValidPort(Port("invalid")))
|
|
assert.False(t, isValidPort(Port("")))
|
|
}
|
|
|
|
func TestIsValidIP(t *testing.T) {
|
|
assert.True(t, isValidIP("127.0.0.1"))
|
|
assert.True(t, isValidIP("192.168.1.1"))
|
|
assert.True(t, isValidIP("::1"))
|
|
assert.False(t, isValidIP("invalid"))
|
|
assert.False(t, isValidIP(""))
|
|
}
|