kubernetes topologycache_test 源码

  • 2022-09-18
  • 浏览 (25)

kubernetes topologycache_test 代码

文件路径:/pkg/controller/endpointslice/topologycache/topologycache_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"

	v1 "k8s.io/api/core/v1"
	discovery "k8s.io/api/discovery/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	utilpointer "k8s.io/utils/pointer"
)

func TestAddHints(t *testing.T) {
	testCases := []struct {
		name                        string
		cpuRatiosByZone             map[string]float64
		sliceInfo                   *SliceInfo
		expectedEndpointsByAddrType map[discovery.AddressType]EndpointZoneInfo
		expectedSlicesToCreate      []*discovery.EndpointSlice
		expectedSlicesToUpdate      []*discovery.EndpointSlice
	}{{
		name:            "empty",
		cpuRatiosByZone: nil,
		sliceInfo: &SliceInfo{
			ServiceKey:  "ns/svc",
			AddressType: discovery.AddressTypeIPv4,
		},
		expectedEndpointsByAddrType: nil,
		expectedSlicesToCreate:      []*discovery.EndpointSlice{},
		expectedSlicesToUpdate:      []*discovery.EndpointSlice{},
	}, {
		name:            "slice to create, no zone ratios",
		cpuRatiosByZone: nil,
		sliceInfo: &SliceInfo{
			ServiceKey:  "ns/svc",
			AddressType: discovery.AddressTypeIPv4,
			ToCreate: []*discovery.EndpointSlice{{
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.1.2.3"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}},
		},
		expectedEndpointsByAddrType: nil,
		expectedSlicesToCreate: []*discovery.EndpointSlice{{
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.1.2.3"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}},
		expectedSlicesToUpdate: []*discovery.EndpointSlice{},
	}, {
		name: "slice to create with 2 endpoints, zone ratios require 3",
		cpuRatiosByZone: map[string]float64{
			"zone-a": 0.3,
			"zone-b": 0.4,
			"zone-c": 0.3,
		},
		sliceInfo: &SliceInfo{
			ServiceKey:  "ns/svc",
			AddressType: discovery.AddressTypeIPv4,
			ToCreate: []*discovery.EndpointSlice{{
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.1.2.3"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.2.4"},
					Zone:       utilpointer.StringPtr("zone-b"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}},
		},
		expectedEndpointsByAddrType: nil,
		expectedSlicesToCreate: []*discovery.EndpointSlice{{
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.1.2.3"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.2.4"},
				Zone:       utilpointer.StringPtr("zone-b"),
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}},
		expectedSlicesToUpdate: []*discovery.EndpointSlice{},
	}, {
		name: "slice to create with 2 endpoints, zone ratios only require 2",
		cpuRatiosByZone: map[string]float64{
			"zone-a": 0.45,
			"zone-b": 0.55,
		},
		sliceInfo: &SliceInfo{
			ServiceKey:  "ns/svc",
			AddressType: discovery.AddressTypeIPv4,
			ToCreate: []*discovery.EndpointSlice{{
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.1.2.3"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.2.4"},
					Zone:       utilpointer.StringPtr("zone-b"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}},
		},
		expectedEndpointsByAddrType: map[discovery.AddressType]EndpointZoneInfo{
			discovery.AddressTypeIPv4: {
				"zone-a": 1,
				"zone-b": 1,
			},
		},
		expectedSlicesToCreate: []*discovery.EndpointSlice{{
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.1.2.3"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.2.4"},
				Zone:       utilpointer.StringPtr("zone-b"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}},
		expectedSlicesToUpdate: []*discovery.EndpointSlice{},
	}, {
		name: "slice to create with 2 ready, 1 unready, 1 unknown endpoints, zone ratios only require 2",
		cpuRatiosByZone: map[string]float64{
			"zone-a": 0.45,
			"zone-b": 0.55,
		},
		sliceInfo: &SliceInfo{
			ServiceKey:  "ns/svc",
			AddressType: discovery.AddressTypeIPv4,
			ToCreate: []*discovery.EndpointSlice{{
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.1.2.3"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.2.4"},
					Zone:       utilpointer.StringPtr("zone-b"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.2.5"},
					Zone:       utilpointer.StringPtr("zone-b"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
				}, {
					Addresses: []string{"10.1.2.6"},
					Zone:      utilpointer.StringPtr("zone-b"),
				}},
			}},
		},
		expectedEndpointsByAddrType: map[discovery.AddressType]EndpointZoneInfo{
			discovery.AddressTypeIPv4: {
				"zone-a": 1,
				"zone-b": 1,
			},
		},
		expectedSlicesToCreate: []*discovery.EndpointSlice{{
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.1.2.3"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.2.4"},
				Zone:       utilpointer.StringPtr("zone-b"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.2.5"},
				Zone:       utilpointer.StringPtr("zone-b"),
				Hints:      nil,
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(false)},
			}, {
				Addresses: []string{"10.1.2.6"},
				Zone:      utilpointer.StringPtr("zone-b"),
				Hints:     nil,
			}},
		}},
		expectedSlicesToUpdate: []*discovery.EndpointSlice{},
	}, {
		name: "slices to create and update within 3 zone threshold",
		cpuRatiosByZone: map[string]float64{
			"zone-a": 0.35,
			"zone-b": 0.35,
			"zone-c": 0.30,
		},
		sliceInfo: &SliceInfo{
			ServiceKey:  "ns/svc",
			AddressType: discovery.AddressTypeIPv4,
			ToCreate: []*discovery.EndpointSlice{{
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.1.2.3"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.2.4"},
					Zone:       utilpointer.StringPtr("zone-b"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}, {
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.1.3.3"},
					Zone:       utilpointer.StringPtr("zone-c"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.3.4"},
					Zone:       utilpointer.StringPtr("zone-c"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.1.3.4"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}},
			ToUpdate: []*discovery.EndpointSlice{{
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.2.2.3"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.2.2.4"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}, {
				Endpoints: []discovery.Endpoint{{
					Addresses:  []string{"10.2.3.3"},
					Zone:       utilpointer.StringPtr("zone-b"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.2.3.4"},
					Zone:       utilpointer.StringPtr("zone-c"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}, {
					Addresses:  []string{"10.2.3.4"},
					Zone:       utilpointer.StringPtr("zone-a"),
					Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
				}},
			}},
		},
		expectedEndpointsByAddrType: map[discovery.AddressType]EndpointZoneInfo{
			discovery.AddressTypeIPv4: {
				"zone-a": 4,
				"zone-b": 3,
				"zone-c": 3,
			},
		},
		expectedSlicesToCreate: []*discovery.EndpointSlice{{
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.1.2.3"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.2.4"},
				Zone:       utilpointer.StringPtr("zone-b"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}, {
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.1.3.3"},
				Zone:       utilpointer.StringPtr("zone-c"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.3.4"},
				Zone:       utilpointer.StringPtr("zone-c"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.1.3.4"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}},
		expectedSlicesToUpdate: []*discovery.EndpointSlice{{
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.2.2.3"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.2.2.4"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}, {
			Endpoints: []discovery.Endpoint{{
				Addresses:  []string{"10.2.3.3"},
				Zone:       utilpointer.StringPtr("zone-b"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-b"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.2.3.4"},
				Zone:       utilpointer.StringPtr("zone-c"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-c"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}, {
				Addresses:  []string{"10.2.3.4"},
				Zone:       utilpointer.StringPtr("zone-a"),
				Hints:      &discovery.EndpointHints{ForZones: []discovery.ForZone{{Name: "zone-a"}}},
				Conditions: discovery.EndpointConditions{Ready: utilpointer.BoolPtr(true)},
			}},
		}},
	}}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			cache := NewTopologyCache()
			cache.cpuRatiosByZone = tc.cpuRatiosByZone

			slicesToCreate, slicesToUpdate := cache.AddHints(tc.sliceInfo)

			expectEquivalentSlices(t, slicesToCreate, tc.expectedSlicesToCreate)
			expectEquivalentSlices(t, slicesToUpdate, tc.expectedSlicesToUpdate)

			endpointsByAddrType, ok := cache.endpointsByService[tc.sliceInfo.ServiceKey]
			if tc.expectedEndpointsByAddrType == nil {
				if ok {
					t.Errorf("Expected no endpoints for Service %s, got %+v", tc.sliceInfo.ServiceKey, endpointsByAddrType)
				}
			} else {
				if len(tc.expectedEndpointsByAddrType) != len(endpointsByAddrType) {
					t.Fatalf("Expected endpoints for %d address types, got %d", len(tc.expectedEndpointsByAddrType), len(endpointsByAddrType))
				}
				for addrType, expectedEndpointZoneInfo := range tc.expectedEndpointsByAddrType {
					endpointZoneInfo, ok := endpointsByAddrType[addrType]
					if !ok {
						t.Fatalf("Expected endpoints for %s address type, got none", addrType)
					}

					if len(expectedEndpointZoneInfo) != len(endpointZoneInfo) {
						t.Fatalf("Expected endpoints for %d zones, got %d", len(expectedEndpointZoneInfo), len(endpointZoneInfo))
					}

					for zone, expectedNum := range expectedEndpointZoneInfo {
						num, ok := endpointZoneInfo[zone]
						if !ok {
							t.Fatalf("Expected endpoints for %s zone, got none", zone)
						}
						if num != expectedNum {
							t.Errorf("Expected %d endpoints for %s zone, got %d", expectedNum, zone, num)
						}
					}
				}
			}
		})
	}
}

func TestSetNodes(t *testing.T) {
	type nodeInfo struct {
		zone   string
		cpu    resource.Quantity
		ready  v1.ConditionStatus
		labels map[string]string
	}

	testCases := []struct {
		name                     string
		nodes                    []nodeInfo
		expectSufficientNodeInfo bool
		expectedCPUByZone        map[string]*resource.Quantity
		expectedRatios           map[string]float64
	}{{
		name:                     "empty",
		nodes:                    []nodeInfo{},
		expectSufficientNodeInfo: false,
		expectedCPUByZone:        nil,
		expectedRatios:           nil,
	}, {
		name: "single node",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
		},
		expectSufficientNodeInfo: false,
		expectedCPUByZone:        nil,
		expectedRatios:           nil,
	}, {
		name: "single zone",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
		},
		expectSufficientNodeInfo: false,
		expectedCPUByZone:        nil,
		expectedRatios:           nil,
	}, {
		name: "2 zones",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
		},
		expectSufficientNodeInfo: true,
		expectedCPUByZone: map[string]*resource.Quantity{
			"zone-a": resource.NewQuantity(1, resource.BinarySI),
			"zone-b": resource.NewQuantity(1, resource.BinarySI),
		},
		expectedRatios: map[string]float64{
			"zone-a": 0.5,
			"zone-b": 0.5,
		},
	}, {
		name: "2 zones, unready node in 1, ready node in 1",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionFalse},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
		},
		expectSufficientNodeInfo: false,
		expectedCPUByZone:        nil,
		expectedRatios:           nil,
	}, {
		name: "2 zones, control plane node in 1, ready node in 1",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue,
				labels: map[string]string{"node-role.kubernetes.io/control-plane": ""}},
		},
		expectSufficientNodeInfo: false,
		expectedCPUByZone:        nil,
		expectedRatios:           nil,
	}, {
		name: "2 zones, unready node in 1, ready node in 2",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionFalse},
		},
		expectSufficientNodeInfo: true,
		expectedCPUByZone: map[string]*resource.Quantity{
			"zone-a": resource.NewQuantity(1, resource.BinarySI),
			"zone-b": resource.NewQuantity(1, resource.BinarySI),
		},
		expectedRatios: map[string]float64{
			"zone-a": 0.5,
			"zone-b": 0.5,
		},
	}, {
		name: "2 zones, control plane node in 1, ready node in 2",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue,
				labels: map[string]string{"node-role.kubernetes.io/control-plane": ""}},
		},
		expectSufficientNodeInfo: true,
		expectedCPUByZone: map[string]*resource.Quantity{
			"zone-a": resource.NewQuantity(1, resource.BinarySI),
			"zone-b": resource.NewQuantity(1, resource.BinarySI),
		},
		expectedRatios: map[string]float64{
			"zone-a": 0.5,
			"zone-b": 0.5,
		},
	}, {
		name: "3 zones, 4 nodes in 1, 2 nodes in 1, 1 node in 1",
		nodes: []nodeInfo{
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-a", cpu: resource.MustParse("1000m"), ready: v1.ConditionTrue},
			{zone: "zone-a", cpu: resource.MustParse("2000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("3000m"), ready: v1.ConditionTrue},
			{zone: "zone-b", cpu: resource.MustParse("1500m"), ready: v1.ConditionTrue},
			{zone: "zone-c", cpu: resource.MustParse("500m"), ready: v1.ConditionTrue},
		},
		expectSufficientNodeInfo: true,
		expectedCPUByZone: map[string]*resource.Quantity{
			"zone-a": resource.NewMilliQuantity(5000, resource.BinarySI),
			"zone-b": resource.NewMilliQuantity(4500, resource.BinarySI),
			"zone-c": resource.NewMilliQuantity(500, resource.BinarySI),
		},
		expectedRatios: map[string]float64{
			"zone-a": 0.5,
			"zone-b": 0.45,
			"zone-c": 0.05,
		},
	}}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			cache := NewTopologyCache()
			nodes := make([]*v1.Node, 0, len(tc.nodes))
			for _, node := range tc.nodes {
				labels := node.labels
				if labels == nil {
					labels = map[string]string{}
				}
				if node.zone != "" {
					labels[v1.LabelTopologyZone] = node.zone
				}
				conditions := []v1.NodeCondition{{
					Type:   v1.NodeReady,
					Status: node.ready,
				}}
				allocatable := v1.ResourceList{
					v1.ResourceCPU: node.cpu,
				}
				nodes = append(nodes, &v1.Node{
					ObjectMeta: metav1.ObjectMeta{
						Labels: labels,
					},
					Status: v1.NodeStatus{
						Allocatable: allocatable,
						Conditions:  conditions,
					},
				})
			}

			cache.SetNodes(nodes)

			if cache.sufficientNodeInfo != tc.expectSufficientNodeInfo {
				t.Errorf("Expected sufficientNodeInfo to be %t, got %t", tc.expectSufficientNodeInfo, cache.sufficientNodeInfo)
			}

			if cache.cpuRatiosByZone == nil || tc.expectedRatios == nil {
				if (cache.cpuRatiosByZone == nil) != (tc.expectedRatios == nil) {
					t.Errorf("Expected %+v, got %+v", tc.expectedRatios, cache.cpuRatiosByZone)
				}
			} else {
				if len(cache.cpuRatiosByZone) != len(tc.expectedRatios) {
					t.Errorf("Expected ratios with %d zones, got %d", len(tc.expectedRatios), len(cache.cpuRatiosByZone))
				}
				for zone, expectedRatio := range tc.expectedRatios {
					actualRatio, ok := cache.cpuRatiosByZone[zone]
					if !ok {
						t.Errorf("Expected ratio for %s zone, got none", zone)
					} else if actualRatio != expectedRatio {
						t.Errorf("Expected ratio to be %f, got %f", expectedRatio, actualRatio)
					}
				}
			}

			if cache.cpuByZone == nil || tc.expectedCPUByZone == nil {
				if (cache.cpuByZone == nil) != (tc.expectedCPUByZone == nil) {
					t.Errorf("Expected %+v, got %+v", tc.expectedCPUByZone, cache.cpuByZone)
				}
			} else {
				if len(cache.cpuByZone) != len(tc.expectedCPUByZone) {
					t.Errorf("Expected CPU with %d zones, got %d", len(tc.expectedCPUByZone), len(cache.cpuByZone))
				}
				for zone, expectedCPU := range tc.expectedCPUByZone {
					actualCPU, ok := cache.cpuByZone[zone]
					if !ok {
						t.Errorf("Expected CPU for %s zone, got none", zone)
					} else if !actualCPU.Equal(*expectedCPU) {
						t.Errorf("Expected CPU to be %d, got %d", expectedCPU.MilliValue(), actualCPU.MilliValue())
					}
				}
			}
		})
	}
}

// Test Helpers

func expectEquivalentSlices(t *testing.T, actualSlices, expectedSlices []*discovery.EndpointSlice) {
	t.Helper()

	if len(actualSlices) != len(expectedSlices) {
		t.Fatalf("Expected %d slices, got %d", len(expectedSlices), len(actualSlices))
	}

	for i, expectedSlice := range expectedSlices {
		actualSlice := actualSlices[i]

		if len(expectedSlice.Endpoints) != len(actualSlice.Endpoints) {
			t.Errorf("Expected %d endpoints, got %d", len(expectedSlice.Endpoints), len(actualSlice.Endpoints))
			continue
		}
		for j, expectedEndpoint := range expectedSlice.Endpoints {
			actualEndpoint := actualSlice.Endpoints[j]
			if !reflect.DeepEqual(actualEndpoint, expectedEndpoint) {
				t.Errorf("Endpoints didn't match\nExpected: %+v\nGot: %+v", expectedEndpoint, actualEndpoint)
			}
		}
	}
}

相关信息

kubernetes 源码目录

相关文章

kubernetes sliceinfo 源码

kubernetes sliceinfo_test 源码

kubernetes topologycache 源码

kubernetes utils 源码

kubernetes utils_test 源码

0  赞