forked from JointCloud/pcm-coordinator
252 lines
6.1 KiB
Go
252 lines
6.1 KiB
Go
package test
|
||
|
||
import (
|
||
"fmt"
|
||
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/entity"
|
||
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/service/collector"
|
||
"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/strategy"
|
||
"math/rand"
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
func TestReplication(t *testing.T) {
|
||
parts := []entity.Participant{
|
||
{Name: "test1", Participant_id: 1},
|
||
{Name: "test2", Participant_id: 2},
|
||
{Name: "test3", Participant_id: 3},
|
||
}
|
||
rsc := []*collector.ResourceStats{
|
||
{
|
||
ClusterId: "1",
|
||
Name: "test1",
|
||
},
|
||
{
|
||
ClusterId: "2",
|
||
Name: "test2"},
|
||
{
|
||
ClusterId: "3",
|
||
Name: "test3"},
|
||
}
|
||
tests := []struct {
|
||
name string
|
||
replica int32
|
||
ps []entity.Participant
|
||
res []*collector.ResourceStats
|
||
}{
|
||
{
|
||
name: "test1",
|
||
replica: 1,
|
||
ps: parts,
|
||
},
|
||
{
|
||
name: "test2",
|
||
replica: 2,
|
||
ps: parts,
|
||
},
|
||
}
|
||
|
||
for _, tt := range tests {
|
||
t.Run(tt.name, func(t *testing.T) {
|
||
var clusterIds []string
|
||
for _, stats := range rsc {
|
||
clusterIds = append(clusterIds, stats.ClusterId)
|
||
}
|
||
repl := strategy.NewReplicationStrategy(clusterIds, 0)
|
||
schedule, err := repl.Schedule()
|
||
if err != nil {
|
||
return
|
||
}
|
||
for _, cluster := range schedule {
|
||
fmt.Println(cluster)
|
||
}
|
||
|
||
})
|
||
}
|
||
|
||
}
|
||
|
||
func TestStaticWeight(t *testing.T) {
|
||
parts := map[string]int32{
|
||
"test1": 6,
|
||
"test2": 5,
|
||
"test3": 2,
|
||
}
|
||
tests := []struct {
|
||
name string
|
||
replica int32
|
||
ps map[string]int32
|
||
}{
|
||
{
|
||
name: "test1",
|
||
replica: 1,
|
||
ps: parts,
|
||
},
|
||
{
|
||
name: "test2",
|
||
replica: 5,
|
||
ps: parts,
|
||
},
|
||
{
|
||
name: "test2",
|
||
replica: 6,
|
||
ps: parts,
|
||
},
|
||
}
|
||
|
||
for _, tt := range tests {
|
||
t.Run(tt.name, func(t *testing.T) {
|
||
repl := strategy.NewStaticWeightStrategy(tt.ps, tt.replica)
|
||
schedule, err := repl.Schedule()
|
||
if err != nil {
|
||
return
|
||
}
|
||
for _, cluster := range schedule {
|
||
fmt.Println(cluster)
|
||
}
|
||
|
||
})
|
||
}
|
||
}
|
||
|
||
func TestRandom(t *testing.T) {
|
||
// 使用当前时间作为随机数种子,确保每次程序运行产生的随机数序列都不同
|
||
rand.Seed(time.Now().UnixNano())
|
||
|
||
/*randomNum := randInt(1, 100)
|
||
fmt.Println("Random number:", randomNum)*/
|
||
total := 5 // 假设总数是5
|
||
first, second := splitIntoTwoRandomParts(total)
|
||
fmt.Printf("第一部分的数量: %d, 第二部分的数量: %d\n", first, second)
|
||
}
|
||
|
||
// randInt 生成一个指定范围内的随机整数,包括min但不包括max
|
||
func randInt(min, max int) int {
|
||
return min + rand.Intn(max-min)
|
||
}
|
||
|
||
func splitIntoTwoRandomParts(total int) (int, int) {
|
||
if total < 2 {
|
||
// 如果总数小于2,则无法分成两部分
|
||
return 0, 0
|
||
}
|
||
// 生成一个随机数作为第一部分的数量(范围在[1, total-1]之间)
|
||
firstPart := rand.Intn(total-1) + 1
|
||
// 第二部分的数量就是总数减去第一部分的数量
|
||
secondPart := total - firstPart
|
||
return firstPart, secondPart
|
||
}
|
||
|
||
func splitIntoRandomParts(total int) (int, int) {
|
||
if total < 2 {
|
||
// 如果总数小于2,则无法分成两部分
|
||
return 0, 0
|
||
}
|
||
// 生成一个随机数作为第一部分的数量(范围在[1, total-1]之间)
|
||
firstPart := rand.Intn(total-1) + 1
|
||
// 第二部分的数量就是总数减去第一部分的数量
|
||
secondPart := total - firstPart
|
||
return firstPart, secondPart
|
||
}
|
||
|
||
func TestRandoms(t *testing.T) {
|
||
// 使用当前时间作为随机数种子,确保每次程序运行产生的随机数序列都不同
|
||
rand.Seed(time.Now().UnixNano())
|
||
|
||
/*randomNum := randInt(1, 100)
|
||
fmt.Println("Random number:", randomNum)*/
|
||
total := 10 // 假设总数是5
|
||
parts := splitRandomParts(total)
|
||
fmt.Println("分配结果:", parts)
|
||
}
|
||
|
||
// splitIntoRandomParts 将总数total随机分成多个部分,并返回这些部分的切片
|
||
func splitRandomParts(total int) []int {
|
||
if total < 2 {
|
||
// 如果总数小于2,则无法分成多个部分
|
||
return []int{total}
|
||
}
|
||
|
||
// 创建一个切片来保存每个部分的数量
|
||
var parts []int
|
||
|
||
// 剩余要分配的副本数
|
||
remaining := total
|
||
|
||
// 随机决定要分成的部分数量(至少2个部分)
|
||
numParts := rand.Intn(total-1) + 2
|
||
|
||
// 确保每个部分至少获得1个副本
|
||
for i := 0; i < numParts-1; i++ {
|
||
// 生成一个随机数(1到剩余副本数之间)
|
||
// 为了避免最后一个部分太小,我们可能需要调整随机数范围
|
||
minPartSize := 1
|
||
if remaining <= numParts-i {
|
||
// 如果剩余副本数不足以让每个部分都至少获得1个,则调整最小部分大小
|
||
minPartSize = remaining / (numParts - i)
|
||
if remaining%(numParts-i) > 0 {
|
||
minPartSize++
|
||
}
|
||
}
|
||
// 生成一个大于等于minPartSize且小于等于remaining的随机数
|
||
partSize := minPartSize + rand.Intn(remaining-minPartSize+1)
|
||
parts = append(parts, partSize)
|
||
remaining -= partSize
|
||
}
|
||
|
||
// 最后一个部分的数量就是剩余的副本数
|
||
parts = append(parts, remaining)
|
||
|
||
return parts
|
||
}
|
||
|
||
func TestNumRandom(t *testing.T) {
|
||
total := 10 // 假设副本数是10
|
||
numParts := 2 // 假设要分成5个集群
|
||
|
||
parts, err := splitIntoParts(total, numParts)
|
||
if err != nil {
|
||
fmt.Println("Error:", err)
|
||
return
|
||
}
|
||
fmt.Println("分配结果:", parts)
|
||
}
|
||
|
||
// splitIntoParts 将总数total随机分成numParts个部分,并返回这些部分的切片
|
||
func splitIntoParts(total int, numParts int) ([]int, error) {
|
||
if total < 1 || numParts < 1 {
|
||
// 总数或部分数量不能小于1
|
||
return nil, fmt.Errorf("total and numParts must be greater than 0")
|
||
}
|
||
if numParts > total {
|
||
// 部分数量不能大于总数
|
||
return nil, fmt.Errorf("numParts cannot be greater than total")
|
||
}
|
||
|
||
// 创建一个切片来保存每个部分的数量
|
||
parts := make([]int, numParts)
|
||
|
||
// 首先将每个部分都分配至少一个副本
|
||
for i := range parts {
|
||
parts[i] = 1
|
||
total--
|
||
}
|
||
|
||
// 剩余要分配的副本数
|
||
remaining := total
|
||
|
||
// 随机分配剩余的副本
|
||
for remaining > 0 {
|
||
// 随机选择一个部分(索引从0到numParts-1)
|
||
partIndex := rand.Intn(numParts)
|
||
|
||
// 如果该部分加上一个副本后不会超过总数,则分配一个副本
|
||
if parts[partIndex]+1 <= total {
|
||
parts[partIndex]++
|
||
remaining--
|
||
}
|
||
}
|
||
|
||
return parts, nil
|
||
}
|