github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/util/sets/set_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 sets 18 19 import ( 20 "fmt" 21 "math/rand" 22 "reflect" 23 "testing" 24 ) 25 26 func TestStringSet(t *testing.T) { 27 s := String{} 28 s2 := String{} 29 if len(s) != 0 { 30 t.Errorf("Expected len=0: %d", len(s)) 31 } 32 s.Insert("a", "b") 33 if len(s) != 2 { 34 t.Errorf("Expected len=2: %d", len(s)) 35 } 36 s.Insert("c") 37 if s.Has("d") { 38 t.Errorf("Unexpected contents: %#v", s) 39 } 40 if !s.Has("a") { 41 t.Errorf("Missing contents: %#v", s) 42 } 43 s.Delete("a") 44 if s.Has("a") { 45 t.Errorf("Unexpected contents: %#v", s) 46 } 47 s.Insert("a") 48 if s.HasAll("a", "b", "d") { 49 t.Errorf("Unexpected contents: %#v", s) 50 } 51 if !s.HasAll("a", "b") { 52 t.Errorf("Missing contents: %#v", s) 53 } 54 s2.Insert("a", "b", "d") 55 if s.IsSuperset(s2) { 56 t.Errorf("Unexpected contents: %#v", s) 57 } 58 s2.Delete("d") 59 if !s.IsSuperset(s2) { 60 t.Errorf("Missing contents: %#v", s) 61 } 62 } 63 64 func TestStringSetDeleteMultiples(t *testing.T) { 65 s := String{} 66 s.Insert("a", "b", "c") 67 if len(s) != 3 { 68 t.Errorf("Expected len=3: %d", len(s)) 69 } 70 71 s.Delete("a", "c") 72 if len(s) != 1 { 73 t.Errorf("Expected len=1: %d", len(s)) 74 } 75 if s.Has("a") { 76 t.Errorf("Unexpected contents: %#v", s) 77 } 78 if s.Has("c") { 79 t.Errorf("Unexpected contents: %#v", s) 80 } 81 if !s.Has("b") { 82 t.Errorf("Missing contents: %#v", s) 83 } 84 85 } 86 87 func TestNewStringSet(t *testing.T) { 88 s := NewString("a", "b", "c") 89 if len(s) != 3 { 90 t.Errorf("Expected len=3: %d", len(s)) 91 } 92 if !s.Has("a") || !s.Has("b") || !s.Has("c") { 93 t.Errorf("Unexpected contents: %#v", s) 94 } 95 } 96 97 func TestStringSetList(t *testing.T) { 98 s := NewString("z", "y", "x", "a") 99 if !reflect.DeepEqual(s.List(), []string{"a", "x", "y", "z"}) { 100 t.Errorf("List gave unexpected result: %#v", s.List()) 101 } 102 } 103 104 func TestStringSetDifference(t *testing.T) { 105 a := NewString("1", "2", "3") 106 b := NewString("1", "2", "4", "5") 107 c := a.Difference(b) 108 d := b.Difference(a) 109 if len(c) != 1 { 110 t.Errorf("Expected len=1: %d", len(c)) 111 } 112 if !c.Has("3") { 113 t.Errorf("Unexpected contents: %#v", c.List()) 114 } 115 if len(d) != 2 { 116 t.Errorf("Expected len=2: %d", len(d)) 117 } 118 if !d.Has("4") || !d.Has("5") { 119 t.Errorf("Unexpected contents: %#v", d.List()) 120 } 121 } 122 123 func TestStringSetSymmetricDifference(t *testing.T) { 124 a := NewString("1", "2", "3") 125 b := NewString("1", "2", "4", "5") 126 c := a.SymmetricDifference(b) 127 d := b.SymmetricDifference(a) 128 if !c.Equal(NewString("3", "4", "5")) { 129 t.Errorf("Unexpected contents: %#v", c.List()) 130 } 131 if !d.Equal(NewString("3", "4", "5")) { 132 t.Errorf("Unexpected contents: %#v", d.List()) 133 } 134 } 135 136 func TestStringSetHasAny(t *testing.T) { 137 a := NewString("1", "2", "3") 138 139 if !a.HasAny("1", "4") { 140 t.Errorf("expected true, got false") 141 } 142 143 if a.HasAny("0", "4") { 144 t.Errorf("expected false, got true") 145 } 146 } 147 148 func TestStringSetEquals(t *testing.T) { 149 // Simple case (order doesn't matter) 150 a := NewString("1", "2") 151 b := NewString("2", "1") 152 if !a.Equal(b) { 153 t.Errorf("Expected to be equal: %v vs %v", a, b) 154 } 155 156 // It is a set; duplicates are ignored 157 b = NewString("2", "2", "1") 158 if !a.Equal(b) { 159 t.Errorf("Expected to be equal: %v vs %v", a, b) 160 } 161 162 // Edge cases around empty sets / empty strings 163 a = NewString() 164 b = NewString() 165 if !a.Equal(b) { 166 t.Errorf("Expected to be equal: %v vs %v", a, b) 167 } 168 169 b = NewString("1", "2", "3") 170 if a.Equal(b) { 171 t.Errorf("Expected to be not-equal: %v vs %v", a, b) 172 } 173 174 b = NewString("1", "2", "") 175 if a.Equal(b) { 176 t.Errorf("Expected to be not-equal: %v vs %v", a, b) 177 } 178 179 // Check for equality after mutation 180 a = NewString() 181 a.Insert("1") 182 if a.Equal(b) { 183 t.Errorf("Expected to be not-equal: %v vs %v", a, b) 184 } 185 186 a.Insert("2") 187 if a.Equal(b) { 188 t.Errorf("Expected to be not-equal: %v vs %v", a, b) 189 } 190 191 a.Insert("") 192 if !a.Equal(b) { 193 t.Errorf("Expected to be equal: %v vs %v", a, b) 194 } 195 196 a.Delete("") 197 if a.Equal(b) { 198 t.Errorf("Expected to be not-equal: %v vs %v", a, b) 199 } 200 } 201 202 func TestStringUnion(t *testing.T) { 203 tests := []struct { 204 s1 String 205 s2 String 206 expected String 207 }{ 208 { 209 NewString("1", "2", "3", "4"), 210 NewString("3", "4", "5", "6"), 211 NewString("1", "2", "3", "4", "5", "6"), 212 }, 213 { 214 NewString("1", "2", "3", "4"), 215 NewString(), 216 NewString("1", "2", "3", "4"), 217 }, 218 { 219 NewString(), 220 NewString("1", "2", "3", "4"), 221 NewString("1", "2", "3", "4"), 222 }, 223 { 224 NewString(), 225 NewString(), 226 NewString(), 227 }, 228 } 229 230 for _, test := range tests { 231 union := test.s1.Union(test.s2) 232 if union.Len() != test.expected.Len() { 233 t.Errorf("Expected union.Len()=%d but got %d", test.expected.Len(), union.Len()) 234 } 235 236 if !union.Equal(test.expected) { 237 t.Errorf("Expected union.Equal(expected) but not true. union:%v expected:%v", union.List(), test.expected.List()) 238 } 239 } 240 } 241 242 func TestStringIntersection(t *testing.T) { 243 tests := []struct { 244 s1 String 245 s2 String 246 expected String 247 }{ 248 { 249 NewString("1", "2", "3", "4"), 250 NewString("3", "4", "5", "6"), 251 NewString("3", "4"), 252 }, 253 { 254 NewString("1", "2", "3", "4"), 255 NewString("1", "2", "3", "4"), 256 NewString("1", "2", "3", "4"), 257 }, 258 { 259 NewString("1", "2", "3", "4"), 260 NewString(), 261 NewString(), 262 }, 263 { 264 NewString(), 265 NewString("1", "2", "3", "4"), 266 NewString(), 267 }, 268 { 269 NewString(), 270 NewString(), 271 NewString(), 272 }, 273 } 274 275 for _, test := range tests { 276 intersection := test.s1.Intersection(test.s2) 277 if intersection.Len() != test.expected.Len() { 278 t.Errorf("Expected intersection.Len()=%d but got %d", test.expected.Len(), intersection.Len()) 279 } 280 281 if !intersection.Equal(test.expected) { 282 t.Errorf("Expected intersection.Equal(expected) but not true. intersection:%v expected:%v", intersection.List(), test.expected.List()) 283 } 284 } 285 } 286 287 type randomStringAlphabet string 288 289 func (a randomStringAlphabet) makeString(minLen, maxLen int) string { 290 n := minLen 291 if minLen < maxLen { 292 n += rand.Intn(maxLen - minLen) 293 } 294 var s string 295 for i := 0; i < n; i++ { 296 s += string(a[rand.Intn(len(a))]) 297 } 298 return s 299 } 300 301 var randomStringMaker = randomStringAlphabet("abcdefghijklmnopqrstuvwxyz0123456789") 302 303 func BenchmarkStringSet(b *testing.B) { 304 cases := []struct { 305 size int 306 minStringLen int 307 maxStringLen int 308 }{ 309 {20, 10, 20}, 310 {50, 10, 30}, 311 {100, 20, 40}, 312 {500, 20, 50}, 313 {1000, 20, 60}, 314 } 315 316 for i := range cases { 317 here := cases[i] 318 makeSet := func() String { 319 s := NewString() 320 for j := 0; j < here.size; j++ { 321 s.Insert(randomStringMaker.makeString(here.minStringLen, here.maxStringLen)) 322 } 323 return s 324 } 325 operands := make([]String, 500) 326 for i := range operands { 327 operands[i] = makeSet() 328 } 329 randOperand := func() String { return operands[rand.Intn(len(operands))] } 330 331 b.Run(fmt.Sprintf("insert-%v", here.size), func(b *testing.B) { 332 b.ReportAllocs() 333 for i := 0; i < b.N; i++ { 334 makeSet() 335 } 336 }) 337 338 b.Run(fmt.Sprintf("key-set-%v", here.size), func(b *testing.B) { 339 b.ReportAllocs() 340 for i := 0; i < b.N; i++ { 341 StringKeySet(randOperand()) 342 } 343 }) 344 345 b.Run(fmt.Sprintf("has-%v", here.size), func(b *testing.B) { 346 b.ReportAllocs() 347 for i := 0; i < b.N; i++ { 348 randOperand().Has(randomStringMaker.makeString(here.minStringLen, here.maxStringLen)) 349 } 350 }) 351 352 b.Run(fmt.Sprintf("intersection-%v", here.size), func(b *testing.B) { 353 b.ReportAllocs() 354 for i := 0; i < b.N; i++ { 355 randOperand().Intersection(randOperand()) 356 } 357 }) 358 359 b.Run(fmt.Sprintf("symmetric-difference-%v", here.size), func(b *testing.B) { 360 b.ReportAllocs() 361 for i := 0; i < b.N; i++ { 362 randOperand().SymmetricDifference(randOperand()) 363 } 364 }) 365 366 b.Run(fmt.Sprintf("list-%v", here.size), func(b *testing.B) { 367 b.ReportAllocs() 368 for i := 0; i < b.N; i++ { 369 randOperand().List() 370 } 371 }) 372 } 373 }