github.com/viant/toolbox@v0.34.5/collections_test.go (about)

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