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  }