diff --git a/g/container/garray/garray_z_unit_basic_test.go b/g/container/garray/garray_z_unit_basic_test.go index 93a3882d5..61a40cf5d 100644 --- a/g/container/garray/garray_z_unit_basic_test.go +++ b/g/container/garray/garray_z_unit_basic_test.go @@ -31,6 +31,7 @@ func Test_SortedIntArray1(t *testing.T) { array.Add(i) } gtest.Assert(array.Slice(), expect) + gtest.Assert(array.Add().Slice(), expect) } func Test_SortedIntArray2(t *testing.T) { @@ -100,6 +101,5 @@ func TestNewFromCopy(t *testing.T) { gtest.AssertIN(array1.PopRands(2), a1) gtest.Assert(len(array1.PopRands(1)), 1) gtest.Assert(len(array1.PopRands(9)), 3) - }) } diff --git a/g/container/garray/garray_z_unit_int_test.go b/g/container/garray/garray_z_unit_int_test.go index 2a65f89f3..1f43da646 100644 --- a/g/container/garray/garray_z_unit_int_test.go +++ b/g/container/garray/garray_z_unit_int_test.go @@ -9,7 +9,9 @@ package garray_test import ( + "github.com/gogf/gf/g/util/gconv" "testing" + "time" "github.com/gogf/gf/g/container/garray" "github.com/gogf/gf/g/test/gtest" @@ -18,12 +20,15 @@ import ( func Test_IntArray_Basic(t *testing.T) { gtest.Case(t, func() { expect := []int{0, 1, 2, 3} + expect2 := []int{} array := garray.NewIntArrayFrom(expect) + array2 := garray.NewIntArrayFrom(expect2) gtest.Assert(array.Slice(), expect) array.Set(0, 100) gtest.Assert(array.Get(0), 100) gtest.Assert(array.Get(1), 1) gtest.Assert(array.Search(100), 0) + gtest.Assert(array2.Search(100), -1) gtest.Assert(array.Contains(100), true) gtest.Assert(array.Remove(0), 100) gtest.Assert(array.Contains(100), false) @@ -44,13 +49,16 @@ func TestIntArray_Sort(t *testing.T) { expect1 := []int{0, 1, 2, 3} expect2 := []int{3, 2, 1, 0} array := garray.NewIntArray() + array2 := garray.NewIntArray(true) for i := 3; i >= 0; i-- { array.Append(i) + array2.Append(i) } array.Sort() gtest.Assert(array.Slice(), expect1) array.Sort(true) gtest.Assert(array.Slice(), expect2) + gtest.Assert(array2.Slice(), expect2) }) } @@ -98,21 +106,48 @@ func TestIntArray_Range(t *testing.T) { gtest.Case(t, func() { value1 := []int{0, 1, 2, 3, 4, 5, 6} array1 := garray.NewIntArrayFrom(value1) + array2 := garray.NewIntArrayFrom(value1, true) gtest.Assert(array1.Range(0, 1), []int{0}) gtest.Assert(array1.Range(1, 2), []int{1}) gtest.Assert(array1.Range(0, 2), []int{0, 1}) gtest.Assert(array1.Range(10, 2), nil) gtest.Assert(array1.Range(-1, 10), value1) + gtest.Assert(array2.Range(1, 2), []int{1}) }) } func TestIntArray_Merge(t *testing.T) { gtest.Case(t, func() { - a1 := []int{0, 1, 2, 3} - a2 := []int{4, 5, 6, 7} - array1 := garray.NewIntArrayFrom(a1) - array2 := garray.NewIntArrayFrom(a2) - gtest.Assert(array1.Merge(array2).Slice(), []int{0, 1, 2, 3, 4, 5, 6, 7}) + func1 := func(v1, v2 interface{}) int { + if gconv.Int(v1) < gconv.Int(v2) { + return 0 + } + return 1 + } + + n1 := []int{0, 1, 2, 3} + n2 := []int{4, 5, 6, 7} + i1 := []interface{}{"1", "2"} + s1 := []string{"a", "b", "c"} + s2 := []string{"e", "f"} + a1 := garray.NewIntArrayFrom(n1) + a2 := garray.NewIntArrayFrom(n2) + a3 := garray.NewArrayFrom(i1) + a4 := garray.NewStringArrayFrom(s1) + + a5 := garray.NewSortedStringArrayFrom(s2) + a6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) + + a7 := garray.NewSortedStringArrayFrom(s1) + a8 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + + gtest.Assert(a1.Merge(a2).Slice(), []int{0, 1, 2, 3, 4, 5, 6, 7}) + gtest.Assert(a1.Merge(a3).Len(), 10) + gtest.Assert(a1.Merge(a4).Len(), 13) + gtest.Assert(a1.Merge(a5).Len(), 15) + gtest.Assert(a1.Merge(a6).Len(), 18) + gtest.Assert(a1.Merge(a7).Len(), 21) + gtest.Assert(a1.Merge(a8).Len(), 23) }) } @@ -124,6 +159,7 @@ func TestIntArray_Fill(t *testing.T) { array2 := garray.NewIntArrayFrom(a2) gtest.Assert(array1.Fill(1, 2, 100).Slice(), []int{0, 100, 100}) gtest.Assert(array2.Fill(0, 2, 100).Slice(), []int{100, 100}) + gtest.Assert(array2.Fill(-1, 2, 100).Slice(), []int{100, 100}) }) } @@ -136,6 +172,7 @@ func TestIntArray_Chunk(t *testing.T) { gtest.Assert(chunks[0], []int{1, 2}) gtest.Assert(chunks[1], []int{3, 4}) gtest.Assert(chunks[2], []int{5}) + gtest.Assert(array1.Chunk(0), nil) }) } @@ -153,6 +190,7 @@ func TestIntArray_SubSlice(t *testing.T) { gtest.Case(t, func() { a1 := []int{0, 1, 2, 3, 4, 5, 6} array1 := garray.NewIntArrayFrom(a1) + array2 := garray.NewIntArrayFrom(a1, true) gtest.Assert(array1.SubSlice(6), []int{6}) gtest.Assert(array1.SubSlice(5), []int{5, 6}) gtest.Assert(array1.SubSlice(8), nil) @@ -168,6 +206,7 @@ func TestIntArray_SubSlice(t *testing.T) { gtest.Assert(array1.SubSlice(-9, 3), nil) gtest.Assert(array1.SubSlice(1, -1), []int{0}) gtest.Assert(array1.SubSlice(1, -3), nil) + gtest.Assert(array2.SubSlice(0, 2), []int{0, 1}) }) } @@ -193,7 +232,6 @@ func TestIntArray_PopRands(t *testing.T) { ns2 := array.PopRands(7) gtest.AssertIN(len(ns2), 6) gtest.AssertIN(ns2, []int{100, 200, 300, 400, 500, 600}) - }) } @@ -226,6 +264,7 @@ func TestNewSortedIntArrayFrom(t *testing.T) { a1 := []int{0, 3, 2, 1, 4, 5, 6} array1 := garray.NewSortedIntArrayFrom(a1, true) gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6") + gtest.Assert(array1.Slice(), a1) }) } @@ -260,7 +299,6 @@ func TestSortedIntArray_Sort(t *testing.T) { gtest.Assert(array2.Len(), 4) gtest.Assert(array2, []int{0, 1, 2, 3}) - }) } @@ -271,7 +309,6 @@ func TestSortedIntArray_Get(t *testing.T) { gtest.Assert(array1.Get(0), 0) gtest.Assert(array1.Get(1), 1) gtest.Assert(array1.Get(3), 5) - }) } @@ -296,7 +333,6 @@ func TestSortedIntArray_Remove(t *testing.T) { i3 = array2.Remove(1) gtest.Assert(array2.Search(4), -1) gtest.Assert(i3, 4) - }) } @@ -308,7 +344,6 @@ func TestSortedIntArray_PopLeft(t *testing.T) { gtest.Assert(i1, 1) gtest.Assert(array1.Len(), 3) gtest.Assert(array1.Search(1), -1) - }) } @@ -348,7 +383,6 @@ func TestSortedIntArray_PopRands(t *testing.T) { gtest.Assert(array2.Len(), 0) gtest.Assert(len(ns2), 4) gtest.AssertIN(ns2, []int{1, 3, 5, 2}) - }) } @@ -365,7 +399,6 @@ func TestSortedIntArray_PopLefts(t *testing.T) { ns2 := array2.PopLefts(5) gtest.Assert(array2.Len(), 0) gtest.AssertIN(ns2, []int{1, 3, 5, 2}) - }) } @@ -389,6 +422,7 @@ func TestSortedIntArray_Range(t *testing.T) { gtest.Case(t, func() { a1 := []int{1, 3, 5, 2, 6, 7} array1 := garray.NewSortedIntArrayFrom(a1) + array2 := garray.NewSortedIntArrayFrom(a1, true) ns1 := array1.Range(1, 4) gtest.Assert(len(ns1), 3) gtest.Assert(ns1, []int{2, 3, 5}) @@ -401,7 +435,7 @@ func TestSortedIntArray_Range(t *testing.T) { nsl := array1.Range(5, 8) gtest.Assert(len(nsl), 1) - + gtest.Assert(array2.Range(1, 2), []int{2}) }) } @@ -418,7 +452,6 @@ func TestSortedIntArray_Contains(t *testing.T) { gtest.Case(t, func() { a1 := []int{1, 3, 5} array1 := garray.NewSortedIntArrayFrom(a1) - //gtest.Assert(array1.Contains(3),true) //todo 这一行应该返回true gtest.Assert(array1.Contains(4), false) }) } @@ -439,7 +472,6 @@ func TestSortedIntArray_Clear(t *testing.T) { array1 := garray.NewSortedIntArrayFrom(a1) array1.Clear() gtest.Assert(array1.Len(), 0) - }) } @@ -453,7 +485,6 @@ func TestSortedIntArray_Chunk(t *testing.T) { gtest.Assert(ns1[0], []int{1, 2}) gtest.Assert(ns1[2], []int{5}) gtest.Assert(len(ns2), 0) - }) } @@ -461,6 +492,7 @@ func TestSortedIntArray_SubSlice(t *testing.T) { gtest.Case(t, func() { a1 := []int{1, 2, 3, 4, 5} array1 := garray.NewSortedIntArrayFrom(a1) + array2 := garray.NewSortedIntArrayFrom(a1, true) ns1 := array1.SubSlice(1, 2) gtest.Assert(len(ns1), 2) gtest.Assert(ns1, []int{2, 3}) @@ -475,6 +507,10 @@ func TestSortedIntArray_SubSlice(t *testing.T) { ns4 := array1.SubSlice(3, 1) gtest.Assert(len(ns4), 1) gtest.Assert(ns4, []int{4}) + gtest.Assert(array1.SubSlice(-1, 1), []int{5}) + gtest.Assert(array1.SubSlice(-9, 1), nil) + gtest.Assert(array1.SubSlice(1, -9), nil) + gtest.Assert(array2.SubSlice(1, 2), []int{2, 3}) }) } @@ -519,7 +555,6 @@ func TestSortedIntArray_SetUnique(t *testing.T) { array1.SetUnique(true) gtest.Assert(array1.Len(), 5) gtest.Assert(array1, []int{1, 2, 3, 4, 5}) - }) } @@ -531,7 +566,6 @@ func TestIntArray_SetArray(t *testing.T) { array1.SetArray(a2) gtest.Assert(array1.Len(), 2) gtest.Assert(array1, []int{6, 7}) - }) } @@ -621,3 +655,171 @@ func TestIntArray_Remove(t *testing.T) { gtest.Assert(array1.Len(), 2) }) } + +func TestIntArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 2, 3, 4} + a1 := garray.NewIntArrayFrom(s1) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 3) + //go1 + go a1.LockFunc(func(n1 []int) { //读写锁 + time.Sleep(2 * time.Second) //暂停2秒 + n1[2] = 6 + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁,所go2读的时候被阻塞。 + gtest.Assert(a1.Contains(6), true) + }) +} + +func TestIntArray_SortFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 4, 3, 2} + a1 := garray.NewIntArrayFrom(s1) + func1 := func(v1, v2 int) bool { + return v1 < v2 + } + a11 := a1.SortFunc(func1) + gtest.Assert(a11, []int{1, 2, 3, 4}) + + }) +} + +func TestIntArray_RLockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 2, 3, 4} + a1 := garray.NewIntArrayFrom(s1) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 1) + //go1 + go a1.RLockFunc(func(n1 []int) { //读锁 + time.Sleep(2 * time.Second) //暂停1秒 + n1[2] = 6 + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertLT(t2-t1, 20) //go1加的读锁,所go2读的时候,并没有阻塞。 + gtest.Assert(a1.Contains(6), true) + }) +} + +func TestSortedIntArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 2, 3, 4} + a1 := garray.NewSortedIntArrayFrom(s1) + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 3) + //go1 + go a1.LockFunc(func(n1 []int) { //读写锁 + time.Sleep(2 * time.Second) //暂停2秒 + n1[2] = 6 + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁,所go2读的时候被阻塞。 + gtest.Assert(a1.Contains(6), true) + }) +} + +func TestSortedIntArray_RLockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 2, 3, 4} + a1 := garray.NewSortedIntArrayFrom(s1) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 1) + //go1 + go a1.RLockFunc(func(n1 []int) { //读锁 + time.Sleep(2 * time.Second) //暂停1秒 + n1[2] = 6 + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertLT(t2-t1, 20) //go1加的读锁,所go2读的时候,并没有阻塞。 + gtest.Assert(a1.Contains(6), true) + }) +} + +func TestSortedIntArray_Merge(t *testing.T) { + gtest.Case(t, func() { + func1 := func(v1, v2 interface{}) int { + if gconv.Int(v1) < gconv.Int(v2) { + return 0 + } + return 1 + } + i0 := []int{1, 2, 3, 4} + s2 := []string{"e", "f"} + i1 := garray.NewIntArrayFrom([]int{1, 2, 3}) + i2 := garray.NewArrayFrom([]interface{}{3}) + s3 := garray.NewStringArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + s5 := garray.NewSortedStringArrayFrom(s2) + s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) + a1 := garray.NewSortedIntArrayFrom(i0) + + gtest.Assert(a1.Merge(s2).Len(), 6) + gtest.Assert(a1.Merge(i1).Len(), 9) + gtest.Assert(a1.Merge(i2).Len(), 10) + gtest.Assert(a1.Merge(s3).Len(), 12) + gtest.Assert(a1.Merge(s4).Len(), 14) + gtest.Assert(a1.Merge(s5).Len(), 16) + gtest.Assert(a1.Merge(s6).Len(), 19) + }) +} diff --git a/g/container/garray/garray_z_unit_interface_test.go b/g/container/garray/garray_z_unit_interface_test.go index 971549a53..d4671f356 100644 --- a/g/container/garray/garray_z_unit_interface_test.go +++ b/g/container/garray/garray_z_unit_interface_test.go @@ -21,22 +21,29 @@ func Test_Array_Basic(t *testing.T) { gtest.Case(t, func() { expect := []interface{}{0, 1, 2, 3} array := garray.NewArrayFrom(expect) + array2 := garray.NewArrayFrom(expect) + array3 := garray.NewArrayFrom([]interface{}{}) gtest.Assert(array.Slice(), expect) array.Set(0, 100) gtest.Assert(array.Get(0), 100) gtest.Assert(array.Get(1), 1) gtest.Assert(array.Search(100), 0) + gtest.Assert(array3.Search(100), -1) gtest.Assert(array.Contains(100), true) gtest.Assert(array.Remove(0), 100) + + gtest.Assert(array2.Remove(3), 3) + gtest.Assert(array2.Remove(1), 1) + gtest.Assert(array.Contains(100), false) array.Append(4) gtest.Assert(array.Len(), 4) array.InsertBefore(0, 100) array.InsertAfter(0, 200) - gtest.Assert(array.Slice(), []interface{}{100, 200, 1, 2, 3, 4}) + gtest.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 4}) array.InsertBefore(5, 300) array.InsertAfter(6, 400) - gtest.Assert(array.Slice(), []interface{}{100, 200, 1, 2, 3, 300, 4, 400}) + gtest.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400}) gtest.Assert(array.Clear().Len(), 0) }) } @@ -112,20 +119,48 @@ func TestArray_Range(t *testing.T) { gtest.Case(t, func() { value1 := []interface{}{0, 1, 2, 3, 4, 5, 6} array1 := garray.NewArrayFrom(value1) + array2 := garray.NewArrayFrom(value1, true) gtest.Assert(array1.Range(0, 1), []interface{}{0}) gtest.Assert(array1.Range(1, 2), []interface{}{1}) gtest.Assert(array1.Range(0, 2), []interface{}{0, 1}) gtest.Assert(array1.Range(-1, 10), value1) + gtest.Assert(array1.Range(10, 2), nil) + gtest.Assert(array2.Range(1, 3), []interface{}{1, 2}) }) } func TestArray_Merge(t *testing.T) { gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3} - a2 := []interface{}{4, 5, 6, 7} - array1 := garray.NewArrayFrom(a1) - array2 := garray.NewArrayFrom(a2) + func1 := func(v1, v2 interface{}) int { + if gconv.Int(v1) < gconv.Int(v2) { + return 0 + } + return 1 + } + + i1 := []interface{}{0, 1, 2, 3} + i2 := []interface{}{4, 5, 6, 7} + array1 := garray.NewArrayFrom(i1) + array2 := garray.NewArrayFrom(i2) gtest.Assert(array1.Merge(array2).Slice(), []interface{}{0, 1, 2, 3, 4, 5, 6, 7}) + + //s1 := []string{"a", "b", "c", "d"} + s2 := []string{"e", "f"} + i3 := garray.NewIntArrayFrom([]int{1, 2, 3}) + i4 := garray.NewArrayFrom([]interface{}{3}) + s3 := garray.NewStringArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + s5 := garray.NewSortedStringArrayFrom(s2) + s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) + a1 := garray.NewArrayFrom(i1) + + gtest.Assert(a1.Merge(s2).Len(), 6) + gtest.Assert(a1.Merge(i3).Len(), 9) + gtest.Assert(a1.Merge(i4).Len(), 10) + gtest.Assert(a1.Merge(s3).Len(), 12) + gtest.Assert(a1.Merge(s4).Len(), 14) + gtest.Assert(a1.Merge(s5).Len(), 16) + gtest.Assert(a1.Merge(s6).Len(), 19) }) } @@ -134,9 +169,10 @@ func TestArray_Fill(t *testing.T) { a1 := []interface{}{0} a2 := []interface{}{0} array1 := garray.NewArrayFrom(a1) - array2 := garray.NewArrayFrom(a2) + array2 := garray.NewArrayFrom(a2, true) gtest.Assert(array1.Fill(1, 2, 100).Slice(), []interface{}{0, 100, 100}) gtest.Assert(array2.Fill(0, 2, 100).Slice(), []interface{}{100, 100}) + gtest.Assert(array2.Fill(-1, 2, 100).Slice(), []interface{}{100, 100}) }) } @@ -149,6 +185,7 @@ func TestArray_Chunk(t *testing.T) { gtest.Assert(chunks[0], []interface{}{1, 2}) gtest.Assert(chunks[1], []interface{}{3, 4}) gtest.Assert(chunks[2], []interface{}{5}) + gtest.Assert(array1.Chunk(0), nil) }) } @@ -166,9 +203,15 @@ func TestArray_SubSlice(t *testing.T) { gtest.Case(t, func() { a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} array1 := garray.NewArrayFrom(a1) + array2 := garray.NewArrayFrom(a1, true) gtest.Assert(array1.SubSlice(0, 2), []interface{}{0, 1}) gtest.Assert(array1.SubSlice(2, 2), []interface{}{2, 3}) gtest.Assert(array1.SubSlice(5, 8), []interface{}{5, 6}) + gtest.Assert(array1.SubSlice(9, 1), nil) + gtest.Assert(array1.SubSlice(-2, 2), []interface{}{5, 6}) + gtest.Assert(array1.SubSlice(-9, 2), nil) + gtest.Assert(array1.SubSlice(1, -2), nil) + gtest.Assert(array2.SubSlice(0, 2), []interface{}{0, 1}) }) } @@ -180,6 +223,14 @@ func TestArray_Rand(t *testing.T) { gtest.Assert(len(array1.Rands(10)), 7) gtest.AssertIN(array1.Rands(1)[0], a1) }) + + gtest.Case(t, func() { + s1 := []interface{}{"a", "b", "c", "d"} + a1 := garray.NewArrayFrom(s1) + i1 := a1.Rand() + gtest.Assert(a1.Contains(i1), true) + gtest.Assert(a1.Len(), 4) + }) } func TestArray_Shuffle(t *testing.T) { @@ -789,3 +840,67 @@ func TestSortedArray_Merge(t *testing.T) { }) } + +func TestArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []interface{}{"a", "b", "c", "d"} + a1 := garray.NewArrayFrom(s1) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 3) + //go1 + go a1.LockFunc(func(n1 []interface{}) { //读写锁 + time.Sleep(2 * time.Second) //暂停2秒 + n1[2] = "g" + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁,所go2读的时候被阻塞。 + gtest.Assert(a1.Contains("g"), true) + }) +} + +func TestArray_RLockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []interface{}{"a", "b", "c", "d"} + a1 := garray.NewArrayFrom(s1) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 1) + //go1 + go a1.RLockFunc(func(n1 []interface{}) { //读锁 + time.Sleep(2 * time.Second) //暂停1秒 + n1[2] = "g" + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertLT(t2-t1, 20) //go1加的读锁,所go2读的时候,并没有阻塞。 + gtest.Assert(a1.Contains("g"), true) + }) +} diff --git a/g/container/garray/garray_z_unit_string_test.go b/g/container/garray/garray_z_unit_string_test.go index 9f3547618..4e8e8fd6e 100644 --- a/g/container/garray/garray_z_unit_string_test.go +++ b/g/container/garray/garray_z_unit_string_test.go @@ -21,6 +21,8 @@ func Test_StringArray_Basic(t *testing.T) { gtest.Case(t, func() { expect := []string{"0", "1", "2", "3"} array := garray.NewStringArrayFrom(expect) + array2 := garray.NewStringArrayFrom(expect, true) + array3 := garray.NewStringArrayFrom([]string{}) gtest.Assert(array.Slice(), expect) array.Set(0, "100") gtest.Assert(array.Get(0), 100) @@ -38,6 +40,8 @@ func Test_StringArray_Basic(t *testing.T) { array.InsertAfter(6, "400") gtest.Assert(array.Slice(), []string{"100", "200", "1", "2", "3", "300", "4", "400"}) gtest.Assert(array.Clear().Len(), 0) + gtest.Assert(array2.Slice(), expect) + gtest.Assert(array3.Search("100"), -1) }) } @@ -100,20 +104,48 @@ func TestString_Range(t *testing.T) { gtest.Case(t, func() { value1 := []string{"0", "1", "2", "3", "4", "5", "6"} array1 := garray.NewStringArrayFrom(value1) + array2 := garray.NewStringArrayFrom(value1, true) gtest.Assert(array1.Range(0, 1), []interface{}{"0"}) gtest.Assert(array1.Range(1, 2), []interface{}{"1"}) gtest.Assert(array1.Range(0, 2), []interface{}{"0", "1"}) gtest.Assert(array1.Range(-1, 10), value1) + gtest.Assert(array1.Range(10, 1), nil) + gtest.Assert(array2.Range(0, 1), []interface{}{"0"}) }) } func TestStringArray_Merge(t *testing.T) { gtest.Case(t, func() { - a1 := []string{"0", "1", "2", "3"} - a2 := []string{"4", "5", "6", "7"} - array1 := garray.NewStringArrayFrom(a1) - array2 := garray.NewStringArrayFrom(a2) + a11 := []string{"0", "1", "2", "3"} + a21 := []string{"4", "5", "6", "7"} + array1 := garray.NewStringArrayFrom(a11) + array2 := garray.NewStringArrayFrom(a21) gtest.Assert(array1.Merge(array2).Slice(), []string{"0", "1", "2", "3", "4", "5", "6", "7"}) + + func1 := func(v1, v2 interface{}) int { + if gconv.Int(v1) < gconv.Int(v2) { + return 0 + } + return 1 + } + + s1 := []string{"a", "b", "c", "d"} + s2 := []string{"e", "f"} + i1 := garray.NewIntArrayFrom([]int{1, 2, 3}) + i2 := garray.NewArrayFrom([]interface{}{3}) + s3 := garray.NewStringArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + s5 := garray.NewSortedStringArrayFrom(s2) + s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) + a1 := garray.NewStringArrayFrom(s1) + + gtest.Assert(a1.Merge(s2).Len(), 6) + gtest.Assert(a1.Merge(i1).Len(), 9) + gtest.Assert(a1.Merge(i2).Len(), 10) + gtest.Assert(a1.Merge(s3).Len(), 12) + gtest.Assert(a1.Merge(s4).Len(), 14) + gtest.Assert(a1.Merge(s5).Len(), 16) + gtest.Assert(a1.Merge(s6).Len(), 19) }) } @@ -140,7 +172,6 @@ func TestStringArray_Chunk(t *testing.T) { gtest.Assert(chunks[1], []string{"3", "4"}) gtest.Assert(chunks[2], []string{"5"}) gtest.Assert(len(array1.Chunk(0)), 0) - }) } @@ -158,9 +189,15 @@ func TestStringArray_SubSlice(t *testing.T) { gtest.Case(t, func() { a1 := []string{"0", "1", "2", "3", "4", "5", "6"} array1 := garray.NewStringArrayFrom(a1) + array2 := garray.NewStringArrayFrom(a1, true) gtest.Assert(array1.SubSlice(0, 2), []string{"0", "1"}) gtest.Assert(array1.SubSlice(2, 2), []string{"2", "3"}) gtest.Assert(array1.SubSlice(5, 8), []string{"5", "6"}) + gtest.Assert(array1.SubSlice(8, 2), nil) + gtest.Assert(array1.SubSlice(1, -2), nil) + gtest.Assert(array1.SubSlice(-5, 2), []string{"2", "3"}) + gtest.Assert(array1.SubSlice(-10, 1), nil) + gtest.Assert(array2.SubSlice(0, 2), []string{"0", "1"}) }) } @@ -173,7 +210,6 @@ func TestStringArray_Rand(t *testing.T) { gtest.AssertIN(array1.Rands(1)[0], a1) gtest.Assert(len(array1.Rand()), 1) gtest.AssertIN(array1.Rand(), a1) - }) } @@ -182,10 +218,9 @@ func TestStringArray_PopRands(t *testing.T) { a1 := []string{"a", "b", "c", "d", "e", "f", "g"} a2 := []string{"1", "2", "3", "4", "5", "6", "7"} array1 := garray.NewStringArrayFrom(a1) - //todo gtest.AssertIN(array1.PopRands(1),a1) gtest.AssertIN(array1.PopRands(1), strings.Join(a1, ",")) gtest.AssertNI(array1.PopRands(1), strings.Join(a2, ",")) - + gtest.Assert(len(array1.PopRands(10)), 5) }) } @@ -276,26 +311,6 @@ func TestStringArray_Sum(t *testing.T) { }) } -//func TestStringArray_SortFunc(t *testing.T) { -// gtest.Case(t, func() { -// a1 := []string{"0","1","2","3","4","5","6"} -// //a2 := []string{"0","a","3","4","5","6"} -// array1 := garray.NewStringArrayFrom(a1) -// -// lesss:=func(v1,v2 string)bool{ -// if v1>v2{ -// return true -// } -// return false -// } -// gtest.Assert(array1.Len(),7) -// gtest.Assert(lesss("1","2"),false) -// gtest.Assert(array1.SortFunc(lesss("1","2")) ,false) -// -// -// }) -//} - func TestStringArray_PopRand(t *testing.T) { gtest.Case(t, func() { a1 := []string{"0", "1", "2", "3", "4", "5", "6"} @@ -325,7 +340,6 @@ func TestStringArray_CountValues(t *testing.T) { gtest.Assert(len(m1), 6) gtest.Assert(m1["2"], 1) gtest.Assert(m1["4"], 2) - }) } @@ -358,7 +372,6 @@ func TestSortedStringArray_SetArray(t *testing.T) { gtest.Assert(array1.Contains("d"), false) gtest.Assert(array1.Contains("b"), false) gtest.Assert(array1.Contains("g"), true) - }) } @@ -368,7 +381,7 @@ func TestSortedStringArray_Sort(t *testing.T) { array1 := garray.NewSortedStringArrayFrom(a1) gtest.Assert(array1, []string{"a", "b", "c", "d"}) - array1.Sort() //todo 这个SortedStringArray.sort这个方法没有必要, + array1.Sort() gtest.Assert(array1.Len(), 4) gtest.Assert(array1.Contains("c"), true) gtest.Assert(array1, []string{"a", "b", "c", "d"}) @@ -381,7 +394,6 @@ func TestSortedStringArray_Get(t *testing.T) { array1 := garray.NewSortedStringArrayFrom(a1) gtest.Assert(array1.Get(2), "c") gtest.Assert(array1.Get(0), "a") - }) } @@ -401,7 +413,6 @@ func TestSortedStringArray_Remove(t *testing.T) { // 此时array1里的元素只剩下2个 gtest.Assert(array1.Remove(1), "d") gtest.Assert(array1.Len(), 1) - }) } @@ -535,7 +546,6 @@ func TestSortedStringArray_Clear(t *testing.T) { array1 := garray.NewSortedStringArrayFrom(a1) array1.Clear() gtest.Assert(array1.Len(), 0) - }) } @@ -565,7 +575,6 @@ func TestSortedStringArray_SubSlice(t *testing.T) { gtest.Assert(s3, nil) gtest.Assert(array2.SubSlice(1, 3), []string{"b", "c", "d"}) - }) } @@ -583,7 +592,6 @@ func TestSortedStringArray_Rand(t *testing.T) { a1 := []string{"e", "a", "d"} array1 := garray.NewSortedStringArrayFrom(a1) gtest.AssertIN(array1.Rand(), []string{"e", "a", "d"}) - }) } @@ -654,7 +662,6 @@ func TestStringArray_Remove(t *testing.T) { s1 = array1.Remove(3) gtest.Assert(s1, "c") gtest.Assert(array1.Len(), 3) - }) } @@ -771,7 +778,6 @@ func TestSortedStringArray_Merge(t *testing.T) { s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) s5 := garray.NewSortedStringArrayFrom(s2) s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) - a1 := garray.NewSortedStringArrayFrom(s1) gtest.Assert(a1.Merge(s2).Len(), 6) @@ -781,6 +787,49 @@ func TestSortedStringArray_Merge(t *testing.T) { gtest.Assert(a1.Merge(s4).Len(), 14) gtest.Assert(a1.Merge(s5).Len(), 16) gtest.Assert(a1.Merge(s6).Len(), 19) - + }) +} + +func TestStringArray_SortFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []string{"a", "d", "c", "b"} + a1 := garray.NewStringArrayFrom(s1) + func1 := func(v1, v2 string) bool { + return v1 < v2 + } + a11 := a1.SortFunc(func1) + gtest.Assert(a11, []string{"a", "b", "c", "d"}) + }) +} + +func TestStringArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []string{"a", "b", "c", "d"} + a1 := garray.NewStringArrayFrom(s1) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 3) + //go1 + go a1.LockFunc(func(n1 []string) { //读写锁 + time.Sleep(2 * time.Second) //暂停2秒 + n1[2] = "g" + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + //go2 + go func() { + time.Sleep(100 * time.Millisecond) //故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 //等待go1完成 + + // 防止ci抖动,以豪秒为单位 + gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁,所go2读的时候被阻塞。 + gtest.Assert(a1.Contains("g"), true) }) }