github.com/viant/toolbox@v0.34.5/collections_async_test.go (about) 1 package toolbox 2 3 import ( 4 "github.com/stretchr/testify/assert" 5 "reflect" 6 "strings" 7 "testing" 8 ) 9 10 func TestIndexSliceAsync(t *testing.T) { 11 12 { 13 type Foo struct { 14 id int 15 name string 16 } 17 18 var fooCollection = []Foo{{1, "A"}, {2, "B"}} 19 var indexedMap = make(map[int]Foo) 20 IndexSliceAsync(fooCollection, indexedMap, func(foo Foo) int { 21 return foo.id 22 }) 23 assert.Equal(t, "A", indexedMap[1].name) 24 } 25 26 { 27 aSlice := []string{"a", "c"} 28 aMap := make(map[string]int) 29 index := 0 30 SliceToMapAsync(aSlice, aMap, CopyStringValueProvider, func(s string) int { 31 index++ 32 return index 33 }) 34 assert.Equal(t, 2, len(aMap)) 35 36 } 37 } 38 39 type sliceItem struct { 40 Id int 41 } 42 43 func TestReverseSlice(t *testing.T) { 44 45 { 46 aSlice := []interface{}{ 47 "abc", "def", "cyz", "adc", "z", 48 } 49 50 ReverseSlice(aSlice) 51 assert.Equal(t, []interface{}{"z", "adc", "cyz", "def", "abc"}, aSlice) 52 } 53 54 ReverseSlice(nil) 55 { 56 aSlice := []*sliceItem{ 57 {1}, {10}, 58 } 59 60 ReverseSlice(aSlice) 61 assert.Equal(t, []*sliceItem{ 62 {10}, {1}, 63 }, aSlice) 64 } 65 66 } 67 68 func TestProcessSliceAsync(t *testing.T) { 69 { 70 aSlice := []interface{}{ 71 "abc", "def", "cyz", "adc", 72 } 73 count := 0 74 ProcessSliceAsync(aSlice, func(item interface{}) bool { 75 count++ 76 return true 77 }) 78 79 assert.Equal(t, 4, count) 80 } 81 82 { 83 aSlice := []string{ 84 "abc", "def", "cyz", "adc", 85 } 86 count := 0 87 ProcessSliceAsync(aSlice, func(item interface{}) bool { 88 count++ 89 return true 90 }) 91 92 assert.Equal(t, 4, count) 93 } 94 } 95 96 func TestProcessSliceWithIndexAsync(t *testing.T) { 97 { 98 aSlice := []interface{}{ 99 "abc", "def", "cyz", "adc", 100 } 101 count := 0 102 ProcessSliceWithIndexAsync(aSlice, func(index int, item interface{}) bool { 103 count += 1 //Test case changed due to index being async 104 return true 105 }) 106 107 assert.Equal(t, 4, count) 108 } 109 { 110 aSlice := []string{ 111 "abc", "def", "cyz", "adc", 112 } 113 count := 0 114 ProcessSliceWithIndexAsync(aSlice, func(index int, item interface{}) bool { 115 count += 1 116 return true 117 }) 118 119 assert.Equal(t, 4, count) 120 } 121 } 122 123 func TestMakeMapFromSliceAsync(t *testing.T) { 124 type Foo struct { 125 id int 126 name string 127 } 128 129 var fooCollection = []Foo{{1, "A"}, {2, "B"}} 130 var testMap = make(map[int]string) 131 SliceToMapAsync(fooCollection, testMap, func(foo Foo) int { 132 return foo.id 133 }, 134 func(foo Foo) string { 135 return foo.name 136 }) 137 138 assert.Equal(t, "A", testMap[1]) 139 assert.Equal(t, "B", testMap[2]) 140 141 } 142 143 func TestSliceToMapAsync(t *testing.T) { 144 aSlice := []string{"a", "c"} 145 aMap := make(map[string]bool) 146 147 SliceToMapAsync(aSlice, aMap, func(s string) string { 148 return s 149 }, func(s string) bool { 150 return true 151 }) 152 assert.Equal(t, 2, len(aMap)) 153 154 } 155 156 func TestProcess2DSliceInBatches(t *testing.T) { 157 slice := [][]interface{}{ 158 {1, 2, 3}, 159 {4, 5, 7}, 160 {7, 8, 9}, 161 {10, 11, 12}, 162 {13, 14, 15}, 163 {16, 17, 18}, 164 {19, 20, 21}, 165 } 166 167 actualItemCount := 0 168 Process2DSliceInBatches(slice, 2, func(item [][]interface{}) { 169 actualItemCount = actualItemCount + len(item) 170 }) 171 assert.Equal(t, 7, actualItemCount) 172 } 173 174 func TestCopySliceElements(t *testing.T) { 175 { 176 source := []interface{}{ 177 "abc", "def", "cyz", 178 } 179 var target = make([]string, 0) 180 CopySliceElements(source, &target) 181 assert.Equal(t, 3, len(target)) 182 for i := 0; i < len(source); i++ { 183 assert.Equal(t, source[i], target[i]) 184 } 185 } 186 { 187 source := []interface{}{ 188 1, 2, 3, 189 } 190 var target = make([]int, 0) 191 CopySliceElements(source, &target) 192 assert.Equal(t, 3, len(target)) 193 for i := 0; i < len(source); i++ { 194 assert.Equal(t, source[i], target[i]) 195 } 196 } 197 { 198 source := []interface{}{ 199 1, 2, 3, 200 } 201 var target = make([]interface{}, 0) 202 CopySliceElements(source, &target) 203 assert.Equal(t, 3, len(target)) 204 for i := 0; i < len(source); i++ { 205 assert.Equal(t, source[i], target[i]) 206 } 207 } 208 209 } 210 211 func TestFilterSliceElements(t *testing.T) { 212 { 213 source := []interface{}{ 214 1, 2, 3, 215 } 216 var target = make([]int, 0) 217 //filter all elements starting with a 218 FilterSliceElements(source, func(item int) bool { 219 return item > 1 220 }, &target) 221 assert.Equal(t, 2, len(target)) 222 assert.Equal(t, 2, target[0]) 223 assert.Equal(t, 3, target[1]) 224 } 225 226 { 227 source := []interface{}{ 228 "abc", "def", "cyz", "adc", 229 } 230 var target = make([]string, 0) 231 //filter all elements starting with a 232 FilterSliceElements(source, func(item string) bool { 233 return strings.HasPrefix(item, "a") 234 }, &target) 235 assert.Equal(t, 2, len(target)) 236 assert.Equal(t, "abc", target[0]) 237 assert.Equal(t, "adc", target[1]) 238 } 239 240 } 241 242 func TestHasSliceAnyElements(t *testing.T) { 243 source := []interface{}{ 244 "abc", "def", "cyz", "adc", 245 } 246 assert.True(t, HasSliceAnyElements(source, "cyz")) 247 assert.False(t, HasSliceAnyElements(source, "cyze")) 248 assert.True(t, HasSliceAnyElements(source, "cyze", "cyz")) 249 } 250 251 func TestMapKeysToSlice(t *testing.T) { 252 m := map[string]int{ 253 "abc": 1, 254 "efg": 2, 255 } 256 var keys = make([]string, 0) 257 MapKeysToSlice(m, &keys) 258 assert.Equal(t, 2, len(keys)) 259 } 260 261 func TestMapKeysToStringSlice(t *testing.T) { 262 m := map[string]int{ 263 "abc": 1, 264 "efg": 2, 265 } 266 slice := MapKeysToStringSlice(m) 267 assert.Equal(t, 2, len(slice)) 268 } 269 270 func TestCopyMapEntries(t *testing.T) { 271 type Foo struct { 272 id int 273 name string 274 } 275 source := map[interface{}]interface{}{ 276 1: Foo{1, "A"}, 277 2: Foo{2, "B"}, 278 } 279 var target = make(map[int]Foo) 280 281 CopyMapEntries(source, target) 282 assert.Equal(t, 2, len(target)) 283 assert.Equal(t, "B", target[2].name) 284 } 285 286 func TestIndexMultimap(t *testing.T) { 287 type Product struct{ vendor, name string } 288 products := []Product{ 289 {"Vendor1", "Product1"}, 290 {"Vendor2", "Product2"}, 291 {"Vendor1", "Product3"}, 292 {"Vendor1", "Product4"}, 293 } 294 295 productsByVendor := make(map[string][]Product) 296 GroupSliceElements(products, productsByVendor, func(product Product) string { 297 return product.vendor 298 }) 299 assert.Equal(t, 2, len(productsByVendor)) 300 assert.Equal(t, 3, len(productsByVendor["Vendor1"])) 301 assert.Equal(t, "Product4", productsByVendor["Vendor1"][2].name) 302 303 } 304 305 func TestSliceToMultiMap(t *testing.T) { 306 type Product struct { 307 vendor, name string 308 productId int 309 } 310 311 products := []Product{ 312 {"Vendor1", "Product1", 1}, 313 {"Vendor2", "Product2", 2}, 314 {"Vendor1", "Product3", 3}, 315 {"Vendor1", "Product4", 4}, 316 } 317 318 productsByVendor := make(map[string][]int) 319 SliceToMultimap(products, productsByVendor, func(product Product) string { 320 return product.vendor 321 }, 322 func(product Product) int { 323 return product.productId 324 }) 325 326 assert.Equal(t, 2, len(productsByVendor)) 327 assert.Equal(t, 3, len(productsByVendor["Vendor1"])) 328 assert.Equal(t, 4, productsByVendor["Vendor1"][2]) 329 330 } 331 332 func TestTransformSlice(t *testing.T) { 333 type Product struct{ vendor, name string } 334 products := []Product{ 335 {"Vendor1", "Product1"}, 336 {"Vendor2", "Product2"}, 337 {"Vendor1", "Product3"}, 338 {"Vendor1", "Product4"}, 339 } 340 var vendors = make([]string, 0) 341 TransformSlice(products, &vendors, func(product Product) string { 342 return product.vendor 343 }) 344 assert.Equal(t, 4, len(vendors)) 345 assert.Equal(t, "Vendor1", vendors[3]) 346 } 347 348 func TestMakeStringMap(t *testing.T) { 349 aMap := MakeStringMap("a:1, b:2", ":", ",") 350 assert.Equal(t, 2, len(aMap)) 351 assert.Equal(t, "1", aMap["a"]) 352 assert.Equal(t, "2", aMap["b"]) 353 } 354 355 func TestMakeReverseStringMap(t *testing.T) { 356 aMap := MakeReverseStringMap("a:1, b:2", ":", ",") 357 assert.Equal(t, 2, len(aMap)) 358 assert.Equal(t, "a", aMap["1"]) 359 assert.Equal(t, "b", aMap["2"]) 360 } 361 362 func TestSortStrings(t *testing.T) { 363 sorted := SortStrings([]string{"z", "b", "c", "a"}) 364 assert.Equal(t, "a", sorted[0]) 365 assert.Equal(t, "z", sorted[3]) 366 367 } 368 369 func TestJoinAsString(t *testing.T) { 370 assert.Equal(t, "a,b", JoinAsString([]string{"a", "b"}, ",")) 371 } 372 373 func TestSetSliceValue(t *testing.T) { 374 375 { 376 var aSlice = make([]string, 2) 377 SetSliceValue(aSlice, 0, "abc") 378 assert.Equal(t, "abc", aSlice[0]) 379 assert.Equal(t, "abc", GetSliceValue(aSlice, 0)) 380 } 381 382 { 383 var aSlice = make([]int, 2) 384 SetSliceValue(aSlice, 0, 100) 385 assert.Equal(t, 100, aSlice[0]) 386 assert.Equal(t, 100, GetSliceValue(aSlice, 0)) 387 } 388 { 389 var aSlice = make([]interface{}, 2) 390 SetSliceValue(aSlice, 0, "a") 391 assert.Equal(t, "a", aSlice[0]) 392 assert.Equal(t, "a", GetSliceValue(aSlice, 0)) 393 } 394 } 395 396 func TestTrueValueProvider(t *testing.T) { 397 assert.True(t, TrueValueProvider(1)) 398 } 399 400 func Test_DeleteEmptyKeys(t *testing.T) { 401 aMap := map[string]interface{}{ 402 "k1": []int{}, 403 "k2": []int{1}, 404 "k3": "", 405 "k40": map[interface{}]interface{}{ 406 "k1": nil, 407 1: 2, 408 "k31": []map[string]interface{}{}, 409 "k41": []map[string]interface{}{ 410 { 411 "z": 1, 412 }, 413 }, 414 }, 415 "k5": map[string]interface{}{ 416 "k1": "", 417 "10": 20, 418 }, 419 } 420 cloned := DeleteEmptyKeys(aMap) 421 assert.Equal(t, map[string]interface{}{ 422 "k2": []interface{}{1}, 423 "k40": map[interface{}]interface{}{ 424 1: 2, 425 "k41": []interface{}{ 426 map[string]interface{}{ 427 "z": 1, 428 }, 429 }, 430 }, 431 "k5": map[string]interface{}{ 432 "10": 20, 433 }, 434 }, cloned) 435 } 436 437 func TestIntersection(t *testing.T) { 438 439 useCase1Actual := []string{} 440 useCase2Actual := []int{} 441 useCase3Actual := []float32{} 442 443 var useCases = []struct { 444 description string 445 sliceA interface{} 446 sliceB interface{} 447 actual interface{} 448 expect interface{} 449 hasError bool 450 }{ 451 { 452 description: "string slice intersection", 453 sliceA: []string{"a", "bc", "z", "eee"}, 454 sliceB: []string{"a2", "bc", "5z", "eee"}, 455 actual: &useCase1Actual, 456 expect: []string{"bc", "eee"}, 457 }, 458 { 459 description: "int slice intersection", 460 sliceA: []int{1, 2, 3, 4}, 461 sliceB: []int{3, 4, 5, 6}, 462 actual: &useCase2Actual, 463 expect: []int{3, 4}, 464 }, 465 { 466 description: "float slice intersection", 467 sliceA: []float32{1.1, 2.1, 3.1, 4.1}, 468 sliceB: []float32{3.1, 4.1, 5.1, 6.1}, 469 actual: &useCase3Actual, 470 expect: []float32{3.1, 4.1}, 471 }, 472 } 473 474 for _, useCase := range useCases { 475 err := Intersect(useCase.sliceA, useCase.sliceB, useCase.actual) 476 if useCase.hasError { 477 assert.NotNil(t, err, useCase.description) 478 continue 479 } 480 if !assert.Nil(t, err, useCase.description) { 481 continue 482 } 483 actual := reflect.ValueOf(useCase.actual).Elem().Interface() 484 assert.EqualValues(t, useCase.expect, actual, useCase.description) 485 } 486 487 }