kubernetes utils_test 源码
kubernetes utils_test 代码
文件路径:/pkg/controller/endpointslice/topologycache/utils_test.go
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package topologycache
import (
"reflect"
"testing"
discovery "k8s.io/api/discovery/v1"
utilpointer "k8s.io/utils/pointer"
)
func Test_redistributeHints(t *testing.T) {
testCases := []struct {
name string
slices []*discovery.EndpointSlice
givingZones map[string]int
receivingZones map[string]int
expectedRedistributions map[string]int
}{{
name: "empty",
slices: []*discovery.EndpointSlice{},
givingZones: map[string]int{},
receivingZones: map[string]int{},
expectedRedistributions: map[string]int{},
}, {
name: "single endpoint",
slices: []*discovery.EndpointSlice{{
Endpoints: []discovery.Endpoint{{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
}},
}},
givingZones: map[string]int{"zone-a": 1},
receivingZones: map[string]int{"zone-b": 1},
expectedRedistributions: map[string]int{"zone-a": -1, "zone-b": 1},
}, {
name: "endpoints from 1 zone redistributed to 2 other zones",
slices: []*discovery.EndpointSlice{{
Endpoints: []discovery.Endpoint{{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
}, {
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
}, {
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
}},
}},
givingZones: map[string]int{"zone-a": 2},
receivingZones: map[string]int{"zone-b": 1, "zone-c": 1},
expectedRedistributions: map[string]int{"zone-a": -2, "zone-b": 1, "zone-c": 1},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actualRedistributions := redistributeHints(tc.slices, tc.givingZones, tc.receivingZones)
if len(actualRedistributions) != len(tc.expectedRedistributions) {
t.Fatalf("Expected redistributions for %d zones, got %d (%+v)", len(tc.expectedRedistributions), len(actualRedistributions), actualRedistributions)
}
for zone, expectedNum := range tc.expectedRedistributions {
actualNum, _ := actualRedistributions[zone]
if actualNum != expectedNum {
t.Errorf("Expected redistribution of %d for zone %s, got %d", expectedNum, zone, actualNum)
}
}
})
}
}
func Test_getGivingAndReceivingZones(t *testing.T) {
testCases := []struct {
name string
allocations map[string]Allocation
allocatedHintsByZone map[string]int
expectedGivingZones map[string]int
expectedReceivingZones map[string]int
}{{
name: "empty",
allocations: map[string]Allocation{},
allocatedHintsByZone: map[string]int{},
expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{},
}, {
name: "simple allocation with no need for rebalancing",
allocations: map[string]Allocation{
"zone-a": {Desired: 1.2},
"zone-b": {Desired: 1.1},
"zone-c": {Desired: 1.0},
},
allocatedHintsByZone: map[string]int{"zone-a": 1, "zone-b": 1, "zone-c": 1},
expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{},
}, {
name: "preference for same zone even when giving an extra endpoint would result in slightly better distribution",
allocations: map[string]Allocation{
"zone-a": {Desired: 5.1},
"zone-b": {Desired: 5.1},
"zone-c": {Desired: 5.8},
},
allocatedHintsByZone: map[string]int{"zone-a": 16},
expectedGivingZones: map[string]int{"zone-a": 10},
expectedReceivingZones: map[string]int{"zone-b": 5, "zone-c": 5},
}, {
name: "when 2 zones need < 1 endpoint, give to zone that needs endpoint most",
allocations: map[string]Allocation{
"zone-a": {Desired: 5.0},
"zone-b": {Desired: 5.6},
"zone-c": {Desired: 5.4},
},
allocatedHintsByZone: map[string]int{"zone-a": 16},
expectedGivingZones: map[string]int{"zone-a": 11},
expectedReceivingZones: map[string]int{"zone-b": 6, "zone-c": 5},
}, {
name: "when 2 zones have extra endpoints, give from zone with most extra",
allocations: map[string]Allocation{
"zone-a": {Desired: 5.0},
"zone-b": {Desired: 5.6},
"zone-c": {Desired: 5.4},
},
allocatedHintsByZone: map[string]int{"zone-b": 8, "zone-c": 8},
expectedGivingZones: map[string]int{"zone-b": 2, "zone-c": 3},
expectedReceivingZones: map[string]int{"zone-a": 5},
}, {
name: "ensure function can handle unexpected data (more allocated than allocations)",
allocations: map[string]Allocation{
"zone-a": {Desired: 5.0},
"zone-b": {Desired: 5.0},
"zone-c": {Desired: 5.0},
},
allocatedHintsByZone: map[string]int{"zone-a": 6, "zone-b": 6, "zone-c": 6},
expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{},
}, {
name: "ensure function can handle unexpected data (negative allocations)",
allocations: map[string]Allocation{
"zone-a": {Desired: -5.0},
"zone-b": {Desired: -5.0},
"zone-c": {Desired: -5.0},
},
allocatedHintsByZone: map[string]int{"zone-a": 6, "zone-b": 6, "zone-c": 6},
expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{},
}, {
name: "ensure function can handle unexpected data (negative allocated)",
allocations: map[string]Allocation{
"zone-a": {Desired: 5.0},
"zone-b": {Desired: 5.0},
"zone-c": {Desired: 5.0},
},
allocatedHintsByZone: map[string]int{"zone-a": -4, "zone-b": -3, "zone-c": -2},
expectedGivingZones: map[string]int{},
expectedReceivingZones: map[string]int{},
}, {
name: "ensure function can handle unexpected data (negative for 1 zone)",
allocations: map[string]Allocation{
"zone-a": {Desired: 5.0},
"zone-b": {Desired: 5.0},
"zone-c": {Desired: 5.0},
},
allocatedHintsByZone: map[string]int{"zone-a": -40, "zone-b": 20, "zone-c": 20},
expectedGivingZones: map[string]int{"zone-b": 15, "zone-c": 15},
expectedReceivingZones: map[string]int{"zone-a": 30},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actualGivingZones, actualReceivingZones := getGivingAndReceivingZones(tc.allocations, tc.allocatedHintsByZone)
if !reflect.DeepEqual(actualGivingZones, tc.expectedGivingZones) {
t.Errorf("Expected %+v giving zones, got %+v", tc.expectedGivingZones, actualGivingZones)
}
if !reflect.DeepEqual(actualReceivingZones, tc.expectedReceivingZones) {
t.Errorf("Expected %+v receiving zones, got %+v", tc.expectedReceivingZones, actualReceivingZones)
}
})
}
}
func Test_getHintsByZone(t *testing.T) {
testCases := []struct {
name string
slice discovery.EndpointSlice
allocatedHintsByZone EndpointZoneInfo
allocations map[string]Allocation
expectedHintsByZone map[string]int
}{{
name: "empty",
slice: discovery.EndpointSlice{},
allocations: map[string]Allocation{},
allocatedHintsByZone: EndpointZoneInfo{},
expectedHintsByZone: map[string]int{},
}, {
name: "single zone hint",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
}},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 3},
},
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
expectedHintsByZone: map[string]int{
"zone-a": 1,
},
}, {
name: "single zone hint with 1 unready endpoint and 1 unknown endpoint",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
}, {
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
}, {
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
}},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 3},
},
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
expectedHintsByZone: map[string]int{
"zone-a": 1,
},
}, {
name: "multiple zone hints",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
{
Zone: utilpointer.StringPtr("zone-b"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 3},
"zone-b": {Maximum: 3},
"zone-c": {Maximum: 3},
},
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1, "zone-b": 1, "zone-c": 1},
expectedHintsByZone: map[string]int{
"zone-a": 1,
"zone-b": 2,
},
}, {
name: "invalid by zones that no longer requires any allocations",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-non-existent"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 3},
},
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1, "zone-b": 1, "zone-c": 1},
expectedHintsByZone: nil,
}, {
name: "invalid by endpoints with nil hints",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: nil,
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 3},
},
allocatedHintsByZone: EndpointZoneInfo{},
expectedHintsByZone: nil,
}, {
name: "invalid by endpoint with no hints",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 3},
},
allocatedHintsByZone: EndpointZoneInfo{},
expectedHintsByZone: nil,
}, {
name: "invalid by hints that would make minimum allocations impossible",
slice: discovery.EndpointSlice{
Endpoints: []discovery.Endpoint{
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
{
Zone: utilpointer.StringPtr("zone-a"),
Hints: &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
},
},
},
allocations: map[string]Allocation{
"zone-a": {Maximum: 2},
},
allocatedHintsByZone: EndpointZoneInfo{"zone-a": 1},
expectedHintsByZone: nil,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
actualHintsByZone := getHintsByZone(&tc.slice, tc.allocatedHintsByZone, tc.allocations)
if !reflect.DeepEqual(actualHintsByZone, tc.expectedHintsByZone) {
// %#v for distinguishing between nil and empty map
t.Errorf("Expected %#v hints by zones, got %#v", tc.expectedHintsByZone, actualHintsByZone)
}
})
}
}
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦