1/* 2Copyright 2020 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package topologymanager 18 19import ( 20 "reflect" 21 "testing" 22 23 v1 "k8s.io/api/core/v1" 24) 25 26func TestPodCalculateAffinity(t *testing.T) { 27 tcases := []struct { 28 name string 29 hp []HintProvider 30 expected []map[string][]TopologyHint 31 }{ 32 { 33 name: "No hint providers", 34 hp: []HintProvider{}, 35 expected: ([]map[string][]TopologyHint)(nil), 36 }, 37 { 38 name: "HintProvider returns empty non-nil map[string][]TopologyHint", 39 hp: []HintProvider{ 40 &mockHintProvider{ 41 map[string][]TopologyHint{}, 42 }, 43 }, 44 expected: []map[string][]TopologyHint{ 45 {}, 46 }, 47 }, 48 { 49 name: "HintProvider returns -nil map[string][]TopologyHint from provider", 50 hp: []HintProvider{ 51 &mockHintProvider{ 52 map[string][]TopologyHint{ 53 "resource": nil, 54 }, 55 }, 56 }, 57 expected: []map[string][]TopologyHint{ 58 { 59 "resource": nil, 60 }, 61 }, 62 }, 63 { 64 name: "Assorted HintProviders", 65 hp: []HintProvider{ 66 &mockHintProvider{ 67 map[string][]TopologyHint{ 68 "resource-1/A": { 69 {NUMANodeAffinity: NewTestBitMask(0), Preferred: true}, 70 {NUMANodeAffinity: NewTestBitMask(0, 1), Preferred: false}, 71 }, 72 "resource-1/B": { 73 {NUMANodeAffinity: NewTestBitMask(1), Preferred: true}, 74 {NUMANodeAffinity: NewTestBitMask(1, 2), Preferred: false}, 75 }, 76 }, 77 }, 78 &mockHintProvider{ 79 map[string][]TopologyHint{ 80 "resource-2/A": { 81 {NUMANodeAffinity: NewTestBitMask(2), Preferred: true}, 82 {NUMANodeAffinity: NewTestBitMask(3, 4), Preferred: false}, 83 }, 84 "resource-2/B": { 85 {NUMANodeAffinity: NewTestBitMask(2), Preferred: true}, 86 {NUMANodeAffinity: NewTestBitMask(3, 4), Preferred: false}, 87 }, 88 }, 89 }, 90 &mockHintProvider{ 91 map[string][]TopologyHint{ 92 "resource-3": nil, 93 }, 94 }, 95 }, 96 expected: []map[string][]TopologyHint{ 97 { 98 "resource-1/A": { 99 {NUMANodeAffinity: NewTestBitMask(0), Preferred: true}, 100 {NUMANodeAffinity: NewTestBitMask(0, 1), Preferred: false}, 101 }, 102 "resource-1/B": { 103 {NUMANodeAffinity: NewTestBitMask(1), Preferred: true}, 104 {NUMANodeAffinity: NewTestBitMask(1, 2), Preferred: false}, 105 }, 106 }, 107 { 108 "resource-2/A": { 109 {NUMANodeAffinity: NewTestBitMask(2), Preferred: true}, 110 {NUMANodeAffinity: NewTestBitMask(3, 4), Preferred: false}, 111 }, 112 "resource-2/B": { 113 {NUMANodeAffinity: NewTestBitMask(2), Preferred: true}, 114 {NUMANodeAffinity: NewTestBitMask(3, 4), Preferred: false}, 115 }, 116 }, 117 { 118 "resource-3": nil, 119 }, 120 }, 121 }, 122 } 123 124 for _, tc := range tcases { 125 podScope := &podScope{ 126 scope{ 127 hintProviders: tc.hp, 128 policy: &mockPolicy{}, 129 name: podTopologyScope, 130 }, 131 } 132 133 podScope.calculateAffinity(&v1.Pod{}) 134 actual := podScope.policy.(*mockPolicy).ph 135 if !reflect.DeepEqual(tc.expected, actual) { 136 t.Errorf("Test Case: %s", tc.name) 137 t.Errorf("Expected result to be %v, got %v", tc.expected, actual) 138 } 139 } 140} 141 142func TestPodAccumulateProvidersHints(t *testing.T) { 143 tcases := []struct { 144 name string 145 hp []HintProvider 146 expected []map[string][]TopologyHint 147 }{ 148 { 149 name: "TopologyHint not set", 150 hp: []HintProvider{}, 151 expected: nil, 152 }, 153 { 154 name: "HintProvider returns empty non-nil map[string][]TopologyHint", 155 hp: []HintProvider{ 156 &mockHintProvider{ 157 map[string][]TopologyHint{}, 158 }, 159 }, 160 expected: []map[string][]TopologyHint{ 161 {}, 162 }, 163 }, 164 { 165 name: "HintProvider returns - nil map[string][]TopologyHint from provider", 166 hp: []HintProvider{ 167 &mockHintProvider{ 168 map[string][]TopologyHint{ 169 "resource": nil, 170 }, 171 }, 172 }, 173 expected: []map[string][]TopologyHint{ 174 { 175 "resource": nil, 176 }, 177 }, 178 }, 179 { 180 name: "2 HintProviders with 1 resource returns hints", 181 hp: []HintProvider{ 182 &mockHintProvider{ 183 map[string][]TopologyHint{ 184 "resource1": {TopologyHint{}}, 185 }, 186 }, 187 &mockHintProvider{ 188 map[string][]TopologyHint{ 189 "resource2": {TopologyHint{}}, 190 }, 191 }, 192 }, 193 expected: []map[string][]TopologyHint{ 194 { 195 "resource1": {TopologyHint{}}, 196 }, 197 { 198 "resource2": {TopologyHint{}}, 199 }, 200 }, 201 }, 202 { 203 name: "2 HintProviders 1 with 1 resource 1 with nil hints", 204 hp: []HintProvider{ 205 &mockHintProvider{ 206 map[string][]TopologyHint{ 207 "resource1": {TopologyHint{}}, 208 }, 209 }, 210 &mockHintProvider{nil}, 211 }, 212 expected: []map[string][]TopologyHint{ 213 { 214 "resource1": {TopologyHint{}}, 215 }, 216 nil, 217 }, 218 }, 219 { 220 name: "2 HintProviders 1 with 1 resource 1 empty hints", 221 hp: []HintProvider{ 222 &mockHintProvider{ 223 map[string][]TopologyHint{ 224 "resource1": {TopologyHint{}}, 225 }, 226 }, 227 &mockHintProvider{ 228 map[string][]TopologyHint{}, 229 }, 230 }, 231 expected: []map[string][]TopologyHint{ 232 { 233 "resource1": {TopologyHint{}}, 234 }, 235 {}, 236 }, 237 }, 238 { 239 name: "HintProvider with 2 resources returns hints", 240 hp: []HintProvider{ 241 &mockHintProvider{ 242 map[string][]TopologyHint{ 243 "resource1": {TopologyHint{}}, 244 "resource2": {TopologyHint{}}, 245 }, 246 }, 247 }, 248 expected: []map[string][]TopologyHint{ 249 { 250 "resource1": {TopologyHint{}}, 251 "resource2": {TopologyHint{}}, 252 }, 253 }, 254 }, 255 } 256 257 for _, tc := range tcases { 258 pScope := podScope{ 259 scope{ 260 hintProviders: tc.hp, 261 }, 262 } 263 actual := pScope.accumulateProvidersHints(&v1.Pod{}) 264 if !reflect.DeepEqual(actual, tc.expected) { 265 t.Errorf("Test Case %s: Expected NUMANodeAffinity in result to be %v, got %v", tc.name, tc.expected, actual) 266 } 267 } 268} 269