github.com/jxskiss/gopkg@v0.17.3/easy/slice_test.go (about)

     1  package easy
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  
     9  	"github.com/jxskiss/gopkg/ptr"
    10  	"github.com/jxskiss/gopkg/reflectx"
    11  )
    12  
    13  func callFunction(f interface{}, args ...interface{}) interface{} {
    14  	fVal := reflect.ValueOf(f)
    15  	argsVal := make([]reflect.Value, 0, len(args))
    16  	for _, arg := range args {
    17  		argsVal = append(argsVal, reflect.ValueOf(arg))
    18  	}
    19  	outVals := fVal.Call(argsVal)
    20  	if len(outVals) > 0 {
    21  		return outVals[0].Interface()
    22  	}
    23  	return nil
    24  }
    25  
    26  var insertSliceTests = []map[string]interface{}{
    27  	{
    28  		"func":  InsertInt64s,
    29  		"slice": []int64{1, 2, 3, 4},
    30  		"elem":  int64(9),
    31  		"index": 3,
    32  		"want":  []int64{1, 2, 3, 9, 4},
    33  	},
    34  	{
    35  		"func":  InsertInt32s,
    36  		"slice": []int32{1, 2, 3, 4},
    37  		"elem":  int32(9),
    38  		"index": 10,
    39  		"want":  []int32{1, 2, 3, 4, 9},
    40  	},
    41  	{
    42  		"func":  InsertStrings,
    43  		"slice": []string{"1", "2", "3", "4"},
    44  		"elem":  "9",
    45  		"index": 3,
    46  		"want":  []string{"1", "2", "3", "9", "4"},
    47  	},
    48  }
    49  
    50  func TestInsertSlice(t *testing.T) {
    51  	for _, test := range insertSliceTests {
    52  		var got interface{}
    53  		insert := func() {
    54  			got = callFunction(test["func"], test["slice"], test["index"], test["elem"])
    55  		}
    56  		if test["want"] == "panic" {
    57  			assert.Panics(t, insert)
    58  		} else {
    59  			assert.NotPanics(t, insert)
    60  			assert.Equal(t, test["want"], got)
    61  		}
    62  	}
    63  }
    64  
    65  var complexTypeData = []*comptyp{
    66  	{
    67  		I32:      32,
    68  		I32_p:    ptr.Int32(32),
    69  		I64:      64,
    70  		I64_p:    ptr.Int64(64),
    71  		Str:      "str",
    72  		Str_p:    ptr.String("str"),
    73  		Simple:   simple{A: "a"},
    74  		Simple_p: &simple{A: "a"},
    75  	},
    76  	{
    77  		I32:      33,
    78  		I32_p:    ptr.Int32(33),
    79  		I64:      65,
    80  		I64_p:    ptr.Int64(65),
    81  		Str:      "str_2",
    82  		Str_p:    ptr.String("str_2"),
    83  		Simple:   simple{A: "b"},
    84  		Simple_p: &simple{A: "b"},
    85  	},
    86  	{
    87  		I32:      34,
    88  		I32_p:    ptr.Int32(34),
    89  		I64:      66,
    90  		I64_p:    ptr.Int64(66),
    91  		Str:      "str_3",
    92  		Str_p:    ptr.String("str_3"),
    93  		Simple:   simple{A: "c"},
    94  		Simple_p: &simple{A: "c"},
    95  	},
    96  	{
    97  		I32:      35,
    98  		I32_p:    nil,
    99  		I64:      67,
   100  		I64_p:    nil,
   101  		Str:      "str_4",
   102  		Str_p:    nil,
   103  		Simple:   simple{A: "d"},
   104  		Simple_p: nil,
   105  	},
   106  }
   107  
   108  var reverseSliceTests = []map[string]interface{}{
   109  	{
   110  		"func":  ReverseInt64s,
   111  		"slice": []int64{1, 2, 3},
   112  		"want":  []int64{3, 2, 1},
   113  	},
   114  	{
   115  		"func":  ReverseInt32s,
   116  		"slice": []int32{1, 2, 3, 4},
   117  		"want":  []int32{4, 3, 2, 1},
   118  	},
   119  	{
   120  		"func":  ReverseStrings,
   121  		"slice": []string{"1", "2", "3"},
   122  		"want":  []string{"3", "2", "1"},
   123  	},
   124  	{
   125  		"func":  ReverseSlice,
   126  		"slice": []int8{1, 2, 3, 4},
   127  		"want":  []int8{4, 3, 2, 1},
   128  	},
   129  	{
   130  		"func":  ReverseSlice,
   131  		"slice": []simple{{"a"}, {"b"}, {"c"}, {"d"}},
   132  		"want":  []simple{{"d"}, {"c"}, {"b"}, {"a"}},
   133  	},
   134  	{
   135  		"func":  ReverseSlice,
   136  		"slice": []int(nil),
   137  		"want":  []int{},
   138  	},
   139  }
   140  
   141  func TestReverseSlice(t *testing.T) {
   142  	for _, test := range reverseSliceTests {
   143  		got := callFunction(test["func"], test["slice"], false)
   144  		assert.Equal(t, test["want"], got)
   145  	}
   146  }
   147  
   148  var reverseSliceInplaceTests = []map[string]interface{}{
   149  	{
   150  		"func":  ReverseInt64s,
   151  		"slice": []int64{1, 2, 3},
   152  		"want":  []int64{3, 2, 1},
   153  	},
   154  	{
   155  		"func":  ReverseInt32s,
   156  		"slice": []int32{1, 2, 3},
   157  		"want":  []int32{3, 2, 1},
   158  	},
   159  	{
   160  		"func":  ReverseStrings,
   161  		"slice": []string{"1", "2", "3"},
   162  		"want":  []string{"3", "2", "1"},
   163  	},
   164  	{
   165  		"func":  ReverseSlice,
   166  		"slice": []int8{1, 2, 3, 4},
   167  		"want":  []int8{4, 3, 2, 1},
   168  	},
   169  	{
   170  		"func":  ReverseSlice,
   171  		"slice": []simple{{"a"}, {"b"}, {"c"}, {"d"}},
   172  		"want":  []simple{{"d"}, {"c"}, {"b"}, {"a"}},
   173  	},
   174  	{
   175  		"func":  ReverseSlice,
   176  		"slice": []int(nil),
   177  		"want":  []int(nil),
   178  	},
   179  }
   180  
   181  func TestReverseSliceInplace(t *testing.T) {
   182  	for _, test := range reverseSliceInplaceTests {
   183  		got := callFunction(test["func"], test["slice"], true)
   184  		assert.Equal(t, test["want"], got)
   185  		assert.Equal(t, test["want"], test["slice"])
   186  	}
   187  }
   188  
   189  var uniqueSliceTests = []map[string]interface{}{
   190  	{
   191  		"func":  UniqueInt64s,
   192  		"slice": []int64{2, 2, 1, 3, 2, 3, 1, 3},
   193  		"want":  []int64{2, 1, 3},
   194  	},
   195  	{
   196  		"func":  UniqueInt32s,
   197  		"slice": []int32{2, 2, 1, 3, 2, 3, 1, 3},
   198  		"want":  []int32{2, 1, 3},
   199  	},
   200  	{
   201  		"func":  UniqueStrings,
   202  		"slice": []string{"2", "2", "1", "3", "2", "3", "1", "3"},
   203  		"want":  []string{"2", "1", "3"},
   204  	},
   205  }
   206  
   207  func TestUniqueSlice(t *testing.T) {
   208  	for _, test := range uniqueSliceTests {
   209  		got := callFunction(test["func"], test["slice"], false)
   210  		assert.Equal(t, test["want"], got)
   211  	}
   212  	for _, test := range uniqueSliceTests {
   213  		got := callFunction(test["func"], test["slice"], true)
   214  		assert.Equal(t, test["want"], got)
   215  		n := reflectx.SliceLen(got)
   216  		changed := reflect.ValueOf(test["slice"]).Slice(0, n).Interface()
   217  		assert.Equal(t, test["want"], changed)
   218  	}
   219  }
   220  
   221  func TestDiffInt64s(t *testing.T) {
   222  	a := []int64{1, 2, 3, 4, 5}
   223  	b := []int64{4, 5, 6, 7, 8}
   224  	want1 := []int64{1, 2, 3}
   225  	assert.Equal(t, want1, DiffInt64s(a, b))
   226  
   227  	want2 := []int64{6, 7, 8}
   228  	assert.Equal(t, want2, DiffInt64s(b, a))
   229  }
   230  
   231  func TestDiffStrings(t *testing.T) {
   232  	a := []string{"1", "2", "3", "4", "5"}
   233  	b := []string{"4", "5", "6", "7", "8"}
   234  	want1 := []string{"1", "2", "3"}
   235  	assert.Equal(t, want1, DiffStrings(a, b))
   236  
   237  	want2 := []string{"6", "7", "8"}
   238  	assert.Equal(t, want2, DiffStrings(b, a))
   239  }
   240  
   241  func TestToMap(t *testing.T) {
   242  	a := &simple{"a"}
   243  	b := &simple{"b"}
   244  	c := &simple{"c"}
   245  	slice := []*simple{a, b, c}
   246  	want := map[string]*simple{"a": a, "b": b, "c": c}
   247  	got := ToMap(slice, "A")
   248  	assert.Equal(t, want, got)
   249  
   250  	assert.Panics(t, func() { ToMap(nil, "A") })
   251  	assert.Panics(t, func() { ToMap(slice, "") })
   252  }
   253  
   254  func TestToMap_Pointer(t *testing.T) {
   255  	a := &comptyp{Str_p: ptr.String("a")}
   256  	b := &comptyp{Str_p: ptr.String("b")}
   257  	c := &comptyp{Str_p: ptr.String("c")}
   258  	slice := []*comptyp{a, b, c}
   259  	want := map[string]*comptyp{"a": a, "b": b, "c": c}
   260  	got := ToMap(slice, "Str_p")
   261  	assert.Equal(t, want, got)
   262  }
   263  
   264  func TestToSliceMap(t *testing.T) {
   265  	a := &comptyp{I32: 1, I32_p: ptr.Int32(1)}
   266  	b := &comptyp{I32: 1, I32_p: ptr.Int32(1)}
   267  	c := &comptyp{I32: 2, I32_p: ptr.Int32(2)}
   268  
   269  	slice1 := []comptyp{*a, *b, *c}
   270  	want1 := map[int32][]comptyp{
   271  		1: {*a, *b},
   272  		2: {*c},
   273  	}
   274  	got1 := ToSliceMap(slice1, "I32").(map[int32][]comptyp)
   275  	assert.Len(t, got1, len(want1))
   276  	assert.ElementsMatch(t, MapKeys(got1), MapKeys(want1))
   277  	assert.ElementsMatch(t, got1[1], want1[1])
   278  	assert.ElementsMatch(t, got1[2], want1[2])
   279  
   280  	want2 := want1
   281  	got2 := ToSliceMap(slice1, "I32_p").(map[int32][]comptyp)
   282  	assert.Len(t, got2, len(want1))
   283  	assert.ElementsMatch(t, MapKeys(got2), MapKeys(want1))
   284  	assert.ElementsMatch(t, got2[1], want2[1])
   285  	assert.ElementsMatch(t, got2[2], want2[2])
   286  
   287  	slice3 := []*comptyp{a, b, c}
   288  	want3 := map[int32][]*comptyp{
   289  		1: {a, b},
   290  		2: {c},
   291  	}
   292  	got3 := ToSliceMap(slice3, "I32").(map[int32][]*comptyp)
   293  	assert.Len(t, got3, len(want3))
   294  	assert.ElementsMatch(t, MapKeys(got3), MapKeys(want3))
   295  	assert.ElementsMatch(t, got3[1], want3[1])
   296  	assert.ElementsMatch(t, got3[2], want3[2])
   297  
   298  	want4 := want3
   299  	got4 := ToSliceMap(slice3, "I32_p").(map[int32][]*comptyp)
   300  	assert.Len(t, got4, len(want4))
   301  	assert.ElementsMatch(t, MapKeys(got4), MapKeys(want4))
   302  	assert.ElementsMatch(t, got4[1], want4[1])
   303  	assert.ElementsMatch(t, got4[2], want4[2])
   304  
   305  	// panics
   306  	assert.Panics(t, func() { ToSliceMap(nil, "I32_p") })
   307  	assert.Panics(t, func() { ToSliceMap(slice1, "") })
   308  	assert.Panics(t, func() { ToSliceMap(a, "I32_p") })
   309  }
   310  
   311  func TestToMapMap(t *testing.T) {
   312  	a := &comptyp{I32: 1, I32_p: ptr.Int32(1)}
   313  	b := &comptyp{I32: 1, I32_p: ptr.Int32(2)}
   314  	c := &comptyp{I32: 3, I32_p: ptr.Int32(3)}
   315  
   316  	slice1 := []comptyp{*a, *b, *c}
   317  	want1 := map[int32]map[int32]comptyp{
   318  		1: {1: *a, 2: *b},
   319  		3: {3: *c},
   320  	}
   321  	got1 := ToMapMap(slice1, "I32", "I32_p")
   322  	assert.Equal(t, want1, got1)
   323  
   324  	slice2 := []*comptyp{a, b, c}
   325  	want2 := map[int32]map[int32]*comptyp{
   326  		1: {1: a, 2: b},
   327  		3: {3: c},
   328  	}
   329  	got2 := ToMapMap(slice2, "I32", "I32_p")
   330  	assert.Equal(t, want2, got2)
   331  
   332  	// panics
   333  	assert.Panics(t, func() { ToMapMap(nil, "I32", "I32_p") })
   334  	assert.Panics(t, func() { ToMapMap(slice1, "", "I32_p") })
   335  	assert.Panics(t, func() { ToMapMap(slice1, "I32", "") })
   336  	assert.Panics(t, func() { ToMapMap(a, "I32", "I32_p") })
   337  }
   338  
   339  func TestToInterfaceSlice(t *testing.T) {
   340  	slice1 := []int{1, 2, 3}
   341  	want := []interface{}{1, 2, 3}
   342  	got := ToInterfaceSlice(slice1)
   343  	assert.Equal(t, want, got)
   344  
   345  	slice2 := []*int{ptr.Int(1), ptr.Int(2), ptr.Int(3)}
   346  	got2 := ToInterfaceSlice(slice2)
   347  	for i, x := range got2 {
   348  		assert.Equal(t, *slice2[i], *(x.(*int)))
   349  	}
   350  
   351  	slice3 := []simple{
   352  		{"a"},
   353  		{"b"},
   354  		{"c"},
   355  	}
   356  	got3 := ToInterfaceSlice(slice3)
   357  	for i, x := range got3 {
   358  		assert.Equal(t, slice3[i], x.(simple))
   359  	}
   360  
   361  	slice4 := []*simple{
   362  		{"a"},
   363  		{"b"},
   364  		{"c"},
   365  	}
   366  	got4 := ToInterfaceSlice(slice4)
   367  	for i, x := range got4 {
   368  		assert.Equal(t, slice4[i].A, x.(*simple).A)
   369  	}
   370  }
   371  
   372  func TestFindFuncAndFilterFunc(t *testing.T) {
   373  	a := &comptyp{I32: 1, Str_p: ptr.String("a")}
   374  	b := &comptyp{I64: 2, Str_p: ptr.String("b")}
   375  	c := &comptyp{I64_p: ptr.Int64(3), Str_p: ptr.String("c")}
   376  	slice := []*comptyp{a, b, c}
   377  
   378  	f1 := func(i int) bool { return slice[i].Str_p == nil }
   379  	got1 := FindFunc(slice, f1)
   380  	all1 := FilterFunc(slice, f1)
   381  
   382  	assert.Equal(t, nil, got1)
   383  	assert.NotNil(t, all1)
   384  	assert.Len(t, all1, 0)
   385  
   386  	f3 := func(i int) bool { return ptr.DerefInt64(slice[i].I64_p) == 3 }
   387  	got3 := FindFunc(slice, f3)
   388  	all3 := FilterFunc(slice, f3)
   389  	assert.Equal(t, c, got3)
   390  	assert.Len(t, all3, 1)
   391  
   392  	assert.Panics(t, func() { FindFunc(slice, nil) })
   393  	assert.Panics(t, func() { FilterFunc(nil, f3) })
   394  	assert.Panics(t, func() { FilterFunc(slice, nil) })
   395  }
   396  
   397  func TestParseInt64s(t *testing.T) {
   398  	strIntIDs := "123,,456,789, ,0,"
   399  	want := []int64{123, 456, 789}
   400  	got, isMalformed := ParseInt64s(strIntIDs, ",", true)
   401  	assert.True(t, isMalformed)
   402  	assert.Equal(t, want, got)
   403  }
   404  
   405  func TestJoinInt64s(t *testing.T) {
   406  	slice := []int64{1, 2, 3, 4, 5}
   407  	want := "1,2,3,4,5"
   408  	got := JoinInt64s(slice, ",")
   409  	assert.Equal(t, want, got)
   410  }
   411  
   412  var splitBatchTests = []map[string]interface{}{
   413  	{
   414  		"total": 0,
   415  		"batch": 10,
   416  		"want":  []IJ(nil),
   417  	},
   418  	{
   419  		"total": 72,
   420  		"batch": -36,
   421  		"want":  []IJ{{0, 72}},
   422  	},
   423  	{
   424  		"total": 72,
   425  		"batch": 0,
   426  		"want":  []IJ{{0, 72}},
   427  	},
   428  	{
   429  		"total": 72,
   430  		"batch": 35,
   431  		"want":  []IJ{{0, 35}, {35, 70}, {70, 72}},
   432  	},
   433  	{
   434  		"total": 72,
   435  		"batch": 24,
   436  		"want":  []IJ{{0, 24}, {24, 48}, {48, 72}},
   437  	},
   438  }
   439  
   440  func TestSplitBatch(t *testing.T) {
   441  	for _, test := range splitBatchTests {
   442  		got := SplitBatch(test["total"].(int), test["batch"].(int))
   443  		assert.Equal(t, test["want"], got)
   444  	}
   445  }
   446  
   447  func TestSplitSlice(t *testing.T) {
   448  	slice := []int{1, 2, 3, 4, 5, 6, 7}
   449  	want := [][]int{{1, 2, 3}, {4, 5, 6}, {7}}
   450  	got := SplitSlice(slice, 3)
   451  	assert.Equal(t, want, got)
   452  }
   453  
   454  func TestSumSlice(t *testing.T) {
   455  	tests := []map[string]interface{}{
   456  		{"slice": []int(nil), "sum": 0},
   457  		{"slice": []int32{1, 2, 3}, "sum": 6},
   458  		{"slice": []uint64{4, 5, 6}, "sum": 15},
   459  	}
   460  	for _, test := range tests {
   461  		got := SumSlice(test["slice"])
   462  		assert.Equal(t, test["sum"], int(got))
   463  	}
   464  }