diff --git a/container/garray/garray_normal_any.go b/container/garray/garray_normal_any.go index cc43e4c88..827941c3a 100644 --- a/container/garray/garray_normal_any.go +++ b/container/garray/garray_normal_any.go @@ -617,3 +617,13 @@ func (a *Array) MarshalJSON() ([]byte, error) { defer a.mu.RUnlock() return json.Marshal(a.array) } + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *Array) UnmarshalJSON(b []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + if err := json.Unmarshal(b, &a.array); err != nil { + return err + } + return nil +} diff --git a/container/garray/garray_normal_int.go b/container/garray/garray_normal_int.go index 0f6ac96a6..2683f96d6 100644 --- a/container/garray/garray_normal_int.go +++ b/container/garray/garray_normal_int.go @@ -624,3 +624,13 @@ func (a *IntArray) MarshalJSON() ([]byte, error) { defer a.mu.RUnlock() return json.Marshal(a.array) } + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *IntArray) UnmarshalJSON(b []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + if err := json.Unmarshal(b, &a.array); err != nil { + return err + } + return nil +} diff --git a/container/garray/garray_normal_str.go b/container/garray/garray_normal_str.go index 871a25aa1..fd9ec956e 100644 --- a/container/garray/garray_normal_str.go +++ b/container/garray/garray_normal_str.go @@ -624,3 +624,13 @@ func (a *StrArray) MarshalJSON() ([]byte, error) { defer a.mu.RUnlock() return json.Marshal(a.array) } + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *StrArray) UnmarshalJSON(b []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + if err := json.Unmarshal(b, &a.array); err != nil { + return err + } + return nil +} diff --git a/container/garray/garray_sorted_any.go b/container/garray/garray_sorted_any.go index ea8057bf4..b9a1bece9 100644 --- a/container/garray/garray_sorted_any.go +++ b/container/garray/garray_sorted_any.go @@ -541,7 +541,7 @@ func (a *SortedArray) String() string { a.mu.RLock() defer a.mu.RUnlock() jsonContent, _ := json.Marshal(a.array) - return string(jsonContent) + return gconv.UnsafeBytesToStr(jsonContent) } // MarshalJSON implements the interface MarshalJSON for json.Marshal. @@ -550,3 +550,16 @@ func (a *SortedArray) MarshalJSON() ([]byte, error) { defer a.mu.RUnlock() return json.Marshal(a.array) } + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *SortedArray) UnmarshalJSON(b []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + if err := json.Unmarshal(b, &a.array); err != nil { + return err + } + sort.Slice(a.array, func(i, j int) bool { + return a.comparator(a.array[i], a.array[j]) < 0 + }) + return nil +} diff --git a/container/garray/garray_sorted_int.go b/container/garray/garray_sorted_int.go index 73d4b20a6..20626d5b6 100644 --- a/container/garray/garray_sorted_int.go +++ b/container/garray/garray_sorted_int.go @@ -549,3 +549,14 @@ func (a *SortedIntArray) MarshalJSON() ([]byte, error) { defer a.mu.RUnlock() return json.Marshal(a.array) } + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *SortedIntArray) UnmarshalJSON(b []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + if err := json.Unmarshal(b, &a.array); err != nil { + return err + } + sort.Ints(a.array) + return nil +} diff --git a/container/garray/garray_sorted_str.go b/container/garray/garray_sorted_str.go index 08848641b..457d0db3a 100644 --- a/container/garray/garray_sorted_str.go +++ b/container/garray/garray_sorted_str.go @@ -10,6 +10,7 @@ import ( "bytes" "encoding/json" "math" + "sort" "github.com/gogf/gf/container/gtype" "github.com/gogf/gf/internal/rwmutex" @@ -548,3 +549,14 @@ func (a *SortedStrArray) MarshalJSON() ([]byte, error) { defer a.mu.RUnlock() return json.Marshal(a.array) } + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *SortedStrArray) UnmarshalJSON(b []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + if err := json.Unmarshal(b, &a.array); err != nil { + return err + } + sort.Strings(a.array) + return nil +} diff --git a/container/garray/garray_z_unit_basic_test.go b/container/garray/garray_z_unit_all_basic_test.go similarity index 100% rename from container/garray/garray_z_unit_basic_test.go rename to container/garray/garray_z_unit_all_basic_test.go diff --git a/container/garray/garray_z_unit_normal_any_array_test.go b/container/garray/garray_z_unit_normal_any_array_test.go new file mode 100644 index 000000000..fdf33da06 --- /dev/null +++ b/container/garray/garray_z_unit_normal_any_array_test.go @@ -0,0 +1,411 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// go test *.go + +package garray_test + +import ( + "encoding/json" + "testing" + "time" + + "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" +) + +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, 2, 2, 3, 4}) + array.InsertBefore(5, 300) + array.InsertAfter(6, 400) + gtest.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400}) + gtest.Assert(array.Clear().Len(), 0) + }) +} + +func TestArray_Sort(t *testing.T) { + gtest.Case(t, func() { + expect1 := []interface{}{0, 1, 2, 3} + expect2 := []interface{}{3, 2, 1, 0} + array := garray.NewArray() + for i := 3; i >= 0; i-- { + array.Append(i) + } + array.SortFunc(func(v1, v2 interface{}) bool { + return v1.(int) < v2.(int) + }) + gtest.Assert(array.Slice(), expect1) + array.SortFunc(func(v1, v2 interface{}) bool { + return v1.(int) > v2.(int) + }) + gtest.Assert(array.Slice(), expect2) + }) +} + +func TestArray_Unique(t *testing.T) { + gtest.Case(t, func() { + expect := []interface{}{1, 1, 2, 3} + array := garray.NewArrayFrom(expect) + gtest.Assert(array.Unique().Slice(), []interface{}{1, 2, 3}) + }) +} + +func TestArray_PushAndPop(t *testing.T) { + gtest.Case(t, func() { + expect := []interface{}{0, 1, 2, 3} + array := garray.NewArrayFrom(expect) + gtest.Assert(array.Slice(), expect) + gtest.Assert(array.PopLeft(), 0) + gtest.Assert(array.PopRight(), 3) + gtest.AssertIN(array.PopRand(), []interface{}{1, 2}) + gtest.AssertIN(array.PopRand(), []interface{}{1, 2}) + gtest.Assert(array.Len(), 0) + array.PushLeft(1).PushRight(2) + gtest.Assert(array.Slice(), []interface{}{1, 2}) + }) +} + +func TestArray_PopRands(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{100, 200, 300, 400, 500, 600} + array := garray.NewFromCopy(a1) + gtest.AssertIN(array.PopRands(2), []interface{}{100, 200, 300, 400, 500, 600}) + }) +} + +func TestArray_PopLeftsAndPopRights(t *testing.T) { + gtest.Case(t, func() { + value1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + value2 := []interface{}{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewArrayFrom(value1) + array2 := garray.NewArrayFrom(value2) + gtest.Assert(array1.PopLefts(2), []interface{}{0, 1}) + gtest.Assert(array1.Slice(), []interface{}{2, 3, 4, 5, 6}) + gtest.Assert(array1.PopRights(2), []interface{}{5, 6}) + gtest.Assert(array1.Slice(), []interface{}{2, 3, 4}) + gtest.Assert(array1.PopRights(20), []interface{}{2, 3, 4}) + gtest.Assert(array1.Slice(), []interface{}{}) + gtest.Assert(array2.PopLefts(20), []interface{}{0, 1, 2, 3, 4, 5, 6}) + gtest.Assert(array2.Slice(), []interface{}{}) + }) +} + +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() { + 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.NewStrArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + s5 := garray.NewSortedStrArrayFrom(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) + }) +} + +func TestArray_Fill(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0} + a2 := []interface{}{0} + array1 := garray.NewArrayFrom(a1) + 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}) + }) +} + +func TestArray_Chunk(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{1, 2, 3, 4, 5} + array1 := garray.NewArrayFrom(a1) + chunks := array1.Chunk(2) + gtest.Assert(len(chunks), 3) + 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) + }) +} + +func TestArray_Pad(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0} + array1 := garray.NewArrayFrom(a1) + gtest.Assert(array1.Pad(3, 1).Slice(), []interface{}{0, 1, 1}) + gtest.Assert(array1.Pad(-4, 1).Slice(), []interface{}{1, 0, 1, 1}) + gtest.Assert(array1.Pad(3, 1).Slice(), []interface{}{1, 0, 1, 1}) + }) +} + +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}) + }) +} + +func TestArray_Rand(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewArrayFrom(a1) + gtest.Assert(len(array1.Rands(2)), 2) + 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) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewArrayFrom(a1) + gtest.Assert(array1.Shuffle().Len(), 7) + }) +} + +func TestArray_Reverse(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewArrayFrom(a1) + gtest.Assert(array1.Reverse().Slice(), []interface{}{6, 5, 4, 3, 2, 1, 0}) + }) +} + +func TestArray_Join(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewArrayFrom(a1) + gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6") + }) +} + +func TestArray_Replace(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + a2 := []interface{}{"a", "b", "c"} + a3 := []interface{}{"m", "n", "p", "z", "x", "y", "d", "u"} + array1 := garray.NewArrayFrom(a1) + array2 := array1.Replace(a2) + gtest.Assert(array2.Len(), 7) + gtest.Assert(array2.Contains("b"), true) + gtest.Assert(array2.Contains(4), true) + gtest.Assert(array2.Contains("v"), false) + array3 := array1.Replace(a3) + gtest.Assert(array3.Len(), 7) + gtest.Assert(array3.Contains(4), false) + gtest.Assert(array3.Contains("p"), true) + gtest.Assert(array3.Contains("u"), false) + }) +} + +func TestArray_SetArray(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} + a2 := []interface{}{"a", "b", "c"} + + array1 := garray.NewArrayFrom(a1) + array1 = array1.SetArray(a2) + gtest.Assert(array1.Len(), 3) + gtest.Assert(array1.Contains("b"), true) + gtest.Assert(array1.Contains("5"), false) + }) +} + +func TestArray_Sum(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3} + a2 := []interface{}{"a", "b", "c"} + a3 := []interface{}{"a", "1", "2"} + + array1 := garray.NewArrayFrom(a1) + array2 := garray.NewArrayFrom(a2) + array3 := garray.NewArrayFrom(a3) + + gtest.Assert(array1.Sum(), 6) + gtest.Assert(array2.Sum(), 0) + gtest.Assert(array3.Sum(), 3) + + }) +} + +func TestArray_Clone(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{0, 1, 2, 3} + array1 := garray.NewArrayFrom(a1) + array2 := array1.Clone() + + gtest.Assert(array1.Len(), 4) + gtest.Assert(array2.Sum(), 6) + gtest.AssertEQ(array1, array2) + + }) +} + +func TestArray_CountValues(t *testing.T) { + gtest.Case(t, func() { + a1 := []interface{}{"a", "b", "c", "d", "e", "d"} + array1 := garray.NewArrayFrom(a1) + array2 := array1.CountValues() + gtest.Assert(len(array2), 5) + gtest.Assert(array2["b"], 1) + gtest.Assert(array2["d"], 2) + }) +} + +func TestArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []interface{}{"a", "b", "c", "d"} + a1 := garray.NewArrayFrom(s1, true) + + 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, true) + + 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) + }) +} + +func TestArray_Json(t *testing.T) { + gtest.Case(t, func() { + s1 := []interface{}{"a", "b", "d", "c"} + a1 := garray.NewArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + gtest.Assert(b1, b2) + gtest.Assert(err1, err2) + + a2 := garray.New() + err1 = json.Unmarshal(b2, &a2) + gtest.Assert(a2.Slice(), s1) + }) +} diff --git a/container/garray/garray_z_unit_int_test.go b/container/garray/garray_z_unit_normal_int_array_test.go similarity index 53% rename from container/garray/garray_z_unit_int_test.go rename to container/garray/garray_z_unit_normal_int_array_test.go index bb2f0838c..dba8cb3ac 100644 --- a/container/garray/garray_z_unit_int_test.go +++ b/container/garray/garray_z_unit_normal_int_array_test.go @@ -9,6 +9,7 @@ package garray_test import ( + "encoding/json" "testing" "time" @@ -260,305 +261,6 @@ func TestIntArray_Join(t *testing.T) { }) } -func TestNewSortedIntArrayFrom(t *testing.T) { - gtest.Case(t, func() { - 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) - }) -} - -func TestNewSortedIntArrayFromCopy(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{0, 5, 2, 1, 4, 3, 6} - array1 := garray.NewSortedIntArrayFromCopy(a1, false) - gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6") - }) -} - -func TestSortedIntArray_SetArray(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{0, 1, 2, 3} - a2 := []int{4, 5, 6} - array1 := garray.NewSortedIntArrayFrom(a1) - array2 := array1.SetArray(a2) - - gtest.Assert(array2.Len(), 3) - gtest.Assert(array2.Search(3), -1) - gtest.Assert(array2.Search(5), 1) - gtest.Assert(array2.Search(6), 2) - }) -} - -func TestSortedIntArray_Sort(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{0, 3, 2, 1} - - array1 := garray.NewSortedIntArrayFrom(a1) - array2 := array1.Sort() - - gtest.Assert(array2.Len(), 4) - gtest.Assert(array2, []int{0, 1, 2, 3}) - }) -} - -func TestSortedIntArray_Get(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 0} - array1 := garray.NewSortedIntArrayFrom(a1) - gtest.Assert(array1.Get(0), 0) - gtest.Assert(array1.Get(1), 1) - gtest.Assert(array1.Get(3), 5) - }) -} - -func TestSortedIntArray_Remove(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 0} - array1 := garray.NewSortedIntArrayFrom(a1) - i1 := array1.Remove(2) - gtest.Assert(i1, 3) - gtest.Assert(array1.Search(5), 2) - - // 再次删除剩下的数组中的第一个 - i2 := array1.Remove(0) - gtest.Assert(i2, 0) - gtest.Assert(array1.Search(5), 1) - - a2 := []int{1, 3, 4} - array2 := garray.NewSortedIntArrayFrom(a2) - i3 := array2.Remove(1) - gtest.Assert(array2.Search(1), 0) - gtest.Assert(i3, 3) - i3 = array2.Remove(1) - gtest.Assert(array2.Search(4), -1) - gtest.Assert(i3, 4) - }) -} - -func TestSortedIntArray_PopLeft(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 2} - array1 := garray.NewSortedIntArrayFrom(a1) - i1 := array1.PopLeft() - gtest.Assert(i1, 1) - gtest.Assert(array1.Len(), 3) - gtest.Assert(array1.Search(1), -1) - }) -} - -func TestSortedIntArray_PopRight(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 2} - array1 := garray.NewSortedIntArrayFrom(a1) - i1 := array1.PopRight() - gtest.Assert(i1, 5) - gtest.Assert(array1.Len(), 3) - gtest.Assert(array1.Search(5), -1) - }) -} - -func TestSortedIntArray_PopRand(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 2} - array1 := garray.NewSortedIntArrayFrom(a1) - i1 := array1.PopRand() - gtest.Assert(array1.Len(), 3) - gtest.Assert(array1.Search(i1), -1) - gtest.AssertIN(i1, []int{1, 3, 5, 2}) - }) -} - -func TestSortedIntArray_PopRands(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 2} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.PopRands(2) - gtest.Assert(array1.Len(), 2) - gtest.AssertIN(ns1, []int{1, 3, 5, 2}) - - a2 := []int{1, 3, 5, 2} - array2 := garray.NewSortedIntArrayFrom(a2) - ns2 := array2.PopRands(5) - gtest.Assert(array2.Len(), 0) - gtest.Assert(len(ns2), 4) - gtest.AssertIN(ns2, []int{1, 3, 5, 2}) - }) -} - -func TestSortedIntArray_PopLefts(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 2} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.PopLefts(2) - gtest.Assert(array1.Len(), 2) - gtest.Assert(ns1, []int{1, 2}) - - a2 := []int{1, 3, 5, 2} - array2 := garray.NewSortedIntArrayFrom(a2) - ns2 := array2.PopLefts(5) - gtest.Assert(array2.Len(), 0) - gtest.AssertIN(ns2, []int{1, 3, 5, 2}) - }) -} - -func TestSortedIntArray_PopRights(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5, 2} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.PopRights(2) - gtest.Assert(array1.Len(), 2) - gtest.Assert(ns1, []int{3, 5}) - - a2 := []int{1, 3, 5, 2} - array2 := garray.NewSortedIntArrayFrom(a2) - ns2 := array2.PopRights(5) - gtest.Assert(array2.Len(), 0) - gtest.AssertIN(ns2, []int{1, 3, 5, 2}) - }) -} - -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}) - - ns2 := array1.Range(5, 4) - gtest.Assert(len(ns2), 0) - - ns3 := array1.Range(-1, 4) - gtest.Assert(len(ns3), 4) - - nsl := array1.Range(5, 8) - gtest.Assert(len(nsl), 1) - gtest.Assert(array2.Range(1, 2), []int{2}) - }) -} - -func TestSortedIntArray_Sum(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - n1 := array1.Sum() - gtest.Assert(n1, 9) - }) -} - -func TestSortedIntArray_Contains(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - gtest.Assert(array1.Contains(4), false) - }) -} - -func TestSortedIntArray_Clone(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - array2 := array1.Clone() - gtest.Assert(array2.Len(), 3) - gtest.Assert(array2, array1) - }) -} - -func TestSortedIntArray_Clear(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 3, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - array1.Clear() - gtest.Assert(array1.Len(), 0) - }) -} - -func TestSortedIntArray_Chunk(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 2, 3, 4, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.Chunk(2) //按每几个元素切成一个数组 - ns2 := array1.Chunk(-1) - gtest.Assert(len(ns1), 3) - gtest.Assert(ns1[0], []int{1, 2}) - gtest.Assert(ns1[2], []int{5}) - gtest.Assert(len(ns2), 0) - }) -} - -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}) - - ns2 := array1.SubSlice(7, 2) - gtest.Assert(len(ns2), 0) - - ns3 := array1.SubSlice(3, 5) - gtest.Assert(len(ns3), 2) - gtest.Assert(ns3, []int{4, 5}) - - 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}) - }) -} - -func TestSortedIntArray_Rand(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 2, 3, 4, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.Rand() //按每几个元素切成一个数组 - gtest.AssertIN(ns1, a1) - }) -} - -func TestSortedIntArray_Rands(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 2, 3, 4, 5} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.Rands(2) //按每几个元素切成一个数组 - gtest.AssertIN(ns1, a1) - gtest.Assert(len(ns1), 2) - - ns2 := array1.Rands(6) //按每几个元素切成一个数组 - gtest.AssertIN(ns2, a1) - gtest.Assert(len(ns2), 5) - }) -} - -func TestSortedIntArray_CountValues(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 2, 3, 4, 5, 3} - array1 := garray.NewSortedIntArrayFrom(a1) - ns1 := array1.CountValues() //按每几个元素切成一个数组 - gtest.Assert(len(ns1), 5) - gtest.Assert(ns1[2], 1) - gtest.Assert(ns1[3], 2) - }) -} - -func TestSortedIntArray_SetUnique(t *testing.T) { - gtest.Case(t, func() { - a1 := []int{1, 2, 3, 4, 5, 3} - array1 := garray.NewSortedIntArrayFrom(a1) - array1.SetUnique(true) - gtest.Assert(array1.Len(), 5) - gtest.Assert(array1, []int{1, 2, 3, 4, 5}) - }) -} - func TestIntArray_SetArray(t *testing.T) { gtest.Case(t, func() { a1 := []int{1, 2, 3, 5} @@ -734,93 +436,17 @@ func TestIntArray_RLockFunc(t *testing.T) { }) } -func TestSortedIntArray_LockFunc(t *testing.T) { +func TestIntArray_Json(t *testing.T) { gtest.Case(t, func() { - s1 := []int{1, 2, 3, 4} - a1 := garray.NewSortedIntArrayFrom(s1, true) - 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) - }) + s1 := []int{1, 4, 3, 2} + a1 := garray.NewIntArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + gtest.Assert(b1, b2) + gtest.Assert(err1, err2) - //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, true) - - 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.NewStrArrayFrom([]string{"g", "h"}) - s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) - s5 := garray.NewSortedStrArrayFrom(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) + a2 := garray.NewIntArray() + err1 = json.Unmarshal(b2, &a2) + gtest.Assert(a2.Slice(), s1) }) } diff --git a/container/garray/garray_z_unit_str_test.go b/container/garray/garray_z_unit_normal_str_array_test.go similarity index 54% rename from container/garray/garray_z_unit_str_test.go rename to container/garray/garray_z_unit_normal_str_array_test.go index fd3a612b5..d2b686e12 100644 --- a/container/garray/garray_z_unit_str_test.go +++ b/container/garray/garray_z_unit_normal_str_array_test.go @@ -9,6 +9,7 @@ package garray_test import ( + "encoding/json" "strings" "testing" "time" @@ -345,315 +346,6 @@ func TestStrArray_CountValues(t *testing.T) { }) } -func TestNewSortedStrArrayFrom(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"a", "d", "c", "b"} - s1 := garray.NewSortedStrArrayFrom(a1, true) - gtest.Assert(s1, []string{"a", "b", "c", "d"}) - s2 := garray.NewSortedStrArrayFrom(a1, false) - gtest.Assert(s2, []string{"a", "b", "c", "d"}) - }) -} - -func TestNewSortedStrArrayFromCopy(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"a", "d", "c", "b"} - s1 := garray.NewSortedStrArrayFromCopy(a1, true) - gtest.Assert(s1.Len(), 4) - gtest.Assert(s1, []string{"a", "b", "c", "d"}) - }) -} - -func TestSortedStrArray_SetArray(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"a", "d", "c", "b"} - a2 := []string{"f", "g", "h"} - array1 := garray.NewSortedStrArrayFrom(a1) - array1.SetArray(a2) - gtest.Assert(array1.Len(), 3) - gtest.Assert(array1.Contains("d"), false) - gtest.Assert(array1.Contains("b"), false) - gtest.Assert(array1.Contains("g"), true) - }) -} - -func TestSortedStrArray_Sort(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - - gtest.Assert(array1, []string{"a", "b", "c", "d"}) - array1.Sort() - gtest.Assert(array1.Len(), 4) - gtest.Assert(array1.Contains("c"), true) - gtest.Assert(array1, []string{"a", "b", "c", "d"}) - }) -} - -func TestSortedStrArray_Get(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - gtest.Assert(array1.Get(2), "c") - gtest.Assert(array1.Get(0), "a") - }) -} - -func TestSortedStrArray_Remove(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - gtest.Assert(array1.Remove(2), "c") - gtest.Assert(array1.Get(2), "d") - gtest.Assert(array1.Len(), 3) - gtest.Assert(array1.Contains("c"), false) - - gtest.Assert(array1.Remove(0), "a") - gtest.Assert(array1.Len(), 2) - gtest.Assert(array1.Contains("a"), false) - - // 此时array1里的元素只剩下2个 - gtest.Assert(array1.Remove(1), "d") - gtest.Assert(array1.Len(), 1) - }) -} - -func TestSortedStrArray_PopLeft(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.PopLeft() - gtest.Assert(s1, "a") - gtest.Assert(array1.Len(), 4) - gtest.Assert(array1.Contains("a"), false) - }) -} - -func TestSortedStrArray_PopRight(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.PopRight() - gtest.Assert(s1, "e") - gtest.Assert(array1.Len(), 4) - gtest.Assert(array1.Contains("e"), false) - }) -} - -func TestSortedStrArray_PopRand(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.PopRand() - gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"}) - gtest.Assert(array1.Len(), 4) - gtest.Assert(array1.Contains(s1), false) - }) -} - -func TestSortedStrArray_PopRands(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.PopRands(2) - gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"}) - gtest.Assert(array1.Len(), 3) - gtest.Assert(len(s1), 2) - - s1 = array1.PopRands(4) - gtest.Assert(len(s1), 3) - gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"}) - }) -} - -func TestSortedStrArray_PopLefts(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.PopLefts(2) - gtest.Assert(s1, []string{"a", "b"}) - gtest.Assert(array1.Len(), 3) - gtest.Assert(len(s1), 2) - - s1 = array1.PopLefts(4) - gtest.Assert(len(s1), 3) - gtest.Assert(s1, []string{"c", "d", "e"}) - }) -} - -func TestSortedStrArray_PopRights(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.PopRights(2) - gtest.Assert(s1, []string{"f", "g"}) - gtest.Assert(array1.Len(), 5) - gtest.Assert(len(s1), 2) - s1 = array1.PopRights(6) - gtest.Assert(len(s1), 5) - gtest.Assert(s1, []string{"a", "b", "c", "d", "e"}) - gtest.Assert(array1.Len(), 0) - }) -} - -func TestSortedStrArray_Range(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - array1 := garray.NewSortedStrArrayFrom(a1) - array2 := garray.NewSortedStrArrayFrom(a1, true) - s1 := array1.Range(2, 4) - gtest.Assert(len(s1), 2) - gtest.Assert(s1, []string{"c", "d"}) - - s1 = array1.Range(-1, 2) - gtest.Assert(len(s1), 2) - gtest.Assert(s1, []string{"a", "b"}) - - s1 = array1.Range(4, 8) - gtest.Assert(len(s1), 3) - gtest.Assert(s1, []string{"e", "f", "g"}) - gtest.Assert(array1.Range(10, 2), nil) - - s2 := array2.Range(2, 4) - gtest.Assert(s2, []string{"c", "d"}) - - }) -} - -func TestSortedStrArray_Sum(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - a2 := []string{"1", "2", "3", "4", "a"} - array1 := garray.NewSortedStrArrayFrom(a1) - array2 := garray.NewSortedStrArrayFrom(a2) - gtest.Assert(array1.Sum(), 0) - gtest.Assert(array2.Sum(), 10) - }) -} - -func TestSortedStrArray_Clone(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - array1 := garray.NewSortedStrArrayFrom(a1) - array2 := array1.Clone() - gtest.Assert(array1, array2) - array1.Remove(1) - gtest.Assert(array2.Len(), 7) - }) -} - -func TestSortedStrArray_Clear(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - array1 := garray.NewSortedStrArrayFrom(a1) - array1.Clear() - gtest.Assert(array1.Len(), 0) - }) -} - -func TestSortedStrArray_SubSlice(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - array1 := garray.NewSortedStrArrayFrom(a1) - array2 := garray.NewSortedStrArrayFrom(a1, true) - s1 := array1.SubSlice(1, 3) - gtest.Assert(len(s1), 3) - gtest.Assert(s1, []string{"b", "c", "d"}) - gtest.Assert(array1.Len(), 7) - - s2 := array1.SubSlice(1, 10) - gtest.Assert(len(s2), 6) - - s3 := array1.SubSlice(10, 2) - gtest.Assert(len(s3), 0) - - s3 = array1.SubSlice(-5, 2) - gtest.Assert(s3, []string{"c", "d"}) - - s3 = array1.SubSlice(-10, 2) - gtest.Assert(s3, nil) - - s3 = array1.SubSlice(1, -2) - gtest.Assert(s3, nil) - - gtest.Assert(array2.SubSlice(1, 3), []string{"b", "c", "d"}) - }) -} - -func TestSortedStrArray_Len(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "c", "b", "f", "g"} - array1 := garray.NewSortedStrArrayFrom(a1) - gtest.Assert(array1.Len(), 7) - - }) -} - -func TestSortedStrArray_Rand(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d"} - array1 := garray.NewSortedStrArrayFrom(a1) - gtest.AssertIN(array1.Rand(), []string{"e", "a", "d"}) - }) -} - -func TestSortedStrArray_Rands(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d"} - array1 := garray.NewSortedStrArrayFrom(a1) - s1 := array1.Rands(2) - - gtest.AssertIN(s1, []string{"e", "a", "d"}) - gtest.Assert(len(s1), 2) - - s1 = array1.Rands(4) - gtest.AssertIN(s1, []string{"e", "a", "d"}) - gtest.Assert(len(s1), 3) - }) -} - -func TestSortedStrArray_Join(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d"} - array1 := garray.NewSortedStrArrayFrom(a1) - gtest.Assert(array1.Join(","), "a,d,e") - gtest.Assert(array1.Join("."), "a.d.e") - }) -} - -func TestSortedStrArray_CountValues(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "a", "c"} - array1 := garray.NewSortedStrArrayFrom(a1) - m1 := array1.CountValues() - gtest.Assert(m1["a"], 2) - gtest.Assert(m1["d"], 1) - - }) -} - -func TestSortedStrArray_Chunk(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "a", "c"} - array1 := garray.NewSortedStrArrayFrom(a1) - array2 := array1.Chunk(2) - gtest.Assert(len(array2), 3) - gtest.Assert(len(array2[0]), 2) - gtest.Assert(array2[1], []string{"c", "d"}) - gtest.Assert(array1.Chunk(0), nil) - }) -} - -func TestSortedStrArray_SetUnique(t *testing.T) { - gtest.Case(t, func() { - a1 := []string{"e", "a", "d", "a", "c"} - array1 := garray.NewSortedStrArrayFrom(a1) - array2 := array1.SetUnique(true) - gtest.Assert(array2.Len(), 4) - gtest.Assert(array2, []string{"a", "c", "d", "e"}) - }) -} - func TestStrArray_Remove(t *testing.T) { gtest.Case(t, func() { a1 := []string{"e", "a", "d", "a", "c"} @@ -699,99 +391,6 @@ func TestStrArray_RLockFunc(t *testing.T) { }) } -func TestSortedStrArray_LockFunc(t *testing.T) { - gtest.Case(t, func() { - s1 := []string{"a", "b", "c", "d"} - a1 := garray.NewSortedStrArrayFrom(s1, true) - - 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) - }) -} - -func TestSortedStrArray_RLockFunc(t *testing.T) { - gtest.Case(t, func() { - s1 := []string{"a", "b", "c", "d"} - a1 := garray.NewSortedStrArrayFrom(s1, true) - - ch1 := make(chan int64, 3) - ch2 := make(chan int64, 1) - //go1 - go a1.RLockFunc(func(n1 []string) { //读锁 - 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) - }) -} - -func TestSortedStrArray_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 - } - - s1 := []string{"a", "b", "c", "d"} - s2 := []string{"e", "f"} - i1 := garray.NewIntArrayFrom([]int{1, 2, 3}) - i2 := garray.NewArrayFrom([]interface{}{3}) - s3 := garray.NewStrArrayFrom([]string{"g", "h"}) - s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) - s5 := garray.NewSortedStrArrayFrom(s2) - s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) - a1 := garray.NewSortedStrArrayFrom(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) - }) -} - func TestStrArray_SortFunc(t *testing.T) { gtest.Case(t, func() { s1 := []string{"a", "d", "c", "b"} @@ -835,3 +434,18 @@ func TestStrArray_LockFunc(t *testing.T) { gtest.Assert(a1.Contains("g"), true) }) } + +func TestStrArray_Json(t *testing.T) { + gtest.Case(t, func() { + s1 := []string{"a", "b", "d", "c"} + a1 := garray.NewStrArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + gtest.Assert(b1, b2) + gtest.Assert(err1, err2) + + a2 := garray.NewStrArray() + err1 = json.Unmarshal(b2, &a2) + gtest.Assert(a2.Slice(), s1) + }) +} diff --git a/container/garray/garray_z_unit_any_test.go b/container/garray/garray_z_unit_sorted_any_array_test.go similarity index 56% rename from container/garray/garray_z_unit_any_test.go rename to container/garray/garray_z_unit_sorted_any_array_test.go index d98c66337..d182d8d95 100644 --- a/container/garray/garray_z_unit_any_test.go +++ b/container/garray/garray_z_unit_sorted_any_array_test.go @@ -9,6 +9,8 @@ package garray_test import ( + "encoding/json" + "github.com/gogf/gf/util/gutil" "strings" "testing" "time" @@ -18,319 +20,6 @@ import ( "github.com/gogf/gf/util/gconv" ) -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, 2, 2, 3, 4}) - array.InsertBefore(5, 300) - array.InsertAfter(6, 400) - gtest.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400}) - gtest.Assert(array.Clear().Len(), 0) - }) -} - -func TestArray_Sort(t *testing.T) { - gtest.Case(t, func() { - expect1 := []interface{}{0, 1, 2, 3} - expect2 := []interface{}{3, 2, 1, 0} - array := garray.NewArray() - for i := 3; i >= 0; i-- { - array.Append(i) - } - array.SortFunc(func(v1, v2 interface{}) bool { - return v1.(int) < v2.(int) - }) - gtest.Assert(array.Slice(), expect1) - array.SortFunc(func(v1, v2 interface{}) bool { - return v1.(int) > v2.(int) - }) - gtest.Assert(array.Slice(), expect2) - }) -} - -func TestArray_Unique(t *testing.T) { - gtest.Case(t, func() { - expect := []interface{}{1, 1, 2, 3} - array := garray.NewArrayFrom(expect) - gtest.Assert(array.Unique().Slice(), []interface{}{1, 2, 3}) - }) -} - -func TestArray_PushAndPop(t *testing.T) { - gtest.Case(t, func() { - expect := []interface{}{0, 1, 2, 3} - array := garray.NewArrayFrom(expect) - gtest.Assert(array.Slice(), expect) - gtest.Assert(array.PopLeft(), 0) - gtest.Assert(array.PopRight(), 3) - gtest.AssertIN(array.PopRand(), []interface{}{1, 2}) - gtest.AssertIN(array.PopRand(), []interface{}{1, 2}) - gtest.Assert(array.Len(), 0) - array.PushLeft(1).PushRight(2) - gtest.Assert(array.Slice(), []interface{}{1, 2}) - }) -} - -func TestArray_PopRands(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{100, 200, 300, 400, 500, 600} - array := garray.NewFromCopy(a1) - gtest.AssertIN(array.PopRands(2), []interface{}{100, 200, 300, 400, 500, 600}) - }) -} - -func TestArray_PopLeftsAndPopRights(t *testing.T) { - gtest.Case(t, func() { - value1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - value2 := []interface{}{0, 1, 2, 3, 4, 5, 6} - array1 := garray.NewArrayFrom(value1) - array2 := garray.NewArrayFrom(value2) - gtest.Assert(array1.PopLefts(2), []interface{}{0, 1}) - gtest.Assert(array1.Slice(), []interface{}{2, 3, 4, 5, 6}) - gtest.Assert(array1.PopRights(2), []interface{}{5, 6}) - gtest.Assert(array1.Slice(), []interface{}{2, 3, 4}) - gtest.Assert(array1.PopRights(20), []interface{}{2, 3, 4}) - gtest.Assert(array1.Slice(), []interface{}{}) - gtest.Assert(array2.PopLefts(20), []interface{}{0, 1, 2, 3, 4, 5, 6}) - gtest.Assert(array2.Slice(), []interface{}{}) - }) -} - -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() { - 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.NewStrArrayFrom([]string{"g", "h"}) - s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) - s5 := garray.NewSortedStrArrayFrom(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) - }) -} - -func TestArray_Fill(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0} - a2 := []interface{}{0} - array1 := garray.NewArrayFrom(a1) - 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}) - }) -} - -func TestArray_Chunk(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{1, 2, 3, 4, 5} - array1 := garray.NewArrayFrom(a1) - chunks := array1.Chunk(2) - gtest.Assert(len(chunks), 3) - 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) - }) -} - -func TestArray_Pad(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0} - array1 := garray.NewArrayFrom(a1) - gtest.Assert(array1.Pad(3, 1).Slice(), []interface{}{0, 1, 1}) - gtest.Assert(array1.Pad(-4, 1).Slice(), []interface{}{1, 0, 1, 1}) - gtest.Assert(array1.Pad(3, 1).Slice(), []interface{}{1, 0, 1, 1}) - }) -} - -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}) - }) -} - -func TestArray_Rand(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - array1 := garray.NewArrayFrom(a1) - gtest.Assert(len(array1.Rands(2)), 2) - 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) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - array1 := garray.NewArrayFrom(a1) - gtest.Assert(array1.Shuffle().Len(), 7) - }) -} - -func TestArray_Reverse(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - array1 := garray.NewArrayFrom(a1) - gtest.Assert(array1.Reverse().Slice(), []interface{}{6, 5, 4, 3, 2, 1, 0}) - }) -} - -func TestArray_Join(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - array1 := garray.NewArrayFrom(a1) - gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6") - }) -} - -func TestArray_Replace(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - a2 := []interface{}{"a", "b", "c"} - a3 := []interface{}{"m", "n", "p", "z", "x", "y", "d", "u"} - array1 := garray.NewArrayFrom(a1) - array2 := array1.Replace(a2) - gtest.Assert(array2.Len(), 7) - gtest.Assert(array2.Contains("b"), true) - gtest.Assert(array2.Contains(4), true) - gtest.Assert(array2.Contains("v"), false) - array3 := array1.Replace(a3) - gtest.Assert(array3.Len(), 7) - gtest.Assert(array3.Contains(4), false) - gtest.Assert(array3.Contains("p"), true) - gtest.Assert(array3.Contains("u"), false) - }) -} - -func TestArray_SetArray(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3, 4, 5, 6} - a2 := []interface{}{"a", "b", "c"} - - array1 := garray.NewArrayFrom(a1) - array1 = array1.SetArray(a2) - gtest.Assert(array1.Len(), 3) - gtest.Assert(array1.Contains("b"), true) - gtest.Assert(array1.Contains("5"), false) - }) -} - -func TestArray_Sum(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3} - a2 := []interface{}{"a", "b", "c"} - a3 := []interface{}{"a", "1", "2"} - - array1 := garray.NewArrayFrom(a1) - array2 := garray.NewArrayFrom(a2) - array3 := garray.NewArrayFrom(a3) - - gtest.Assert(array1.Sum(), 6) - gtest.Assert(array2.Sum(), 0) - gtest.Assert(array3.Sum(), 3) - - }) -} - -func TestArray_Clone(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{0, 1, 2, 3} - array1 := garray.NewArrayFrom(a1) - array2 := array1.Clone() - - gtest.Assert(array1.Len(), 4) - gtest.Assert(array2.Sum(), 6) - gtest.AssertEQ(array1, array2) - - }) -} - -func TestArray_CountValues(t *testing.T) { - gtest.Case(t, func() { - a1 := []interface{}{"a", "b", "c", "d", "e", "d"} - array1 := garray.NewArrayFrom(a1) - array2 := array1.CountValues() - gtest.Assert(len(array2), 5) - gtest.Assert(array2["b"], 1) - gtest.Assert(array2["d"], 2) - }) -} - func TestSortedArray_NewSortedArrayFrom(t *testing.T) { gtest.Case(t, func() { a1 := []interface{}{"a", "f", "c"} @@ -838,70 +527,21 @@ func TestSortedArray_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 TestArray_LockFunc(t *testing.T) { +func TestSortedArray_Json(t *testing.T) { gtest.Case(t, func() { - s1 := []interface{}{"a", "b", "c", "d"} - a1 := garray.NewArrayFrom(s1, true) + s1 := []interface{}{"a", "b", "d", "c"} + s2 := []interface{}{"a", "b", "c", "d"} + a1 := garray.NewSortedArrayFrom(s1, gutil.ComparatorString) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + gtest.Assert(b1, b2) + gtest.Assert(err1, err2) - 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, true) - - 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) + a2 := garray.NewSortedArray(gutil.ComparatorString) + err1 = json.Unmarshal(b2, &a2) + gtest.Assert(a2.Slice(), s2) }) } diff --git a/container/garray/garray_z_unit_sorted_int_array_test.go b/container/garray/garray_z_unit_sorted_int_array_test.go new file mode 100644 index 000000000..83fa4d7ae --- /dev/null +++ b/container/garray/garray_z_unit_sorted_int_array_test.go @@ -0,0 +1,426 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// go test *.go + +package garray_test + +import ( + "encoding/json" + "testing" + "time" + + "github.com/gogf/gf/util/gconv" + + "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/test/gtest" +) + +func TestNewSortedIntArrayFrom(t *testing.T) { + gtest.Case(t, func() { + 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) + }) +} + +func TestNewSortedIntArrayFromCopy(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{0, 5, 2, 1, 4, 3, 6} + array1 := garray.NewSortedIntArrayFromCopy(a1, false) + gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6") + }) +} + +func TestSortedIntArray_SetArray(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{0, 1, 2, 3} + a2 := []int{4, 5, 6} + array1 := garray.NewSortedIntArrayFrom(a1) + array2 := array1.SetArray(a2) + + gtest.Assert(array2.Len(), 3) + gtest.Assert(array2.Search(3), -1) + gtest.Assert(array2.Search(5), 1) + gtest.Assert(array2.Search(6), 2) + }) +} + +func TestSortedIntArray_Sort(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{0, 3, 2, 1} + + array1 := garray.NewSortedIntArrayFrom(a1) + array2 := array1.Sort() + + gtest.Assert(array2.Len(), 4) + gtest.Assert(array2, []int{0, 1, 2, 3}) + }) +} + +func TestSortedIntArray_Get(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 0} + array1 := garray.NewSortedIntArrayFrom(a1) + gtest.Assert(array1.Get(0), 0) + gtest.Assert(array1.Get(1), 1) + gtest.Assert(array1.Get(3), 5) + }) +} + +func TestSortedIntArray_Remove(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 0} + array1 := garray.NewSortedIntArrayFrom(a1) + i1 := array1.Remove(2) + gtest.Assert(i1, 3) + gtest.Assert(array1.Search(5), 2) + + // 再次删除剩下的数组中的第一个 + i2 := array1.Remove(0) + gtest.Assert(i2, 0) + gtest.Assert(array1.Search(5), 1) + + a2 := []int{1, 3, 4} + array2 := garray.NewSortedIntArrayFrom(a2) + i3 := array2.Remove(1) + gtest.Assert(array2.Search(1), 0) + gtest.Assert(i3, 3) + i3 = array2.Remove(1) + gtest.Assert(array2.Search(4), -1) + gtest.Assert(i3, 4) + }) +} + +func TestSortedIntArray_PopLeft(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 2} + array1 := garray.NewSortedIntArrayFrom(a1) + i1 := array1.PopLeft() + gtest.Assert(i1, 1) + gtest.Assert(array1.Len(), 3) + gtest.Assert(array1.Search(1), -1) + }) +} + +func TestSortedIntArray_PopRight(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 2} + array1 := garray.NewSortedIntArrayFrom(a1) + i1 := array1.PopRight() + gtest.Assert(i1, 5) + gtest.Assert(array1.Len(), 3) + gtest.Assert(array1.Search(5), -1) + }) +} + +func TestSortedIntArray_PopRand(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 2} + array1 := garray.NewSortedIntArrayFrom(a1) + i1 := array1.PopRand() + gtest.Assert(array1.Len(), 3) + gtest.Assert(array1.Search(i1), -1) + gtest.AssertIN(i1, []int{1, 3, 5, 2}) + }) +} + +func TestSortedIntArray_PopRands(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 2} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.PopRands(2) + gtest.Assert(array1.Len(), 2) + gtest.AssertIN(ns1, []int{1, 3, 5, 2}) + + a2 := []int{1, 3, 5, 2} + array2 := garray.NewSortedIntArrayFrom(a2) + ns2 := array2.PopRands(5) + gtest.Assert(array2.Len(), 0) + gtest.Assert(len(ns2), 4) + gtest.AssertIN(ns2, []int{1, 3, 5, 2}) + }) +} + +func TestSortedIntArray_PopLefts(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 2} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.PopLefts(2) + gtest.Assert(array1.Len(), 2) + gtest.Assert(ns1, []int{1, 2}) + + a2 := []int{1, 3, 5, 2} + array2 := garray.NewSortedIntArrayFrom(a2) + ns2 := array2.PopLefts(5) + gtest.Assert(array2.Len(), 0) + gtest.AssertIN(ns2, []int{1, 3, 5, 2}) + }) +} + +func TestSortedIntArray_PopRights(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5, 2} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.PopRights(2) + gtest.Assert(array1.Len(), 2) + gtest.Assert(ns1, []int{3, 5}) + + a2 := []int{1, 3, 5, 2} + array2 := garray.NewSortedIntArrayFrom(a2) + ns2 := array2.PopRights(5) + gtest.Assert(array2.Len(), 0) + gtest.AssertIN(ns2, []int{1, 3, 5, 2}) + }) +} + +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}) + + ns2 := array1.Range(5, 4) + gtest.Assert(len(ns2), 0) + + ns3 := array1.Range(-1, 4) + gtest.Assert(len(ns3), 4) + + nsl := array1.Range(5, 8) + gtest.Assert(len(nsl), 1) + gtest.Assert(array2.Range(1, 2), []int{2}) + }) +} + +func TestSortedIntArray_Sum(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + n1 := array1.Sum() + gtest.Assert(n1, 9) + }) +} + +func TestSortedIntArray_Contains(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + gtest.Assert(array1.Contains(4), false) + }) +} + +func TestSortedIntArray_Clone(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + array2 := array1.Clone() + gtest.Assert(array2.Len(), 3) + gtest.Assert(array2, array1) + }) +} + +func TestSortedIntArray_Clear(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 3, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + array1.Clear() + gtest.Assert(array1.Len(), 0) + }) +} + +func TestSortedIntArray_Chunk(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 2, 3, 4, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.Chunk(2) //按每几个元素切成一个数组 + ns2 := array1.Chunk(-1) + gtest.Assert(len(ns1), 3) + gtest.Assert(ns1[0], []int{1, 2}) + gtest.Assert(ns1[2], []int{5}) + gtest.Assert(len(ns2), 0) + }) +} + +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}) + + ns2 := array1.SubSlice(7, 2) + gtest.Assert(len(ns2), 0) + + ns3 := array1.SubSlice(3, 5) + gtest.Assert(len(ns3), 2) + gtest.Assert(ns3, []int{4, 5}) + + 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}) + }) +} + +func TestSortedIntArray_Rand(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 2, 3, 4, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.Rand() //按每几个元素切成一个数组 + gtest.AssertIN(ns1, a1) + }) +} + +func TestSortedIntArray_Rands(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 2, 3, 4, 5} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.Rands(2) //按每几个元素切成一个数组 + gtest.AssertIN(ns1, a1) + gtest.Assert(len(ns1), 2) + + ns2 := array1.Rands(6) //按每几个元素切成一个数组 + gtest.AssertIN(ns2, a1) + gtest.Assert(len(ns2), 5) + }) +} + +func TestSortedIntArray_CountValues(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 2, 3, 4, 5, 3} + array1 := garray.NewSortedIntArrayFrom(a1) + ns1 := array1.CountValues() //按每几个元素切成一个数组 + gtest.Assert(len(ns1), 5) + gtest.Assert(ns1[2], 1) + gtest.Assert(ns1[3], 2) + }) +} + +func TestSortedIntArray_SetUnique(t *testing.T) { + gtest.Case(t, func() { + a1 := []int{1, 2, 3, 4, 5, 3} + array1 := garray.NewSortedIntArrayFrom(a1) + array1.SetUnique(true) + gtest.Assert(array1.Len(), 5) + gtest.Assert(array1, []int{1, 2, 3, 4, 5}) + }) +} + +func TestSortedIntArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 2, 3, 4} + a1 := garray.NewSortedIntArrayFrom(s1, true) + 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, true) + + 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.NewStrArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + s5 := garray.NewSortedStrArrayFrom(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) + }) +} + +func TestSortedIntArray_Json(t *testing.T) { + gtest.Case(t, func() { + s1 := []int{1, 4, 3, 2} + s2 := []int{1, 2, 3, 4} + a1 := garray.NewSortedIntArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + gtest.Assert(b1, b2) + gtest.Assert(err1, err2) + + a2 := garray.NewSortedIntArray() + err1 = json.Unmarshal(b2, &a2) + gtest.Assert(a2.Slice(), s2) + }) +} diff --git a/container/garray/garray_z_unit_sorted_str_array_test.go b/container/garray/garray_z_unit_sorted_str_array_test.go new file mode 100644 index 000000000..bc6003d4d --- /dev/null +++ b/container/garray/garray_z_unit_sorted_str_array_test.go @@ -0,0 +1,437 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// go test *.go + +package garray_test + +import ( + "encoding/json" + "testing" + "time" + + "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/test/gtest" + "github.com/gogf/gf/util/gconv" +) + +func TestNewSortedStrArrayFrom(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"a", "d", "c", "b"} + s1 := garray.NewSortedStrArrayFrom(a1, true) + gtest.Assert(s1, []string{"a", "b", "c", "d"}) + s2 := garray.NewSortedStrArrayFrom(a1, false) + gtest.Assert(s2, []string{"a", "b", "c", "d"}) + }) +} + +func TestNewSortedStrArrayFromCopy(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"a", "d", "c", "b"} + s1 := garray.NewSortedStrArrayFromCopy(a1, true) + gtest.Assert(s1.Len(), 4) + gtest.Assert(s1, []string{"a", "b", "c", "d"}) + }) +} + +func TestSortedStrArray_SetArray(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"a", "d", "c", "b"} + a2 := []string{"f", "g", "h"} + array1 := garray.NewSortedStrArrayFrom(a1) + array1.SetArray(a2) + gtest.Assert(array1.Len(), 3) + gtest.Assert(array1.Contains("d"), false) + gtest.Assert(array1.Contains("b"), false) + gtest.Assert(array1.Contains("g"), true) + }) +} + +func TestSortedStrArray_Sort(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + + gtest.Assert(array1, []string{"a", "b", "c", "d"}) + array1.Sort() + gtest.Assert(array1.Len(), 4) + gtest.Assert(array1.Contains("c"), true) + gtest.Assert(array1, []string{"a", "b", "c", "d"}) + }) +} + +func TestSortedStrArray_Get(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + gtest.Assert(array1.Get(2), "c") + gtest.Assert(array1.Get(0), "a") + }) +} + +func TestSortedStrArray_Remove(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + gtest.Assert(array1.Remove(2), "c") + gtest.Assert(array1.Get(2), "d") + gtest.Assert(array1.Len(), 3) + gtest.Assert(array1.Contains("c"), false) + + gtest.Assert(array1.Remove(0), "a") + gtest.Assert(array1.Len(), 2) + gtest.Assert(array1.Contains("a"), false) + + // 此时array1里的元素只剩下2个 + gtest.Assert(array1.Remove(1), "d") + gtest.Assert(array1.Len(), 1) + }) +} + +func TestSortedStrArray_PopLeft(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.PopLeft() + gtest.Assert(s1, "a") + gtest.Assert(array1.Len(), 4) + gtest.Assert(array1.Contains("a"), false) + }) +} + +func TestSortedStrArray_PopRight(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.PopRight() + gtest.Assert(s1, "e") + gtest.Assert(array1.Len(), 4) + gtest.Assert(array1.Contains("e"), false) + }) +} + +func TestSortedStrArray_PopRand(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.PopRand() + gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"}) + gtest.Assert(array1.Len(), 4) + gtest.Assert(array1.Contains(s1), false) + }) +} + +func TestSortedStrArray_PopRands(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.PopRands(2) + gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"}) + gtest.Assert(array1.Len(), 3) + gtest.Assert(len(s1), 2) + + s1 = array1.PopRands(4) + gtest.Assert(len(s1), 3) + gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"}) + }) +} + +func TestSortedStrArray_PopLefts(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.PopLefts(2) + gtest.Assert(s1, []string{"a", "b"}) + gtest.Assert(array1.Len(), 3) + gtest.Assert(len(s1), 2) + + s1 = array1.PopLefts(4) + gtest.Assert(len(s1), 3) + gtest.Assert(s1, []string{"c", "d", "e"}) + }) +} + +func TestSortedStrArray_PopRights(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.PopRights(2) + gtest.Assert(s1, []string{"f", "g"}) + gtest.Assert(array1.Len(), 5) + gtest.Assert(len(s1), 2) + s1 = array1.PopRights(6) + gtest.Assert(len(s1), 5) + gtest.Assert(s1, []string{"a", "b", "c", "d", "e"}) + gtest.Assert(array1.Len(), 0) + }) +} + +func TestSortedStrArray_Range(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + array1 := garray.NewSortedStrArrayFrom(a1) + array2 := garray.NewSortedStrArrayFrom(a1, true) + s1 := array1.Range(2, 4) + gtest.Assert(len(s1), 2) + gtest.Assert(s1, []string{"c", "d"}) + + s1 = array1.Range(-1, 2) + gtest.Assert(len(s1), 2) + gtest.Assert(s1, []string{"a", "b"}) + + s1 = array1.Range(4, 8) + gtest.Assert(len(s1), 3) + gtest.Assert(s1, []string{"e", "f", "g"}) + gtest.Assert(array1.Range(10, 2), nil) + + s2 := array2.Range(2, 4) + gtest.Assert(s2, []string{"c", "d"}) + + }) +} + +func TestSortedStrArray_Sum(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + a2 := []string{"1", "2", "3", "4", "a"} + array1 := garray.NewSortedStrArrayFrom(a1) + array2 := garray.NewSortedStrArrayFrom(a2) + gtest.Assert(array1.Sum(), 0) + gtest.Assert(array2.Sum(), 10) + }) +} + +func TestSortedStrArray_Clone(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + array1 := garray.NewSortedStrArrayFrom(a1) + array2 := array1.Clone() + gtest.Assert(array1, array2) + array1.Remove(1) + gtest.Assert(array2.Len(), 7) + }) +} + +func TestSortedStrArray_Clear(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + array1 := garray.NewSortedStrArrayFrom(a1) + array1.Clear() + gtest.Assert(array1.Len(), 0) + }) +} + +func TestSortedStrArray_SubSlice(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + array1 := garray.NewSortedStrArrayFrom(a1) + array2 := garray.NewSortedStrArrayFrom(a1, true) + s1 := array1.SubSlice(1, 3) + gtest.Assert(len(s1), 3) + gtest.Assert(s1, []string{"b", "c", "d"}) + gtest.Assert(array1.Len(), 7) + + s2 := array1.SubSlice(1, 10) + gtest.Assert(len(s2), 6) + + s3 := array1.SubSlice(10, 2) + gtest.Assert(len(s3), 0) + + s3 = array1.SubSlice(-5, 2) + gtest.Assert(s3, []string{"c", "d"}) + + s3 = array1.SubSlice(-10, 2) + gtest.Assert(s3, nil) + + s3 = array1.SubSlice(1, -2) + gtest.Assert(s3, nil) + + gtest.Assert(array2.SubSlice(1, 3), []string{"b", "c", "d"}) + }) +} + +func TestSortedStrArray_Len(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "c", "b", "f", "g"} + array1 := garray.NewSortedStrArrayFrom(a1) + gtest.Assert(array1.Len(), 7) + + }) +} + +func TestSortedStrArray_Rand(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d"} + array1 := garray.NewSortedStrArrayFrom(a1) + gtest.AssertIN(array1.Rand(), []string{"e", "a", "d"}) + }) +} + +func TestSortedStrArray_Rands(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d"} + array1 := garray.NewSortedStrArrayFrom(a1) + s1 := array1.Rands(2) + + gtest.AssertIN(s1, []string{"e", "a", "d"}) + gtest.Assert(len(s1), 2) + + s1 = array1.Rands(4) + gtest.AssertIN(s1, []string{"e", "a", "d"}) + gtest.Assert(len(s1), 3) + }) +} + +func TestSortedStrArray_Join(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d"} + array1 := garray.NewSortedStrArrayFrom(a1) + gtest.Assert(array1.Join(","), "a,d,e") + gtest.Assert(array1.Join("."), "a.d.e") + }) +} + +func TestSortedStrArray_CountValues(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "a", "c"} + array1 := garray.NewSortedStrArrayFrom(a1) + m1 := array1.CountValues() + gtest.Assert(m1["a"], 2) + gtest.Assert(m1["d"], 1) + + }) +} + +func TestSortedStrArray_Chunk(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "a", "c"} + array1 := garray.NewSortedStrArrayFrom(a1) + array2 := array1.Chunk(2) + gtest.Assert(len(array2), 3) + gtest.Assert(len(array2[0]), 2) + gtest.Assert(array2[1], []string{"c", "d"}) + gtest.Assert(array1.Chunk(0), nil) + }) +} + +func TestSortedStrArray_SetUnique(t *testing.T) { + gtest.Case(t, func() { + a1 := []string{"e", "a", "d", "a", "c"} + array1 := garray.NewSortedStrArrayFrom(a1) + array2 := array1.SetUnique(true) + gtest.Assert(array2.Len(), 4) + gtest.Assert(array2, []string{"a", "c", "d", "e"}) + }) +} + +func TestSortedStrArray_LockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []string{"a", "b", "c", "d"} + a1 := garray.NewSortedStrArrayFrom(s1, true) + + 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) + }) +} + +func TestSortedStrArray_RLockFunc(t *testing.T) { + gtest.Case(t, func() { + s1 := []string{"a", "b", "c", "d"} + a1 := garray.NewSortedStrArrayFrom(s1, true) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 1) + //go1 + go a1.RLockFunc(func(n1 []string) { //读锁 + 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) + }) +} + +func TestSortedStrArray_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 + } + + s1 := []string{"a", "b", "c", "d"} + s2 := []string{"e", "f"} + i1 := garray.NewIntArrayFrom([]int{1, 2, 3}) + i2 := garray.NewArrayFrom([]interface{}{3}) + s3 := garray.NewStrArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1) + s5 := garray.NewSortedStrArrayFrom(s2) + s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) + a1 := garray.NewSortedStrArrayFrom(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) + }) +} + +func TestSortedStrArray_Json(t *testing.T) { + gtest.Case(t, func() { + s1 := []string{"a", "b", "d", "c"} + s2 := []string{"a", "b", "c", "d"} + a1 := garray.NewSortedStrArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + gtest.Assert(b1, b2) + gtest.Assert(err1, err2) + + a2 := garray.NewSortedStrArray() + err1 = json.Unmarshal(b2, &a2) + gtest.Assert(a2.Slice(), s2) + }) +} diff --git a/container/gvar/gvar.go b/container/gvar/gvar.go index 895a8c8eb..61522399b 100644 --- a/container/gvar/gvar.go +++ b/container/gvar/gvar.go @@ -43,6 +43,17 @@ func (v *Var) MarshalJSON() ([]byte, error) { return json.Marshal(v.Val()) } +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (v *Var) UnmarshalJSON(b []byte) error { + var i interface{} + err := json.Unmarshal(b, &i) + if err != nil { + return err + } + v.Set(i) + return nil +} + // Set sets to , and returns the old value. func (v *Var) Set(value interface{}) (old interface{}) { if v.safe { diff --git a/util/gutil/gutil_comparator.go b/util/gutil/gutil_comparator.go index 3f62ab1d6..6a3d1f2c1 100644 --- a/util/gutil/gutil_comparator.go +++ b/util/gutil/gutil_comparator.go @@ -1,3 +1,9 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package gutil import (