k8s.io/apimachinery@v0.29.2/pkg/util/intstr/intstr_test.go (about) 1 /* 2 Copyright 2014 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 intstr 18 19 import ( 20 "encoding/json" 21 "reflect" 22 "testing" 23 24 "sigs.k8s.io/yaml" 25 ) 26 27 func TestFromInt(t *testing.T) { 28 i := FromInt(93) 29 if i.Type != Int || i.IntVal != 93 { 30 t.Errorf("Expected IntVal=93, got %+v", i) 31 } 32 } 33 34 func TestFromInt32(t *testing.T) { 35 i := FromInt32(93) 36 if i.Type != Int || i.IntVal != 93 { 37 t.Errorf("Expected IntVal=93, got %+v", i) 38 } 39 } 40 41 func TestFromString(t *testing.T) { 42 i := FromString("76") 43 if i.Type != String || i.StrVal != "76" { 44 t.Errorf("Expected StrVal=\"76\", got %+v", i) 45 } 46 } 47 48 type IntOrStringHolder struct { 49 IOrS IntOrString `json:"val"` 50 } 51 52 func TestIntOrStringUnmarshalJSON(t *testing.T) { 53 cases := []struct { 54 input string 55 result IntOrString 56 }{ 57 {"{\"val\": 123}", FromInt32(123)}, 58 {"{\"val\": \"123\"}", FromString("123")}, 59 } 60 61 for _, c := range cases { 62 var result IntOrStringHolder 63 if err := json.Unmarshal([]byte(c.input), &result); err != nil { 64 t.Errorf("Failed to unmarshal input '%v': %v", c.input, err) 65 } 66 if result.IOrS != c.result { 67 t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result) 68 } 69 } 70 } 71 72 func TestIntOrStringMarshalJSON(t *testing.T) { 73 cases := []struct { 74 input IntOrString 75 result string 76 }{ 77 {FromInt32(123), "{\"val\":123}"}, 78 {FromString("123"), "{\"val\":\"123\"}"}, 79 } 80 81 for _, c := range cases { 82 input := IntOrStringHolder{c.input} 83 result, err := json.Marshal(&input) 84 if err != nil { 85 t.Errorf("Failed to marshal input '%v': %v", input, err) 86 } 87 if string(result) != c.result { 88 t.Errorf("Failed to marshal input '%v': expected: %+v, got %q", input, c.result, string(result)) 89 } 90 } 91 } 92 93 func TestIntOrStringMarshalJSONUnmarshalYAML(t *testing.T) { 94 cases := []struct { 95 input IntOrString 96 }{ 97 {FromInt32(123)}, 98 {FromString("123")}, 99 } 100 101 for _, c := range cases { 102 input := IntOrStringHolder{c.input} 103 jsonMarshalled, err := json.Marshal(&input) 104 if err != nil { 105 t.Errorf("1: Failed to marshal input: '%v': %v", input, err) 106 } 107 108 var result IntOrStringHolder 109 err = yaml.Unmarshal(jsonMarshalled, &result) 110 if err != nil { 111 t.Errorf("2: Failed to unmarshal '%+v': %v", string(jsonMarshalled), err) 112 } 113 114 if !reflect.DeepEqual(input, result) { 115 t.Errorf("3: Failed to marshal input '%+v': got %+v", input, result) 116 } 117 } 118 } 119 120 func TestGetIntFromIntOrString(t *testing.T) { 121 tests := []struct { 122 input IntOrString 123 expectErr bool 124 expectVal int 125 expectPerc bool 126 }{ 127 { 128 input: FromInt32(200), 129 expectErr: false, 130 expectVal: 200, 131 expectPerc: false, 132 }, 133 { 134 input: FromString("200"), 135 expectErr: true, 136 expectPerc: false, 137 }, 138 { 139 input: FromString("30%0"), 140 expectErr: true, 141 expectPerc: false, 142 }, 143 { 144 input: FromString("40%"), 145 expectErr: false, 146 expectVal: 40, 147 expectPerc: true, 148 }, 149 { 150 input: FromString("%"), 151 expectErr: true, 152 expectPerc: false, 153 }, 154 { 155 input: FromString("a%"), 156 expectErr: true, 157 expectPerc: false, 158 }, 159 { 160 input: FromString("a"), 161 expectErr: true, 162 expectPerc: false, 163 }, 164 { 165 input: FromString("40#"), 166 expectErr: true, 167 expectPerc: false, 168 }, 169 { 170 input: FromString("40%%"), 171 expectErr: true, 172 expectPerc: false, 173 }, 174 } 175 for _, test := range tests { 176 t.Run("", func(t *testing.T) { 177 value, isPercent, err := getIntOrPercentValueSafely(&test.input) 178 if test.expectVal != value { 179 t.Fatalf("expected value does not match, expected: %d, got: %d", test.expectVal, value) 180 } 181 if test.expectPerc != isPercent { 182 t.Fatalf("expected percent does not match, expected: %t, got: %t", test.expectPerc, isPercent) 183 } 184 if test.expectErr != (err != nil) { 185 t.Fatalf("expected error does not match, expected error: %v, got: %v", test.expectErr, err) 186 } 187 }) 188 } 189 190 } 191 192 func TestGetIntFromIntOrPercent(t *testing.T) { 193 tests := []struct { 194 input IntOrString 195 total int 196 roundUp bool 197 expectErr bool 198 expectVal int 199 }{ 200 { 201 input: FromInt32(123), 202 expectErr: false, 203 expectVal: 123, 204 }, 205 { 206 input: FromString("90%"), 207 total: 100, 208 roundUp: true, 209 expectErr: false, 210 expectVal: 90, 211 }, 212 { 213 input: FromString("90%"), 214 total: 95, 215 roundUp: true, 216 expectErr: false, 217 expectVal: 86, 218 }, 219 { 220 input: FromString("90%"), 221 total: 95, 222 roundUp: false, 223 expectErr: false, 224 expectVal: 85, 225 }, 226 { 227 input: FromString("%"), 228 expectErr: true, 229 }, 230 { 231 input: FromString("90#"), 232 expectErr: true, 233 }, 234 { 235 input: FromString("#%"), 236 expectErr: true, 237 }, 238 { 239 input: FromString("90"), 240 expectErr: true, 241 }, 242 } 243 244 for i, test := range tests { 245 t.Logf("test case %d", i) 246 value, err := GetScaledValueFromIntOrPercent(&test.input, test.total, test.roundUp) 247 if test.expectErr && err == nil { 248 t.Errorf("expected error, but got none") 249 continue 250 } 251 if !test.expectErr && err != nil { 252 t.Errorf("unexpected err: %v", err) 253 continue 254 } 255 if test.expectVal != value { 256 t.Errorf("expected %v, but got %v", test.expectVal, value) 257 } 258 } 259 } 260 261 func TestGetValueFromIntOrPercentNil(t *testing.T) { 262 _, err := GetScaledValueFromIntOrPercent(nil, 0, false) 263 if err == nil { 264 t.Errorf("expected error got none") 265 } 266 } 267 268 func TestParse(t *testing.T) { 269 tests := []struct { 270 input string 271 output IntOrString 272 }{ 273 { 274 input: "0", 275 output: IntOrString{Type: Int, IntVal: 0}, 276 }, 277 { 278 input: "2147483647", // math.MaxInt32 279 output: IntOrString{Type: Int, IntVal: 2147483647}, 280 }, 281 { 282 input: "-2147483648", // math.MinInt32 283 output: IntOrString{Type: Int, IntVal: -2147483648}, 284 }, 285 { 286 input: "2147483648", // math.MaxInt32+1 287 output: IntOrString{Type: String, StrVal: "2147483648"}, 288 }, 289 { 290 input: "-2147483649", // math.MinInt32-1 291 output: IntOrString{Type: String, StrVal: "-2147483649"}, 292 }, 293 { 294 input: "9223372036854775807", // math.MaxInt64 295 output: IntOrString{Type: String, StrVal: "9223372036854775807"}, 296 }, 297 { 298 input: "-9223372036854775808", // math.MinInt64 299 output: IntOrString{Type: String, StrVal: "-9223372036854775808"}, 300 }, 301 { 302 input: "9223372036854775808", // math.MaxInt64+1 303 output: IntOrString{Type: String, StrVal: "9223372036854775808"}, 304 }, 305 { 306 input: "-9223372036854775809", // math.MinInt64-1 307 output: IntOrString{Type: String, StrVal: "-9223372036854775809"}, 308 }, 309 } 310 311 for i, test := range tests { 312 t.Logf("test case %d", i) 313 value := Parse(test.input) 314 if test.output.Type != value.Type { 315 t.Errorf("expected type %d (%v), but got %d (%v)", test.output.Type, test.output, value.Type, value) 316 continue 317 } 318 if value.Type == Int && test.output.IntVal != value.IntVal { 319 t.Errorf("expected int value %d (%v), but got %d (%v)", test.output.IntVal, test.output, value.IntVal, value) 320 continue 321 } 322 if value.Type == String && test.output.StrVal != value.StrVal { 323 t.Errorf("expected string value %q (%v), but got %q (%v)", test.output.StrVal, test.output, value.StrVal, value) 324 } 325 } 326 }