k8s.io/kubernetes@v1.29.3/pkg/scheduler/framework/cycle_state_test.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package framework 18 19 import ( 20 "fmt" 21 "testing" 22 ) 23 24 type fakeData struct { 25 data string 26 } 27 28 func (f *fakeData) Clone() StateData { 29 copy := &fakeData{ 30 data: f.data, 31 } 32 return copy 33 } 34 35 var key StateKey = "fakedata_key" 36 37 // createCycleStateWithFakeData creates *CycleState with fakeData. 38 // The given data is used in stored fakeData. 39 func createCycleStateWithFakeData(data string, recordPluginMetrics bool) *CycleState { 40 c := NewCycleState() 41 c.Write(key, &fakeData{ 42 data: data, 43 }) 44 c.SetRecordPluginMetrics(recordPluginMetrics) 45 return c 46 } 47 48 // isCycleStateEqual returns whether two CycleState, which has fakeData in storage, is equal or not. 49 // And if they are not equal, returns message which shows why not equal. 50 func isCycleStateEqual(a, b *CycleState) (bool, string) { 51 if a == nil && b == nil { 52 return true, "" 53 } 54 if a == nil || b == nil { 55 return false, fmt.Sprintf("one CycleState is nil, but another one is not nil. A: %v, B: %v", a, b) 56 } 57 58 if a.recordPluginMetrics != b.recordPluginMetrics { 59 return false, fmt.Sprintf("CycleState A and B have a different recordPluginMetrics. A: %v, B: %v", a.recordPluginMetrics, b.recordPluginMetrics) 60 } 61 62 var msg string 63 isEqual := true 64 countA := 0 65 a.storage.Range(func(k, v1 interface{}) bool { 66 countA++ 67 v2, ok := b.storage.Load(k) 68 if !ok { 69 isEqual = false 70 msg = fmt.Sprintf("CycleState B doesn't have the data which CycleState A has. key: %v, data: %v", k, v1) 71 return false 72 } 73 74 typed1, ok1 := v1.(*fakeData) 75 typed2, ok2 := v2.(*fakeData) 76 if !ok1 || !ok2 { 77 isEqual = false 78 msg = fmt.Sprintf("CycleState has the data which is not type *fakeData.") 79 return false 80 } 81 82 if typed1.data != typed2.data { 83 isEqual = false 84 msg = fmt.Sprintf("CycleState B has a different data on key %v. A: %v, B: %v", k, typed1.data, typed2.data) 85 return false 86 } 87 88 return true 89 }) 90 91 if !isEqual { 92 return false, msg 93 } 94 95 countB := 0 96 b.storage.Range(func(k, _ interface{}) bool { 97 countB++ 98 return true 99 }) 100 101 if countA != countB { 102 return false, fmt.Sprintf("two Cyclestates have different numbers of data. A: %v, B: %v", countA, countB) 103 } 104 105 return true, "" 106 } 107 108 func TestCycleStateClone(t *testing.T) { 109 tests := []struct { 110 name string 111 state *CycleState 112 wantClonedState *CycleState 113 }{ 114 { 115 name: "clone with recordPluginMetrics true", 116 state: createCycleStateWithFakeData("data", true), 117 wantClonedState: createCycleStateWithFakeData("data", true), 118 }, 119 { 120 name: "clone with recordPluginMetrics false", 121 state: createCycleStateWithFakeData("data", false), 122 wantClonedState: createCycleStateWithFakeData("data", false), 123 }, 124 { 125 name: "clone with nil CycleState", 126 state: nil, 127 wantClonedState: nil, 128 }, 129 } 130 131 for _, tt := range tests { 132 t.Run(tt.name, func(t *testing.T) { 133 state := tt.state 134 stateCopy := state.Clone() 135 136 if isEqual, msg := isCycleStateEqual(stateCopy, tt.wantClonedState); !isEqual { 137 t.Errorf("unexpected cloned state: %v", msg) 138 } 139 140 if state == nil || stateCopy == nil { 141 // not need to run the rest check in this case. 142 return 143 } 144 145 stateCopy.Write(key, &fakeData{data: "modified"}) 146 if isEqual, _ := isCycleStateEqual(state, stateCopy); isEqual { 147 t.Errorf("the change for a cloned state should not affect the original state.") 148 } 149 }) 150 } 151 }