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 }